Merge branch 'mangowm:main' into main

This commit is contained in:
Davide Greco 2026-04-06 14:23:16 +02:00 committed by GitHub
commit 76ad12e51c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 621 additions and 117 deletions

View file

@ -294,9 +294,8 @@ static inline uint32_t client_set_size(Client *c, uint32_t width,
uint32_t height) {
#ifdef XWAYLAND
if (client_is_x11(c)) {
struct wlr_surface_state *state =
&c->surface.xwayland->surface->current;
struct wlr_xwayland_surface *surface = c->surface.xwayland;
struct wlr_surface_state *state = &surface->surface->current;
if ((int32_t)c->geom.width - 2 * (int32_t)c->bw ==
(int32_t)state->width &&
@ -309,6 +308,22 @@ static inline uint32_t client_set_size(Client *c, uint32_t width,
return 0;
}
xcb_size_hints_t *size_hints = surface->size_hints;
int32_t width = c->geom.width - 2 * c->bw;
int32_t height = c->geom.height - 2 * c->bw;
if (c->mon && c->mon->isoverview && size_hints &&
c->geom.width - 2 * (int32_t)c->bw < size_hints->min_width &&
c->geom.height - 2 * (int32_t)c->bw < size_hints->min_height)
return 0;
if (size_hints &&
c->geom.width - 2 * (int32_t)c->bw < size_hints->min_width)
width = size_hints->min_width;
if (size_hints &&
c->geom.height - 2 * (int32_t)c->bw < size_hints->min_height)
height = size_hints->min_height;
wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x + c->bw,
c->geom.y + c->bw, width, height);
return 1;
@ -350,7 +365,7 @@ static inline void client_set_maximized(Client *c, bool maximized) {
static inline void client_set_tiled(Client *c, uint32_t edges) {
struct wlr_xdg_toplevel *toplevel;
#ifdef XWAYLAND
if (client_is_x11(c) && c->force_maximize) {
if (client_is_x11(c) && c->force_fakemaximize) {
wlr_xwayland_surface_set_maximized(c->surface.xwayland,
edges != WLR_EDGE_NONE,
edges != WLR_EDGE_NONE);
@ -365,7 +380,7 @@ static inline void client_set_tiled(Client *c, uint32_t edges) {
wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges);
}
if (c->force_maximize) {
if (c->force_fakemaximize) {
wlr_xdg_toplevel_set_maximized(toplevel, edges != WLR_EDGE_NONE);
}
}

View file

@ -90,7 +90,7 @@ typedef struct {
int32_t no_force_center;
int32_t isterm;
int32_t allow_csd;
int32_t force_maximize;
int32_t force_fakemaximize;
int32_t force_tiled_state;
int32_t force_tearing;
int32_t noswallow;
@ -2059,7 +2059,7 @@ bool parse_option(Config *config, char *key, char *value) {
rule->indleinhibit_when_focus = -1;
rule->isterm = -1;
rule->allow_csd = -1;
rule->force_maximize = -1;
rule->force_fakemaximize = -1;
rule->force_tiled_state = -1;
rule->force_tearing = -1;
rule->noswallow = -1;
@ -2173,8 +2173,8 @@ bool parse_option(Config *config, char *key, char *value) {
rule->isterm = atoi(val);
} else if (strcmp(key, "allow_csd") == 0) {
rule->allow_csd = atoi(val);
} else if (strcmp(key, "force_maximize") == 0) {
rule->force_maximize = atoi(val);
} else if (strcmp(key, "force_fakemaximize") == 0) {
rule->force_fakemaximize = atoi(val);
} else if (strcmp(key, "force_tiled_state") == 0) {
rule->force_tiled_state = atoi(val);
} else if (strcmp(key, "force_tearing") == 0) {
@ -3214,7 +3214,7 @@ void override_config(void) {
config.accel_profile = CLAMP_INT(config.accel_profile, 0, 2);
config.accel_speed = CLAMP_FLOAT(config.accel_speed, -1.0f, 1.0f);
config.scroll_method = CLAMP_INT(config.scroll_method, 0, 4);
config.scroll_button = CLAMP_INT(config.scroll_button, 272, 276);
config.scroll_button = CLAMP_INT(config.scroll_button, 272, 279);
config.click_method = CLAMP_INT(config.click_method, 0, 2);
config.send_events_mode = CLAMP_INT(config.send_events_mode, 0, 2);
config.button_map = CLAMP_INT(config.button_map, 0, 1);
@ -3264,7 +3264,7 @@ void set_value_default() {
config.animation_fade_in = 1;
config.animation_fade_out = 1;
config.tag_animation_direction = HORIZONTAL;
config.zoom_initial_ratio = 0.3f;
config.zoom_initial_ratio = 0.4f;
config.zoom_end_ratio = 0.8f;
config.fadein_begin_opacity = 0.5f;
config.fadeout_begin_opacity = 0.5f;

View file

@ -380,7 +380,11 @@ int32_t moveresize(const Arg *arg) {
/* Float the window and tell motionnotify to grab it */
if (grabc->isfloating == 0 && arg->ui == CurMove) {
grabc->drag_to_tile = true;
exit_scroller_stack(grabc);
setfloating(grabc, 1);
grabc->old_stack_inner_per = 0.0f;
grabc->old_master_inner_per = 0.0f;
set_size_per(grabc->mon, grabc);
}
switch (cursor_mode = arg->ui) {
@ -552,7 +556,7 @@ int32_t restore_minimized(const Arg *arg) {
if (selmon && selmon->sel && selmon->sel->is_in_scratchpad &&
selmon->sel->is_scratchpad_show) {
selmon->sel->isminimized = 0;
client_pending_minimized_state(selmon->sel, 0);
selmon->sel->is_scratchpad_show = 0;
selmon->sel->is_in_scratchpad = 0;
selmon->sel->isnamedscratchpad = 0;
@ -863,7 +867,6 @@ int32_t spawn_shell(const Arg *arg) {
}
int32_t spawn(const Arg *arg) {
if (!arg->v)
return 0;
@ -876,28 +879,21 @@ int32_t spawn(const Arg *arg) {
dup2(STDERR_FILENO, STDOUT_FILENO);
setsid();
// 2. 解析参数
char *argv[64];
int32_t argc = 0;
char *token = strtok((char *)arg->v, " ");
while (token != NULL && argc < 63) {
wordexp_t p;
if (wordexp(token, &p, 0) == 0) {
argv[argc++] = p.we_wordv[0];
} else {
argv[argc++] = token;
}
token = strtok(NULL, " ");
// 2. 对整个参数字符串进行单词展开
wordexp_t p;
if (wordexp(arg->v, &p, 0) != 0) {
wlr_log(WLR_DEBUG, "mango: wordexp failed for '%s'\n", arg->v);
_exit(EXIT_FAILURE);
}
argv[argc] = NULL;
// 3. 执行命令
execvp(argv[0], argv);
// 3. 执行命令p.we_wordv 已经是 argv 数组)
execvp(p.we_wordv[0], p.we_wordv);
// 4. execvp 失败时:打印错误并直接退出(避免 coredump
wlr_log(WLR_DEBUG, "mango: execvp '%s' failed: %s\n", argv[0],
// 4. execvp 失败时:打印错误,释放 wordexp 资源,然后退出
wlr_log(WLR_DEBUG, "mango: execvp '%s' failed: %s\n", p.we_wordv[0],
strerror(errno));
_exit(EXIT_FAILURE); // 使用 _exit 避免缓冲区刷新等操作
wordfree(&p); // 释放 wordexp 分配的内存
_exit(EXIT_FAILURE);
}
return 0;
}

View file

@ -391,7 +391,7 @@ struct Client {
struct dwl_opacity_animation opacity_animation;
int32_t isterm, noswallow;
int32_t allow_csd;
int32_t force_maximize;
int32_t force_fakemaximize;
int32_t force_tiled_state;
pid_t pid;
Client *swallowing, *swallowedby;
@ -807,6 +807,10 @@ static int32_t keep_idle_inhibit(void *data);
static void check_keep_idle_inhibit(Client *c);
static void pre_caculate_before_arrange(Monitor *m, bool want_animation,
bool from_view, bool only_caculate);
static void client_pending_fullscreen_state(Client *c, int32_t isfullscreen);
static void client_pending_maximized_state(Client *c, int32_t ismaximized);
static void client_pending_minimized_state(Client *c, int32_t isminimized);
#include "data/static_keymap.h"
#include "dispatch/bind_declare.h"
#include "layout/layout.h"
@ -1064,11 +1068,33 @@ void clear_fullscreen_flag(Client *c) {
}
}
void client_pending_fullscreen_state(Client *c, int32_t isfullscreen) {
c->isfullscreen = isfullscreen;
if (c->foreign_toplevel && !c->iskilling)
wlr_foreign_toplevel_handle_v1_set_fullscreen(c->foreign_toplevel,
isfullscreen);
}
void client_pending_maximized_state(Client *c, int32_t ismaximized) {
c->ismaximizescreen = ismaximized;
if (c->foreign_toplevel && !c->iskilling)
wlr_foreign_toplevel_handle_v1_set_maximized(c->foreign_toplevel,
ismaximized);
}
void client_pending_minimized_state(Client *c, int32_t isminimized) {
c->isminimized = isminimized;
if (c->foreign_toplevel && !c->iskilling)
wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel,
isminimized);
}
void show_scratchpad(Client *c) {
c->is_scratchpad_show = 1;
if (c->isfullscreen || c->ismaximizescreen) {
c->isfullscreen = 0; // 清除窗口全屏标志
c->ismaximizescreen = 0;
client_pending_fullscreen_state(c, 0);
client_pending_maximized_state(c, 0);
c->bw = c->isnoborder ? 0 : config.borderpx;
}
@ -1107,9 +1133,6 @@ void swallow(Client *c, Client *w) {
c->bw = w->bw;
c->isfloating = w->isfloating;
c->isurgent = w->isurgent;
c->isfullscreen = w->isfullscreen;
c->ismaximizescreen = w->ismaximizescreen;
c->isminimized = w->isminimized;
c->is_in_scratchpad = w->is_in_scratchpad;
c->is_scratchpad_show = w->is_scratchpad_show;
c->tags = w->tags;
@ -1121,6 +1144,7 @@ void swallow(Client *c, Client *w) {
c->scroller_proportion = w->scroller_proportion;
c->next_in_stack = w->next_in_stack;
c->prev_in_stack = w->prev_in_stack;
if (w->next_in_stack)
w->next_in_stack->prev_in_stack = c;
if (w->prev_in_stack)
@ -1139,11 +1163,9 @@ void swallow(Client *c, Client *w) {
if (!c->foreign_toplevel && c->mon)
add_foreign_toplevel(c);
if (c->isminimized && c->foreign_toplevel) {
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel,
false);
wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, true);
}
client_pending_fullscreen_state(c, w->isfullscreen);
client_pending_maximized_state(c, w->ismaximizescreen);
client_pending_minimized_state(c, w->isminimized);
}
bool switch_scratchpad_client_state(Client *c) {
@ -1326,7 +1348,7 @@ void toggle_hotarea(int32_t x_root, int32_t y_root) {
static void apply_rule_properties(Client *c, const ConfigWinRule *r) {
APPLY_INT_PROP(c, r, isterm);
APPLY_INT_PROP(c, r, allow_csd);
APPLY_INT_PROP(c, r, force_maximize);
APPLY_INT_PROP(c, r, force_fakemaximize);
APPLY_INT_PROP(c, r, force_tiled_state);
APPLY_INT_PROP(c, r, force_tearing);
APPLY_INT_PROP(c, r, noswallow);
@ -4081,7 +4103,7 @@ void init_client_properties(Client *c) {
c->old_master_mfact_per = 0.0f;
c->isterm = 0;
c->allow_csd = 0;
c->force_maximize = 0;
c->force_fakemaximize = 0;
c->force_tiled_state = 1;
c->force_tearing = 0;
c->allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
@ -4239,7 +4261,7 @@ void maximizenotify(struct wl_listener *listener, void *data) {
void unminimize(Client *c) {
if (c && c->is_in_scratchpad && c->is_scratchpad_show) {
c->isminimized = 0;
client_pending_minimized_state(c, 0);
c->is_scratchpad_show = 0;
c->is_in_scratchpad = 0;
c->isnamedscratchpad = 0;
@ -4267,13 +4289,12 @@ void set_minimized(Client *c) {
c->oldtags = c->mon->tagset[c->mon->seltags];
c->mini_restore_tag = c->tags;
c->tags = 0;
c->isminimized = 1;
client_pending_minimized_state(c, 1);
c->is_in_scratchpad = 1;
c->is_scratchpad_show = 0;
focusclient(focustop(selmon), 1);
arrange(c->mon, false, false);
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, false);
wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, true);
wl_list_remove(&c->link); // 从原来位置移除
wl_list_insert(clients.prev, &c->link); // 插入尾部
}
@ -5050,11 +5071,11 @@ setfloating(Client *c, int32_t floating) {
if (floating == 1 && c != grabc) {
if (c->isfullscreen) {
c->isfullscreen = 0;
client_pending_fullscreen_state(c, 0);
client_set_fullscreen(c, 0);
}
c->ismaximizescreen = 0;
client_pending_maximized_state(c, 0);
exit_scroller_stack(c);
// 重新计算居中的坐标
@ -5120,7 +5141,7 @@ setfloating(Client *c, int32_t floating) {
save_old_size_per(c->mon);
}
if (!c->force_maximize)
if (!c->force_fakemaximize)
client_set_maximized(c, false);
if (!c->isfloating || c->force_tiled_state) {
@ -5179,12 +5200,12 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
return;
int32_t old_maximizescreen_state = c->ismaximizescreen;
c->ismaximizescreen = maximizescreen;
client_pending_maximized_state(c, maximizescreen);
if (maximizescreen) {
if (c->isfullscreen) {
c->isfullscreen = 0;
client_pending_fullscreen_state(c, 0);
client_set_fullscreen(c, 0);
}
@ -5197,10 +5218,8 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
wlr_scene_node_raise_to_top(&c->scene->node);
if (!is_scroller_layout(c->mon) || c->isfloating)
resize(c, maximizescreen_box, 0);
c->ismaximizescreen = 1;
} else {
c->bw = c->isnoborder ? 0 : config.borderpx;
c->ismaximizescreen = 0;
if (c->isfloating)
setfloating(c, 1);
}
@ -5215,9 +5234,9 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
save_old_size_per(c->mon);
}
if (!c->force_maximize && !c->ismaximizescreen) {
if (!c->force_fakemaximize && !c->ismaximizescreen) {
client_set_maximized(c, false);
} else if (!c->force_maximize && c->ismaximizescreen) {
} else if (!c->force_fakemaximize && c->ismaximizescreen) {
client_set_maximized(c, true);
}
@ -5248,14 +5267,15 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自
c->isfullscreen = fullscreen;
client_set_fullscreen(c, fullscreen);
client_pending_fullscreen_state(c, fullscreen);
if (fullscreen) {
if (c->ismaximizescreen && !c->force_maximize) {
if (c->ismaximizescreen && !c->force_fakemaximize) {
client_set_maximized(c, false);
}
c->ismaximizescreen = 0;
client_pending_maximized_state(c, 0);
exit_scroller_stack(c);
c->isfakefullscreen = 0;
@ -5264,10 +5284,8 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自
wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层
if (!is_scroller_layout(c->mon) || c->isfloating)
resize(c, c->mon->m, 1);
c->isfullscreen = 1;
} else {
c->bw = c->isnoborder ? 0 : config.borderpx;
c->isfullscreen = 0;
if (c->isfloating)
setfloating(c, 1);
}
@ -5459,8 +5477,7 @@ void show_hide_client(Client *c) {
c->tags = c->oldtags;
arrange(c->mon, false, false);
}
c->isminimized = 0;
wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, false);
client_pending_minimized_state(c, 0);
focusclient(c, 1);
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true);
}
@ -5884,8 +5901,8 @@ void overview_backup(Client *c) {
c->isfloating = 0;
}
if (c->isfullscreen || c->ismaximizescreen) {
c->isfullscreen = 0; // 清除窗口全屏标志
c->ismaximizescreen = 0;
client_pending_fullscreen_state(c, 0); // 清除窗口全屏标志
client_pending_maximized_state(c, 0);
}
c->bw = c->isnoborder ? 0 : config.borderpx;
@ -5915,8 +5932,8 @@ void overview_restore(Client *c, const Arg *arg) {
} else if (want_restore_fullscreen(c) && c->isfullscreen) {
setfullscreen(c, 1);
} else {
c->isfullscreen = 0;
c->ismaximizescreen = 0;
client_pending_fullscreen_state(c, 0);
client_pending_maximized_state(c, 0);
setfullscreen(c, false);
}
} else {
@ -6489,13 +6506,11 @@ void activatex11(struct wl_listener *listener, void *data) {
return;
if (c->isminimized) {
c->isminimized = 0;
client_pending_minimized_state(c, 0);
c->tags = c->mini_restore_tag;
c->is_scratchpad_show = 0;
c->is_in_scratchpad = 0;
c->isnamedscratchpad = 0;
wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel,
false);
setborder_color(c);
if (VISIBLEON(c, c->mon)) {
need_arrange = true;