mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-07-10 11:04:10 -04:00
commit
621ea37a24
48 changed files with 2500 additions and 4052 deletions
|
|
@ -46,8 +46,8 @@ static void finish_exchange_arrange_and_focus(Client *c1, Client *c2,
|
|||
} else {
|
||||
arrange(c1->mon, false, false);
|
||||
}
|
||||
wl_list_remove(&c2->flink);
|
||||
wl_list_insert(&c1->flink, &c2->flink);
|
||||
|
||||
wl_list_safe_reinsert_next(&c1->flink, &c2->flink);
|
||||
|
||||
if (config.warpcursor)
|
||||
warp_cursor(c1);
|
||||
|
|
@ -57,7 +57,14 @@ void client_tile_resize(Client *c, struct wlr_box geo, int32_t interact) {
|
|||
if (!ISFAKETILED(c))
|
||||
return;
|
||||
|
||||
if (!c->isfullscreen && !c->ismaximizescreen) {
|
||||
if (!c->mon->isoverview && !c->isfullscreen &&
|
||||
(c->group_next || c->group_prev)) {
|
||||
geo.y = geo.y + config.group_bar_height;
|
||||
geo.height -= config.group_bar_height;
|
||||
}
|
||||
|
||||
if ((!c->isfullscreen && !c->ismaximizescreen) ||
|
||||
is_scroller_layout(c->mon)) {
|
||||
resize(c, geo, interact);
|
||||
}
|
||||
}
|
||||
|
|
@ -73,7 +80,7 @@ void client_active(Client *c) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (c->swallowing || !c->mon)
|
||||
if (c->swallowdby || !c->mon)
|
||||
return;
|
||||
|
||||
if (c->isminimized) {
|
||||
|
|
@ -104,19 +111,199 @@ void client_add_jump_label_node(Client *c) {
|
|||
wlr_scene_node_set_enabled(&c->jump_label_node->scene_buffer->node, false);
|
||||
}
|
||||
|
||||
void client_add_tab_bar_node(Client *c) {
|
||||
void client_add_group_bar(Client *c) {
|
||||
|
||||
if (config.tab_bar_height <= 0) {
|
||||
if (config.group_bar_height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
MangoNodeData *mangonodedata = ecalloc(1, sizeof(MangoNodeData));
|
||||
mangonodedata->node_data = c;
|
||||
mangonodedata->type = MANGO_TITLE_NODE;
|
||||
uint32_t layer = c->isoverlay ? LyrOverlay
|
||||
: c->isfloating || c->isfullscreen ? LyrTop
|
||||
: c->ismaximizescreen ? LyrMaximize
|
||||
: LyrTile;
|
||||
|
||||
c->tab_bar_node = mango_tab_bar_node_create(
|
||||
mangonodedata, layers[LyrDecorate], config.tabdata, 0, 0);
|
||||
wlr_scene_node_lower_to_bottom(&c->tab_bar_node->scene_buffer->node);
|
||||
wlr_scene_node_set_enabled(&c->tab_bar_node->scene_buffer->node, false);
|
||||
mango_tab_bar_node_update(c->tab_bar_node, client_get_title(c), 1.0);
|
||||
c->group_bar = mango_group_bar_create(c, GroupBar, layers[layer],
|
||||
config.groupbardata, 0, 0);
|
||||
wlr_scene_node_lower_to_bottom(&c->group_bar->scene_buffer->node);
|
||||
wlr_scene_node_set_enabled(&c->group_bar->scene_buffer->node, false);
|
||||
mango_group_bar_update(c->group_bar, client_get_title(c),
|
||||
c->mon ? c->mon->wlr_output->scale
|
||||
: selmon ? selmon->wlr_output->scale
|
||||
: 1.0f);
|
||||
}
|
||||
|
||||
void client_focus_group_member(Client *c) {
|
||||
if (!c->group_prev && !c->group_next)
|
||||
return;
|
||||
|
||||
if (c->isgroupfocusing)
|
||||
return;
|
||||
|
||||
Client *head = c;
|
||||
while (head->group_prev)
|
||||
head = head->group_prev;
|
||||
|
||||
Client *cur_focusing = NULL;
|
||||
while (head) {
|
||||
if (head->isgroupfocusing) {
|
||||
cur_focusing = head;
|
||||
break;
|
||||
}
|
||||
head = head->group_next;
|
||||
}
|
||||
|
||||
if (!cur_focusing || !cur_focusing->mon)
|
||||
return;
|
||||
|
||||
if (cur_focusing && cur_focusing->mon->isoverview)
|
||||
return;
|
||||
|
||||
cur_focusing->isgroupfocusing = false;
|
||||
c->mon = cur_focusing->mon;
|
||||
client_replace(c, cur_focusing, true, false);
|
||||
mango_group_bar_set_focus(cur_focusing->group_bar, false);
|
||||
|
||||
c->isgroupfocusing = true;
|
||||
mango_group_bar_set_focus(c->group_bar, true);
|
||||
|
||||
client_reparent_group(c);
|
||||
|
||||
focusclient(c, 1);
|
||||
|
||||
arrange(c->mon, false, false);
|
||||
}
|
||||
|
||||
void client_check_tab_node_visible(Client *c) {
|
||||
|
||||
if (!c || !c->mon)
|
||||
return;
|
||||
|
||||
Client *head = c;
|
||||
while (head->group_prev)
|
||||
head = head->group_prev;
|
||||
|
||||
Client *cur = head;
|
||||
while (cur) {
|
||||
if (!c->mon->isoverview && cur->group_bar &&
|
||||
(cur->group_next || cur->group_prev) && TAGMATCH(c, c->mon) &&
|
||||
ISNORMAL(c) && !c->isfullscreen) {
|
||||
wlr_scene_node_set_enabled(&cur->group_bar->scene_buffer->node,
|
||||
true);
|
||||
} else {
|
||||
wlr_scene_node_set_enabled(&cur->group_bar->scene_buffer->node,
|
||||
false);
|
||||
}
|
||||
cur = cur->group_next;
|
||||
}
|
||||
}
|
||||
|
||||
void client_raise_group(Client *c) {
|
||||
if (!c || !c->mon)
|
||||
return;
|
||||
|
||||
Client *head = c;
|
||||
while (head->group_prev)
|
||||
head = head->group_prev;
|
||||
|
||||
Client *cur = head;
|
||||
while (cur) {
|
||||
if (cur->group_bar) {
|
||||
wlr_scene_node_raise_to_top(&cur->group_bar->scene_buffer->node);
|
||||
}
|
||||
wlr_scene_node_raise_to_top(&cur->scene->node);
|
||||
cur = cur->group_next;
|
||||
}
|
||||
}
|
||||
|
||||
void client_reparent_group(Client *c) {
|
||||
if (!c || !c->mon)
|
||||
return;
|
||||
|
||||
int32_t layer = c->isoverlay ? LyrOverlay
|
||||
: c->isfloating || c->isfullscreen ? LyrTop
|
||||
: c->ismaximizescreen ? LyrMaximize
|
||||
: LyrTile;
|
||||
|
||||
Client *head = c;
|
||||
while (head->group_prev)
|
||||
head = head->group_prev;
|
||||
|
||||
Client *cur = head;
|
||||
while (cur) {
|
||||
if (cur->group_bar) {
|
||||
wlr_scene_node_reparent(&cur->group_bar->scene_buffer->node,
|
||||
layers[layer]);
|
||||
}
|
||||
wlr_scene_node_reparent(&cur->scene->node, layers[layer]);
|
||||
cur = cur->group_next;
|
||||
}
|
||||
}
|
||||
|
||||
void client_handle_decorate_click(MangoGroupBar *gb) {
|
||||
|
||||
if (!gb)
|
||||
return;
|
||||
|
||||
if (gb->node_data) {
|
||||
Client *c = gb->node_data;
|
||||
client_focus_group_member(c);
|
||||
}
|
||||
}
|
||||
|
||||
void client_set_group_mon(Client *c, Monitor *m) {
|
||||
Client *head = c;
|
||||
while (head->group_prev)
|
||||
head = head->group_prev;
|
||||
|
||||
Client *cur = head;
|
||||
while (cur) {
|
||||
client_change_mon(cur, m);
|
||||
cur = cur->group_next;
|
||||
}
|
||||
}
|
||||
|
||||
void client_set_group_config(Client *c) {
|
||||
Client *head = c;
|
||||
while (head->group_prev)
|
||||
head = head->group_prev;
|
||||
|
||||
Client *cur = head;
|
||||
while (cur) {
|
||||
mango_jump_label_node_apply_config(cur->jump_label_node,
|
||||
&config.jumplabeldata);
|
||||
wlr_scene_rect_set_color(cur->droparea, config.dropcolor);
|
||||
wlr_scene_rect_set_color(cur->splitindicator[0], config.splitcolor);
|
||||
wlr_scene_rect_set_color(cur->splitindicator[1], config.splitcolor);
|
||||
mango_group_bar_apply_config(cur->group_bar, &config.groupbardata);
|
||||
cur = cur->group_next;
|
||||
}
|
||||
}
|
||||
|
||||
void client_group_detach(Client *c) {
|
||||
if (c->group_prev)
|
||||
c->group_prev->group_next = c->group_next;
|
||||
if (c->group_next)
|
||||
c->group_next->group_prev = c->group_prev;
|
||||
c->group_prev = NULL;
|
||||
c->group_next = NULL;
|
||||
c->isgroupfocusing = false;
|
||||
}
|
||||
|
||||
void client_group_replace(Client *old, Client *new) {
|
||||
client_group_detach(new);
|
||||
|
||||
new->group_prev = old->group_prev;
|
||||
new->group_next = old->group_next;
|
||||
if (old->group_prev)
|
||||
old->group_prev->group_next = new;
|
||||
if (old->group_next)
|
||||
old->group_next->group_prev = new;
|
||||
old->group_prev = NULL;
|
||||
old->group_next = NULL;
|
||||
|
||||
if (old->is_logic_hide || (!new->group_prev && !new->group_next)) {
|
||||
new->isgroupfocusing = false;
|
||||
} else {
|
||||
new->isgroupfocusing = old->isgroupfocusing;
|
||||
}
|
||||
}
|
||||
61
src/action/monitor.h
Normal file
61
src/action/monitor.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
bool mango_scene_output_commit(struct wlr_scene_output *scene_output,
|
||||
struct wlr_output_state *state) {
|
||||
struct wlr_output *wlr_output = scene_output->output;
|
||||
Monitor *m = wlr_output->data;
|
||||
bool committed = false;
|
||||
|
||||
bool frame_allow_tearing = check_tearing_frame_allow(m);
|
||||
|
||||
if (!wlr_scene_output_needs_frame(scene_output))
|
||||
return true;
|
||||
|
||||
// 构建状态,将场景的 Buffer 附着到 state 上
|
||||
if (!wlr_scene_output_build_state(scene_output, state, NULL))
|
||||
return false;
|
||||
|
||||
if (frame_allow_tearing) {
|
||||
state->tearing_page_flip = true;
|
||||
} else {
|
||||
state->tearing_page_flip = false;
|
||||
}
|
||||
|
||||
// 测试是否支持撕裂
|
||||
if (state->tearing_page_flip == true) {
|
||||
if (!wlr_output_test_state(wlr_output, state)) {
|
||||
// 如果 DRM 拒绝(例如当前输出/驱动不支持撕裂),降级关闭撕裂
|
||||
state->tearing_page_flip = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 提交状态
|
||||
committed = wlr_output_commit_state(wlr_output, state);
|
||||
if (!committed && state->tearing_page_flip) {
|
||||
// 重试一次
|
||||
state->tearing_page_flip = false;
|
||||
committed = wlr_output_commit_state(wlr_output, state);
|
||||
}
|
||||
|
||||
if (committed) {
|
||||
if (state == &m->pending) {
|
||||
wlr_output_state_finish(&m->pending);
|
||||
wlr_output_state_init(&m->pending);
|
||||
}
|
||||
} else {
|
||||
wlr_log(WLR_INFO, "Failed to commit output %s", m->wlr_output->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return committed;
|
||||
}
|
||||
|
||||
bool mango_output_commit(Monitor *m) {
|
||||
|
||||
bool committed = wlr_output_commit_state(m->wlr_output, &m->pending);
|
||||
if (committed) {
|
||||
wlr_output_state_finish(&m->pending);
|
||||
wlr_output_state_init(&m->pending);
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Failed to commit frame");
|
||||
}
|
||||
return committed;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -30,7 +30,7 @@ struct dvec2 calculate_animation_curve_at(double t, int32_t type) {
|
|||
|
||||
void handle_snapshot_meta_destroy(struct wl_listener *listener, void *data) {
|
||||
SnapshotMetadata *meta = wl_container_of(listener, meta, destroy);
|
||||
wl_list_remove(&meta->destroy.link); // 安全移除监听器
|
||||
wl_list_remove(&meta->destroy.link);
|
||||
free(meta);
|
||||
}
|
||||
|
||||
|
|
@ -175,6 +175,7 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
|||
}
|
||||
meta->orig_width = scene_buffer->dst_width;
|
||||
meta->orig_height = scene_buffer->dst_height;
|
||||
meta->type = Snapshot;
|
||||
|
||||
struct wlr_scene_surface *scene_surface =
|
||||
wlr_scene_surface_try_from_buffer(scene_buffer);
|
||||
|
|
@ -212,11 +213,8 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
|||
|
||||
// Effects
|
||||
wlr_scene_buffer_set_opacity(snapshot_buffer, scene_buffer->opacity);
|
||||
wlr_scene_buffer_set_corner_radius(snapshot_buffer,
|
||||
scene_buffer->corner_radius,
|
||||
scene_buffer->corners);
|
||||
|
||||
wlr_scene_buffer_set_backdrop_blur(snapshot_buffer, false);
|
||||
wlr_scene_buffer_set_corner_radii(snapshot_buffer,
|
||||
scene_buffer->corners);
|
||||
|
||||
if (scene_surface != NULL && scene_surface->surface->buffer != NULL) {
|
||||
wlr_scene_buffer_set_buffer(snapshot_buffer,
|
||||
|
|
@ -248,6 +246,8 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
|||
|
||||
break;
|
||||
}
|
||||
case WLR_SCENE_NODE_BLUR:
|
||||
break;
|
||||
case WLR_SCENE_NODE_OPTIMIZED_BLUR:
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
void layer_actual_size(LayerSurface *l, int32_t *width, int32_t *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;
|
||||
*width = l->geom.width;
|
||||
*height = l->geom.height;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -151,6 +149,34 @@ void set_layer_dir_animaiton(LayerSurface *l, struct wlr_box *geo) {
|
|||
}
|
||||
}
|
||||
|
||||
void layer_draw_shield(LayerSurface *l) {
|
||||
int32_t width, height;
|
||||
|
||||
if (!l->mapped)
|
||||
return;
|
||||
|
||||
if (active_capture_count > 0 && l->shield_when_capture) {
|
||||
|
||||
layer_actual_size(l, &width, &height);
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
wlr_scene_node_set_enabled(&l->shield->node, false);
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_scene_node_raise_to_top(&l->shield->node);
|
||||
wlr_scene_node_set_position(&l->shield->node, 0, 0);
|
||||
wlr_scene_rect_set_size(l->shield, width, height);
|
||||
wlr_scene_node_set_enabled(&l->shield->node, true);
|
||||
} else {
|
||||
if (l->shield->node.enabled) {
|
||||
wlr_scene_node_lower_to_bottom(&l->shield->node);
|
||||
wlr_scene_node_set_position(&l->shield->node, 0, 0);
|
||||
wlr_scene_node_set_enabled(&l->shield->node, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void layer_draw_shadow(LayerSurface *l) {
|
||||
|
||||
if (!l->mapped || !l->shadow)
|
||||
|
|
@ -187,8 +213,7 @@ void layer_draw_shadow(LayerSurface *l) {
|
|||
|
||||
struct clipped_region clipped_region = {
|
||||
.area = intersection_box,
|
||||
.corner_radius = config.border_radius,
|
||||
.corners = config.border_radius_location_default,
|
||||
.corners = corner_radii_all(config.border_radius),
|
||||
};
|
||||
|
||||
wlr_scene_node_set_position(&l->shadow->node, shadow_box.x, shadow_box.y);
|
||||
|
|
@ -328,9 +353,14 @@ void layer_animation_next_tick(LayerSurface *l) {
|
|||
(1.0 - config.fadein_begin_opacity),
|
||||
1.0f);
|
||||
|
||||
if (config.animation_fade_in)
|
||||
if (config.animation_fade_in) {
|
||||
if (config.blur && !l->noblur && !config.blur_optimized) {
|
||||
wlr_scene_blur_set_strength(l->blur, opacity);
|
||||
wlr_scene_blur_set_alpha(l->blur, opacity);
|
||||
}
|
||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||
scene_buffer_apply_opacity, &opacity);
|
||||
}
|
||||
|
||||
wlr_scene_node_set_position(&l->scene->node, x, y);
|
||||
|
||||
|
|
@ -358,6 +388,10 @@ void layer_animation_next_tick(LayerSurface *l) {
|
|||
.height = height,
|
||||
};
|
||||
|
||||
if (config.blur && config.blur_layer && !l->noblur && l->blur)
|
||||
wlr_scene_blur_set_size(l->blur, l->animation.current.width,
|
||||
l->animation.current.height);
|
||||
|
||||
if (animation_passed >= 1.0) {
|
||||
l->animation.running = false;
|
||||
l->need_output_flush = false;
|
||||
|
|
@ -374,6 +408,10 @@ void init_fadeout_layers(LayerSurface *l) {
|
|||
if (!l->mon || !l->scene)
|
||||
return;
|
||||
|
||||
if (l->shield_when_capture) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((l->animation_type_close &&
|
||||
strcmp(l->animation_type_close, "none") == 0) ||
|
||||
(!l->animation_type_close &&
|
||||
|
|
@ -567,8 +605,10 @@ bool layer_draw_frame(LayerSurface *l) {
|
|||
if (config.animations && config.layer_animations && l->animation.running &&
|
||||
!l->noanim) {
|
||||
layer_animation_next_tick(l);
|
||||
layer_draw_shield(l);
|
||||
layer_draw_shadow(l);
|
||||
} else {
|
||||
layer_draw_shield(l);
|
||||
layer_draw_shadow(l);
|
||||
l->need_output_flush = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,10 +45,9 @@ void set_tagin_animation(Monitor *m, Client *c) {
|
|||
|
||||
void set_arrange_visible(Monitor *m, Client *c, bool want_animation) {
|
||||
|
||||
if (!ISTILED(c) || ((!c->is_clip_to_hide || !is_scroller_layout(c->mon)) &&
|
||||
(!c->is_monocle_hide || !is_monocle_layout(c->mon)))) {
|
||||
if (!ISTILED(c) || (!c->is_clip_to_hide || !is_scroller_layout(c->mon))) {
|
||||
c->is_clip_to_hide = false;
|
||||
c->is_monocle_hide = false;
|
||||
c->is_logic_hide = false;
|
||||
wlr_scene_node_set_enabled(&c->scene->node, true);
|
||||
wlr_scene_node_set_enabled(&c->scene_surface->node, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,4 +205,30 @@ void wl_list_swap(struct wl_list *l1, struct wl_list *l2) {
|
|||
tmp2_prev->next = l1;
|
||||
tmp2_next->prev = l1;
|
||||
}
|
||||
}
|
||||
|
||||
void wl_list_safe_reinsert_prev(struct wl_list *l1, struct wl_list *l2) {
|
||||
if (!l1 || !l2)
|
||||
return;
|
||||
if (l1 == l2)
|
||||
return;
|
||||
if (l1->prev == l2)
|
||||
return;
|
||||
|
||||
wl_list_remove(l2);
|
||||
wl_list_init(l2);
|
||||
wl_list_insert(l1->prev, l2);
|
||||
}
|
||||
|
||||
void wl_list_safe_reinsert_next(struct wl_list *l1, struct wl_list *l2) {
|
||||
if (!l1 || !l2)
|
||||
return;
|
||||
if (l1 == l2)
|
||||
return;
|
||||
if (l1->next == l2)
|
||||
return;
|
||||
|
||||
wl_list_remove(l2);
|
||||
wl_list_init(l2);
|
||||
wl_list_insert(l1, l2);
|
||||
}
|
||||
|
|
@ -12,4 +12,6 @@ char *join_strings(char *arr[], const char *sep);
|
|||
char *join_strings_with_suffix(char *arr[], const char *suffix,
|
||||
const char *sep);
|
||||
char *string_printf(const char *fmt, ...);
|
||||
void wl_list_swap(struct wl_list *l1, struct wl_list *l2);
|
||||
void wl_list_swap(struct wl_list *l1, struct wl_list *l2);
|
||||
void wl_list_safe_reinsert_prev(struct wl_list *l1, struct wl_list *l2);
|
||||
void wl_list_safe_reinsert_next(struct wl_list *l1, struct wl_list *l2);
|
||||
|
|
@ -22,6 +22,11 @@ enum { NUM_TYPE_MINUS, NUM_TYPE_PLUS, NUM_TYPE_DEFAULT };
|
|||
|
||||
enum { KEY_TYPE_CODE, KEY_TYPE_SYM };
|
||||
|
||||
enum render_bit_depth {
|
||||
MANGO_RENDER_BIT_DEPTH_DEFAULT = 0,
|
||||
MANGO_RENDER_BIT_DEPTH_8,
|
||||
MANGO_RENDER_BIT_DEPTH_10,
|
||||
};
|
||||
typedef struct {
|
||||
uint32_t keycode1;
|
||||
uint32_t keycode2;
|
||||
|
|
@ -74,11 +79,13 @@ typedef struct {
|
|||
int32_t isunglobal;
|
||||
int32_t isglobal;
|
||||
int32_t isoverlay;
|
||||
int32_t shield_when_capture;
|
||||
int32_t allow_shortcuts_inhibit;
|
||||
int32_t ignore_maximize;
|
||||
int32_t ignore_minimize;
|
||||
int32_t isnosizehint;
|
||||
int32_t idleinhibit_when_focus;
|
||||
int32_t vrr_only_fullscreen;
|
||||
char *monitor;
|
||||
int32_t offsetx;
|
||||
int32_t offsety;
|
||||
|
|
@ -113,6 +120,8 @@ typedef struct {
|
|||
float refresh; // Refresh rate
|
||||
int32_t vrr; // variable refresh rate
|
||||
int32_t custom; // enable custom mode
|
||||
int32_t hdr; // enable hdr mode
|
||||
int32_t disable; // prefer disable
|
||||
} ConfigMonitorRule;
|
||||
|
||||
// 修改后的宏定义
|
||||
|
|
@ -179,6 +188,7 @@ typedef struct {
|
|||
char *layer_name; // 布局名称
|
||||
char *animation_type_open;
|
||||
char *animation_type_close;
|
||||
int32_t shield_when_capture;
|
||||
int32_t noblur;
|
||||
int32_t noanim;
|
||||
int32_t noshadow;
|
||||
|
|
@ -332,7 +342,7 @@ typedef struct {
|
|||
uint32_t gappoh;
|
||||
uint32_t gappov;
|
||||
uint32_t borderpx;
|
||||
uint32_t tab_bar_height;
|
||||
uint32_t group_bar_height;
|
||||
float scratchpad_width_ratio;
|
||||
float scratchpad_height_ratio;
|
||||
float rootcolor[4];
|
||||
|
|
@ -410,7 +420,9 @@ typedef struct {
|
|||
struct xkb_context *ctx;
|
||||
struct xkb_keymap *keymap;
|
||||
DecorateDrawData jumplabeldata;
|
||||
DecorateDrawData tabdata;
|
||||
DecorateDrawData groupbardata;
|
||||
|
||||
int32_t hdr_depth;
|
||||
} Config;
|
||||
|
||||
typedef int32_t (*FuncType)(const Arg *);
|
||||
|
|
@ -418,7 +430,7 @@ Config config;
|
|||
|
||||
bool parse_config_file(Config *config, const char *file_path, bool must_exist);
|
||||
bool apply_rule_to_state(Monitor *m, const ConfigMonitorRule *rule,
|
||||
struct wlr_output_state *state, int vrr, int custom);
|
||||
struct wlr_output_state *state);
|
||||
bool monitor_matches_rule(Monitor *m, const ConfigMonitorRule *rule);
|
||||
|
||||
// Helper function to trim whitespace from start and end of a string
|
||||
|
|
@ -1010,9 +1022,17 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
|||
if (strcmp(func_name, "focusstack") == 0) {
|
||||
func = focusstack;
|
||||
(*arg).i = parse_circle_direction(arg_value);
|
||||
} else if (strcmp(func_name, "groupfocus") == 0) {
|
||||
func = groupfocus;
|
||||
(*arg).i = parse_circle_direction(arg_value);
|
||||
} else if (strcmp(func_name, "focusdir") == 0) {
|
||||
func = focusdir;
|
||||
(*arg).i = parse_direction(arg_value);
|
||||
} else if (strcmp(func_name, "groupjoin") == 0) {
|
||||
func = groupjoin;
|
||||
(*arg).i = parse_direction(arg_value);
|
||||
} else if (strcmp(func_name, "groupleave") == 0) {
|
||||
func = groupleave;
|
||||
} else if (strcmp(func_name, "focusid") == 0) {
|
||||
func = focusid;
|
||||
} else if (strcmp(func_name, "incnmaster") == 0) {
|
||||
|
|
@ -1277,6 +1297,15 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
|||
} else if (strcmp(func_name, "toggle_monitor") == 0) {
|
||||
func = toggle_monitor;
|
||||
(*arg).v = strdup(arg_value);
|
||||
} else if (strcmp(func_name, "sleep_monitor") == 0) {
|
||||
func = sleep_monitor;
|
||||
(*arg).v = strdup(arg_value);
|
||||
} else if (strcmp(func_name, "wakeup_monitor") == 0) {
|
||||
func = wakeup_monitor;
|
||||
(*arg).v = strdup(arg_value);
|
||||
} else if (strcmp(func_name, "sleep_toggle_monitor") == 0) {
|
||||
func = sleep_toggle_monitor;
|
||||
(*arg).v = strdup(arg_value);
|
||||
} else if (strcmp(func_name, "scroller_stack") == 0) {
|
||||
func = scroller_stack;
|
||||
(*arg).i = parse_direction(arg_value);
|
||||
|
|
@ -1510,6 +1539,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
config->drag_floating_refresh_interval = atof(value);
|
||||
} else if (strcmp(key, "allow_tearing") == 0) {
|
||||
config->allow_tearing = atoi(value);
|
||||
} else if (strcmp(key, "hdr_depth") == 0) {
|
||||
config->hdr_depth = atoi(value);
|
||||
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
|
||||
config->allow_shortcuts_inhibit = atoi(value);
|
||||
} else if (strcmp(key, "allow_lock_transparent") == 0) {
|
||||
|
|
@ -1765,76 +1796,76 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
config->cursor_size = atoi(value);
|
||||
} else if (strcmp(key, "cursor_theme") == 0) {
|
||||
config->cursor_theme = strdup(value);
|
||||
} else if (strcmp(key, "tab_bar_decorate_font_desc") == 0) {
|
||||
config->tabdata.font_desc = strdup(value);
|
||||
} else if (strcmp(key, "tab_bar_decorate_fg_color") == 0) {
|
||||
} else if (strcmp(key, "group_bar_decorate_font_desc") == 0) {
|
||||
config->groupbardata.font_desc = strdup(value);
|
||||
} else if (strcmp(key, "group_bar_decorate_fg_color") == 0) {
|
||||
int64_t color = parse_color(value);
|
||||
if (color == -1) {
|
||||
fprintf(stderr,
|
||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
||||
"tab_bar_decorate_fg_color "
|
||||
"group_bar_decorate_fg_color "
|
||||
"format: %s\n",
|
||||
value);
|
||||
return false;
|
||||
} else {
|
||||
convert_hex_to_rgba(config->tabdata.fg_color, color);
|
||||
convert_hex_to_rgba(config->groupbardata.fg_color, color);
|
||||
}
|
||||
} else if (strcmp(key, "tab_bar_decorate_bg_color") == 0) {
|
||||
} else if (strcmp(key, "group_bar_decorate_bg_color") == 0) {
|
||||
int64_t color = parse_color(value);
|
||||
if (color == -1) {
|
||||
fprintf(stderr,
|
||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
||||
"tab_bar_decorate_bg_color "
|
||||
"group_bar_decorate_bg_color "
|
||||
"format: %s\n",
|
||||
value);
|
||||
return false;
|
||||
} else {
|
||||
convert_hex_to_rgba(config->tabdata.bg_color, color);
|
||||
convert_hex_to_rgba(config->groupbardata.bg_color, color);
|
||||
}
|
||||
} else if (strcmp(key, "tab_bar_decorate_focus_fg_color") == 0) {
|
||||
} else if (strcmp(key, "group_bar_decorate_focus_fg_color") == 0) {
|
||||
int64_t color = parse_color(value);
|
||||
if (color == -1) {
|
||||
fprintf(stderr,
|
||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
||||
"tab_bar_decorate_focus_fg_color "
|
||||
"group_bar_decorate_focus_fg_color "
|
||||
"format: %s\n",
|
||||
value);
|
||||
return false;
|
||||
} else {
|
||||
convert_hex_to_rgba(config->tabdata.focus_fg_color, color);
|
||||
convert_hex_to_rgba(config->groupbardata.focus_fg_color, color);
|
||||
}
|
||||
} else if (strcmp(key, "tab_bar_decorate_focus_bg_color") == 0) {
|
||||
} else if (strcmp(key, "group_bar_decorate_focus_bg_color") == 0) {
|
||||
int64_t color = parse_color(value);
|
||||
if (color == -1) {
|
||||
fprintf(stderr,
|
||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
||||
"tab_bar_decorate_focus_bg_color "
|
||||
"group_bar_decorate_focus_bg_color "
|
||||
"format: %s\n",
|
||||
value);
|
||||
return false;
|
||||
} else {
|
||||
convert_hex_to_rgba(config->tabdata.focus_bg_color, color);
|
||||
convert_hex_to_rgba(config->groupbardata.focus_bg_color, color);
|
||||
}
|
||||
} else if (strcmp(key, "tab_bar_decorate_border_color") == 0) {
|
||||
} else if (strcmp(key, "group_bar_decorate_border_color") == 0) {
|
||||
int64_t color = parse_color(value);
|
||||
if (color == -1) {
|
||||
fprintf(stderr,
|
||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
||||
"tab_bar_decorate_border_color "
|
||||
"group_bar_decorate_border_color "
|
||||
"format: %s\n",
|
||||
value);
|
||||
return false;
|
||||
} else {
|
||||
convert_hex_to_rgba(config->tabdata.border_color, color);
|
||||
convert_hex_to_rgba(config->groupbardata.border_color, color);
|
||||
}
|
||||
} else if (strcmp(key, "tab_bar_decorate_border_width") == 0) {
|
||||
config->tabdata.border_width = CLAMP_INT(atoi(value), 0, 100);
|
||||
} else if (strcmp(key, "tab_bar_decorate_corner_radius") == 0) {
|
||||
config->tabdata.corner_radius = CLAMP_INT(atoi(value), 0, 100);
|
||||
} else if (strcmp(key, "tab_bar_decorate_padding_x") == 0) {
|
||||
config->tabdata.padding_x = CLAMP_INT(atoi(value), 0, 100);
|
||||
} else if (strcmp(key, "tab_bar_decorate_padding_y") == 0) {
|
||||
config->tabdata.padding_y = CLAMP_INT(atoi(value), 0, 100);
|
||||
} else if (strcmp(key, "group_bar_decorate_border_width") == 0) {
|
||||
config->groupbardata.border_width = CLAMP_INT(atoi(value), 0, 100);
|
||||
} else if (strcmp(key, "group_bar_decorate_corner_radius") == 0) {
|
||||
config->groupbardata.corner_radius = CLAMP_INT(atoi(value), 0, 100);
|
||||
} else if (strcmp(key, "group_bar_decorate_padding_x") == 0) {
|
||||
config->groupbardata.padding_x = CLAMP_INT(atoi(value), 0, 100);
|
||||
} else if (strcmp(key, "group_bar_decorate_padding_y") == 0) {
|
||||
config->groupbardata.padding_y = CLAMP_INT(atoi(value), 0, 100);
|
||||
} else if (strcmp(key, "jump_label_decorate_font_desc") == 0) {
|
||||
config->jumplabeldata.font_desc = strdup(value);
|
||||
} else if (strcmp(key, "jump_label_decorate_fg_color") == 0) {
|
||||
|
|
@ -1951,8 +1982,8 @@ 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, "tab_bar_height") == 0) {
|
||||
config->tab_bar_height = atoi(value);
|
||||
} else if (strcmp(key, "group_bar_height") == 0) {
|
||||
config->group_bar_height = atoi(value);
|
||||
} else if (strcmp(key, "rootcolor") == 0) {
|
||||
int64_t color = parse_color(value);
|
||||
if (color == -1) {
|
||||
|
|
@ -2106,7 +2137,9 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
rule->height = -1;
|
||||
rule->refresh = 0.0f;
|
||||
rule->vrr = 0;
|
||||
rule->hdr = 0;
|
||||
rule->custom = 0;
|
||||
rule->disable = 0;
|
||||
|
||||
bool parse_error = false;
|
||||
char *token = strtok(value, ",");
|
||||
|
|
@ -2144,6 +2177,10 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
rule->refresh = CLAMP_FLOAT(atof(val), 0.001f, 1000.0f);
|
||||
} else if (strcmp(key, "vrr") == 0) {
|
||||
rule->vrr = CLAMP_INT(atoi(val), 0, 1);
|
||||
} else if (strcmp(key, "hdr") == 0) {
|
||||
rule->hdr = CLAMP_INT(atoi(val), 0, 1);
|
||||
} else if (strcmp(key, "disable") == 0) {
|
||||
rule->disable = CLAMP_INT(atoi(val), 0, 1);
|
||||
} else if (strcmp(key, "custom") == 0) {
|
||||
rule->custom = CLAMP_INT(atoi(val), 0, 1);
|
||||
} else {
|
||||
|
|
@ -2274,6 +2311,7 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
rule->layer_name = NULL;
|
||||
rule->animation_type_open = NULL;
|
||||
rule->animation_type_close = NULL;
|
||||
rule->shield_when_capture = 0;
|
||||
rule->noblur = 0;
|
||||
rule->noanim = 0;
|
||||
rule->noshadow = 0;
|
||||
|
|
@ -2296,6 +2334,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
rule->animation_type_open = strdup(val);
|
||||
} else if (strcmp(key, "animation_type_close") == 0) {
|
||||
rule->animation_type_close = strdup(val);
|
||||
} else if (strcmp(key, "shield_when_capture") == 0) {
|
||||
rule->shield_when_capture = CLAMP_INT(atoi(val), 0, 1);
|
||||
} else if (strcmp(key, "noblur") == 0) {
|
||||
rule->noblur = CLAMP_INT(atoi(val), 0, 1);
|
||||
} else if (strcmp(key, "noanim") == 0) {
|
||||
|
|
@ -2349,11 +2389,13 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
rule->isunglobal = -1;
|
||||
rule->isglobal = -1;
|
||||
rule->isoverlay = -1;
|
||||
rule->shield_when_capture = -1;
|
||||
rule->allow_shortcuts_inhibit = -1;
|
||||
rule->ignore_maximize = -1;
|
||||
rule->ignore_minimize = -1;
|
||||
rule->isnosizehint = -1;
|
||||
rule->idleinhibit_when_focus = -1;
|
||||
rule->vrr_only_fullscreen = -1;
|
||||
rule->isterm = -1;
|
||||
rule->allow_csd = -1;
|
||||
rule->force_fakemaximize = -1;
|
||||
|
|
@ -2456,6 +2498,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
rule->focused_opacity = atof(val);
|
||||
} else if (strcmp(key, "isoverlay") == 0) {
|
||||
rule->isoverlay = atoi(val);
|
||||
} else if (strcmp(key, "shield_when_capture") == 0) {
|
||||
rule->shield_when_capture = atoi(val);
|
||||
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
|
||||
rule->allow_shortcuts_inhibit = atoi(val);
|
||||
} else if (strcmp(key, "ignore_maximize") == 0) {
|
||||
|
|
@ -2466,6 +2510,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
rule->isnosizehint = atoi(val);
|
||||
} else if (strcmp(key, "idleinhibit_when_focus") == 0) {
|
||||
rule->idleinhibit_when_focus = atoi(val);
|
||||
} else if (strcmp(key, "vrr_only_fullscreen") == 0) {
|
||||
rule->vrr_only_fullscreen = atoi(val);
|
||||
} else if (strcmp(key, "isterm") == 0) {
|
||||
rule->isterm = atoi(val);
|
||||
} else if (strcmp(key, "allow_csd") == 0) {
|
||||
|
|
@ -3401,9 +3447,9 @@ void free_config(void) {
|
|||
config.jumplabeldata.font_desc = NULL;
|
||||
}
|
||||
|
||||
if (config.tabdata.font_desc) {
|
||||
free((void *)config.tabdata.font_desc);
|
||||
config.tabdata.font_desc = NULL;
|
||||
if (config.groupbardata.font_desc) {
|
||||
free((void *)config.groupbardata.font_desc);
|
||||
config.groupbardata.font_desc = NULL;
|
||||
}
|
||||
|
||||
if (config.tablet_map_to_mon) {
|
||||
|
|
@ -3496,6 +3542,7 @@ void override_config(void) {
|
|||
config.drag_tile_to_tile = CLAMP_INT(config.drag_tile_to_tile, 0, 1);
|
||||
config.drag_tile_small = CLAMP_INT(config.drag_tile_small, 0, 1);
|
||||
config.allow_tearing = CLAMP_INT(config.allow_tearing, 0, 2);
|
||||
config.hdr_depth = CLAMP_INT(config.hdr_depth, 0, 2);
|
||||
config.allow_shortcuts_inhibit =
|
||||
CLAMP_INT(config.allow_shortcuts_inhibit, 0, 1);
|
||||
config.allow_lock_transparent =
|
||||
|
|
@ -3569,7 +3616,7 @@ void override_config(void) {
|
|||
config.scratchpad_height_ratio =
|
||||
CLAMP_FLOAT(config.scratchpad_height_ratio, 0.1f, 1.0f);
|
||||
config.borderpx = CLAMP_INT(config.borderpx, 0, 200);
|
||||
config.tab_bar_height = CLAMP_INT(config.tab_bar_height, 0, 500);
|
||||
config.group_bar_height = CLAMP_INT(config.group_bar_height, 0, 500);
|
||||
config.smartgaps = CLAMP_INT(config.smartgaps, 0, 1);
|
||||
config.blur = CLAMP_INT(config.blur, 0, 1);
|
||||
config.blur_layer = CLAMP_INT(config.blur_layer, 0, 1);
|
||||
|
|
@ -3598,12 +3645,14 @@ void override_config(void) {
|
|||
config.unfocused_opacity =
|
||||
CLAMP_FLOAT(config.unfocused_opacity, 0.0f, 1.0f);
|
||||
|
||||
config.tabdata.border_width =
|
||||
CLAMP_INT(config.tabdata.border_width, 0, 100);
|
||||
config.tabdata.corner_radius =
|
||||
CLAMP_INT(config.tabdata.corner_radius, 0, 100);
|
||||
config.tabdata.padding_x = CLAMP_INT(config.tabdata.padding_x, 0, 100);
|
||||
config.tabdata.padding_y = CLAMP_INT(config.tabdata.padding_y, 0, 100);
|
||||
config.groupbardata.border_width =
|
||||
CLAMP_INT(config.groupbardata.border_width, 0, 100);
|
||||
config.groupbardata.corner_radius =
|
||||
CLAMP_INT(config.groupbardata.corner_radius, 0, 100);
|
||||
config.groupbardata.padding_x =
|
||||
CLAMP_INT(config.groupbardata.padding_x, 0, 100);
|
||||
config.groupbardata.padding_y =
|
||||
CLAMP_INT(config.groupbardata.padding_y, 0, 100);
|
||||
|
||||
config.jumplabeldata.border_width =
|
||||
CLAMP_INT(config.jumplabeldata.border_width, 0, 100);
|
||||
|
|
@ -3683,11 +3732,12 @@ void set_value_default() {
|
|||
config.view_current_to_back = 0;
|
||||
config.single_scratchpad = 1;
|
||||
config.xwayland_persistence = 1;
|
||||
config.syncobj_enable = 0;
|
||||
config.syncobj_enable = 1;
|
||||
config.tag_carousel = 0;
|
||||
config.drag_tile_refresh_interval = 8.0f;
|
||||
config.drag_floating_refresh_interval = 8.0f;
|
||||
config.allow_tearing = TEARING_DISABLED;
|
||||
config.hdr_depth = MANGO_RENDER_BIT_DEPTH_10;
|
||||
config.allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
|
||||
config.allow_lock_transparent = 0;
|
||||
config.no_border_when_single = 0;
|
||||
|
|
@ -3701,7 +3751,7 @@ void set_value_default() {
|
|||
config.idleinhibit_ignore_visible = 0;
|
||||
|
||||
config.borderpx = 4;
|
||||
config.tab_bar_height = 50;
|
||||
config.group_bar_height = 50;
|
||||
config.overviewgappi = 5;
|
||||
config.overviewgappo = 30;
|
||||
config.cursor_hide_timeout = 0;
|
||||
|
|
@ -3738,7 +3788,6 @@ void set_value_default() {
|
|||
config.blur_layer = 0;
|
||||
config.blur_optimized = 1;
|
||||
config.border_radius = 0;
|
||||
config.border_radius_location_default = CORNER_LOCATION_ALL;
|
||||
config.blur_params.num_passes = 1;
|
||||
config.blur_params.radius = 5;
|
||||
config.blur_params.noise = 0.02f;
|
||||
|
|
@ -3789,30 +3838,30 @@ void set_value_default() {
|
|||
config.animation_curve_opafadeout[2] = 0.5;
|
||||
config.animation_curve_opafadeout[3] = 0.5;
|
||||
|
||||
config.tabdata.fg_color[0] = 0xc4 / 255.0f;
|
||||
config.tabdata.fg_color[1] = 0x93 / 255.0f;
|
||||
config.tabdata.fg_color[2] = 0x9d / 255.0f;
|
||||
config.tabdata.fg_color[3] = 1.0f;
|
||||
config.tabdata.bg_color[0] = 0x32 / 255.0f;
|
||||
config.tabdata.bg_color[1] = 0x32 / 255.0f;
|
||||
config.tabdata.bg_color[2] = 0x32 / 255.0f;
|
||||
config.tabdata.bg_color[3] = 1.0f;
|
||||
config.tabdata.focus_fg_color[0] = 0xed / 255.0f;
|
||||
config.tabdata.focus_fg_color[1] = 0xa6 / 255.0f;
|
||||
config.tabdata.focus_fg_color[2] = 0xb4 / 255.0f;
|
||||
config.tabdata.focus_fg_color[3] = 1.0f;
|
||||
config.tabdata.focus_bg_color[0] = 0x4e / 255.0f;
|
||||
config.tabdata.focus_bg_color[1] = 0x45 / 255.0f;
|
||||
config.tabdata.focus_bg_color[2] = 0x3c / 255.0f;
|
||||
config.tabdata.focus_bg_color[3] = 1.0f;
|
||||
config.tabdata.border_color[0] = 0x8b / 255.0f;
|
||||
config.tabdata.border_color[1] = 0xaa / 255.0f;
|
||||
config.tabdata.border_color[2] = 0x9b / 255.0f;
|
||||
config.tabdata.border_color[3] = 1.0f;
|
||||
config.tabdata.border_width = 4;
|
||||
config.tabdata.corner_radius = 5;
|
||||
config.tabdata.padding_x = 0;
|
||||
config.tabdata.padding_y = 0;
|
||||
config.groupbardata.fg_color[0] = 0xc4 / 255.0f;
|
||||
config.groupbardata.fg_color[1] = 0x93 / 255.0f;
|
||||
config.groupbardata.fg_color[2] = 0x9d / 255.0f;
|
||||
config.groupbardata.fg_color[3] = 1.0f;
|
||||
config.groupbardata.bg_color[0] = 0x32 / 255.0f;
|
||||
config.groupbardata.bg_color[1] = 0x32 / 255.0f;
|
||||
config.groupbardata.bg_color[2] = 0x32 / 255.0f;
|
||||
config.groupbardata.bg_color[3] = 1.0f;
|
||||
config.groupbardata.focus_fg_color[0] = 0xed / 255.0f;
|
||||
config.groupbardata.focus_fg_color[1] = 0xa6 / 255.0f;
|
||||
config.groupbardata.focus_fg_color[2] = 0xb4 / 255.0f;
|
||||
config.groupbardata.focus_fg_color[3] = 1.0f;
|
||||
config.groupbardata.focus_bg_color[0] = 0x4e / 255.0f;
|
||||
config.groupbardata.focus_bg_color[1] = 0x45 / 255.0f;
|
||||
config.groupbardata.focus_bg_color[2] = 0x3c / 255.0f;
|
||||
config.groupbardata.focus_bg_color[3] = 1.0f;
|
||||
config.groupbardata.border_color[0] = 0x8b / 255.0f;
|
||||
config.groupbardata.border_color[1] = 0xaa / 255.0f;
|
||||
config.groupbardata.border_color[2] = 0x9b / 255.0f;
|
||||
config.groupbardata.border_color[3] = 1.0f;
|
||||
config.groupbardata.border_width = 4;
|
||||
config.groupbardata.corner_radius = 5;
|
||||
config.groupbardata.padding_x = 0;
|
||||
config.groupbardata.padding_y = 0;
|
||||
|
||||
config.jumplabeldata.fg_color[0] = 0xc4 / 255.0f;
|
||||
config.jumplabeldata.fg_color[1] = 0x93 / 255.0f;
|
||||
|
|
@ -3952,7 +4001,7 @@ bool parse_config(void) {
|
|||
config.tag_rules_count = 0;
|
||||
config.cursor_theme = NULL;
|
||||
config.jumplabeldata.font_desc = NULL;
|
||||
config.tabdata.font_desc = NULL;
|
||||
config.groupbardata.font_desc = NULL;
|
||||
config.tablet_map_to_mon = NULL;
|
||||
strcpy(config.keymode, "default");
|
||||
|
||||
|
|
@ -4017,16 +4066,13 @@ void reset_blur_params(void) {
|
|||
void reapply_monitor_rules(void) {
|
||||
ConfigMonitorRule *mr;
|
||||
Monitor *m = NULL;
|
||||
int32_t ji, vrr, custom;
|
||||
int32_t ji;
|
||||
int32_t mx, my;
|
||||
struct wlr_output_state state;
|
||||
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (!m->wlr_output->enabled)
|
||||
continue;
|
||||
|
||||
wlr_output_state_init(&state);
|
||||
|
||||
for (ji = 0; ji < config.monitor_rules_count; ji++) {
|
||||
if (config.monitor_rules_count < 1)
|
||||
break;
|
||||
|
|
@ -4036,18 +4082,33 @@ void reapply_monitor_rules(void) {
|
|||
if (monitor_matches_rule(m, mr)) {
|
||||
mx = mr->x == INT32_MAX ? m->m.x : mr->x;
|
||||
my = mr->y == INT32_MAX ? m->m.y : mr->y;
|
||||
vrr = mr->vrr >= 0 ? mr->vrr : 0;
|
||||
custom = mr->custom >= 0 ? mr->custom : 0;
|
||||
|
||||
(void)apply_rule_to_state(m, mr, &state, vrr, custom);
|
||||
apply_rule_to_state(m, mr, &m->pending);
|
||||
|
||||
wlr_output_layout_add(output_layout, m->wlr_output, mx, my);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wlr_output_state_finish(&state);
|
||||
if (m->prefer_disable) {
|
||||
wlr_output_state_set_enabled(&m->pending, false);
|
||||
} else {
|
||||
wlr_output_state_set_enabled(&m->pending, true);
|
||||
}
|
||||
|
||||
if (m->hdr_enable) {
|
||||
output_state_setup_hdr(m, false, &m->pending);
|
||||
}
|
||||
|
||||
if (!(mango_scene_output_commit(m->scene_output, &m->pending))) {
|
||||
if (m->hdr_enable) {
|
||||
output_state_setup_hdr(m, true, &m->pending);
|
||||
}
|
||||
}
|
||||
wlr_output_effective_resolution(m->wlr_output, &m->m.width,
|
||||
&m->m.height);
|
||||
}
|
||||
|
||||
updatemons(NULL, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -4116,14 +4177,7 @@ void reapply_property(void) {
|
|||
if (!c->isnoborder && !c->isfullscreen) {
|
||||
c->bw = config.borderpx;
|
||||
}
|
||||
|
||||
mango_jump_label_node_apply_config(c->jump_label_node,
|
||||
&config.jumplabeldata);
|
||||
mango_tab_bar_node_apply_config(c->tab_bar_node, &config.tabdata);
|
||||
|
||||
wlr_scene_rect_set_color(c->droparea, config.dropcolor);
|
||||
wlr_scene_rect_set_color(c->splitindicator[0], config.splitcolor);
|
||||
wlr_scene_rect_set_color(c->splitindicator[1], config.splitcolor);
|
||||
client_set_group_config(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ int32_t minimized(const Arg *arg);
|
|||
int32_t restore_minimized(const Arg *arg);
|
||||
int32_t toggle_scratchpad(const Arg *arg);
|
||||
int32_t focusdir(const Arg *arg);
|
||||
int32_t groupjoin(const Arg *arg);
|
||||
int32_t groupleave(const Arg *arg);
|
||||
int32_t toggleoverview(const Arg *arg);
|
||||
int32_t togglejump(const Arg *arg);
|
||||
int32_t set_proportion(const Arg *arg);
|
||||
|
|
@ -38,6 +40,7 @@ int32_t toggleglobal(const Arg *arg);
|
|||
int32_t incnmaster(const Arg *arg);
|
||||
int32_t focusmon(const Arg *arg);
|
||||
int32_t focusstack(const Arg *arg);
|
||||
int32_t groupfocus(const Arg *arg);
|
||||
int32_t chvt(const Arg *arg);
|
||||
int32_t reload_config(const Arg *arg);
|
||||
int32_t smartmovewin(const Arg *arg);
|
||||
|
|
@ -70,6 +73,9 @@ int32_t setoption(const Arg *arg);
|
|||
int32_t disable_monitor(const Arg *arg);
|
||||
int32_t enable_monitor(const Arg *arg);
|
||||
int32_t toggle_monitor(const Arg *arg);
|
||||
int32_t sleep_monitor(const Arg *arg);
|
||||
int32_t wakeup_monitor(const Arg *arg);
|
||||
int32_t sleep_toggle_monitor(const Arg *arg);
|
||||
int32_t scroller_stack(const Arg *arg);
|
||||
int32_t toggle_all_floating(const Arg *arg);
|
||||
int32_t dwindle_toggle_split_direction(const Arg *arg);
|
||||
|
|
|
|||
|
|
@ -156,6 +156,94 @@ int32_t focusdir(const Arg *arg) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t groupjoin(const Arg *arg) {
|
||||
|
||||
if (!selmon)
|
||||
return 0;
|
||||
|
||||
Monitor *oldmon = NULL;
|
||||
|
||||
Client *need_join_client = arg->tc ? arg->tc : selmon->sel;
|
||||
if (!need_join_client || !need_join_client->mon)
|
||||
return 0;
|
||||
|
||||
if (need_join_client->mon->isoverview)
|
||||
return 0;
|
||||
|
||||
Client *need_replace_client = NULL;
|
||||
need_replace_client = direction_select(arg);
|
||||
|
||||
if (!need_replace_client || !need_replace_client->mon)
|
||||
return 0;
|
||||
|
||||
if (need_join_client == need_replace_client)
|
||||
return 0;
|
||||
|
||||
if (need_join_client->group_next || need_join_client->group_prev) {
|
||||
groupleave(&(Arg){.tc = need_join_client});
|
||||
}
|
||||
|
||||
if (need_join_client->mon != need_replace_client->mon) {
|
||||
oldmon = need_join_client->mon;
|
||||
need_join_client->mon = need_replace_client->mon;
|
||||
}
|
||||
|
||||
if (!need_replace_client->group_prev && !need_replace_client->group_next) {
|
||||
need_replace_client->isgroupfocusing = true;
|
||||
}
|
||||
|
||||
need_join_client->group_next = need_replace_client;
|
||||
|
||||
if (need_replace_client->group_prev) {
|
||||
need_replace_client->group_prev->group_next = need_join_client;
|
||||
}
|
||||
|
||||
need_join_client->group_prev = need_replace_client->group_prev;
|
||||
|
||||
need_replace_client->group_prev = need_join_client;
|
||||
|
||||
client_focus_group_member(need_join_client);
|
||||
arrange(need_join_client->mon, false, false);
|
||||
|
||||
// oldmon可能已经死掉了
|
||||
if (oldmon) {
|
||||
arrange(oldmon, false, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t groupleave(const Arg *arg) {
|
||||
|
||||
if (!selmon)
|
||||
return 0;
|
||||
Client *tc = arg->tc ? arg->tc : selmon->sel;
|
||||
if (!tc || !tc->mon || !tc->isgroupfocusing)
|
||||
return 0;
|
||||
if (!tc->group_next && !tc->group_prev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tc->mon->isoverview)
|
||||
return 0;
|
||||
|
||||
Client *rc = tc->group_next ? tc->group_next : tc->group_prev;
|
||||
|
||||
client_focus_group_member(rc);
|
||||
client_group_detach(tc);
|
||||
|
||||
tc->isgroupfocusing = false;
|
||||
tc->is_logic_hide = false;
|
||||
|
||||
if (!rc->group_prev && !rc->group_next) {
|
||||
rc->isgroupfocusing = false;
|
||||
}
|
||||
|
||||
arrange(tc->mon, false, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t focuslast(const Arg *arg) {
|
||||
Client *c = NULL;
|
||||
Client *tc = NULL;
|
||||
|
|
@ -261,6 +349,34 @@ int32_t focusstack(const Arg *arg) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t groupfocus(const Arg *arg) {
|
||||
Client *c = arg->tc ? arg->tc : selmon->sel;
|
||||
if (!c || !c->mon)
|
||||
return 0;
|
||||
|
||||
if (!c->group_prev && !c->group_next) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (c->mon->isoverview)
|
||||
return 0;
|
||||
|
||||
Client *tc = NULL;
|
||||
|
||||
if (arg->i == NEXT) {
|
||||
tc = c->group_next;
|
||||
} else {
|
||||
tc = c->group_prev;
|
||||
}
|
||||
|
||||
if (!tc)
|
||||
return 0;
|
||||
|
||||
client_focus_group_member(tc);
|
||||
arrange(tc->mon, false, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t incnmaster(const Arg *arg) {
|
||||
if (!arg || !selmon)
|
||||
return 0;
|
||||
|
|
@ -366,7 +482,7 @@ int32_t moveresize(const Arg *arg) {
|
|||
|
||||
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
||||
return 0;
|
||||
xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
|
||||
xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL, NULL);
|
||||
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen ||
|
||||
grabc->ismaximizescreen) {
|
||||
grabc = NULL;
|
||||
|
|
@ -1427,15 +1543,7 @@ int32_t toggleoverlay(const Arg *arg) {
|
|||
|
||||
c->isoverlay ^= 1;
|
||||
|
||||
if (c->isoverlay) {
|
||||
wlr_scene_node_reparent(&c->scene->node, layers[LyrOverlay]);
|
||||
wlr_scene_node_raise_to_top(&c->scene->node);
|
||||
} else if (client_should_overtop(c) && c->isfloating) {
|
||||
wlr_scene_node_reparent(&c->scene->node, layers[LyrTop]);
|
||||
} else {
|
||||
wlr_scene_node_reparent(&c->scene->node,
|
||||
layers[c->isfloating ? LyrTop : LyrTile]);
|
||||
}
|
||||
client_reparent_group(c);
|
||||
setborder_color(c);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1825,12 +1933,12 @@ int32_t togglejump(const Arg *arg) {
|
|||
|
||||
int32_t disable_monitor(const Arg *arg) {
|
||||
Monitor *m = NULL;
|
||||
struct wlr_output_state state = {0};
|
||||
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (match_monitor_spec(arg->v, m)) {
|
||||
wlr_output_state_set_enabled(&state, false);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
m->asleep = 1;
|
||||
wlr_output_state_set_enabled(&m->pending, false);
|
||||
mango_output_commit(m);
|
||||
m->only_sleep = 0;
|
||||
updatemons(NULL, NULL);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1840,12 +1948,11 @@ int32_t disable_monitor(const Arg *arg) {
|
|||
|
||||
int32_t enable_monitor(const Arg *arg) {
|
||||
Monitor *m = NULL;
|
||||
struct wlr_output_state state = {0};
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (match_monitor_spec(arg->v, m)) {
|
||||
wlr_output_state_set_enabled(&state, true);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
m->asleep = 0;
|
||||
wlr_output_state_set_enabled(&m->pending, true);
|
||||
mango_output_commit(m);
|
||||
m->only_sleep = 0;
|
||||
updatemons(NULL, NULL);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1855,12 +1962,54 @@ int32_t enable_monitor(const Arg *arg) {
|
|||
|
||||
int32_t toggle_monitor(const Arg *arg) {
|
||||
Monitor *m = NULL;
|
||||
struct wlr_output_state state = {0};
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (match_monitor_spec(arg->v, m)) {
|
||||
wlr_output_state_set_enabled(&state, !m->wlr_output->enabled);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
m->asleep = !m->wlr_output->enabled;
|
||||
wlr_output_state_set_enabled(&m->pending, !m->wlr_output->enabled);
|
||||
mango_output_commit(m);
|
||||
m->only_sleep = 0;
|
||||
updatemons(NULL, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sleep_monitor(const Arg *arg) {
|
||||
Monitor *m = NULL;
|
||||
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (match_monitor_spec(arg->v, m)) {
|
||||
wlr_output_state_set_enabled(&m->pending, false);
|
||||
mango_output_commit(m);
|
||||
m->only_sleep = 1;
|
||||
updatemons(NULL, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t wakeup_monitor(const Arg *arg) {
|
||||
Monitor *m = NULL;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (match_monitor_spec(arg->v, m)) {
|
||||
wlr_output_state_set_enabled(&m->pending, true);
|
||||
mango_output_commit(m);
|
||||
m->only_sleep = 0;
|
||||
updatemons(NULL, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sleep_toggle_monitor(const Arg *arg) {
|
||||
Monitor *m = NULL;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (match_monitor_spec(arg->v, m)) {
|
||||
wlr_output_state_set_enabled(&m->pending, !m->wlr_output->enabled);
|
||||
mango_output_commit(m);
|
||||
m->only_sleep = !m->wlr_output->enabled;
|
||||
updatemons(NULL, NULL);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1912,13 +2061,11 @@ int32_t scroller_apply_stack(Client *c, Client *target_client,
|
|||
|
||||
if (direction == LEFT || direction == UP) {
|
||||
if (c != stack_head) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(stack_head->link.prev, &c->link);
|
||||
wl_list_safe_reinsert_prev(&stack_head->link, &c->link);
|
||||
}
|
||||
} else if (direction == RIGHT || direction == DOWN) {
|
||||
if (c != stack_tail) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(&stack_tail->link, &c->link);
|
||||
wl_list_safe_reinsert_next(&stack_head->link, &c->link);
|
||||
}
|
||||
}
|
||||
sync_scroller_state_to_clients(m, tag);
|
||||
|
|
@ -2001,7 +2148,8 @@ int32_t dwindle_set_split_direction(Client *c, bool istoggle, bool horizontal) {
|
|||
leaf->custom_leaf_split_h = false;
|
||||
}
|
||||
bool hit_no_border = check_hit_no_border(c);
|
||||
apply_split_border(c, hit_no_border);
|
||||
struct ivec2 offsets = compute_edge_offsets(c);
|
||||
client_draw_split_border(c, hit_no_border, offsets);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2040,6 +2188,13 @@ int32_t focusid(const Arg *arg) {
|
|||
return 0;
|
||||
|
||||
Client *c = arg->tc;
|
||||
|
||||
if (c->swallowdby)
|
||||
return 0;
|
||||
|
||||
if (c->group_next || c->group_prev)
|
||||
client_focus_group_member(c);
|
||||
|
||||
client_active(c);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -59,10 +59,9 @@ static const struct wlr_buffer_impl text_buffer_impl = {
|
|||
.end_data_ptr_access = text_buffer_end_data_ptr_access,
|
||||
};
|
||||
|
||||
struct mango_jump_label_node *
|
||||
mango_jump_label_node_create(struct wlr_scene_tree *parent,
|
||||
DecorateDrawData data) {
|
||||
struct mango_jump_label_node *node = calloc(1, sizeof(*node));
|
||||
MangoJumpLabel *mango_jump_label_node_create(struct wlr_scene_tree *parent,
|
||||
DecorateDrawData data) {
|
||||
MangoJumpLabel *node = calloc(1, sizeof(*node));
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -104,7 +103,7 @@ mango_jump_label_node_create(struct wlr_scene_tree *parent,
|
|||
return node;
|
||||
}
|
||||
|
||||
void mango_jump_label_node_destroy(struct mango_jump_label_node *node) {
|
||||
void mango_jump_label_node_destroy(MangoJumpLabel *node) {
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
|
|
@ -136,8 +135,8 @@ void mango_jump_label_node_destroy(struct mango_jump_label_node *node) {
|
|||
free(node);
|
||||
}
|
||||
|
||||
void mango_jump_label_node_set_background(struct mango_jump_label_node *node,
|
||||
float r, float g, float b, float a) {
|
||||
void mango_jump_label_node_set_background(MangoJumpLabel *node, float r,
|
||||
float g, float b, float a) {
|
||||
if (!node)
|
||||
return;
|
||||
node->bg_color[0] = r;
|
||||
|
|
@ -146,9 +145,9 @@ void mango_jump_label_node_set_background(struct mango_jump_label_node *node,
|
|||
node->bg_color[3] = a;
|
||||
}
|
||||
|
||||
void mango_jump_label_node_set_border(struct mango_jump_label_node *node,
|
||||
float r, float g, float b, float a,
|
||||
int32_t width, int32_t radius) {
|
||||
void mango_jump_label_node_set_border(MangoJumpLabel *node, float r, float g,
|
||||
float b, float a, int32_t width,
|
||||
int32_t radius) {
|
||||
if (!node)
|
||||
return;
|
||||
node->border_color[0] = r;
|
||||
|
|
@ -159,17 +158,16 @@ void mango_jump_label_node_set_border(struct mango_jump_label_node *node,
|
|||
node->corner_radius = radius;
|
||||
}
|
||||
|
||||
void mango_jump_label_node_set_padding(struct mango_jump_label_node *node,
|
||||
int32_t pad_x, int32_t pad_y) {
|
||||
void mango_jump_label_node_set_padding(MangoJumpLabel *node, int32_t pad_x,
|
||||
int32_t pad_y) {
|
||||
if (!node)
|
||||
return;
|
||||
node->padding_x = pad_x >= 0 ? pad_x : 0;
|
||||
node->padding_y = pad_y >= 0 ? pad_y : 0;
|
||||
}
|
||||
|
||||
static void get_text_pixel_size(struct mango_jump_label_node *node,
|
||||
const char *text, float scale, int32_t *out_w,
|
||||
int32_t *out_h) {
|
||||
static void get_text_pixel_size(MangoJumpLabel *node, const char *text,
|
||||
float scale, int32_t *out_w, int32_t *out_h) {
|
||||
if (node->measure_scale != scale) {
|
||||
pango_cairo_context_set_resolution(node->measure_context, 96.0 * scale);
|
||||
node->measure_scale = scale;
|
||||
|
|
@ -184,6 +182,10 @@ static void get_text_pixel_size(struct mango_jump_label_node *node,
|
|||
|
||||
static void draw_rounded_rect(cairo_t *cr, double x, double y, double w,
|
||||
double h, double r) {
|
||||
// 宽高非正时不绘制任何东西
|
||||
if (w <= 0.0 || h <= 0.0)
|
||||
return;
|
||||
|
||||
double degrees = G_PI / 180.0;
|
||||
cairo_new_sub_path(cr);
|
||||
cairo_arc(cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees);
|
||||
|
|
@ -193,14 +195,14 @@ static void draw_rounded_rect(cairo_t *cr, double x, double y, double w,
|
|||
cairo_close_path(cr);
|
||||
}
|
||||
|
||||
void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
||||
const char *text, float scale) {
|
||||
void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
|
||||
float scale) {
|
||||
if (!node || !text)
|
||||
return;
|
||||
if (scale <= 0.0f)
|
||||
scale = 1.0f;
|
||||
|
||||
/* 脏检查,加入 focused 状态 */
|
||||
// 脏检查
|
||||
if (node->cached_scale == scale && node->cached_font_desc &&
|
||||
strcmp(node->cached_font_desc, node->font_desc) == 0 &&
|
||||
node->cached_text && strcmp(node->cached_text, text) == 0 &&
|
||||
|
|
@ -222,7 +224,7 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
|||
return;
|
||||
}
|
||||
|
||||
/* 更新缓存 */
|
||||
// 更新缓存
|
||||
g_free(node->cached_text);
|
||||
node->cached_text = g_strdup(text);
|
||||
g_free(node->cached_font_desc);
|
||||
|
|
@ -266,6 +268,7 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
|||
int32_t box_logical_w = logical_text_w + 2 * node->padding_x;
|
||||
int32_t box_logical_h = logical_text_h + 2 * node->padding_y;
|
||||
|
||||
// 物理像素尺寸包含边框,避免边框越界
|
||||
int32_t required_pixel_w =
|
||||
(int32_t)((box_logical_w + 2 * node->border_width) * scale + 0.5f);
|
||||
int32_t required_pixel_h =
|
||||
|
|
@ -318,13 +321,15 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
|||
radius = bg_w / 2.0;
|
||||
if (radius > bg_h / 2.0)
|
||||
radius = bg_h / 2.0;
|
||||
if (radius < 0.0)
|
||||
radius = 0.0;
|
||||
|
||||
const float *active_bg =
|
||||
node->focused ? node->focus_bg_color : node->bg_color;
|
||||
const float *active_fg =
|
||||
node->focused ? node->focus_fg_color : node->fg_color;
|
||||
|
||||
bool draw_bg = (active_bg[3] > 0.0f); // 使用 active_bg
|
||||
bool draw_bg = (active_bg[3] > 0.0f) && (bg_w > 0.0 && bg_h > 0.0);
|
||||
bool draw_border =
|
||||
(node->border_width > 0) && (node->border_color[3] > 0.0f);
|
||||
|
||||
|
|
@ -340,25 +345,28 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
|||
}
|
||||
}
|
||||
|
||||
cairo_save(cr);
|
||||
double text_x = (node->border_width + node->padding_x) * scale;
|
||||
double text_y = (node->border_width + node->padding_y) * scale;
|
||||
cairo_translate(cr, text_x, text_y);
|
||||
// 文本绘制仅在背景区域有有效空间时进行
|
||||
if (bg_w > 0.0 && bg_h > 0.0) {
|
||||
cairo_save(cr);
|
||||
double text_x = (node->border_width + node->padding_x) * scale;
|
||||
double text_y = (node->border_width + node->padding_y) * scale;
|
||||
cairo_translate(cr, text_x, text_y);
|
||||
|
||||
PangoContext *ctx = pango_cairo_create_context(cr);
|
||||
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
||||
PangoLayout *layout = pango_layout_new(ctx);
|
||||
PangoFontDescription *desc = get_cached_font_desc(node->font_desc);
|
||||
pango_layout_set_font_description(layout, desc);
|
||||
pango_layout_set_text(layout, text, -1);
|
||||
PangoContext *ctx = pango_cairo_create_context(cr);
|
||||
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
||||
PangoLayout *layout = pango_layout_new(ctx);
|
||||
PangoFontDescription *desc = get_cached_font_desc(node->font_desc);
|
||||
pango_layout_set_font_description(layout, desc);
|
||||
pango_layout_set_text(layout, text, -1);
|
||||
|
||||
cairo_set_source_rgba(cr, active_fg[0], active_fg[1], active_fg[2],
|
||||
active_fg[3]);
|
||||
pango_cairo_show_layout(cr, layout);
|
||||
cairo_set_source_rgba(cr, active_fg[0], active_fg[1], active_fg[2],
|
||||
active_fg[3]);
|
||||
pango_cairo_show_layout(cr, layout);
|
||||
|
||||
g_object_unref(layout);
|
||||
g_object_unref(ctx);
|
||||
cairo_restore(cr);
|
||||
g_object_unref(layout);
|
||||
g_object_unref(ctx);
|
||||
cairo_restore(cr);
|
||||
}
|
||||
|
||||
if (draw_border) {
|
||||
cairo_set_source_rgba(cr, node->border_color[0], node->border_color[1],
|
||||
|
|
@ -371,15 +379,35 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
|||
double bw = bg_w + border;
|
||||
double bh = bg_h + border;
|
||||
|
||||
if (radius > 0.0) {
|
||||
double outer_radius = radius + half_lw;
|
||||
if (outer_radius < 0.0)
|
||||
outer_radius = 0.0;
|
||||
draw_rounded_rect(cr, bx, by, bw, bh, outer_radius);
|
||||
} else {
|
||||
cairo_rectangle(cr, bx, by, bw, bh);
|
||||
// 确保边框矩形不越界且宽高为正
|
||||
if (bx < 0.0) {
|
||||
bw += bx; // bx 为负,bw 缩小
|
||||
bx = 0.0;
|
||||
}
|
||||
if (by < 0.0) {
|
||||
bh += by;
|
||||
by = 0.0;
|
||||
}
|
||||
if (bx + bw > (double)node->surface_pixel_w)
|
||||
bw = (double)node->surface_pixel_w - bx;
|
||||
if (by + bh > (double)node->surface_pixel_h)
|
||||
bh = (double)node->surface_pixel_h - by;
|
||||
if (bw < 0.0)
|
||||
bw = 0.0;
|
||||
if (bh < 0.0)
|
||||
bh = 0.0;
|
||||
|
||||
if (bw > 0.0 && bh > 0.0) {
|
||||
if (radius > 0.0) {
|
||||
double outer_radius = radius + half_lw;
|
||||
if (outer_radius < 0.0)
|
||||
outer_radius = 0.0;
|
||||
draw_rounded_rect(cr, bx, by, bw, bh, outer_radius);
|
||||
} else {
|
||||
cairo_rectangle(cr, bx, by, bw, bh);
|
||||
}
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
|
||||
cairo_surface_flush(node->surface);
|
||||
|
|
@ -407,67 +435,71 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
|||
node->logical_height);
|
||||
}
|
||||
|
||||
void mango_jump_label_node_set_focus(struct mango_jump_label_node *node,
|
||||
bool focused) {
|
||||
void mango_jump_label_node_set_focus(MangoJumpLabel *node, bool focused) {
|
||||
if (!node || node->focused == focused)
|
||||
return;
|
||||
node->focused = focused;
|
||||
// 使用缓存的文本和缩放触发重绘(如果无文本则不重绘)
|
||||
if (node->cached_text && node->cached_scale > 0.0f) {
|
||||
mango_jump_label_node_update(node, node->cached_text,
|
||||
node->cached_scale);
|
||||
}
|
||||
}
|
||||
|
||||
struct mango_tab_bar_node *
|
||||
mango_tab_bar_node_create(void *mango_node_data, struct wlr_scene_tree *parent,
|
||||
DecorateDrawData data, int32_t width,
|
||||
int32_t height) {
|
||||
struct mango_tab_bar_node *node = calloc(1, sizeof(*node));
|
||||
if (!node)
|
||||
MangoGroupBar *mango_group_bar_create(void *cdata, uint32_t type,
|
||||
struct wlr_scene_tree *parent,
|
||||
DecorateDrawData data, int32_t width,
|
||||
int32_t height) {
|
||||
MangoGroupBar *mangobar = calloc(1, sizeof(*mangobar));
|
||||
if (!mangobar)
|
||||
return NULL;
|
||||
|
||||
node->scene_buffer = wlr_scene_buffer_create(parent, NULL);
|
||||
if (!node->scene_buffer) {
|
||||
free(node);
|
||||
mangobar->scene_buffer = wlr_scene_buffer_create(parent, NULL);
|
||||
if (!mangobar->scene_buffer) {
|
||||
free(mangobar);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(node->fg_color, data.fg_color, sizeof(node->fg_color));
|
||||
memcpy(node->bg_color, data.bg_color, sizeof(node->bg_color));
|
||||
memcpy(node->focus_fg_color, data.focus_fg_color,
|
||||
sizeof(node->focus_fg_color));
|
||||
memcpy(node->focus_bg_color, data.focus_bg_color,
|
||||
sizeof(node->focus_bg_color));
|
||||
memcpy(node->border_color, data.border_color, sizeof(node->border_color));
|
||||
node->border_width = data.border_width;
|
||||
node->corner_radius = data.corner_radius;
|
||||
node->padding_x = data.padding_x;
|
||||
node->padding_y = data.padding_y;
|
||||
node->font_desc =
|
||||
memcpy(mangobar->fg_color, data.fg_color, sizeof(mangobar->fg_color));
|
||||
memcpy(mangobar->bg_color, data.bg_color, sizeof(mangobar->bg_color));
|
||||
memcpy(mangobar->focus_fg_color, data.focus_fg_color,
|
||||
sizeof(mangobar->focus_fg_color));
|
||||
memcpy(mangobar->focus_bg_color, data.focus_bg_color,
|
||||
sizeof(mangobar->focus_bg_color));
|
||||
memcpy(mangobar->border_color, data.border_color,
|
||||
sizeof(mangobar->border_color));
|
||||
mangobar->border_width = data.border_width;
|
||||
mangobar->corner_radius = data.corner_radius;
|
||||
mangobar->padding_x = data.padding_x;
|
||||
mangobar->padding_y = data.padding_y;
|
||||
mangobar->font_desc =
|
||||
g_strdup(data.font_desc ? data.font_desc : "monospace Bold 16");
|
||||
|
||||
node->target_width = width;
|
||||
node->target_height = height;
|
||||
node->focused = false;
|
||||
node->cached_focused = false;
|
||||
mangobar->target_width = width;
|
||||
mangobar->target_height = height;
|
||||
mangobar->focused = false;
|
||||
mangobar->cached_focused = false;
|
||||
|
||||
node->measure_surface =
|
||||
mangobar->measure_surface =
|
||||
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
|
||||
node->measure_cr = cairo_create(node->measure_surface);
|
||||
node->measure_context = pango_cairo_create_context(node->measure_cr);
|
||||
node->measure_layout = pango_layout_new(node->measure_context);
|
||||
node->measure_scale = 1.0f;
|
||||
mangobar->measure_cr = cairo_create(mangobar->measure_surface);
|
||||
mangobar->measure_context =
|
||||
pango_cairo_create_context(mangobar->measure_cr);
|
||||
mangobar->measure_layout = pango_layout_new(mangobar->measure_context);
|
||||
mangobar->measure_scale = 1.0f;
|
||||
|
||||
node->cached_scale = -1.0f;
|
||||
node->last_text = NULL;
|
||||
node->last_scale = 0.0f;
|
||||
node->scene_buffer->node.data = mango_node_data;
|
||||
mangobar->cached_scale = -1.0f;
|
||||
mangobar->last_text = NULL;
|
||||
mangobar->last_scale = 0.0f;
|
||||
|
||||
return node;
|
||||
mangobar->type = type;
|
||||
mangobar->node_data = cdata;
|
||||
|
||||
mangobar->scene_buffer->node.data = mangobar;
|
||||
|
||||
return mangobar;
|
||||
}
|
||||
|
||||
void mango_tab_bar_node_destroy(struct mango_tab_bar_node *node) {
|
||||
void mango_group_bar_destroy(MangoGroupBar *node) {
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
|
|
@ -492,19 +524,17 @@ void mango_tab_bar_node_destroy(struct mango_tab_bar_node *node) {
|
|||
if (node->measure_cr)
|
||||
cairo_destroy(node->measure_cr);
|
||||
|
||||
void *data = node->scene_buffer->node.data;
|
||||
wlr_scene_node_destroy(&node->scene_buffer->node);
|
||||
|
||||
g_free(node->font_desc);
|
||||
g_free(node->cached_text);
|
||||
g_free(node->cached_font_desc);
|
||||
g_free(node->last_text);
|
||||
free(data);
|
||||
free(node);
|
||||
}
|
||||
|
||||
void mango_tab_bar_node_set_size(struct mango_tab_bar_node *node, int32_t width,
|
||||
int32_t height) {
|
||||
void mango_group_bar_set_size(MangoGroupBar *node, int32_t width,
|
||||
int32_t height) {
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
|
|
@ -522,11 +552,11 @@ void mango_tab_bar_node_set_size(struct mango_tab_bar_node *node, int32_t width,
|
|||
const char *redraw_text = node->last_text ? node->last_text : "";
|
||||
float redraw_scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
||||
|
||||
mango_tab_bar_node_update(node, redraw_text, redraw_scale);
|
||||
mango_group_bar_update(node, redraw_text, redraw_scale);
|
||||
}
|
||||
|
||||
void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
||||
const char *text, float scale) {
|
||||
void mango_group_bar_update(MangoGroupBar *node, const char *text,
|
||||
float scale) {
|
||||
if (!node || !text)
|
||||
return;
|
||||
if (scale <= 0.0f)
|
||||
|
|
@ -538,7 +568,7 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
|||
node->last_text = safe_text; // 所有权转移
|
||||
node->last_scale = scale;
|
||||
|
||||
// 脏检查加入 focused
|
||||
// 脏检查
|
||||
if (node->cached_scale == scale && node->cached_font_desc &&
|
||||
strcmp(node->cached_font_desc, node->font_desc) == 0 &&
|
||||
node->cached_text && strcmp(node->cached_text, safe_text) == 0 &&
|
||||
|
|
@ -608,8 +638,18 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
|||
if (box_logical_h < 0)
|
||||
box_logical_h = 0;
|
||||
|
||||
// surface 物理尺寸包含边框,避免边框绘制越界
|
||||
int32_t required_pixel_w = (int32_t)(node->target_width * scale + 0.5f);
|
||||
int32_t required_pixel_h = (int32_t)(node->target_height * scale + 0.5f);
|
||||
// 如果边框会伸出 target 区域,则扩展 surface 尺寸以完全容纳
|
||||
double border_phys = node->border_width * scale;
|
||||
if (border_phys > 0.0) {
|
||||
// 边框描边会向外延伸 half line width,所以需要额外空间
|
||||
int extra_w = (int32_t)ceil(border_phys * 0.5);
|
||||
int extra_h = (int32_t)ceil(border_phys * 0.5);
|
||||
required_pixel_w += extra_w;
|
||||
required_pixel_h += extra_h;
|
||||
}
|
||||
if (required_pixel_w < 1)
|
||||
required_pixel_w = 1;
|
||||
if (required_pixel_h < 1)
|
||||
|
|
@ -641,7 +681,6 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
|||
cairo_paint(cr);
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
||||
|
||||
double border_phys = node->border_width * scale;
|
||||
double bg_x = border_phys;
|
||||
double bg_y = border_phys;
|
||||
double bg_w = box_logical_w * scale;
|
||||
|
|
@ -657,13 +696,15 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
|||
radius = bg_w / 2.0;
|
||||
if (radius > bg_h / 2.0)
|
||||
radius = bg_h / 2.0;
|
||||
if (radius < 0.0)
|
||||
radius = 0.0;
|
||||
|
||||
const float *active_bg =
|
||||
node->focused ? node->focus_bg_color : node->bg_color;
|
||||
const float *active_fg =
|
||||
node->focused ? node->focus_fg_color : node->fg_color;
|
||||
|
||||
bool draw_bg = (active_bg[3] > 0.0f);
|
||||
bool draw_bg = (active_bg[3] > 0.0f) && (bg_w > 0.0 && bg_h > 0.0);
|
||||
bool draw_border =
|
||||
(node->border_width > 0) && (node->border_color[3] > 0.0f);
|
||||
|
||||
|
|
@ -679,43 +720,46 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
|||
}
|
||||
}
|
||||
|
||||
int32_t text_area_logical_w = box_logical_w - 2 * node->padding_x;
|
||||
int32_t text_area_logical_h = box_logical_h - 2 * node->padding_y;
|
||||
if (text_area_logical_w > 0 && text_area_logical_h > 0) {
|
||||
cairo_save(cr);
|
||||
// 仅在背景区域有空间时进行
|
||||
if (bg_w > 0.0 && bg_h > 0.0) {
|
||||
int32_t text_area_logical_w = box_logical_w - 2 * node->padding_x;
|
||||
int32_t text_area_logical_h = box_logical_h - 2 * node->padding_y;
|
||||
if (text_area_logical_w > 0 && text_area_logical_h > 0) {
|
||||
cairo_save(cr);
|
||||
|
||||
double text_x = (node->border_width + node->padding_x) * scale;
|
||||
double text_y = (node->border_width + node->padding_y) * scale;
|
||||
double text_area_w = text_area_logical_w * scale;
|
||||
double text_area_h = text_area_logical_h * scale;
|
||||
double text_x = (node->border_width + node->padding_x) * scale;
|
||||
double text_y = (node->border_width + node->padding_y) * scale;
|
||||
double text_area_w = text_area_logical_w * scale;
|
||||
double text_area_h = text_area_logical_h * scale;
|
||||
|
||||
PangoContext *ctx = pango_cairo_create_context(cr);
|
||||
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
||||
PangoLayout *layout = pango_layout_new(ctx);
|
||||
PangoFontDescription *desc = get_cached_font_desc(node->font_desc);
|
||||
pango_layout_set_font_description(layout, desc);
|
||||
pango_layout_set_text(layout, safe_text, -1);
|
||||
PangoContext *ctx = pango_cairo_create_context(cr);
|
||||
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
||||
PangoLayout *layout = pango_layout_new(ctx);
|
||||
PangoFontDescription *desc = get_cached_font_desc(node->font_desc);
|
||||
pango_layout_set_font_description(layout, desc);
|
||||
pango_layout_set_text(layout, safe_text, -1);
|
||||
|
||||
pango_layout_set_wrap(layout, PANGO_WRAP_NONE);
|
||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||
pango_layout_set_width(layout, (int)(text_area_w * PANGO_SCALE));
|
||||
pango_layout_set_wrap(layout, PANGO_WRAP_NONE);
|
||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||
pango_layout_set_width(layout, (int)(text_area_w * PANGO_SCALE));
|
||||
|
||||
int text_pixel_w, text_pixel_h;
|
||||
pango_layout_get_pixel_size(layout, &text_pixel_w, &text_pixel_h);
|
||||
double y_offset = (text_area_h - text_pixel_h) / 2.0;
|
||||
if (y_offset < 0)
|
||||
y_offset = 0;
|
||||
int text_pixel_w, text_pixel_h;
|
||||
pango_layout_get_pixel_size(layout, &text_pixel_w, &text_pixel_h);
|
||||
double y_offset = (text_area_h - text_pixel_h) / 2.0;
|
||||
if (y_offset < 0)
|
||||
y_offset = 0;
|
||||
|
||||
cairo_translate(cr, text_x, text_y + y_offset);
|
||||
cairo_translate(cr, text_x, text_y + y_offset);
|
||||
|
||||
cairo_set_source_rgba(cr, active_fg[0], active_fg[1], active_fg[2],
|
||||
active_fg[3]);
|
||||
pango_cairo_show_layout(cr, layout);
|
||||
cairo_set_source_rgba(cr, active_fg[0], active_fg[1], active_fg[2],
|
||||
active_fg[3]);
|
||||
pango_cairo_show_layout(cr, layout);
|
||||
|
||||
g_object_unref(layout);
|
||||
g_object_unref(ctx);
|
||||
cairo_restore(cr);
|
||||
g_object_unref(layout);
|
||||
g_object_unref(ctx);
|
||||
cairo_restore(cr);
|
||||
}
|
||||
}
|
||||
|
||||
if (draw_border) {
|
||||
|
|
@ -729,15 +773,35 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
|||
double bw = bg_w + border_phys;
|
||||
double bh = bg_h + border_phys;
|
||||
|
||||
if (radius > 0.0) {
|
||||
double outer_radius = radius + half_lw;
|
||||
if (outer_radius < 0.0)
|
||||
outer_radius = 0.0;
|
||||
draw_rounded_rect(cr, bx, by, bw, bh, outer_radius);
|
||||
} else {
|
||||
cairo_rectangle(cr, bx, by, bw, bh);
|
||||
// 确保边框矩形不越界且宽高为正
|
||||
if (bx < 0.0) {
|
||||
bw += bx;
|
||||
bx = 0.0;
|
||||
}
|
||||
if (by < 0.0) {
|
||||
bh += by;
|
||||
by = 0.0;
|
||||
}
|
||||
if (bx + bw > (double)node->surface_pixel_w)
|
||||
bw = (double)node->surface_pixel_w - bx;
|
||||
if (by + bh > (double)node->surface_pixel_h)
|
||||
bh = (double)node->surface_pixel_h - by;
|
||||
if (bw < 0.0)
|
||||
bw = 0.0;
|
||||
if (bh < 0.0)
|
||||
bh = 0.0;
|
||||
|
||||
if (bw > 0.0 && bh > 0.0) {
|
||||
if (radius > 0.0) {
|
||||
double outer_radius = radius + half_lw;
|
||||
if (outer_radius < 0.0)
|
||||
outer_radius = 0.0;
|
||||
draw_rounded_rect(cr, bx, by, bw, bh, outer_radius);
|
||||
} else {
|
||||
cairo_rectangle(cr, bx, by, bw, bh);
|
||||
}
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
|
||||
cairo_surface_flush(node->surface);
|
||||
|
|
@ -765,19 +829,18 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
|||
node->logical_height);
|
||||
}
|
||||
|
||||
void mango_tab_bar_node_set_focus(struct mango_tab_bar_node *node,
|
||||
bool focused) {
|
||||
void mango_group_bar_set_focus(MangoGroupBar *node, bool focused) {
|
||||
if (!node || node->focused == focused)
|
||||
return;
|
||||
node->focused = focused;
|
||||
if (node->last_text) {
|
||||
float scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
||||
mango_tab_bar_node_update(node, node->last_text, scale);
|
||||
mango_group_bar_update(node, node->last_text, scale);
|
||||
}
|
||||
}
|
||||
|
||||
void mango_tab_bar_node_set_colors(struct mango_tab_bar_node *node,
|
||||
const float fg[4], const float bg[4]) {
|
||||
void mango_group_bar_set_colors(MangoGroupBar *node, const float fg[4],
|
||||
const float bg[4]) {
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
|
|
@ -786,11 +849,11 @@ void mango_tab_bar_node_set_colors(struct mango_tab_bar_node *node,
|
|||
|
||||
if (!node->focused && node->last_text) {
|
||||
float scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
||||
mango_tab_bar_node_update(node, node->last_text, scale);
|
||||
mango_group_bar_update(node, node->last_text, scale);
|
||||
}
|
||||
}
|
||||
|
||||
void mango_jump_label_node_apply_config(struct mango_jump_label_node *node,
|
||||
void mango_jump_label_node_apply_config(MangoJumpLabel *node,
|
||||
const DecorateDrawData *data) {
|
||||
if (!node || !data)
|
||||
return;
|
||||
|
|
@ -817,8 +880,8 @@ void mango_jump_label_node_apply_config(struct mango_jump_label_node *node,
|
|||
}
|
||||
}
|
||||
|
||||
void mango_tab_bar_node_apply_config(struct mango_tab_bar_node *node,
|
||||
const DecorateDrawData *data) {
|
||||
void mango_group_bar_apply_config(MangoGroupBar *node,
|
||||
const DecorateDrawData *data) {
|
||||
if (!node || !data)
|
||||
return;
|
||||
|
||||
|
|
@ -840,6 +903,6 @@ void mango_tab_bar_node_apply_config(struct mango_tab_bar_node *node,
|
|||
|
||||
if (node->last_text) {
|
||||
float scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
||||
mango_tab_bar_node_update(node, node->last_text, scale);
|
||||
mango_group_bar_update(node, node->last_text, scale);
|
||||
}
|
||||
}
|
||||
|
|
@ -26,8 +26,7 @@ struct mango_text_buffer {
|
|||
struct wlr_buffer base;
|
||||
cairo_surface_t *surface;
|
||||
};
|
||||
|
||||
struct mango_jump_label_node {
|
||||
typedef struct {
|
||||
struct wlr_scene_buffer *scene_buffer;
|
||||
struct mango_text_buffer *buffer;
|
||||
cairo_surface_t *surface;
|
||||
|
|
@ -70,13 +69,15 @@ struct mango_jump_label_node {
|
|||
|
||||
int32_t logical_width;
|
||||
int32_t logical_height;
|
||||
};
|
||||
} MangoJumpLabel;
|
||||
|
||||
struct mango_tab_bar_node {
|
||||
typedef struct {
|
||||
uint32_t type; // must at first in struct
|
||||
struct wlr_scene_buffer *scene_buffer;
|
||||
struct mango_text_buffer *buffer;
|
||||
cairo_surface_t *surface;
|
||||
int surface_pixel_w, surface_pixel_h;
|
||||
void *node_data; // 存储窗口指针
|
||||
|
||||
// 初始配置
|
||||
float fg_color[4];
|
||||
|
|
@ -126,41 +127,38 @@ struct mango_tab_bar_node {
|
|||
|
||||
int32_t logical_width;
|
||||
int32_t logical_height;
|
||||
};
|
||||
} MangoGroupBar;
|
||||
|
||||
void mango_text_global_finish(void);
|
||||
struct mango_jump_label_node *
|
||||
mango_jump_label_node_create(struct wlr_scene_tree *parent,
|
||||
DecorateDrawData data);
|
||||
void mango_jump_label_node_destroy(struct mango_jump_label_node *node);
|
||||
void mango_jump_label_node_set_background(struct mango_jump_label_node *node,
|
||||
float r, float g, float b, float a);
|
||||
void mango_jump_label_node_set_border(struct mango_jump_label_node *node,
|
||||
float r, float g, float b, float a,
|
||||
int32_t width, int32_t radius);
|
||||
void mango_jump_label_node_set_padding(struct mango_jump_label_node *node,
|
||||
int32_t pad_x, int32_t pad_y);
|
||||
void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
||||
const char *text, float scale);
|
||||
MangoJumpLabel *mango_jump_label_node_create(struct wlr_scene_tree *parent,
|
||||
DecorateDrawData data);
|
||||
void mango_jump_label_node_destroy(MangoJumpLabel *node);
|
||||
void mango_jump_label_node_set_background(MangoJumpLabel *node, float r,
|
||||
float g, float b, float a);
|
||||
void mango_jump_label_node_set_border(MangoJumpLabel *node, float r, float g,
|
||||
float b, float a, int32_t width,
|
||||
int32_t radius);
|
||||
void mango_jump_label_node_set_padding(MangoJumpLabel *node, int32_t pad_x,
|
||||
int32_t pad_y);
|
||||
void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
|
||||
float scale);
|
||||
|
||||
struct mango_tab_bar_node *
|
||||
mango_tab_bar_node_create(void *mango_node_data, struct wlr_scene_tree *parent,
|
||||
DecorateDrawData data, int32_t width, int32_t height);
|
||||
void mango_tab_bar_node_destroy(struct mango_tab_bar_node *node);
|
||||
void mango_tab_bar_node_set_size(struct mango_tab_bar_node *node, int32_t width,
|
||||
int32_t height);
|
||||
void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
||||
const char *text, float scale);
|
||||
MangoGroupBar *mango_group_bar_create(void *cdata, uint32_t type,
|
||||
struct wlr_scene_tree *parent,
|
||||
DecorateDrawData data, int32_t width,
|
||||
int32_t height);
|
||||
void mango_group_bar_destroy(MangoGroupBar *node);
|
||||
void mango_group_bar_set_size(MangoGroupBar *node, int32_t width,
|
||||
int32_t height);
|
||||
void mango_group_bar_update(MangoGroupBar *node, const char *text, float scale);
|
||||
|
||||
void mango_jump_label_node_set_focus(struct mango_jump_label_node *node,
|
||||
bool focused);
|
||||
void mango_tab_bar_node_set_focus(struct mango_tab_bar_node *node,
|
||||
bool focused);
|
||||
void mango_jump_label_node_set_focus(MangoJumpLabel *node, bool focused);
|
||||
void mango_group_bar_set_focus(MangoGroupBar *node, bool focused);
|
||||
|
||||
void mango_tab_bar_node_set_colors(struct mango_tab_bar_node *node,
|
||||
const float fg[4], const float bg[4]);
|
||||
void mango_jump_label_node_apply_config(struct mango_jump_label_node *node,
|
||||
void mango_group_bar_set_colors(MangoGroupBar *node, const float fg[4],
|
||||
const float bg[4]);
|
||||
void mango_jump_label_node_apply_config(MangoJumpLabel *node,
|
||||
const DecorateDrawData *data);
|
||||
void mango_tab_bar_node_apply_config(struct mango_tab_bar_node *node,
|
||||
const DecorateDrawData *data);
|
||||
void mango_group_bar_apply_config(MangoGroupBar *node,
|
||||
const DecorateDrawData *data);
|
||||
#endif // jump_label_node_H
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "dwl-ipc.h"
|
||||
#include "ext-workspace.h"
|
||||
#include "foreign-toplevel.h"
|
||||
#include "hdr.h"
|
||||
#include "tablet.h"
|
||||
#include "tearing.h"
|
||||
#include "text-input.h"
|
||||
|
|
|
|||
|
|
@ -1,309 +0,0 @@
|
|||
#include "dwl-ipc-unstable-v2-protocol.h"
|
||||
|
||||
static void dwl_ipc_manager_bind(struct wl_client *client, void *data,
|
||||
uint32_t version, uint32_t id);
|
||||
static void dwl_ipc_manager_destroy(struct wl_resource *resource);
|
||||
static void dwl_ipc_manager_get_output(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t id, struct wl_resource *output);
|
||||
static void dwl_ipc_manager_release(struct wl_client *client,
|
||||
struct wl_resource *resource);
|
||||
static void dwl_ipc_output_destroy(struct wl_resource *resource);
|
||||
static void dwl_ipc_output_printstatus(Monitor *monitor);
|
||||
static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output);
|
||||
static void dwl_ipc_output_set_client_tags(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t and_tags,
|
||||
uint32_t xor_tags);
|
||||
static void dwl_ipc_output_set_layout(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t index);
|
||||
static void dwl_ipc_output_set_tags(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t tagmask, uint32_t toggle_tagset);
|
||||
static void dwl_ipc_output_quit(struct wl_client *client,
|
||||
struct wl_resource *resource);
|
||||
static void dwl_ipc_output_dispatch(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *dispatch, const char *arg1,
|
||||
const char *arg2, const char *arg3,
|
||||
const char *arg4, const char *arg5);
|
||||
static void dwl_ipc_output_release(struct wl_client *client,
|
||||
struct wl_resource *resource);
|
||||
|
||||
/* global event handlers */
|
||||
static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {
|
||||
.release = dwl_ipc_manager_release,
|
||||
.get_output = dwl_ipc_manager_get_output};
|
||||
static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {
|
||||
.release = dwl_ipc_output_release,
|
||||
.set_tags = dwl_ipc_output_set_tags,
|
||||
.quit = dwl_ipc_output_quit,
|
||||
.dispatch = dwl_ipc_output_dispatch,
|
||||
.set_layout = dwl_ipc_output_set_layout,
|
||||
.set_client_tags = dwl_ipc_output_set_client_tags};
|
||||
|
||||
void dwl_ipc_manager_bind(struct wl_client *client, void *data,
|
||||
uint32_t version, uint32_t id) {
|
||||
struct wl_resource *manager_resource =
|
||||
wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id);
|
||||
if (!manager_resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
wl_resource_set_implementation(manager_resource,
|
||||
&dwl_manager_implementation, NULL,
|
||||
dwl_ipc_manager_destroy);
|
||||
|
||||
zdwl_ipc_manager_v2_send_tags(manager_resource, LENGTH(tags));
|
||||
|
||||
for (uint32_t i = 0; i < LENGTH(layouts); i++)
|
||||
zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol);
|
||||
}
|
||||
|
||||
void dwl_ipc_manager_destroy(struct wl_resource *resource) {
|
||||
/* No state to destroy */
|
||||
}
|
||||
|
||||
void dwl_ipc_manager_get_output(struct wl_client *client,
|
||||
struct wl_resource *resource, uint32_t id,
|
||||
struct wl_resource *output) {
|
||||
DwlIpcOutput *ipc_output;
|
||||
struct wlr_output *op = wlr_output_from_resource(output);
|
||||
if (!op)
|
||||
return;
|
||||
Monitor *monitor = op->data;
|
||||
struct wl_resource *output_resource =
|
||||
wl_resource_create(client, &zdwl_ipc_output_v2_interface,
|
||||
wl_resource_get_version(resource), id);
|
||||
if (!output_resource)
|
||||
return;
|
||||
|
||||
ipc_output = ecalloc(1, sizeof(*ipc_output));
|
||||
ipc_output->resource = output_resource;
|
||||
ipc_output->mon = monitor;
|
||||
wl_resource_set_implementation(output_resource, &dwl_output_implementation,
|
||||
ipc_output, dwl_ipc_output_destroy);
|
||||
wl_list_insert(&monitor->dwl_ipc_outputs, &ipc_output->link);
|
||||
dwl_ipc_output_printstatus_to(ipc_output);
|
||||
}
|
||||
|
||||
void dwl_ipc_manager_release(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static void dwl_ipc_output_destroy(struct wl_resource *resource) {
|
||||
DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource);
|
||||
wl_list_remove(&ipc_output->link);
|
||||
free(ipc_output);
|
||||
}
|
||||
|
||||
// 修改IPC输出函数,接受掩码参数
|
||||
void dwl_ipc_output_printstatus(Monitor *monitor) {
|
||||
DwlIpcOutput *ipc_output;
|
||||
wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link)
|
||||
dwl_ipc_output_printstatus_to(ipc_output);
|
||||
}
|
||||
|
||||
// 修改主IPC输出函数,根据掩码发送相应事件
|
||||
void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) {
|
||||
Monitor *monitor = ipc_output->mon;
|
||||
Client *c = NULL, *focused = NULL;
|
||||
struct wlr_keyboard *keyboard;
|
||||
xkb_layout_index_t current;
|
||||
int32_t tagmask, state, numclients, focused_client, tag;
|
||||
const char *title, *appid, *symbol;
|
||||
char kb_layout[32];
|
||||
focused = focustop(monitor);
|
||||
zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon);
|
||||
|
||||
for (tag = 0; tag < LENGTH(tags); tag++) {
|
||||
numclients = state = focused_client = 0;
|
||||
tagmask = 1 << tag;
|
||||
if ((tagmask & monitor->tagset[monitor->seltags]) != 0)
|
||||
state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != monitor)
|
||||
continue;
|
||||
if (!(c->tags & tagmask))
|
||||
continue;
|
||||
if (c == focused)
|
||||
focused_client = 1;
|
||||
if (c->isurgent)
|
||||
state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT;
|
||||
numclients++;
|
||||
}
|
||||
zdwl_ipc_output_v2_send_tag(ipc_output->resource, tag, state,
|
||||
numclients, focused_client);
|
||||
}
|
||||
|
||||
title = focused ? client_get_title(focused) : "";
|
||||
appid = focused ? client_get_appid(focused) : "";
|
||||
|
||||
if (monitor->isoverview) {
|
||||
symbol = overviewlayout.symbol;
|
||||
} else {
|
||||
symbol = monitor->pertag->ltidxs[monitor->pertag->curtag]->symbol;
|
||||
}
|
||||
|
||||
keyboard = &kb_group->wlr_group->keyboard;
|
||||
current = xkb_state_serialize_layout(keyboard->xkb_state,
|
||||
XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
get_layout_abbr(kb_layout,
|
||||
xkb_keymap_layout_get_name(keyboard->keymap, current));
|
||||
|
||||
zdwl_ipc_output_v2_send_layout(
|
||||
ipc_output->resource,
|
||||
monitor->pertag->ltidxs[monitor->pertag->curtag] - layouts);
|
||||
zdwl_ipc_output_v2_send_title(ipc_output->resource, title ? title : broken);
|
||||
zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid ? appid : broken);
|
||||
zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, symbol);
|
||||
if (wl_resource_get_version(ipc_output->resource) >=
|
||||
ZDWL_IPC_OUTPUT_V2_FULLSCREEN_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_fullscreen(ipc_output->resource,
|
||||
focused ? focused->isfullscreen : 0);
|
||||
}
|
||||
if (wl_resource_get_version(ipc_output->resource) >=
|
||||
ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_floating(ipc_output->resource,
|
||||
focused ? focused->isfloating : 0);
|
||||
}
|
||||
if (wl_resource_get_version(ipc_output->resource) >=
|
||||
ZDWL_IPC_OUTPUT_V2_X_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_x(ipc_output->resource,
|
||||
focused ? focused->geom.x : 0);
|
||||
}
|
||||
if (wl_resource_get_version(ipc_output->resource) >=
|
||||
ZDWL_IPC_OUTPUT_V2_Y_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_y(ipc_output->resource,
|
||||
focused ? focused->geom.y : 0);
|
||||
}
|
||||
if (wl_resource_get_version(ipc_output->resource) >=
|
||||
ZDWL_IPC_OUTPUT_V2_WIDTH_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_width(ipc_output->resource,
|
||||
focused ? focused->geom.width : 0);
|
||||
}
|
||||
if (wl_resource_get_version(ipc_output->resource) >=
|
||||
ZDWL_IPC_OUTPUT_V2_HEIGHT_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_height(ipc_output->resource,
|
||||
focused ? focused->geom.height : 0);
|
||||
}
|
||||
if (wl_resource_get_version(ipc_output->resource) >=
|
||||
ZDWL_IPC_OUTPUT_V2_LAST_LAYER_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_last_layer(ipc_output->resource,
|
||||
monitor->last_open_surface);
|
||||
}
|
||||
|
||||
if (wl_resource_get_version(ipc_output->resource) >=
|
||||
ZDWL_IPC_OUTPUT_V2_KB_LAYOUT_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_kb_layout(ipc_output->resource, kb_layout);
|
||||
}
|
||||
|
||||
if (wl_resource_get_version(ipc_output->resource) >=
|
||||
ZDWL_IPC_OUTPUT_V2_KEYMODE_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_keymode(ipc_output->resource, keymode.mode);
|
||||
}
|
||||
|
||||
if (wl_resource_get_version(ipc_output->resource) >=
|
||||
ZDWL_IPC_OUTPUT_V2_SCALEFACTOR_SINCE_VERSION) {
|
||||
zdwl_ipc_output_v2_send_scalefactor(ipc_output->resource,
|
||||
monitor->wlr_output->scale * 100);
|
||||
}
|
||||
|
||||
zdwl_ipc_output_v2_send_frame(ipc_output->resource);
|
||||
}
|
||||
|
||||
void dwl_ipc_output_set_client_tags(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t and_tags, uint32_t xor_tags) {
|
||||
DwlIpcOutput *ipc_output;
|
||||
Monitor *monitor = NULL;
|
||||
Client *selected_client = NULL;
|
||||
uint32_t newtags = 0;
|
||||
|
||||
ipc_output = wl_resource_get_user_data(resource);
|
||||
if (!ipc_output)
|
||||
return;
|
||||
|
||||
monitor = ipc_output->mon;
|
||||
selected_client = focustop(monitor);
|
||||
if (!selected_client)
|
||||
return;
|
||||
|
||||
newtags = (selected_client->tags & and_tags) ^ xor_tags;
|
||||
if (!newtags)
|
||||
return;
|
||||
|
||||
selected_client->tags = newtags;
|
||||
if (selmon == monitor)
|
||||
focusclient(focustop(monitor), 1);
|
||||
arrange(selmon, false, false);
|
||||
printstatus(IPC_WATCH_ARRANGGE);
|
||||
}
|
||||
|
||||
void dwl_ipc_output_set_layout(struct wl_client *client,
|
||||
struct wl_resource *resource, uint32_t index) {
|
||||
DwlIpcOutput *ipc_output;
|
||||
Monitor *monitor = NULL;
|
||||
|
||||
ipc_output = wl_resource_get_user_data(resource);
|
||||
if (!ipc_output)
|
||||
return;
|
||||
|
||||
monitor = ipc_output->mon;
|
||||
if (index >= LENGTH(layouts))
|
||||
index = 0;
|
||||
|
||||
monitor->pertag->ltidxs[monitor->pertag->curtag] = &layouts[index];
|
||||
clear_fullscreen_and_maximized_state(monitor);
|
||||
arrange(monitor, false, false);
|
||||
printstatus(IPC_WATCH_ARRANGGE);
|
||||
}
|
||||
|
||||
void dwl_ipc_output_set_tags(struct wl_client *client,
|
||||
struct wl_resource *resource, uint32_t tagmask,
|
||||
uint32_t toggle_tagset) {
|
||||
DwlIpcOutput *ipc_output;
|
||||
Monitor *monitor = NULL;
|
||||
uint32_t newtags = tagmask & TAGMASK;
|
||||
|
||||
ipc_output = wl_resource_get_user_data(resource);
|
||||
if (!ipc_output)
|
||||
return;
|
||||
monitor = ipc_output->mon;
|
||||
|
||||
view_in_mon(&(Arg){.ui = newtags}, true, monitor, true);
|
||||
}
|
||||
|
||||
void dwl_ipc_output_quit(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
quit(&(Arg){0});
|
||||
}
|
||||
|
||||
void dwl_ipc_output_dispatch(struct wl_client *client,
|
||||
struct wl_resource *resource, const char *dispatch,
|
||||
const char *arg1, const char *arg2,
|
||||
const char *arg3, const char *arg4,
|
||||
const char *arg5) {
|
||||
|
||||
int32_t (*func)(const Arg *);
|
||||
Arg arg;
|
||||
func = parse_func_name((char *)dispatch, &arg, (char *)arg1, (char *)arg2,
|
||||
(char *)arg3, (char *)arg4, (char *)arg5);
|
||||
if (func) {
|
||||
func(&arg);
|
||||
}
|
||||
|
||||
if (arg.v)
|
||||
free(arg.v);
|
||||
if (arg.v2)
|
||||
free(arg.v2);
|
||||
if (arg.v3)
|
||||
free(arg.v3);
|
||||
}
|
||||
|
||||
void dwl_ipc_output_release(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "wlr_ext_workspace_v1.h"
|
||||
#include <wlr/types/wlr_ext_workspace_v1.h>
|
||||
|
||||
#define EXT_WORKSPACE_ENABLE_CAPS \
|
||||
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \
|
||||
|
|
@ -148,7 +148,7 @@ static void add_workspace_by_tag(int32_t tag, Monitor *m) {
|
|||
wlr_ext_workspace_handle_v1_set_name(workspace->ext_workspace, name);
|
||||
}
|
||||
|
||||
void dwl_ext_workspace_printstatus(Monitor *m) {
|
||||
void mango_ext_workspace_printstatus(Monitor *m) {
|
||||
struct workspace *w;
|
||||
uint32_t tag_status = 0;
|
||||
|
||||
|
|
@ -199,7 +199,7 @@ void refresh_monitors_workspaces_status(Monitor *m) {
|
|||
}
|
||||
}
|
||||
|
||||
dwl_ext_workspace_printstatus(m);
|
||||
mango_ext_workspace_printstatus(m);
|
||||
}
|
||||
|
||||
void workspaces_init() {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ void handle_foreign_maximize_request(struct wl_listener *listener, void *data) {
|
|||
Client *c = wl_container_of(listener, c, foreign_maximize_request);
|
||||
struct wlr_foreign_toplevel_handle_v1_maximized_event *event = data;
|
||||
|
||||
if (c->swallowing || !c->mon)
|
||||
if (c->swallowdby || !c->mon)
|
||||
return;
|
||||
|
||||
if (c->ismaximizescreen && !event->maximized) {
|
||||
|
|
@ -30,7 +30,7 @@ void handle_foreign_minimize_request(struct wl_listener *listener, void *data) {
|
|||
Client *c = wl_container_of(listener, c, foreign_minimize_request);
|
||||
struct wlr_foreign_toplevel_handle_v1_minimized_event *event = data;
|
||||
|
||||
if (c->swallowing || !c->mon)
|
||||
if (c->swallowdby || !c->mon)
|
||||
return;
|
||||
|
||||
if (!c->isminimized && event->minimized) {
|
||||
|
|
@ -55,7 +55,7 @@ void handle_foreign_fullscreen_request(struct wl_listener *listener,
|
|||
Client *c = wl_container_of(listener, c, foreign_fullscreen_request);
|
||||
struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data;
|
||||
|
||||
if (c->swallowing || !c->mon)
|
||||
if (c->swallowdby || !c->mon)
|
||||
return;
|
||||
|
||||
if (c->isfullscreen && !event->fullscreen) {
|
||||
|
|
|
|||
131
src/ext-protocol/hdr.h
Normal file
131
src/ext-protocol/hdr.h
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#include <drm_fourcc.h>
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
static uint32_t output_formats_8bit[] = {
|
||||
DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888, DRM_FORMAT_RGBX8888,
|
||||
DRM_FORMAT_BGRX8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
|
||||
DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_RGB888,
|
||||
DRM_FORMAT_BGR888,
|
||||
};
|
||||
|
||||
static uint32_t output_formats_10bit[] = {
|
||||
DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_RGBX1010102,
|
||||
DRM_FORMAT_BGRX1010102, DRM_FORMAT_ARGB2101010, DRM_FORMAT_ABGR2101010,
|
||||
DRM_FORMAT_RGBA1010102, DRM_FORMAT_BGRA1010102,
|
||||
};
|
||||
|
||||
static bool output_set_render_format(Monitor *m, uint32_t candidates[],
|
||||
size_t count,
|
||||
struct wlr_output_state *state) {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
wlr_output_state_set_render_format(state, candidates[i]);
|
||||
if (wlr_output_test_state(m->wlr_output, state))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool output_format_in_candidates(uint32_t format, uint32_t candidates[],
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; i++)
|
||||
if (candidates[i] == format)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum render_bit_depth bit_depth_from_format(uint32_t render_format) {
|
||||
if (output_format_in_candidates(render_format, output_formats_10bit,
|
||||
ARRAY_SIZE(output_formats_10bit)))
|
||||
return MANGO_RENDER_BIT_DEPTH_10;
|
||||
if (output_format_in_candidates(render_format, output_formats_8bit,
|
||||
ARRAY_SIZE(output_formats_8bit)))
|
||||
return MANGO_RENDER_BIT_DEPTH_8;
|
||||
return MANGO_RENDER_BIT_DEPTH_DEFAULT;
|
||||
}
|
||||
|
||||
static bool output_supports_hdr(const struct wlr_output *output,
|
||||
const char **reason) {
|
||||
const char *r = NULL;
|
||||
if (!(output->supported_primaries & WLR_COLOR_NAMED_PRIMARIES_BT2020))
|
||||
r = "BT2020 primaries not supported";
|
||||
else if (!(output->supported_transfer_functions &
|
||||
WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ))
|
||||
r = "PQ transfer function not supported";
|
||||
else if (!drw->features.output_color_transform)
|
||||
r = "renderer doesn't support output color transforms";
|
||||
if (reason)
|
||||
*reason = r;
|
||||
return !r;
|
||||
}
|
||||
|
||||
void output_enable_hdr(Monitor *m, struct wlr_output_state *os, bool enabled,
|
||||
bool silent) {
|
||||
if (enabled && !output_supports_hdr(m->wlr_output, NULL))
|
||||
enabled = false;
|
||||
|
||||
if (!enabled) {
|
||||
if (m->wlr_output->supported_primaries ||
|
||||
m->wlr_output->supported_transfer_functions) {
|
||||
if (!silent)
|
||||
wlr_log(WLR_DEBUG, "Disabling HDR on output %s",
|
||||
m->wlr_output->name);
|
||||
wlr_output_state_set_image_description(os, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!silent)
|
||||
wlr_log(WLR_DEBUG, "Enabling HDR on output %s", m->wlr_output->name);
|
||||
struct wlr_output_image_description desc = {
|
||||
.primaries = WLR_COLOR_NAMED_PRIMARIES_BT2020,
|
||||
.transfer_function = WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ,
|
||||
};
|
||||
wlr_output_state_set_image_description(os, &desc);
|
||||
}
|
||||
|
||||
void output_state_setup_hdr(Monitor *m, bool silent,
|
||||
struct wlr_output_state *state) {
|
||||
uint32_t render_format = m->wlr_output->render_format;
|
||||
const char *unsupported_reason = NULL;
|
||||
bool hdr_supported =
|
||||
output_supports_hdr(m->wlr_output, &unsupported_reason);
|
||||
bool hdr_succeeded = false;
|
||||
|
||||
enum render_bit_depth depth = config.hdr_depth;
|
||||
if (depth == MANGO_RENDER_BIT_DEPTH_DEFAULT)
|
||||
depth = bit_depth_from_format(render_format);
|
||||
|
||||
if (!hdr_supported && depth == MANGO_RENDER_BIT_DEPTH_10) {
|
||||
if (!silent)
|
||||
wlr_log(WLR_INFO, "Cannot enable HDR on output %s: %s",
|
||||
m->wlr_output->name, unsupported_reason);
|
||||
depth = MANGO_RENDER_BIT_DEPTH_8;
|
||||
}
|
||||
|
||||
if (depth == MANGO_RENDER_BIT_DEPTH_10 &&
|
||||
bit_depth_from_format(render_format) == depth) {
|
||||
hdr_succeeded = true; // 上次已经成功设置10位,直接复用
|
||||
} else if (depth == MANGO_RENDER_BIT_DEPTH_10) {
|
||||
hdr_succeeded = output_set_render_format(
|
||||
m, output_formats_10bit, ARRAY_SIZE(output_formats_10bit), state);
|
||||
if (!hdr_succeeded) {
|
||||
if (!silent)
|
||||
wlr_log(WLR_INFO,
|
||||
"No 10 bit color formats supported, HDR disabled.");
|
||||
if (!output_set_render_format(m, output_formats_8bit,
|
||||
ARRAY_SIZE(output_formats_8bit),
|
||||
state))
|
||||
if (!silent)
|
||||
wlr_log(WLR_ERROR, "No 8 bit color formats either!");
|
||||
}
|
||||
} else {
|
||||
// 明确要求8位或自动降级
|
||||
if (!output_set_render_format(m, output_formats_8bit,
|
||||
ARRAY_SIZE(output_formats_8bit), state))
|
||||
if (!silent)
|
||||
wlr_log(WLR_ERROR, "No 8 bit color formats supported!");
|
||||
}
|
||||
|
||||
output_enable_hdr(m, state, hdr_succeeded, silent);
|
||||
}
|
||||
|
|
@ -281,7 +281,7 @@ void tablettoolmotion(struct TabletTool *tool, bool change_x, bool change_y,
|
|||
if (config.sloppyfocus)
|
||||
selmon = xytomon(cursor->x, cursor->y);
|
||||
|
||||
xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy);
|
||||
xytonode(cursor->x, cursor->y, &surface, &c, NULL, NULL, &sx, &sy);
|
||||
if (cursor_mode == CurPressed && !seat->drag &&
|
||||
surface != seat->pointer_state.focused_surface &&
|
||||
toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <stdbool.h>
|
||||
#include <wlr/types/wlr_tearing_control_v1.h>
|
||||
|
||||
struct tearing_controller {
|
||||
|
|
@ -64,6 +65,9 @@ bool check_tearing_frame_allow(Monitor *m) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!selmon)
|
||||
return false;
|
||||
|
||||
Client *c = selmon->sel;
|
||||
|
||||
/* tearing is only allowed for the output with the active client */
|
||||
|
|
@ -94,79 +98,3 @@ bool check_tearing_frame_allow(Monitor *m) {
|
|||
/* honor tearing as requested by action */
|
||||
return c->force_tearing == STATE_ENABLED;
|
||||
}
|
||||
|
||||
bool custom_wlr_scene_output_commit(struct wlr_scene_output *scene_output,
|
||||
struct wlr_output_state *state) {
|
||||
struct wlr_output *wlr_output = scene_output->output;
|
||||
Monitor *m = wlr_output->data;
|
||||
|
||||
// 检查是否需要帧
|
||||
if (!wlr_scene_output_needs_frame(scene_output)) {
|
||||
wlr_log(WLR_DEBUG, "No frame needed for output %s", wlr_output->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 构建输出状态
|
||||
if (!wlr_scene_output_build_state(scene_output, state, NULL)) {
|
||||
wlr_log(WLR_ERROR, "Failed to build output state for %s",
|
||||
wlr_output->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 测试撕裂翻页
|
||||
if (state->tearing_page_flip) {
|
||||
if (!wlr_output_test_state(wlr_output, state)) {
|
||||
state->tearing_page_flip = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试提交
|
||||
bool committed = wlr_output_commit_state(wlr_output, state);
|
||||
|
||||
// 如果启用撕裂翻页但提交失败,重试禁用撕裂翻页
|
||||
if (!committed && state->tearing_page_flip) {
|
||||
wlr_log(WLR_DEBUG, "Retrying commit without tearing for %s",
|
||||
wlr_output->name);
|
||||
state->tearing_page_flip = false;
|
||||
committed = wlr_output_commit_state(wlr_output, state);
|
||||
}
|
||||
|
||||
// 处理状态清理
|
||||
if (committed) {
|
||||
wlr_log(WLR_DEBUG, "Successfully committed output %s",
|
||||
wlr_output->name);
|
||||
if (state == &m->pending) {
|
||||
wlr_output_state_finish(&m->pending);
|
||||
wlr_output_state_init(&m->pending);
|
||||
}
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Failed to commit output %s", wlr_output->name);
|
||||
// 即使提交失败,也清理状态避免积累
|
||||
if (state == &m->pending) {
|
||||
wlr_output_state_finish(&m->pending);
|
||||
wlr_output_state_init(&m->pending);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void apply_tear_state(Monitor *m) {
|
||||
if (wlr_scene_output_needs_frame(m->scene_output)) {
|
||||
wlr_output_state_init(&m->pending);
|
||||
if (wlr_scene_output_build_state(m->scene_output, &m->pending, NULL)) {
|
||||
struct wlr_output_state *pending = &m->pending;
|
||||
pending->tearing_page_flip = true;
|
||||
|
||||
if (!custom_wlr_scene_output_commit(m->scene_output, pending)) {
|
||||
wlr_log(WLR_ERROR, "Failed to commit output %s",
|
||||
m->scene_output->output->name);
|
||||
}
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Failed to build state for output %s",
|
||||
m->scene_output->output->name);
|
||||
wlr_output_state_finish(&m->pending);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#include <wlr/types/wlr_input_method_v2.h>
|
||||
#include <wlr/types/wlr_text_input_v3.h>
|
||||
|
||||
struct dwl_input_method_relay {
|
||||
struct mango_input_method_relay {
|
||||
struct wl_list text_inputs;
|
||||
struct wlr_input_method_v2 *input_method;
|
||||
struct wlr_surface *focused_surface;
|
||||
|
|
@ -26,11 +26,12 @@ struct dwl_input_method_relay {
|
|||
struct wl_listener focused_surface_destroy;
|
||||
};
|
||||
|
||||
struct dwl_input_method_popup {
|
||||
struct mango_input_method_popup {
|
||||
uint32_t type; // must at first in struct
|
||||
struct wlr_input_popup_surface_v2 *popup_surface;
|
||||
struct wlr_scene_tree *tree;
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
struct dwl_input_method_relay *relay;
|
||||
struct mango_input_method_relay *relay;
|
||||
struct wl_list link;
|
||||
|
||||
struct wl_listener destroy;
|
||||
|
|
@ -38,7 +39,7 @@ struct dwl_input_method_popup {
|
|||
};
|
||||
|
||||
struct text_input {
|
||||
struct dwl_input_method_relay *relay;
|
||||
struct mango_input_method_relay *relay;
|
||||
struct wlr_text_input_v3 *input;
|
||||
struct wl_list link;
|
||||
|
||||
|
|
@ -50,20 +51,20 @@ struct text_input {
|
|||
|
||||
struct wlr_input_method_manager_v2 *input_method_manager;
|
||||
struct wlr_text_input_manager_v3 *text_input_manager;
|
||||
struct dwl_input_method_relay *dwl_input_method_relay;
|
||||
struct mango_input_method_relay *mango_input_method_relay;
|
||||
|
||||
/*-------------------封装给外部调用-------------------------------*/
|
||||
bool dwl_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
||||
struct wlr_keyboard_key_event *event);
|
||||
bool mango_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
||||
struct wlr_keyboard_key_event *event);
|
||||
|
||||
bool dwl_im_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard);
|
||||
bool mango_im_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard);
|
||||
|
||||
struct dwl_input_method_relay *dwl_im_relay_create();
|
||||
struct mango_input_method_relay *mango_im_relay_create();
|
||||
|
||||
void dwl_im_relay_finish(struct dwl_input_method_relay *relay);
|
||||
void mango_im_relay_finish(struct mango_input_method_relay *relay);
|
||||
|
||||
void dwl_im_relay_set_focus(struct dwl_input_method_relay *relay,
|
||||
struct wlr_surface *surface);
|
||||
void mango_im_relay_set_focus(struct mango_input_method_relay *relay,
|
||||
struct wlr_surface *surface);
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
/*------------------协议内部代码------------------------------*/
|
||||
|
|
@ -97,7 +98,7 @@ is_keyboard_emulated_by_input_method(struct wlr_keyboard *keyboard,
|
|||
static struct wlr_input_method_keyboard_grab_v2 *
|
||||
get_keyboard_grab(KeyboardGroup *keyboard) {
|
||||
struct wlr_input_method_v2 *input_method =
|
||||
dwl_input_method_relay->input_method;
|
||||
mango_input_method_relay->input_method;
|
||||
if (!input_method || !input_method->keyboard_grab) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -114,7 +115,7 @@ get_keyboard_grab(KeyboardGroup *keyboard) {
|
|||
return input_method->keyboard_grab;
|
||||
}
|
||||
|
||||
bool dwl_im_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard) {
|
||||
bool mango_im_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard) {
|
||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
||||
get_keyboard_grab(keyboard);
|
||||
|
||||
|
|
@ -132,8 +133,8 @@ bool dwl_im_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard) {
|
|||
}
|
||||
}
|
||||
|
||||
bool dwl_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
||||
struct wlr_keyboard_key_event *event) {
|
||||
bool mango_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
||||
struct wlr_keyboard_key_event *event) {
|
||||
|
||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
||||
get_keyboard_grab(keyboard);
|
||||
|
|
@ -149,7 +150,7 @@ bool dwl_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
|||
}
|
||||
|
||||
static struct text_input *
|
||||
get_active_text_input(struct dwl_input_method_relay *relay) {
|
||||
get_active_text_input(struct mango_input_method_relay *relay) {
|
||||
struct text_input *text_input;
|
||||
|
||||
if (!relay->input_method) {
|
||||
|
|
@ -164,7 +165,7 @@ get_active_text_input(struct dwl_input_method_relay *relay) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void update_active_text_input(struct dwl_input_method_relay *relay) {
|
||||
static void update_active_text_input(struct mango_input_method_relay *relay) {
|
||||
struct text_input *active_text_input = get_active_text_input(relay);
|
||||
|
||||
if (relay->input_method && relay->active_text_input != active_text_input) {
|
||||
|
|
@ -180,7 +181,7 @@ static void update_active_text_input(struct dwl_input_method_relay *relay) {
|
|||
}
|
||||
|
||||
static void
|
||||
update_text_inputs_focused_surface(struct dwl_input_method_relay *relay) {
|
||||
update_text_inputs_focused_surface(struct mango_input_method_relay *relay) {
|
||||
struct text_input *text_input;
|
||||
wl_list_for_each(text_input, &relay->text_inputs, link) {
|
||||
struct wlr_text_input_v3 *input = text_input->input;
|
||||
|
|
@ -206,8 +207,8 @@ update_text_inputs_focused_surface(struct dwl_input_method_relay *relay) {
|
|||
}
|
||||
}
|
||||
|
||||
static void update_popup_position(struct dwl_input_method_popup *popup) {
|
||||
struct dwl_input_method_relay *relay = popup->relay;
|
||||
static void update_popup_position(struct mango_input_method_popup *popup) {
|
||||
struct mango_input_method_relay *relay = popup->relay;
|
||||
struct text_input *text_input = relay->active_text_input;
|
||||
struct wlr_box cursor_rect;
|
||||
struct wlr_xdg_surface *xdg_surface;
|
||||
|
|
@ -281,8 +282,8 @@ static void update_popup_position(struct dwl_input_method_popup *popup) {
|
|||
});
|
||||
}
|
||||
|
||||
static void update_popups_position(struct dwl_input_method_relay *relay) {
|
||||
struct dwl_input_method_popup *popup;
|
||||
static void update_popups_position(struct mango_input_method_relay *relay) {
|
||||
struct mango_input_method_popup *popup;
|
||||
wl_list_for_each(popup, &relay->popups, link) {
|
||||
update_popup_position(popup);
|
||||
}
|
||||
|
|
@ -290,11 +291,10 @@ static void update_popups_position(struct dwl_input_method_relay *relay) {
|
|||
|
||||
static void handle_input_method_commit(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
struct mango_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, input_method_commit);
|
||||
struct wlr_input_method_v2 *input_method = data;
|
||||
struct text_input *text_input;
|
||||
assert(relay->input_method == input_method);
|
||||
struct wlr_input_method_v2 *input_method = relay->input_method;
|
||||
|
||||
text_input = relay->active_text_input;
|
||||
if (!text_input) {
|
||||
|
|
@ -322,9 +322,10 @@ static void handle_input_method_commit(struct wl_listener *listener,
|
|||
|
||||
static void handle_keyboard_grab_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
struct mango_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, keyboard_grab_destroy);
|
||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
||||
relay->input_method->keyboard_grab;
|
||||
wl_list_remove(&relay->keyboard_grab_destroy.link);
|
||||
|
||||
if (keyboard_grab->keyboard) {
|
||||
|
|
@ -335,7 +336,7 @@ static void handle_keyboard_grab_destroy(struct wl_listener *listener,
|
|||
|
||||
static void handle_input_method_grab_keyboard(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
struct mango_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, input_method_grab_keyboard);
|
||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
||||
|
||||
|
|
@ -354,9 +355,8 @@ static void handle_input_method_grab_keyboard(struct wl_listener *listener,
|
|||
|
||||
static void handle_input_method_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
struct mango_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, input_method_destroy);
|
||||
assert(relay->input_method == data);
|
||||
wl_list_remove(&relay->input_method_commit.link);
|
||||
wl_list_remove(&relay->input_method_grab_keyboard.link);
|
||||
wl_list_remove(&relay->input_method_new_popup_surface.link);
|
||||
|
|
@ -369,7 +369,7 @@ static void handle_input_method_destroy(struct wl_listener *listener,
|
|||
|
||||
static void handle_popup_surface_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct dwl_input_method_popup *popup =
|
||||
struct mango_input_method_popup *popup =
|
||||
wl_container_of(listener, popup, destroy);
|
||||
wlr_scene_node_destroy(&popup->tree->node);
|
||||
wl_list_remove(&popup->destroy.link);
|
||||
|
|
@ -380,18 +380,18 @@ static void handle_popup_surface_destroy(struct wl_listener *listener,
|
|||
|
||||
static void handle_popup_surface_commit(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct dwl_input_method_popup *popup =
|
||||
struct mango_input_method_popup *popup =
|
||||
wl_container_of(listener, popup, commit);
|
||||
update_popup_position(popup);
|
||||
}
|
||||
|
||||
static void handle_input_method_new_popup_surface(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
struct mango_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, input_method_new_popup_surface);
|
||||
|
||||
struct dwl_input_method_popup *popup =
|
||||
ecalloc(1, sizeof(struct dwl_input_method_popup));
|
||||
struct mango_input_method_popup *popup =
|
||||
ecalloc(1, sizeof(struct mango_input_method_popup));
|
||||
popup->popup_surface = data;
|
||||
popup->relay = relay;
|
||||
|
||||
|
|
@ -405,6 +405,8 @@ static void handle_input_method_new_popup_surface(struct wl_listener *listener,
|
|||
popup->tree = wlr_scene_tree_create(layers[LyrIMPopup]);
|
||||
popup->scene_surface = wlr_scene_subsurface_tree_create(
|
||||
popup->tree, popup->popup_surface->surface);
|
||||
|
||||
popup->type = XdgImPopup;
|
||||
popup->scene_surface->node.data = popup;
|
||||
|
||||
wl_list_insert(&relay->popups, &popup->link);
|
||||
|
|
@ -413,7 +415,7 @@ static void handle_input_method_new_popup_surface(struct wl_listener *listener,
|
|||
}
|
||||
|
||||
static void handle_new_input_method(struct wl_listener *listener, void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
struct mango_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, new_input_method);
|
||||
struct wlr_input_method_v2 *input_method = data;
|
||||
if (seat != input_method->seat) {
|
||||
|
|
@ -449,7 +451,7 @@ static void handle_new_input_method(struct wl_listener *listener, void *data) {
|
|||
update_active_text_input(relay);
|
||||
}
|
||||
|
||||
static void send_state_to_input_method(struct dwl_input_method_relay *relay) {
|
||||
static void send_state_to_input_method(struct mango_input_method_relay *relay) {
|
||||
|
||||
struct wlr_input_method_v2 *input_method = relay->input_method;
|
||||
struct wlr_text_input_v3 *input = relay->active_text_input->input;
|
||||
|
|
@ -474,7 +476,7 @@ static void send_state_to_input_method(struct dwl_input_method_relay *relay) {
|
|||
static void handle_text_input_enable(struct wl_listener *listener, void *data) {
|
||||
struct text_input *text_input =
|
||||
wl_container_of(listener, text_input, enable);
|
||||
struct dwl_input_method_relay *relay = text_input->relay;
|
||||
struct mango_input_method_relay *relay = text_input->relay;
|
||||
|
||||
update_active_text_input(relay);
|
||||
if (relay->active_text_input == text_input) {
|
||||
|
|
@ -495,7 +497,7 @@ static void handle_text_input_disable(struct wl_listener *listener,
|
|||
static void handle_text_input_commit(struct wl_listener *listener, void *data) {
|
||||
struct text_input *text_input =
|
||||
wl_container_of(listener, text_input, commit);
|
||||
struct dwl_input_method_relay *relay = text_input->relay;
|
||||
struct mango_input_method_relay *relay = text_input->relay;
|
||||
|
||||
if (relay->active_text_input == text_input) {
|
||||
update_popups_position(relay);
|
||||
|
|
@ -517,7 +519,7 @@ static void handle_text_input_destroy(struct wl_listener *listener,
|
|||
}
|
||||
|
||||
static void handle_new_text_input(struct wl_listener *listener, void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
struct mango_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, new_text_input);
|
||||
struct wlr_text_input_v3 *wlr_text_input = data;
|
||||
struct text_input *text_input = ecalloc(1, sizeof(struct text_input));
|
||||
|
|
@ -547,26 +549,26 @@ static void handle_new_text_input(struct wl_listener *listener, void *data) {
|
|||
|
||||
static void handle_focused_surface_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct dwl_input_method_relay *relay =
|
||||
struct mango_input_method_relay *relay =
|
||||
wl_container_of(listener, relay, focused_surface_destroy);
|
||||
assert(relay->focused_surface == data);
|
||||
|
||||
dwl_im_relay_set_focus(relay, NULL);
|
||||
mango_im_relay_set_focus(relay, NULL);
|
||||
}
|
||||
|
||||
struct dwl_input_method_relay *dwl_im_relay_create() {
|
||||
struct dwl_input_method_relay *relay =
|
||||
ecalloc(1, sizeof(struct dwl_input_method_relay));
|
||||
struct mango_input_method_relay *mango_im_relay_create() {
|
||||
struct mango_input_method_relay *relay =
|
||||
ecalloc(1, sizeof(struct mango_input_method_relay));
|
||||
wl_list_init(&relay->text_inputs);
|
||||
wl_list_init(&relay->popups);
|
||||
relay->popup_tree = wlr_scene_tree_create(&scene->tree);
|
||||
|
||||
relay->new_text_input.notify = handle_new_text_input;
|
||||
wl_signal_add(&text_input_manager->events.text_input,
|
||||
wl_signal_add(&text_input_manager->events.new_text_input,
|
||||
&relay->new_text_input);
|
||||
|
||||
relay->new_input_method.notify = handle_new_input_method;
|
||||
wl_signal_add(&input_method_manager->events.input_method,
|
||||
wl_signal_add(&input_method_manager->events.new_input_method,
|
||||
&relay->new_input_method);
|
||||
|
||||
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
||||
|
|
@ -574,14 +576,14 @@ struct dwl_input_method_relay *dwl_im_relay_create() {
|
|||
return relay;
|
||||
}
|
||||
|
||||
void dwl_im_relay_finish(struct dwl_input_method_relay *relay) {
|
||||
void mango_im_relay_finish(struct mango_input_method_relay *relay) {
|
||||
wl_list_remove(&relay->new_text_input.link);
|
||||
wl_list_remove(&relay->new_input_method.link);
|
||||
free(relay);
|
||||
}
|
||||
|
||||
void dwl_im_relay_set_focus(struct dwl_input_method_relay *relay,
|
||||
struct wlr_surface *surface) {
|
||||
void mango_im_relay_set_focus(struct mango_input_method_relay *relay,
|
||||
struct wlr_surface *surface) {
|
||||
if (relay->focused_surface == surface) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,975 +0,0 @@
|
|||
#include "wlr_ext_workspace_v1.h"
|
||||
#include "ext-workspace-v1-protocol.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
|
||||
#define EXT_WORKSPACE_V1_VERSION 1
|
||||
|
||||
struct wlr_ext_workspace_v1_group_output {
|
||||
struct wlr_output *output;
|
||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
||||
struct wl_listener output_bind;
|
||||
struct wl_listener output_destroy;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
// These structs wrap wl_resource of each interface to access the request queue
|
||||
// (wlr_ext_workspace_manager_v1_resource.requests) assigned per manager
|
||||
// resource
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource {
|
||||
struct wl_resource *resource;
|
||||
struct wlr_ext_workspace_manager_v1 *manager;
|
||||
struct wl_list requests; // wlr_ext_workspace_v1_request.link
|
||||
struct wl_list workspace_resources; // wlr_ext_workspace_v1_resource.link
|
||||
struct wl_list group_resources; // wlr_ext_workspace_group_v1_resource.link
|
||||
struct wl_list link; // wlr_ext_workspace_manager_v1.resources
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_group_v1_resource {
|
||||
struct wl_resource *resource;
|
||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager;
|
||||
struct wl_list link; // wlr_ext_workspace_group_v1.resources
|
||||
struct wl_list
|
||||
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.group_resources
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_v1_resource {
|
||||
struct wl_resource *resource;
|
||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager;
|
||||
struct wl_list link; // wlr_ext_workspace_v1.resources
|
||||
struct wl_list
|
||||
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.workspace_resources
|
||||
};
|
||||
|
||||
static const struct ext_workspace_group_handle_v1_interface group_impl;
|
||||
|
||||
static struct wlr_ext_workspace_group_v1_resource *
|
||||
group_resource_from_resource(struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(
|
||||
resource, &ext_workspace_group_handle_v1_interface, &group_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static const struct ext_workspace_handle_v1_interface workspace_impl;
|
||||
|
||||
static struct wlr_ext_workspace_v1_resource *
|
||||
workspace_resource_from_resource(struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(resource, &ext_workspace_handle_v1_interface,
|
||||
&workspace_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static const struct ext_workspace_manager_v1_interface manager_impl;
|
||||
|
||||
static struct wlr_ext_workspace_manager_v1_resource *
|
||||
manager_resource_from_resource(struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(
|
||||
resource, &ext_workspace_manager_v1_interface, &manager_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static void workspace_handle_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static void workspace_handle_activate(struct wl_client *client,
|
||||
struct wl_resource *workspace_resource) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
workspace_resource_from_resource(workspace_resource);
|
||||
if (!workspace_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
wl_resource_post_no_memory(workspace_resource);
|
||||
return;
|
||||
}
|
||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE;
|
||||
req->activate.workspace = workspace_res->workspace;
|
||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||
}
|
||||
|
||||
static void
|
||||
workspace_handle_deactivate(struct wl_client *client,
|
||||
struct wl_resource *workspace_resource) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
workspace_resource_from_resource(workspace_resource);
|
||||
if (!workspace_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
wl_resource_post_no_memory(workspace_resource);
|
||||
return;
|
||||
}
|
||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE;
|
||||
req->deactivate.workspace = workspace_res->workspace;
|
||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||
}
|
||||
|
||||
static void workspace_handle_assign(struct wl_client *client,
|
||||
struct wl_resource *workspace_resource,
|
||||
struct wl_resource *group_resource) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
workspace_resource_from_resource(workspace_resource);
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
group_resource_from_resource(group_resource);
|
||||
if (!workspace_res || !group_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
wl_resource_post_no_memory(workspace_resource);
|
||||
return;
|
||||
}
|
||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN;
|
||||
req->assign.group = group_res->group;
|
||||
req->assign.workspace = workspace_res->workspace;
|
||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||
}
|
||||
|
||||
static void workspace_handle_remove(struct wl_client *client,
|
||||
struct wl_resource *workspace_resource) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
workspace_resource_from_resource(workspace_resource);
|
||||
if (!workspace_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
wl_resource_post_no_memory(workspace_resource);
|
||||
return;
|
||||
}
|
||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE;
|
||||
req->remove.workspace = workspace_res->workspace;
|
||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||
}
|
||||
|
||||
static const struct ext_workspace_handle_v1_interface workspace_impl = {
|
||||
.destroy = workspace_handle_destroy,
|
||||
.activate = workspace_handle_activate,
|
||||
.deactivate = workspace_handle_deactivate,
|
||||
.assign = workspace_handle_assign,
|
||||
.remove = workspace_handle_remove,
|
||||
};
|
||||
|
||||
static void group_handle_create_workspace(struct wl_client *client,
|
||||
struct wl_resource *group_resource,
|
||||
const char *name) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
group_resource_from_resource(group_resource);
|
||||
if (!group_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
wl_resource_post_no_memory(group_resource);
|
||||
return;
|
||||
}
|
||||
req->create_workspace.name = strdup(name);
|
||||
if (!req->create_workspace.name) {
|
||||
free(req);
|
||||
wl_resource_post_no_memory(group_resource);
|
||||
return;
|
||||
}
|
||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE;
|
||||
req->create_workspace.group = group_res->group;
|
||||
wl_list_insert(group_res->manager->requests.prev, &req->link);
|
||||
}
|
||||
|
||||
static void group_handle_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct ext_workspace_group_handle_v1_interface group_impl = {
|
||||
.create_workspace = group_handle_create_workspace,
|
||||
.destroy = group_handle_destroy,
|
||||
};
|
||||
|
||||
static void destroy_workspace_resource(
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res) {
|
||||
wl_list_remove(&workspace_res->link);
|
||||
wl_list_remove(&workspace_res->manager_resource_link);
|
||||
wl_resource_set_user_data(workspace_res->resource, NULL);
|
||||
free(workspace_res);
|
||||
}
|
||||
|
||||
static void workspace_resource_destroy(struct wl_resource *resource) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
workspace_resource_from_resource(resource);
|
||||
if (workspace_res) {
|
||||
destroy_workspace_resource(workspace_res);
|
||||
}
|
||||
}
|
||||
|
||||
static struct wlr_ext_workspace_v1_resource *create_workspace_resource(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
calloc(1, sizeof(*workspace_res));
|
||||
if (!workspace_res) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wl_client *client = wl_resource_get_client(manager_res->resource);
|
||||
workspace_res->resource =
|
||||
wl_resource_create(client, &ext_workspace_handle_v1_interface,
|
||||
wl_resource_get_version(manager_res->resource), 0);
|
||||
if (!workspace_res->resource) {
|
||||
free(workspace_res);
|
||||
return NULL;
|
||||
}
|
||||
wl_resource_set_implementation(workspace_res->resource, &workspace_impl,
|
||||
workspace_res, workspace_resource_destroy);
|
||||
|
||||
workspace_res->workspace = workspace;
|
||||
workspace_res->manager = manager_res;
|
||||
wl_list_insert(&workspace->resources, &workspace_res->link);
|
||||
wl_list_insert(&manager_res->workspace_resources,
|
||||
&workspace_res->manager_resource_link);
|
||||
|
||||
return workspace_res;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_group_resource(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
||||
wl_list_remove(&group_res->link);
|
||||
wl_list_remove(&group_res->manager_resource_link);
|
||||
wl_resource_set_user_data(group_res->resource, NULL);
|
||||
free(group_res);
|
||||
}
|
||||
|
||||
static void group_handle_resource_destroy(struct wl_resource *resource) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
group_resource_from_resource(resource);
|
||||
if (group_res) {
|
||||
destroy_group_resource(group_res);
|
||||
}
|
||||
}
|
||||
|
||||
static struct wlr_ext_workspace_group_v1_resource *create_group_resource(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
calloc(1, sizeof(*group_res));
|
||||
if (!group_res) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wl_client *client = wl_resource_get_client(manager_res->resource);
|
||||
uint32_t version = wl_resource_get_version(manager_res->resource);
|
||||
group_res->resource = wl_resource_create(
|
||||
client, &ext_workspace_group_handle_v1_interface, version, 0);
|
||||
if (group_res->resource == NULL) {
|
||||
free(group_res);
|
||||
return NULL;
|
||||
}
|
||||
wl_resource_set_implementation(group_res->resource, &group_impl, group_res,
|
||||
group_handle_resource_destroy);
|
||||
|
||||
group_res->group = group;
|
||||
group_res->manager = manager_res;
|
||||
wl_list_insert(&group->resources, &group_res->link);
|
||||
wl_list_insert(&manager_res->group_resources,
|
||||
&group_res->manager_resource_link);
|
||||
|
||||
return group_res;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_requests(struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
||||
if (req->type == WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE) {
|
||||
free(req->create_workspace.name);
|
||||
}
|
||||
wl_list_remove(&req->link);
|
||||
free(req);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_requests_by(struct wlr_ext_workspace_manager_v1_resource *manager_res,
|
||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_ext_workspace_handle_v1 *workspace) {
|
||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
||||
switch (req->type) {
|
||||
case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE:
|
||||
if (group && req->create_workspace.group == group) {
|
||||
req->create_workspace.group = NULL;
|
||||
}
|
||||
break;
|
||||
case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE:
|
||||
if (workspace && req->activate.workspace == workspace) {
|
||||
req->activate.workspace = NULL;
|
||||
}
|
||||
break;
|
||||
case WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE:
|
||||
if (workspace && req->deactivate.workspace == workspace) {
|
||||
req->deactivate.workspace = NULL;
|
||||
}
|
||||
break;
|
||||
case WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN:
|
||||
if (workspace && req->assign.workspace == workspace) {
|
||||
req->assign.workspace = NULL;
|
||||
}
|
||||
if (group && req->assign.group == group) {
|
||||
req->assign.group = NULL;
|
||||
}
|
||||
break;
|
||||
case WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE:
|
||||
if (workspace && req->remove.workspace == workspace) {
|
||||
req->remove.workspace = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void manager_handle_commit(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
||||
manager_resource_from_resource(resource);
|
||||
if (!manager_res) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_commit_event commit_event = {
|
||||
.requests = &manager_res->requests,
|
||||
};
|
||||
wl_signal_emit_mutable(&manager_res->manager->events.commit, &commit_event);
|
||||
destroy_requests(manager_res);
|
||||
}
|
||||
|
||||
static void handle_idle(void *data) {
|
||||
struct wlr_ext_workspace_manager_v1 *manager = data;
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
||||
ext_workspace_manager_v1_send_done(manager_res->resource);
|
||||
}
|
||||
manager->idle_source = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
manager_schedule_done(struct wlr_ext_workspace_manager_v1 *manager) {
|
||||
if (!manager->idle_source) {
|
||||
manager->idle_source =
|
||||
wl_event_loop_add_idle(manager->event_loop, handle_idle, manager);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
workspace_send_details(struct wlr_ext_workspace_v1_resource *workspace_res) {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace = workspace_res->workspace;
|
||||
struct wl_resource *resource = workspace_res->resource;
|
||||
|
||||
ext_workspace_handle_v1_send_capabilities(resource, workspace->caps);
|
||||
if (workspace->coordinates.size > 0) {
|
||||
ext_workspace_handle_v1_send_coordinates(resource,
|
||||
&workspace->coordinates);
|
||||
}
|
||||
if (workspace->name) {
|
||||
ext_workspace_handle_v1_send_name(resource, workspace->name);
|
||||
}
|
||||
if (workspace->id) {
|
||||
ext_workspace_handle_v1_send_id(resource, workspace->id);
|
||||
}
|
||||
ext_workspace_handle_v1_send_state(resource, workspace->state);
|
||||
manager_schedule_done(workspace->manager);
|
||||
}
|
||||
|
||||
static void manager_handle_stop(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
ext_workspace_manager_v1_send_finished(resource);
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct ext_workspace_manager_v1_interface manager_impl = {
|
||||
.commit = manager_handle_commit,
|
||||
.stop = manager_handle_stop,
|
||||
};
|
||||
|
||||
static void destroy_manager_resource(
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||
destroy_requests(manager_res);
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp2;
|
||||
wl_list_for_each_safe(workspace_res, tmp2,
|
||||
&manager_res->workspace_resources,
|
||||
manager_resource_link) {
|
||||
destroy_workspace_resource(workspace_res);
|
||||
}
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res, *tmp3;
|
||||
wl_list_for_each_safe(group_res, tmp3, &manager_res->group_resources,
|
||||
manager_resource_link) {
|
||||
destroy_group_resource(group_res);
|
||||
}
|
||||
|
||||
wl_list_remove(&manager_res->link);
|
||||
wl_resource_set_user_data(manager_res->resource, NULL);
|
||||
free(manager_res);
|
||||
}
|
||||
|
||||
static void manager_resource_destroy(struct wl_resource *resource) {
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
||||
manager_resource_from_resource(resource);
|
||||
if (manager_res) {
|
||||
destroy_manager_resource(manager_res);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
group_send_details(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
||||
struct wlr_ext_workspace_group_handle_v1 *group = group_res->group;
|
||||
struct wl_resource *resource = group_res->resource;
|
||||
struct wl_client *client = wl_resource_get_client(resource);
|
||||
|
||||
ext_workspace_group_handle_v1_send_capabilities(resource, group->caps);
|
||||
|
||||
struct wlr_ext_workspace_v1_group_output *group_output;
|
||||
wl_list_for_each(group_output, &group->outputs, link) {
|
||||
struct wl_resource *output_resource;
|
||||
wl_resource_for_each(output_resource,
|
||||
&group_output->output->resources) {
|
||||
if (wl_resource_get_client(output_resource) == client) {
|
||||
ext_workspace_group_handle_v1_send_output_enter(
|
||||
resource, output_resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
manager_schedule_done(group->manager);
|
||||
}
|
||||
|
||||
static void manager_bind(struct wl_client *client, void *data, uint32_t version,
|
||||
uint32_t id) {
|
||||
struct wlr_ext_workspace_manager_v1 *manager = data;
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
||||
calloc(1, sizeof(*manager_res));
|
||||
if (!manager_res) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
|
||||
manager_res->manager = manager;
|
||||
wl_list_init(&manager_res->requests);
|
||||
wl_list_init(&manager_res->workspace_resources);
|
||||
wl_list_init(&manager_res->group_resources);
|
||||
|
||||
manager_res->resource = wl_resource_create(
|
||||
client, &ext_workspace_manager_v1_interface, version, id);
|
||||
if (!manager_res->resource) {
|
||||
free(manager_res);
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
wl_resource_set_implementation(manager_res->resource, &manager_impl,
|
||||
manager_res, manager_resource_destroy);
|
||||
wl_list_insert(&manager->resources, &manager_res->link);
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
||||
wl_list_for_each(group, &manager->groups, link) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
create_group_resource(group, manager_res);
|
||||
if (!group_res) {
|
||||
wl_resource_post_no_memory(manager_res->resource);
|
||||
continue;
|
||||
}
|
||||
ext_workspace_manager_v1_send_workspace_group(manager_res->resource,
|
||||
group_res->resource);
|
||||
group_send_details(group_res);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
||||
wl_list_for_each(workspace, &manager->workspaces, link) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
create_workspace_resource(workspace, manager_res);
|
||||
if (!workspace_res) {
|
||||
wl_resource_post_no_memory(manager_res->resource);
|
||||
continue;
|
||||
}
|
||||
ext_workspace_manager_v1_send_workspace(manager_res->resource,
|
||||
workspace_res->resource);
|
||||
workspace_send_details(workspace_res);
|
||||
|
||||
if (!workspace->group) {
|
||||
continue;
|
||||
}
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
||||
wl_list_for_each(group_res, &workspace->group->resources, link) {
|
||||
if (group_res->manager == manager_res) {
|
||||
ext_workspace_group_handle_v1_send_workspace_enter(
|
||||
group_res->resource, workspace_res->resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ext_workspace_manager_v1_send_done(manager_res->resource);
|
||||
}
|
||||
|
||||
static void manager_handle_display_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_ext_workspace_manager_v1 *manager =
|
||||
wl_container_of(listener, manager, display_destroy);
|
||||
|
||||
wl_signal_emit_mutable(&manager->events.destroy, NULL);
|
||||
assert(wl_list_empty(&manager->events.commit.listener_list));
|
||||
assert(wl_list_empty(&manager->events.destroy.listener_list));
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1 *group, *tmp;
|
||||
wl_list_for_each_safe(group, tmp, &manager->groups, link) {
|
||||
wlr_ext_workspace_group_handle_v1_destroy(group);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, *tmp2;
|
||||
wl_list_for_each_safe(workspace, tmp2, &manager->workspaces, link) {
|
||||
wlr_ext_workspace_handle_v1_destroy(workspace);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res, *tmp3;
|
||||
wl_list_for_each_safe(manager_res, tmp3, &manager->resources, link) {
|
||||
destroy_manager_resource(manager_res);
|
||||
}
|
||||
|
||||
if (manager->idle_source) {
|
||||
wl_event_source_remove(manager->idle_source);
|
||||
}
|
||||
|
||||
wl_list_remove(&manager->display_destroy.link);
|
||||
wl_global_destroy(manager->global);
|
||||
free(manager);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_manager_v1 *
|
||||
wlr_ext_workspace_manager_v1_create(struct wl_display *display,
|
||||
uint32_t version) {
|
||||
assert(version <= EXT_WORKSPACE_V1_VERSION);
|
||||
|
||||
struct wlr_ext_workspace_manager_v1 *manager = calloc(1, sizeof(*manager));
|
||||
if (!manager) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
manager->global =
|
||||
wl_global_create(display, &ext_workspace_manager_v1_interface, version,
|
||||
manager, manager_bind);
|
||||
if (!manager->global) {
|
||||
free(manager);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
manager->event_loop = wl_display_get_event_loop(display);
|
||||
|
||||
manager->display_destroy.notify = manager_handle_display_destroy;
|
||||
wl_display_add_destroy_listener(display, &manager->display_destroy);
|
||||
|
||||
wl_list_init(&manager->groups);
|
||||
wl_list_init(&manager->workspaces);
|
||||
wl_list_init(&manager->resources);
|
||||
wl_signal_init(&manager->events.commit);
|
||||
wl_signal_init(&manager->events.destroy);
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1 *
|
||||
wlr_ext_workspace_group_handle_v1_create(
|
||||
struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps) {
|
||||
struct wlr_ext_workspace_group_handle_v1 *group = calloc(1, sizeof(*group));
|
||||
if (!group) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
group->manager = manager;
|
||||
group->caps = caps;
|
||||
|
||||
wl_list_init(&group->outputs);
|
||||
wl_list_init(&group->resources);
|
||||
wl_signal_init(&group->events.destroy);
|
||||
|
||||
wl_list_insert(manager->groups.prev, &group->link);
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||
create_group_resource(group, manager_res);
|
||||
if (!group_res) {
|
||||
continue;
|
||||
}
|
||||
ext_workspace_manager_v1_send_workspace_group(manager_res->resource,
|
||||
group_res->resource);
|
||||
group_send_details(group_res);
|
||||
}
|
||||
|
||||
manager_schedule_done(manager);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static void
|
||||
workspace_send_group(struct wlr_ext_workspace_handle_v1 *workspace,
|
||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
bool enter) {
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
||||
wl_list_for_each(group_res, &group->resources, link) {
|
||||
if (group_res->manager != workspace_res->manager) {
|
||||
continue;
|
||||
}
|
||||
if (enter) {
|
||||
ext_workspace_group_handle_v1_send_workspace_enter(
|
||||
group_res->resource, workspace_res->resource);
|
||||
} else {
|
||||
ext_workspace_group_handle_v1_send_workspace_leave(
|
||||
group_res->resource, workspace_res->resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
manager_schedule_done(workspace->manager);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_group_output(struct wlr_ext_workspace_v1_group_output *group_output) {
|
||||
wl_list_remove(&group_output->output_bind.link);
|
||||
wl_list_remove(&group_output->output_destroy.link);
|
||||
wl_list_remove(&group_output->link);
|
||||
free(group_output);
|
||||
}
|
||||
|
||||
static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_output *output, bool enter) {
|
||||
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
||||
wl_list_for_each(group_res, &group->resources, link) {
|
||||
struct wl_client *client = wl_resource_get_client(group_res->resource);
|
||||
|
||||
struct wl_resource *output_resource;
|
||||
wl_resource_for_each(output_resource, &output->resources) {
|
||||
if (wl_resource_get_client(output_resource) != client) {
|
||||
continue;
|
||||
}
|
||||
if (enter) {
|
||||
ext_workspace_group_handle_v1_send_output_enter(
|
||||
group_res->resource, output_resource);
|
||||
} else {
|
||||
ext_workspace_group_handle_v1_send_output_leave(
|
||||
group_res->resource, output_resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
manager_schedule_done(group->manager);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_group_handle_v1_destroy(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group) {
|
||||
if (!group) {
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_emit_mutable(&group->events.destroy, NULL);
|
||||
|
||||
assert(wl_list_empty(&group->events.destroy.listener_list));
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
||||
wl_list_for_each(workspace, &group->manager->workspaces, link) {
|
||||
if (workspace->group == group) {
|
||||
workspace_send_group(workspace, group, false);
|
||||
workspace->group = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res, *tmp;
|
||||
wl_list_for_each_safe(group_res, tmp, &group->resources, link) {
|
||||
ext_workspace_group_handle_v1_send_removed(group_res->resource);
|
||||
destroy_group_resource(group_res);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||
wl_list_for_each(manager_res, &group->manager->resources, link) {
|
||||
clear_requests_by(manager_res, group, NULL);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_group_output *group_output, *tmp3;
|
||||
wl_list_for_each_safe(group_output, tmp3, &group->outputs, link) {
|
||||
group_send_output(group, group_output->output, false);
|
||||
destroy_group_output(group_output);
|
||||
}
|
||||
|
||||
manager_schedule_done(group->manager);
|
||||
|
||||
wl_list_remove(&group->link);
|
||||
free(group);
|
||||
}
|
||||
|
||||
static void handle_output_bind(struct wl_listener *listener, void *data) {
|
||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
||||
wl_container_of(listener, group_output, output_bind);
|
||||
struct wlr_output_event_bind *event = data;
|
||||
struct wl_client *client = wl_resource_get_client(event->resource);
|
||||
|
||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
||||
wl_list_for_each(group_res, &group_output->group->resources, link) {
|
||||
if (wl_resource_get_client(group_res->resource) == client) {
|
||||
ext_workspace_group_handle_v1_send_output_enter(group_res->resource,
|
||||
event->resource);
|
||||
}
|
||||
}
|
||||
|
||||
manager_schedule_done(group_output->group->manager);
|
||||
}
|
||||
|
||||
static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
||||
wl_container_of(listener, group_output, output_destroy);
|
||||
group_send_output(group_output->group, group_output->output, false);
|
||||
destroy_group_output(group_output);
|
||||
}
|
||||
|
||||
static struct wlr_ext_workspace_v1_group_output *
|
||||
get_group_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_output *output) {
|
||||
struct wlr_ext_workspace_v1_group_output *group_output;
|
||||
wl_list_for_each(group_output, &group->outputs, link) {
|
||||
if (group_output->output == output) {
|
||||
return group_output;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_group_handle_v1_output_enter(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_output *output) {
|
||||
if (get_group_output(group, output)) {
|
||||
return;
|
||||
}
|
||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
||||
calloc(1, sizeof(*group_output));
|
||||
if (!group_output) {
|
||||
return;
|
||||
}
|
||||
group_output->output = output;
|
||||
group_output->group = group;
|
||||
wl_list_insert(&group->outputs, &group_output->link);
|
||||
|
||||
group_output->output_bind.notify = handle_output_bind;
|
||||
wl_signal_add(&output->events.bind, &group_output->output_bind);
|
||||
group_output->output_destroy.notify = handle_output_destroy;
|
||||
wl_signal_add(&output->events.destroy, &group_output->output_destroy);
|
||||
|
||||
group_send_output(group, output, true);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_group_handle_v1_output_leave(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||
struct wlr_output *output) {
|
||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
||||
get_group_output(group, output);
|
||||
if (!group_output) {
|
||||
return;
|
||||
}
|
||||
|
||||
group_send_output(group, output, false);
|
||||
destroy_group_output(group_output);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 *
|
||||
wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
|
||||
const char *id, uint32_t caps) {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace =
|
||||
calloc(1, sizeof(*workspace));
|
||||
if (!workspace) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
workspace->manager = manager;
|
||||
workspace->caps = caps;
|
||||
|
||||
if (id) {
|
||||
workspace->id = strdup(id);
|
||||
if (!workspace->id) {
|
||||
free(workspace);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
wl_list_init(&workspace->resources);
|
||||
wl_array_init(&workspace->coordinates);
|
||||
wl_signal_init(&workspace->events.destroy);
|
||||
|
||||
wl_list_insert(manager->workspaces.prev, &workspace->link);
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||
create_workspace_resource(workspace, manager_res);
|
||||
if (!workspace_res) {
|
||||
continue;
|
||||
}
|
||||
ext_workspace_manager_v1_send_workspace(manager_res->resource,
|
||||
workspace_res->resource);
|
||||
workspace_send_details(workspace_res);
|
||||
}
|
||||
|
||||
manager_schedule_done(manager);
|
||||
|
||||
return workspace;
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_destroy(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace) {
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_emit_mutable(&workspace->events.destroy, NULL);
|
||||
|
||||
assert(wl_list_empty(&workspace->events.destroy.listener_list));
|
||||
|
||||
if (workspace->group) {
|
||||
workspace_send_group(workspace, workspace->group, false);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp;
|
||||
wl_list_for_each_safe(workspace_res, tmp, &workspace->resources, link) {
|
||||
ext_workspace_handle_v1_send_removed(workspace_res->resource);
|
||||
destroy_workspace_resource(workspace_res);
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||
wl_list_for_each(manager_res, &workspace->manager->resources, link) {
|
||||
clear_requests_by(manager_res, NULL, workspace);
|
||||
}
|
||||
|
||||
manager_schedule_done(workspace->manager);
|
||||
|
||||
wl_list_remove(&workspace->link);
|
||||
wl_array_release(&workspace->coordinates);
|
||||
free(workspace->id);
|
||||
free(workspace->name);
|
||||
free(workspace);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_group(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
||||
struct wlr_ext_workspace_group_handle_v1 *group) {
|
||||
if (workspace->group == group) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (workspace->group) {
|
||||
workspace_send_group(workspace, workspace->group, false);
|
||||
}
|
||||
workspace->group = group;
|
||||
if (group) {
|
||||
workspace_send_group(workspace, group, true);
|
||||
}
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_name(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, const char *name) {
|
||||
assert(name);
|
||||
|
||||
if (workspace->name && strcmp(workspace->name, name) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(workspace->name);
|
||||
workspace->name = strdup(name);
|
||||
if (workspace->name == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
||||
ext_workspace_handle_v1_send_name(workspace_res->resource,
|
||||
workspace->name);
|
||||
}
|
||||
|
||||
manager_schedule_done(workspace->manager);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_coordinates(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, const uint32_t *coords,
|
||||
size_t coords_len) {
|
||||
size_t size = coords_len * sizeof(coords[0]);
|
||||
if (size == workspace->coordinates.size &&
|
||||
(size == 0 || memcmp(workspace->coordinates.data, coords, size) == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
wl_array_release(&workspace->coordinates);
|
||||
wl_array_init(&workspace->coordinates);
|
||||
struct wl_array arr = {
|
||||
.data = (void *)coords,
|
||||
.size = size,
|
||||
};
|
||||
wl_array_copy(&workspace->coordinates, &arr);
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
||||
ext_workspace_handle_v1_send_coordinates(workspace_res->resource,
|
||||
&workspace->coordinates);
|
||||
}
|
||||
|
||||
manager_schedule_done(workspace->manager);
|
||||
}
|
||||
|
||||
static void workspace_set_state(struct wlr_ext_workspace_handle_v1 *workspace,
|
||||
enum ext_workspace_handle_v1_state state,
|
||||
bool enabled) {
|
||||
uint32_t old_state = workspace->state;
|
||||
if (enabled) {
|
||||
workspace->state |= state;
|
||||
} else {
|
||||
workspace->state &= ~state;
|
||||
}
|
||||
if (old_state == workspace->state) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
||||
ext_workspace_handle_v1_send_state(workspace_res->resource,
|
||||
workspace->state);
|
||||
}
|
||||
|
||||
manager_schedule_done(workspace->manager);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_active(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_ACTIVE,
|
||||
enabled);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_urgent(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_URGENT,
|
||||
enabled);
|
||||
}
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_hidden(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_HIDDEN,
|
||||
enabled);
|
||||
}
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||
* future consistency of this API.
|
||||
*/
|
||||
#ifndef WLR_USE_UNSTABLE
|
||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||
#endif
|
||||
|
||||
#ifndef WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
|
||||
#define WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
|
||||
|
||||
#include <wayland-protocols/ext-workspace-v1-enum.h>
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
struct wlr_output;
|
||||
|
||||
enum wlr_ext_workspace_v1_request_type {
|
||||
WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE,
|
||||
WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE,
|
||||
WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE,
|
||||
WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN,
|
||||
WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE,
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_v1_request {
|
||||
enum wlr_ext_workspace_v1_request_type type;
|
||||
struct wl_list link; // wlr_ext_workspace_manager_v1_resource.requests
|
||||
union {
|
||||
struct {
|
||||
char *name;
|
||||
struct wlr_ext_workspace_group_handle_v1
|
||||
*group; // NULL if destroyed
|
||||
} create_workspace;
|
||||
struct {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||
} activate;
|
||||
struct {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||
} deactivate;
|
||||
struct {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||
struct wlr_ext_workspace_group_handle_v1
|
||||
*group; // NULL if destroyed
|
||||
} assign;
|
||||
struct {
|
||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||
} remove;
|
||||
};
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_v1_commit_event {
|
||||
struct wl_list *requests; // wlr_ext_workspace_v1_request.link
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_manager_v1 {
|
||||
struct wl_global *global;
|
||||
struct wl_list groups; // wlr_ext_workspace_group_handle_v1.link
|
||||
struct wl_list workspaces; // wlr_ext_workspace_handle_v1.link
|
||||
|
||||
struct {
|
||||
struct wl_signal commit; // wlr_ext_workspace_v1_commit_event
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
||||
struct wl_event_source *idle_source;
|
||||
struct wl_event_loop *event_loop;
|
||||
struct wl_listener display_destroy;
|
||||
};
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1 {
|
||||
struct wlr_ext_workspace_manager_v1 *manager;
|
||||
uint32_t caps; // ext_workspace_group_handle_v1_group_capabilities
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct wl_list link; // wlr_ext_workspace_manager_v1.groups
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link
|
||||
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
||||
};
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 {
|
||||
struct wlr_ext_workspace_manager_v1 *manager;
|
||||
struct wlr_ext_workspace_group_handle_v1 *group; // May be NULL
|
||||
char *id;
|
||||
char *name;
|
||||
struct wl_array coordinates;
|
||||
uint32_t caps; // ext_workspace_handle_v1_workspace_capabilities
|
||||
uint32_t state; // ext_workspace_handle_v1_state
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_list resources; // wlr_ext_workspace_v1_resource.link
|
||||
};
|
||||
};
|
||||
|
||||
struct wlr_ext_workspace_manager_v1 *
|
||||
wlr_ext_workspace_manager_v1_create(struct wl_display *display,
|
||||
uint32_t version);
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1 *
|
||||
wlr_ext_workspace_group_handle_v1_create(
|
||||
struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps);
|
||||
void wlr_ext_workspace_group_handle_v1_destroy(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group);
|
||||
|
||||
void wlr_ext_workspace_group_handle_v1_output_enter(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output);
|
||||
void wlr_ext_workspace_group_handle_v1_output_leave(
|
||||
struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output);
|
||||
|
||||
struct wlr_ext_workspace_handle_v1 *
|
||||
wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
|
||||
const char *id, uint32_t caps);
|
||||
void wlr_ext_workspace_handle_v1_destroy(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace);
|
||||
|
||||
void wlr_ext_workspace_handle_v1_set_group(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
||||
struct wlr_ext_workspace_group_handle_v1 *group);
|
||||
void wlr_ext_workspace_handle_v1_set_name(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, const char *name);
|
||||
void wlr_ext_workspace_handle_v1_set_coordinates(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, const uint32_t *coords,
|
||||
size_t coords_len);
|
||||
void wlr_ext_workspace_handle_v1_set_active(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
||||
void wlr_ext_workspace_handle_v1_set_urgent(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
||||
void wlr_ext_workspace_handle_v1_set_hidden(
|
||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
||||
|
||||
#endif
|
||||
|
|
@ -31,7 +31,7 @@ Client *termforwin(Client *w) {
|
|||
return NULL;
|
||||
|
||||
wl_list_for_each(c, &fstack, flink) {
|
||||
if (c->isterm && !c->swallowing && c->pid &&
|
||||
if (c->isterm && !c->swallowdby && c->pid &&
|
||||
isdescprocess(c->pid, w->pid)) {
|
||||
return c;
|
||||
}
|
||||
|
|
@ -48,9 +48,9 @@ Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (c->swallowedby) {
|
||||
appid = client_get_appid(c->swallowedby);
|
||||
title = client_get_title(c->swallowedby);
|
||||
if (c->swallowing) {
|
||||
appid = client_get_appid(c->swallowing);
|
||||
title = client_get_title(c->swallowing);
|
||||
} else {
|
||||
appid = client_get_appid(c);
|
||||
title = client_get_title(c);
|
||||
|
|
@ -184,11 +184,11 @@ Client *find_client_by_direction(Client *tc, const Arg *arg,
|
|||
break;
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!c || c == tc)
|
||||
if (!c || !c->mon || c == tc)
|
||||
continue;
|
||||
if (!findfloating && c->isfloating)
|
||||
continue;
|
||||
if (c->is_monocle_hide)
|
||||
if (!VISIBLEON(c, c->mon))
|
||||
continue;
|
||||
if (c->isunglobal)
|
||||
continue;
|
||||
|
|
@ -197,11 +197,6 @@ Client *find_client_by_direction(Client *tc, const Arg *arg,
|
|||
if (!(c->tags & c->mon->tagset[c->mon->seltags]))
|
||||
continue;
|
||||
|
||||
if (step == 0 && ((!tc->mon->isoverview &&
|
||||
!client_is_in_same_stack(tc, c, NULL)) ||
|
||||
c->mon != tc->mon))
|
||||
continue;
|
||||
|
||||
int32_t c_l = c->geom.x;
|
||||
int32_t c_r = c->geom.x + c->geom.width;
|
||||
int32_t c_t = c->geom.y;
|
||||
|
|
@ -257,17 +252,24 @@ Client *find_client_by_direction(Client *tc, const Arg *arg,
|
|||
if (!match_dir)
|
||||
continue;
|
||||
|
||||
if (step == 0) {
|
||||
if (c->mon != tc->mon)
|
||||
continue;
|
||||
if (!tc->mon->isoverview &&
|
||||
!client_is_in_same_stack(tc, c, NULL))
|
||||
continue;
|
||||
if (orth_dist != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
int64_t penalty = 0;
|
||||
if (main_dist < 0) {
|
||||
penalty = 10000000000LL; // 主方向重叠(反方向)的极大惩罚
|
||||
penalty = 10000000000LL;
|
||||
main_dist = -main_dist;
|
||||
}
|
||||
|
||||
// 正交方向无重叠惩罚,优先选择在同一行/列的窗口
|
||||
int64_t no_overlap_penalty = 0;
|
||||
if (orth_dist > 0) {
|
||||
// LEFT/RIGHT 时 orth_dist 是垂直间距,>0 表示垂直无重叠
|
||||
// UP/DOWN 时 orth_dist 是水平间距,>0 表示水平无重叠
|
||||
no_overlap_penalty = 10000000LL;
|
||||
}
|
||||
|
||||
|
|
@ -442,7 +444,7 @@ Client *get_focused_stack_client(Client *sc, Client *custom_focus_client) {
|
|||
return sc;
|
||||
|
||||
wl_list_for_each(tc, &fstack, flink) {
|
||||
if (tc->iskilling || tc->isunglobal || tc->is_monocle_hide)
|
||||
if (tc->iskilling || tc->isunglobal)
|
||||
continue;
|
||||
if (!VISIBLEON(tc, sc->mon))
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -100,23 +100,30 @@ static bool layer_ignores_focus(LayerSurface *l) {
|
|||
}
|
||||
|
||||
void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
||||
LayerSurface **pl, double *nx, double *ny) {
|
||||
struct wlr_scene_node *node, *pnode;
|
||||
LayerSurface **pl, MangoGroupBar **gb, double *nx, double *ny) {
|
||||
struct wlr_scene_node *node = NULL, *pnode = NULL;
|
||||
struct wlr_surface *surface = NULL;
|
||||
Client *c = NULL;
|
||||
LayerSurface *l = NULL;
|
||||
MangoGroupBar *mangogroupbar = NULL;
|
||||
int32_t layer;
|
||||
Client *ovc = NULL;
|
||||
|
||||
for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
|
||||
if (psurface)
|
||||
*psurface = NULL;
|
||||
if (pc)
|
||||
*pc = NULL;
|
||||
if (pl)
|
||||
*pl = NULL;
|
||||
if (gb)
|
||||
*gb = NULL;
|
||||
|
||||
for (layer = NUM_LAYERS - 1; layer >= 0; layer--) {
|
||||
if (layer == LyrFadeOut)
|
||||
continue;
|
||||
|
||||
if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
|
||||
continue;
|
||||
|
||||
if (!node->enabled)
|
||||
node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny);
|
||||
if (!node)
|
||||
continue;
|
||||
|
||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
||||
|
|
@ -125,32 +132,44 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
|||
wlr_scene_buffer_from_node(node));
|
||||
if (scene_surface) {
|
||||
surface = scene_surface->surface;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* start from the topmost layer,
|
||||
find a sureface that can be focused by pointer,
|
||||
impopup neither a client nor a layer surface.*/
|
||||
if (layer == LyrIMPopup) {
|
||||
c = NULL;
|
||||
l = NULL;
|
||||
} else {
|
||||
for (pnode = node; pnode && !c; pnode = &pnode->parent->node)
|
||||
c = pnode->data;
|
||||
if (c && c->type == LayerShell) {
|
||||
l = (LayerSurface *)c;
|
||||
c = NULL;
|
||||
void *data = NULL;
|
||||
for (pnode = node; pnode; pnode = &pnode->parent->node) {
|
||||
if (pnode->data) {
|
||||
data = pnode->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
Client *temp_c = (Client *)data;
|
||||
if (temp_c->type == LayerShell) {
|
||||
l = (LayerSurface *)temp_c;
|
||||
} else if (temp_c->type == GroupBar) {
|
||||
mangogroupbar = (MangoGroupBar *)temp_c;
|
||||
} else if (temp_c->type == XDGShell || temp_c->type == X11) {
|
||||
c = temp_c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node->type == WLR_SCENE_NODE_RECT) {
|
||||
if (c) {
|
||||
if (c && (c->type == XDGShell || c->type == X11)) {
|
||||
surface = client_surface(c);
|
||||
}
|
||||
break;
|
||||
|
||||
if (l && l->type == LayerShell) {
|
||||
surface = l->layer_surface->surface;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (psurface)
|
||||
|
|
@ -159,6 +178,8 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
|||
*pc = c;
|
||||
if (pl)
|
||||
*pl = l;
|
||||
if (gb)
|
||||
*gb = mangogroupbar;
|
||||
|
||||
if (selmon && selmon->isoverview && config.ov_no_resize) {
|
||||
ovc = xytoclient(x, y);
|
||||
|
|
@ -174,12 +195,12 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
|||
if (ovc && (!l || layer_ignores_focus(l) || is_below)) {
|
||||
if (pc)
|
||||
*pc = ovc;
|
||||
|
||||
if (psurface)
|
||||
*psurface = ovc ? client_surface(ovc) : NULL;
|
||||
|
||||
if (pl && ovc)
|
||||
if (pl)
|
||||
*pl = NULL;
|
||||
if (gb)
|
||||
*gb = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -181,4 +181,4 @@ bool match_monitor_spec(char *spec, Monitor *m) {
|
|||
free(serial_rule);
|
||||
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,11 +143,17 @@ static cJSON *build_client_json(Client *c) {
|
|||
|
||||
cJSON_AddNumberToObject(obj, "id", c->id);
|
||||
cJSON_AddNumberToObject(obj, "pid", c->pid);
|
||||
cJSON_AddStringToObject(obj, "foreign_toplevel_id",
|
||||
c->ext_foreign_toplevel->identifier);
|
||||
cJSON_AddStringToObject(obj, "title", client_get_title(c));
|
||||
cJSON_AddStringToObject(obj, "appid", client_get_appid(c));
|
||||
cJSON_AddStringToObject(obj, "monitor",
|
||||
c->mon ? c->mon->wlr_output->name : "");
|
||||
cJSON_AddItemToObject(obj, "tags", tags_mask_to_array(c->tags));
|
||||
cJSON_AddBoolToObject(obj, "is_swallowing", c->swallowing ? true : false);
|
||||
cJSON_AddBoolToObject(obj, "is_swallowedby", c->swallowdby ? true : false);
|
||||
cJSON_AddBoolToObject(obj, "is_group", c->group_prev || c->group_next);
|
||||
cJSON_AddBoolToObject(obj, "is_visible", c->mon && VISIBLEON(c, c->mon));
|
||||
cJSON_AddBoolToObject(obj, "is_focused", c->isfocusing);
|
||||
cJSON_AddBoolToObject(obj, "is_fullscreen", c->isfullscreen);
|
||||
cJSON_AddBoolToObject(obj, "is_floating", c->isfloating);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ void set_size_per(Monitor *m, Client *c) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (!found || c->isfloating) {
|
||||
c->master_mfact_per = m->pertag->mfacts[m->pertag->curtag];
|
||||
c->master_inner_per = 1.0f;
|
||||
c->stack_inner_per = 1.0f;
|
||||
|
|
@ -37,21 +37,6 @@ void set_size_per(Monitor *m, Client *c) {
|
|||
}
|
||||
}
|
||||
|
||||
void monocle_set_focus(Client *c, bool focused) {
|
||||
|
||||
if (!c || !c->mon)
|
||||
return;
|
||||
|
||||
c->is_monocle_hide = !focused;
|
||||
mango_tab_bar_node_set_focus(c->tab_bar_node, focused);
|
||||
wlr_scene_node_set_enabled(&c->scene->node, focused);
|
||||
|
||||
if (!focused) {
|
||||
c->animation.current = c->animainit_geom = c->animation.initial =
|
||||
c->pending = c->current = c->geom;
|
||||
}
|
||||
}
|
||||
|
||||
void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
|
||||
int32_t offsety, uint32_t time,
|
||||
int32_t type) {
|
||||
|
|
@ -1147,14 +1132,8 @@ void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
|||
client_add_jump_label_node(c);
|
||||
}
|
||||
|
||||
if (m->pertag->ltidxs[m->pertag->curtag]->id == MONOCLE &&
|
||||
!c->tab_bar_node) {
|
||||
client_add_tab_bar_node(c);
|
||||
}
|
||||
|
||||
if (c->tab_bar_node && c->mon == m) {
|
||||
wlr_scene_node_set_enabled(&c->tab_bar_node->scene_buffer->node,
|
||||
false);
|
||||
if (c->group_bar->scene_buffer->node.enabled) {
|
||||
client_check_tab_node_visible(c);
|
||||
}
|
||||
|
||||
if (c->mon == m && (c->isglobal || c->isunglobal)) {
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ static void dwindle_assign(DwindleNode *node, int32_t ax, int32_t ay,
|
|||
!node->client->ismaximizescreen) {
|
||||
struct wlr_box box = {ax, ay, MANGO_MAX(1, aw),
|
||||
MANGO_MAX(1, ah)};
|
||||
resize(node->client, box, 0);
|
||||
client_tile_resize(node->client, box, 0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -290,18 +290,37 @@ void center_tile(Monitor *m) {
|
|||
int32_t should_overspread =
|
||||
config.center_master_overspread && (n <= nmasters);
|
||||
|
||||
int32_t left_num = 0;
|
||||
int32_t right_num = 0;
|
||||
for (int j = 0; j < stack_num; j++) {
|
||||
if ((j % 2) ^ (n % 2 == 0)) {
|
||||
right_num++;
|
||||
} else {
|
||||
left_num++;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t master_surplus_height =
|
||||
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
||||
(m->w.height - 2 * cur_gappov -
|
||||
cur_gappiv * ie * (master_num > 0 ? master_num - 1 : 0));
|
||||
float master_surplus_ratio = 1.0;
|
||||
int32_t init_master_surplus = master_surplus_height;
|
||||
|
||||
int32_t slave_left_surplus_height =
|
||||
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num / 2 - 1));
|
||||
(m->w.height - 2 * cur_gappov -
|
||||
cur_gappiv * ie * (left_num > 0 ? left_num - 1 : 0));
|
||||
float slave_left_surplus_ratio = 1.0;
|
||||
int32_t init_slave_left_surplus = slave_left_surplus_height;
|
||||
|
||||
int32_t slave_right_surplus_height =
|
||||
(m->w.height - 2 * cur_gappov -
|
||||
cur_gappiv * ie * ((stack_num + 1) / 2 - 1));
|
||||
cur_gappiv * ie * (right_num > 0 ? right_num - 1 : 0));
|
||||
float slave_right_surplus_ratio = 1.0;
|
||||
int32_t init_slave_right_surplus = slave_right_surplus_height;
|
||||
|
||||
int32_t init_single_stack_surplus =
|
||||
(m->w.height - 2 * cur_gappov -
|
||||
cur_gappiv * ie * (stack_num > 0 ? stack_num - 1 : 0));
|
||||
|
||||
if (n > nmasters || !should_overspread) {
|
||||
// 计算主区域宽度(居中模式)
|
||||
|
|
@ -349,6 +368,8 @@ void center_tile(Monitor *m) {
|
|||
if (c->master_inner_per > 0.0f) {
|
||||
h = master_surplus_height * c->master_inner_per /
|
||||
master_surplus_ratio;
|
||||
if (r == 1)
|
||||
h = m->w.height - my - cur_gappov;
|
||||
master_surplus_height = master_surplus_height - h;
|
||||
master_surplus_ratio =
|
||||
master_surplus_ratio - c->master_inner_per;
|
||||
|
|
@ -357,8 +378,12 @@ void center_tile(Monitor *m) {
|
|||
h = (m->w.height - my - cur_gappov -
|
||||
cur_gappiv * ie * (r - 1)) /
|
||||
r;
|
||||
c->master_inner_per = h / (m->w.height - my - cur_gappov -
|
||||
cur_gappiv * ie * (r - 1));
|
||||
if (r == 1)
|
||||
h = m->w.height - my - cur_gappov;
|
||||
c->master_inner_per =
|
||||
init_master_surplus > 0
|
||||
? ((float)h / (float)init_master_surplus)
|
||||
: 0;
|
||||
c->master_mfact_per = mfact;
|
||||
}
|
||||
|
||||
|
|
@ -377,16 +402,20 @@ void center_tile(Monitor *m) {
|
|||
// 单个堆叠窗口
|
||||
r = n - i;
|
||||
if (c->stack_inner_per > 0.0f) {
|
||||
h = (m->w.height - 2 * cur_gappov -
|
||||
cur_gappiv * ie * (stack_num - 1)) *
|
||||
c->stack_inner_per;
|
||||
h = init_single_stack_surplus * c->stack_inner_per;
|
||||
if (r == 1)
|
||||
h = m->w.height - ety - cur_gappov;
|
||||
c->master_mfact_per = mfact;
|
||||
} else {
|
||||
h = (m->w.height - ety - cur_gappov -
|
||||
cur_gappiv * ie * (r - 1)) /
|
||||
r;
|
||||
c->stack_inner_per = h / (m->w.height - ety - cur_gappov -
|
||||
cur_gappiv * ie * (r - 1));
|
||||
if (r == 1)
|
||||
h = m->w.height - ety - cur_gappov;
|
||||
c->stack_inner_per =
|
||||
init_single_stack_surplus > 0
|
||||
? ((float)h / (float)init_single_stack_surplus)
|
||||
: 0;
|
||||
c->master_mfact_per = mfact;
|
||||
}
|
||||
|
||||
|
|
@ -403,7 +432,7 @@ void center_tile(Monitor *m) {
|
|||
.width = tw,
|
||||
.height = h},
|
||||
0);
|
||||
ety += h + cur_gappiv * ie; // 使用理论高度累加
|
||||
ety += h + cur_gappiv * ie;
|
||||
} else {
|
||||
// 多个堆叠窗口:交替放在左右两侧
|
||||
r = (n - i + 1) / 2;
|
||||
|
|
@ -413,6 +442,8 @@ void center_tile(Monitor *m) {
|
|||
if (c->stack_inner_per > 0.0f) {
|
||||
h = slave_right_surplus_height * c->stack_inner_per /
|
||||
slave_right_surplus_ratio;
|
||||
if (r == 1)
|
||||
h = m->w.height - ety - cur_gappov;
|
||||
slave_right_surplus_height =
|
||||
slave_right_surplus_height - h;
|
||||
slave_right_surplus_ratio =
|
||||
|
|
@ -422,9 +453,12 @@ void center_tile(Monitor *m) {
|
|||
h = (m->w.height - ety - cur_gappov -
|
||||
cur_gappiv * ie * (r - 1)) /
|
||||
r;
|
||||
if (r == 1)
|
||||
h = m->w.height - ety - cur_gappov;
|
||||
c->stack_inner_per =
|
||||
h / (m->w.height - ety - cur_gappov -
|
||||
cur_gappiv * ie * (r - 1));
|
||||
init_slave_right_surplus > 0
|
||||
? ((float)h / (float)init_slave_right_surplus)
|
||||
: 0;
|
||||
c->master_mfact_per = mfact;
|
||||
}
|
||||
|
||||
|
|
@ -436,12 +470,14 @@ void center_tile(Monitor *m) {
|
|||
.width = tw,
|
||||
.height = h},
|
||||
0);
|
||||
ety += h + cur_gappiv * ie; // 使用理论高度累加
|
||||
ety += h + cur_gappiv * ie;
|
||||
} else {
|
||||
// 左侧堆叠窗口
|
||||
if (c->stack_inner_per > 0.0f) {
|
||||
h = slave_left_surplus_height * c->stack_inner_per /
|
||||
slave_left_surplus_ratio;
|
||||
if (r == 1)
|
||||
h = m->w.height - oty - cur_gappov;
|
||||
slave_left_surplus_height =
|
||||
slave_left_surplus_height - h;
|
||||
slave_left_surplus_ratio =
|
||||
|
|
@ -451,9 +487,12 @@ void center_tile(Monitor *m) {
|
|||
h = (m->w.height - oty - cur_gappov -
|
||||
cur_gappiv * ie * (r - 1)) /
|
||||
r;
|
||||
if (r == 1)
|
||||
h = m->w.height - oty - cur_gappov;
|
||||
c->stack_inner_per =
|
||||
h / (m->w.height - oty - cur_gappov -
|
||||
cur_gappiv * ie * (r - 1));
|
||||
init_slave_left_surplus > 0
|
||||
? ((float)h / (float)init_slave_left_surplus)
|
||||
: 0;
|
||||
c->master_mfact_per = mfact;
|
||||
}
|
||||
|
||||
|
|
@ -464,7 +503,7 @@ void center_tile(Monitor *m) {
|
|||
.width = tw,
|
||||
.height = h},
|
||||
0);
|
||||
oty += h + cur_gappiv * ie; // 使用理论高度累加
|
||||
oty += h + cur_gappiv * ie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -545,83 +584,32 @@ void deck(Monitor *m) {
|
|||
}
|
||||
}
|
||||
|
||||
void monocle(Monitor *m) {
|
||||
Client *c = NULL, *fc = NULL;
|
||||
void // 17
|
||||
monocle(Monitor *m) {
|
||||
Client *c = NULL;
|
||||
struct wlr_box geom;
|
||||
|
||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||
int32_t cur_gapiv = enablegaps ? m->gappiv : 0;
|
||||
int32_t cur_gapih = enablegaps ? m->gappih : 0;
|
||||
|
||||
if (config.smartgaps && m->visible_fake_tiling_clients == 1) {
|
||||
cur_gappov = cur_gappoh = cur_gapiv = cur_gapih = 0;
|
||||
}
|
||||
|
||||
int n = m->visible_fake_tiling_clients;
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
wl_list_for_each(c, &fstack, flink) {
|
||||
if (c->iskilling || c->isunglobal || !ISFAKETILED(c))
|
||||
continue;
|
||||
if (VISIBLEON(c, m)) {
|
||||
fc = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 1) {
|
||||
geom.x = m->w.x + cur_gappoh;
|
||||
geom.y = m->w.y + cur_gappov;
|
||||
geom.width = m->w.width - 2 * cur_gappoh;
|
||||
geom.height = m->w.height - 2 * cur_gappov;
|
||||
client_tile_resize(fc, geom, 0);
|
||||
monocle_set_focus(fc, true);
|
||||
return;
|
||||
}
|
||||
|
||||
int tab_bar_height = config.tab_bar_height;
|
||||
|
||||
int tab_bar_inner_gap_height =
|
||||
config.tab_bar_height > 0 ? 2 * cur_gapiv : 0;
|
||||
int tab_bar_y_offset = config.tab_bar_height > 0 ? cur_gapiv : 0;
|
||||
|
||||
int tab_y = m->w.y + cur_gappov;
|
||||
int main_y = tab_y + tab_bar_height + tab_bar_y_offset;
|
||||
int main_height = m->w.height - 2 * cur_gappov - tab_bar_inner_gap_height -
|
||||
tab_bar_height;
|
||||
|
||||
int tab_area_width = m->w.width - 2 * cur_gappoh;
|
||||
|
||||
int total_gaps = (n - 1) * cur_gapih;
|
||||
int base_width = (tab_area_width - total_gaps) / n;
|
||||
int remainder = (tab_area_width - total_gaps) % n;
|
||||
|
||||
int tab_x = m->w.x + cur_gappoh;
|
||||
int idx = 0;
|
||||
cur_gappoh = config.smartgaps && m->visible_fake_tiling_clients == 1
|
||||
? 0
|
||||
: cur_gappoh;
|
||||
cur_gappov = config.smartgaps && m->visible_fake_tiling_clients == 1
|
||||
? 0
|
||||
: cur_gappov;
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || !ISFAKETILED(c))
|
||||
continue;
|
||||
|
||||
if (c == fc) {
|
||||
monocle_set_focus(c, true);
|
||||
} else {
|
||||
monocle_set_focus(c, false);
|
||||
}
|
||||
|
||||
geom.x = m->w.x + cur_gappoh;
|
||||
geom.y = main_y;
|
||||
geom.y = m->w.y + cur_gappov;
|
||||
geom.width = m->w.width - 2 * cur_gappoh;
|
||||
geom.height = main_height;
|
||||
geom.height = m->w.height - 2 * cur_gappov;
|
||||
client_tile_resize(c, geom, 0);
|
||||
|
||||
int tw = base_width + (idx < remainder ? 1 : 0);
|
||||
global_draw_tab_bar(c, tab_x, tab_y, tw, tab_bar_height);
|
||||
|
||||
tab_x += tw + cur_gapih;
|
||||
idx++;
|
||||
}
|
||||
if ((c = focustop(m)))
|
||||
wlr_scene_node_raise_to_top(&c->scene->node);
|
||||
}
|
||||
|
||||
// 网格布局窗口大小和位置计算
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
typedef struct {
|
||||
float x, y, w, h;
|
||||
} OvPlacedRect;
|
||||
|
|
@ -232,16 +231,20 @@ void overview_scale(Monitor *m) {
|
|||
float base_x = m->w.x + target_gappo + dx;
|
||||
float base_y = m->w.y + target_gappo + dy;
|
||||
|
||||
// 收集所有客户端的目标几何,最后统一调用 client_tile_resize
|
||||
struct wlr_box overview_boxes[n]; // C99 VLA,n > 0 时有效
|
||||
for (int k = 0; k < n; k++) {
|
||||
Client *cl = items[k].c;
|
||||
struct wlr_box geom;
|
||||
geom.x = (int)(base_x + placed[k].x + 0.5f);
|
||||
geom.y = (int)(base_y + placed[k].y + 0.5f);
|
||||
float w = items[k].orig_w * best_s;
|
||||
float h = items[k].orig_h * best_s;
|
||||
geom.width = (int)(geom.x + w + 0.5f) - geom.x;
|
||||
geom.height = (int)(geom.y + h + 0.5f) - geom.y;
|
||||
resize(cl, geom, 0);
|
||||
int ix = (int)(base_x + placed[k].x + 0.5f);
|
||||
int iy = (int)(base_y + placed[k].y + 0.5f);
|
||||
int iw = (int)(ix + w + 0.5f) - ix;
|
||||
int ih = (int)(iy + h + 0.5f) - iy;
|
||||
overview_boxes[k] = (struct wlr_box){ix, iy, iw, ih};
|
||||
}
|
||||
|
||||
for (int k = 0; k < n; k++) {
|
||||
client_tile_resize(items[k].c, overview_boxes[k], 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -280,74 +283,69 @@ void overview_resize(Monitor *m) {
|
|||
return;
|
||||
}
|
||||
|
||||
// 临时存储每个客户端的目标几何
|
||||
struct wlr_box boxes[n]; // C99 VLA
|
||||
|
||||
if (n == 1) {
|
||||
int32_t cw = (m->w.width - 2 * target_gappo) * single_width_ratio;
|
||||
int32_t ch = (m->w.height - 2 * target_gappo) * single_height_ratio;
|
||||
c_arr[0]->geom.x = m->w.x + (m->w.width - cw) / 2;
|
||||
c_arr[0]->geom.y = m->w.y + (m->w.height - ch) / 2;
|
||||
c_arr[0]->geom.width = cw;
|
||||
c_arr[0]->geom.height = ch;
|
||||
resize(c_arr[0], c_arr[0]->geom, 0);
|
||||
free(c_arr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (n == 2) {
|
||||
boxes[0].x = m->w.x + (m->w.width - cw) / 2;
|
||||
boxes[0].y = m->w.y + (m->w.height - ch) / 2;
|
||||
boxes[0].width = cw;
|
||||
boxes[0].height = ch;
|
||||
} else if (n == 2) {
|
||||
int32_t cw = (m->w.width - 2 * target_gappo - target_gappi) / 2;
|
||||
int32_t ch = (m->w.height - 2 * target_gappo) * 0.65f;
|
||||
|
||||
c_arr[0]->geom.x = m->w.x + target_gappo;
|
||||
c_arr[0]->geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
||||
c_arr[0]->geom.width = cw;
|
||||
c_arr[0]->geom.height = ch;
|
||||
resize(c_arr[0], c_arr[0]->geom, 0);
|
||||
boxes[0].x = m->w.x + target_gappo;
|
||||
boxes[0].y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
||||
boxes[0].width = cw;
|
||||
boxes[0].height = ch;
|
||||
|
||||
c_arr[1]->geom.x = m->w.x + cw + target_gappo + target_gappi;
|
||||
c_arr[1]->geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
||||
c_arr[1]->geom.width = cw;
|
||||
c_arr[1]->geom.height = ch;
|
||||
resize(c_arr[1], c_arr[1]->geom, 0);
|
||||
boxes[1].x = m->w.x + cw + target_gappo + target_gappi;
|
||||
boxes[1].y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
||||
boxes[1].width = cw;
|
||||
boxes[1].height = ch;
|
||||
} else {
|
||||
int32_t cols = 1;
|
||||
while (cols * cols < n)
|
||||
cols++;
|
||||
int32_t rows = (n + cols - 1) / cols;
|
||||
|
||||
free(c_arr);
|
||||
return;
|
||||
}
|
||||
int32_t ch =
|
||||
(m->w.height - 2 * target_gappo - (rows - 1) * target_gappi) / rows;
|
||||
int32_t cw =
|
||||
(m->w.width - 2 * target_gappo - (cols - 1) * target_gappi) / cols;
|
||||
|
||||
int32_t cols = 1;
|
||||
while (cols * cols < n) {
|
||||
cols++;
|
||||
}
|
||||
int32_t rows = (n + cols - 1) / cols;
|
||||
if (ch < 1)
|
||||
ch = 1;
|
||||
if (cw < 1)
|
||||
cw = 1;
|
||||
|
||||
int32_t ch =
|
||||
(m->w.height - 2 * target_gappo - (rows - 1) * target_gappi) / rows;
|
||||
int32_t cw =
|
||||
(m->w.width - 2 * target_gappo - (cols - 1) * target_gappi) / cols;
|
||||
|
||||
if (ch < 1)
|
||||
ch = 1;
|
||||
if (cw < 1)
|
||||
cw = 1;
|
||||
|
||||
int32_t overcols = n % cols;
|
||||
int32_t dx = 0;
|
||||
if (overcols) {
|
||||
dx = (m->w.width - overcols * cw - (overcols - 1) * target_gappi) / 2 -
|
||||
target_gappo;
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
int32_t cx = m->w.x + (i % cols) * (cw + target_gappi);
|
||||
int32_t cy = m->w.y + (i / cols) * (ch + target_gappi);
|
||||
|
||||
if (overcols && i >= n - overcols) {
|
||||
cx += dx;
|
||||
int32_t overcols = n % cols;
|
||||
int32_t dx = 0;
|
||||
if (overcols) {
|
||||
dx = (m->w.width - overcols * cw - (overcols - 1) * target_gappi) /
|
||||
2 -
|
||||
target_gappo;
|
||||
}
|
||||
|
||||
c_arr[i]->geom.x = cx + target_gappo;
|
||||
c_arr[i]->geom.y = cy + target_gappo;
|
||||
c_arr[i]->geom.width = cw;
|
||||
c_arr[i]->geom.height = ch;
|
||||
resize(c_arr[i], c_arr[i]->geom, 0);
|
||||
for (int i = 0; i < n; i++) {
|
||||
int32_t cx = m->w.x + (i % cols) * (cw + target_gappi);
|
||||
int32_t cy = m->w.y + (i / cols) * (ch + target_gappi);
|
||||
if (overcols && i >= n - overcols)
|
||||
cx += dx;
|
||||
|
||||
boxes[i].x = cx + target_gappo;
|
||||
boxes[i].y = cy + target_gappo;
|
||||
boxes[i].width = cw;
|
||||
boxes[i].height = ch;
|
||||
}
|
||||
}
|
||||
|
||||
// 统一应用所有几何变更,使用 client_tile_resize
|
||||
for (int k = 0; k < n; k++) {
|
||||
client_tile_resize(c_arr[k], boxes[k], 0);
|
||||
}
|
||||
|
||||
free(c_arr);
|
||||
|
|
@ -365,10 +363,9 @@ void create_jump_hints(Monitor *m) {
|
|||
char c_char = jump_labels[label_idx];
|
||||
c->jump_char = c_char;
|
||||
|
||||
// 把字符变成字符串
|
||||
char label_text[2] = {c_char, '\0'};
|
||||
|
||||
mango_jump_label_node_update(c->jump_label_node, label_text, 1.0f);
|
||||
mango_jump_label_node_update(c->jump_label_node, label_text,
|
||||
m->wlr_output->scale);
|
||||
wlr_scene_node_set_enabled(&c->jump_label_node->scene_buffer->node,
|
||||
true);
|
||||
wlr_scene_node_raise_to_top(
|
||||
|
|
@ -385,12 +382,10 @@ void create_jump_hints(Monitor *m) {
|
|||
void begin_jump_mode(Monitor *m) { m->is_jump_mode = 1; }
|
||||
|
||||
void finish_jump_mode(Monitor *m) {
|
||||
Client *c = NULL;
|
||||
|
||||
if (!m->is_jump_mode) {
|
||||
if (!m->is_jump_mode)
|
||||
return;
|
||||
}
|
||||
|
||||
Client *c;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (VISIBLEON(c, m)) {
|
||||
if (c->jump_label_node->scene_buffer->node.enabled) {
|
||||
|
|
@ -400,12 +395,10 @@ void finish_jump_mode(Monitor *m) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
m->is_jump_mode = 0;
|
||||
}
|
||||
|
||||
void overview(Monitor *m) {
|
||||
|
||||
if (config.ov_no_resize) {
|
||||
overview_scale(m);
|
||||
} else {
|
||||
|
|
@ -415,4 +408,4 @@ void overview(Monitor *m) {
|
|||
if (m->is_jump_mode) {
|
||||
create_jump_hints(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ scroller_node_create(struct TagScrollerState *st, Client *c) {
|
|||
return n;
|
||||
}
|
||||
|
||||
/* 从 tag 状态中移除一个节点并释放 */
|
||||
static void scroller_node_remove(struct TagScrollerState *st,
|
||||
struct ScrollerStackNode *target) {
|
||||
if (!st || !target)
|
||||
|
|
@ -223,7 +222,7 @@ void arrange_stack_node(struct ScrollerStackNode *head, struct wlr_box geometry,
|
|||
.y = current_y,
|
||||
.width = geometry.width,
|
||||
.height = client_height};
|
||||
resize(iter->client, client_geom, 0);
|
||||
client_tile_resize(iter->client, client_geom, 0);
|
||||
remain_proportion -= iter->stack_proportion;
|
||||
remain_client_height -= client_height;
|
||||
current_y += client_height + gappiv;
|
||||
|
|
@ -272,7 +271,7 @@ void arrange_stack_vertical_node(struct ScrollerStackNode *head,
|
|||
.x = current_x,
|
||||
.height = geometry.height,
|
||||
.width = client_width};
|
||||
resize(iter->client, client_geom, 0);
|
||||
client_tile_resize(iter->client, client_geom, 0);
|
||||
remain_proportion -= iter->stack_proportion;
|
||||
remain_client_width -= client_width;
|
||||
current_x += client_width + gappih;
|
||||
|
|
@ -508,6 +507,7 @@ void scroller(Monitor *m) {
|
|||
|
||||
void vertical_scroller(Monitor *m) {
|
||||
uint32_t tag = m->pertag->curtag;
|
||||
int32_t bar_height = 0;
|
||||
struct TagScrollerState *st = ensure_scroller_state(m, tag);
|
||||
Client *c = NULL;
|
||||
float scroller_default_proportion_single =
|
||||
|
|
@ -696,7 +696,12 @@ void vertical_scroller(Monitor *m) {
|
|||
arrange_stack_vertical_node(heads[focus_index], target_geom,
|
||||
cur_gappih);
|
||||
} else {
|
||||
target_geom.y = root_client->geom.y;
|
||||
bar_height = !root_client->isfullscreen && (root_client->group_prev ||
|
||||
root_client->group_next)
|
||||
? config.group_bar_height
|
||||
: 0;
|
||||
|
||||
target_geom.y = root_client->geom.y - bar_height;
|
||||
vertical_check_scroller_root_inside_mon(heads[focus_index]->client,
|
||||
&target_geom);
|
||||
arrange_stack_vertical_node(heads[focus_index], target_geom,
|
||||
|
|
@ -709,8 +714,15 @@ void vertical_scroller(Monitor *m) {
|
|||
up_geom.width = m->w.width - 2 * cur_gappoh;
|
||||
up_geom.height = max_client_height * cur->scroller_proportion;
|
||||
vertical_scroll_adjust_fullandmax(cur->client, &up_geom);
|
||||
|
||||
bar_height = !heads[focus_index - i + 1]->client->isfullscreen &&
|
||||
(heads[focus_index - i + 1]->client->group_prev ||
|
||||
heads[focus_index - i + 1]->client->group_next)
|
||||
? config.group_bar_height
|
||||
: 0;
|
||||
|
||||
up_geom.y = heads[focus_index - i + 1]->client->geom.y - cur_gappiv -
|
||||
up_geom.height;
|
||||
up_geom.height - bar_height;
|
||||
arrange_stack_vertical_node(cur, up_geom, cur_gappih);
|
||||
}
|
||||
|
||||
|
|
@ -773,16 +785,14 @@ void scroller_insert_stack(Client *c, Client *target_client,
|
|||
if (tnode->prev_in_stack)
|
||||
tnode->prev_in_stack->next_in_stack = newnode;
|
||||
tnode->prev_in_stack = newnode;
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(tnode->client->link.prev, &c->link);
|
||||
wl_list_safe_reinsert_prev(&tnode->client->link, &c->link);
|
||||
} else {
|
||||
newnode->prev_in_stack = tnode;
|
||||
newnode->next_in_stack = tnode->next_in_stack;
|
||||
if (tnode->next_in_stack)
|
||||
tnode->next_in_stack->prev_in_stack = newnode;
|
||||
tnode->next_in_stack = newnode;
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(&tnode->client->link, &c->link);
|
||||
wl_list_safe_reinsert_next(&tnode->client->link, &c->link);
|
||||
}
|
||||
|
||||
/* 处理堆叠头部的全屏/最大化状态*/
|
||||
|
|
@ -821,13 +831,11 @@ void scroller_drop_tile(Client *c, Client *closest, int vertical) {
|
|||
return;
|
||||
} else if (closest->drop_direction == UP) {
|
||||
if (c != stack_head) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(stack_head->link.prev, &c->link);
|
||||
wl_list_safe_reinsert_prev(&stack_head->link, &c->link);
|
||||
}
|
||||
} else if (closest->drop_direction == DOWN) {
|
||||
if (c != stack_tail) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(&stack_tail->link, &c->link);
|
||||
wl_list_safe_reinsert_next(&stack_head->link, &c->link);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -841,13 +849,11 @@ void scroller_drop_tile(Client *c, Client *closest, int vertical) {
|
|||
return;
|
||||
} else if (closest->drop_direction == LEFT) {
|
||||
if (c != stack_head) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(stack_head->link.prev, &c->link);
|
||||
wl_list_safe_reinsert_prev(&stack_head->link, &c->link);
|
||||
}
|
||||
} else if (closest->drop_direction == RIGHT) {
|
||||
if (c != stack_tail) {
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(&stack_tail->link, &c->link);
|
||||
wl_list_safe_reinsert_next(&stack_head->link, &c->link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -902,7 +908,6 @@ static void update_scroller_state(Monitor *m) {
|
|||
break;
|
||||
}
|
||||
|
||||
/* 移除不再可见的节点 */
|
||||
struct ScrollerStackNode *n = st->all_first;
|
||||
while (n) {
|
||||
bool found = false;
|
||||
|
|
|
|||
835
src/mango.c
835
src/mango.c
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue