Merge branch 'main' into feat/focus-animation
This commit is contained in:
@@ -827,7 +827,7 @@ void init_fadeout_client(Client *c) {
|
||||
wl_list_insert(&fadeout_clients, &fadeout_cient->fadeout_link);
|
||||
|
||||
// 请求刷新屏幕
|
||||
wlr_output_schedule_frame(c->mon->wlr_output);
|
||||
request_fresh_all_monitors();
|
||||
}
|
||||
|
||||
void client_commit(Client *c) {
|
||||
@@ -858,7 +858,7 @@ void client_commit(Client *c) {
|
||||
}
|
||||
}
|
||||
// 请求刷新屏幕
|
||||
wlr_output_schedule_frame(c->mon->wlr_output);
|
||||
request_fresh_all_monitors();
|
||||
}
|
||||
|
||||
void client_set_pending_state(Client *c) {
|
||||
|
||||
@@ -244,4 +244,14 @@ struct wlr_scene_tree *wlr_scene_tree_snapshot(struct wlr_scene_node *node,
|
||||
wlr_scene_node_set_enabled(&snapshot->node, true);
|
||||
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
void request_fresh_all_monitors(void) {
|
||||
Monitor *m = NULL;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (!m->wlr_output->enabled) {
|
||||
continue;
|
||||
}
|
||||
wlr_output_schedule_frame(m->wlr_output);
|
||||
}
|
||||
}
|
||||
@@ -930,8 +930,6 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
||||
(*arg).v = strdup(arg_value);
|
||||
} else if (strcmp(func_name, "switch_layout") == 0) {
|
||||
func = switch_layout;
|
||||
} else if (strcmp(func_name, "switch_keyboard_layout") == 0) {
|
||||
func = switch_keyboard_layout;
|
||||
} else if (strcmp(func_name, "togglefloating") == 0) {
|
||||
func = togglefloating;
|
||||
} else if (strcmp(func_name, "togglefullscreen") == 0) {
|
||||
@@ -3196,5 +3194,6 @@ void reset_option(void) {
|
||||
int reload_config(const Arg *arg) {
|
||||
parse_config();
|
||||
reset_option();
|
||||
printstatus();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ int spawn_on_empty(const Arg *arg);
|
||||
int setkeymode(const Arg *arg);
|
||||
int setlayout(const Arg *arg);
|
||||
int switch_layout(const Arg *arg);
|
||||
int switch_keyboard_layout(const Arg *arg);
|
||||
int setmfact(const Arg *arg);
|
||||
int quit(const Arg *arg);
|
||||
int moveresize(const Arg *arg);
|
||||
|
||||
@@ -814,124 +814,6 @@ int spawn_on_empty(const Arg *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int switch_keyboard_layout(const Arg *arg) {
|
||||
if (!kb_group || !kb_group->wlr_group || !seat) {
|
||||
wlr_log(WLR_ERROR, "Invalid keyboard group or seat");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct wlr_keyboard *keyboard = &kb_group->wlr_group->keyboard;
|
||||
if (!keyboard || !keyboard->keymap) {
|
||||
wlr_log(WLR_ERROR, "Invalid keyboard or keymap");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 1. 获取当前布局和计算下一个布局
|
||||
xkb_layout_index_t current = xkb_state_serialize_layout(
|
||||
keyboard->xkb_state, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
const int num_layouts = xkb_keymap_num_layouts(keyboard->keymap);
|
||||
if (num_layouts < 2) {
|
||||
wlr_log(WLR_INFO, "Only one layout available");
|
||||
return 0;
|
||||
}
|
||||
xkb_layout_index_t next = (current + 1) % num_layouts;
|
||||
|
||||
// 2. 创建上下文
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!context) {
|
||||
wlr_log(WLR_ERROR, "Failed to create XKB context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. 分配并获取布局缩写
|
||||
const char **layout_ids = calloc(num_layouts, sizeof(char *));
|
||||
if (!layout_ids) {
|
||||
wlr_log(WLR_ERROR, "Failed to allocate layout IDs");
|
||||
goto cleanup_context;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_layouts; i++) {
|
||||
layout_ids[i] =
|
||||
get_layout_abbr(xkb_keymap_layout_get_name(keyboard->keymap, i));
|
||||
if (!layout_ids[i]) {
|
||||
wlr_log(WLR_ERROR, "Failed to get layout abbreviation");
|
||||
goto cleanup_layouts;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 直接修改 rules.layout(保持原有逻辑)
|
||||
struct xkb_rule_names rules = xkb_rules;
|
||||
// 验证规则是否有效
|
||||
if (!check_keyboard_rules_validate(&rules)) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"Keyboard rules validation failed, skipping layout reset");
|
||||
rules = xkb_default_rules;
|
||||
}
|
||||
|
||||
char *layout_buf = (char *)rules.layout; // 假设这是可修改的
|
||||
|
||||
// 清空原有内容(安全方式)
|
||||
unsigned int layout_buf_size = strlen(layout_buf) + 1;
|
||||
memset(layout_buf, 0, layout_buf_size);
|
||||
|
||||
// 构建新的布局字符串
|
||||
for (int i = 0; i < num_layouts; i++) {
|
||||
const char *layout = layout_ids[(next + i) % num_layouts];
|
||||
|
||||
if (i > 0) {
|
||||
strncat(layout_buf, ",", layout_buf_size - strlen(layout_buf) - 1);
|
||||
}
|
||||
|
||||
if (strchr(layout, ',')) {
|
||||
// 处理包含逗号的布局名
|
||||
char *quoted = malloc(strlen(layout) + 3);
|
||||
if (quoted) {
|
||||
snprintf(quoted, strlen(layout) + 3, "\"%s\"", layout);
|
||||
strncat(layout_buf, quoted,
|
||||
layout_buf_size - strlen(layout_buf) - 1);
|
||||
free(quoted);
|
||||
}
|
||||
} else {
|
||||
strncat(layout_buf, layout,
|
||||
layout_buf_size - strlen(layout_buf) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 创建新 keymap
|
||||
struct xkb_keymap *new_keymap =
|
||||
xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
if (!new_keymap) {
|
||||
wlr_log(WLR_ERROR, "Failed to create keymap for layouts: %s",
|
||||
rules.layout);
|
||||
goto cleanup_layouts;
|
||||
}
|
||||
|
||||
// 6. 应用新 keymap
|
||||
unsigned int depressed = keyboard->modifiers.depressed;
|
||||
unsigned int latched = keyboard->modifiers.latched;
|
||||
unsigned int locked = keyboard->modifiers.locked;
|
||||
|
||||
wlr_keyboard_set_keymap(keyboard, new_keymap);
|
||||
wlr_keyboard_notify_modifiers(keyboard, depressed, latched, locked, 0);
|
||||
keyboard->modifiers.group = 0;
|
||||
|
||||
// 7. 更新 seat
|
||||
wlr_seat_set_keyboard(seat, keyboard);
|
||||
wlr_seat_keyboard_notify_modifiers(seat, &keyboard->modifiers);
|
||||
|
||||
// 8. 清理资源
|
||||
xkb_keymap_unref(new_keymap);
|
||||
|
||||
cleanup_layouts:
|
||||
free(layout_ids);
|
||||
|
||||
cleanup_context:
|
||||
xkb_context_unref(context);
|
||||
|
||||
printstatus();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int switch_layout(const Arg *arg) {
|
||||
|
||||
int jk, ji;
|
||||
|
||||
@@ -134,6 +134,10 @@ void dwl_ext_workspace_printstatus(Monitor *m) {
|
||||
if (!w->m->pertag->no_hide[w->tag])
|
||||
wlr_ext_workspace_handle_v1_set_hidden(w->ext_workspace,
|
||||
true);
|
||||
else {
|
||||
wlr_ext_workspace_handle_v1_set_hidden(w->ext_workspace,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
if ((m->tagset[m->seltags] & (1 << (w->tag - 1)) & TAGMASK) ||
|
||||
|
||||
@@ -340,21 +340,33 @@ Client *focustop(Monitor *m) {
|
||||
}
|
||||
|
||||
Client *get_next_stack_client(Client *c, bool reverse) {
|
||||
if (!c || !c->mon)
|
||||
return NULL; // 添加输入检查
|
||||
|
||||
Client *next = NULL;
|
||||
if (reverse) {
|
||||
wl_list_for_each_reverse(next, &c->link, link) {
|
||||
if (!next)
|
||||
continue; // 安全检查
|
||||
|
||||
if (c->mon->has_visible_fullscreen_client && !next->isfloating &&
|
||||
!next->isfullscreen)
|
||||
continue;
|
||||
if (VISIBLEON(next, c->mon) && next != c)
|
||||
|
||||
// 添加更安全的 VISIBLEON 检查
|
||||
if (next != c && next->mon && VISIBLEON(next, c->mon))
|
||||
return next;
|
||||
}
|
||||
} else {
|
||||
wl_list_for_each(next, &c->link, link) {
|
||||
if (!next)
|
||||
continue; // 安全检查
|
||||
|
||||
if (c->mon->has_visible_fullscreen_client && !next->isfloating &&
|
||||
!next->isfullscreen)
|
||||
continue;
|
||||
if (VISIBLEON(next, c->mon) && next != c)
|
||||
|
||||
if (next != c && next->mon && VISIBLEON(next, c->mon))
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
68
src/mango.c
68
src/mango.c
@@ -705,6 +705,7 @@ static void refresh_monitors_workspaces_status(Monitor *m);
|
||||
static void init_client_properties(Client *c);
|
||||
static bool check_keyboard_rules_validate(struct xkb_rule_names *rules);
|
||||
static float *get_border_color(Client *c);
|
||||
static void request_fresh_all_monitors(void);
|
||||
|
||||
#include "data/static_keymap.h"
|
||||
#include "dispatch/bind_declare.h"
|
||||
@@ -2384,18 +2385,9 @@ KeyboardGroup *createkeyboardgroup(void) {
|
||||
group->wlr_group = wlr_keyboard_group_create();
|
||||
group->wlr_group->data = group;
|
||||
|
||||
// 4. 直接修改 rules.layout(保持原有逻辑)
|
||||
struct xkb_rule_names rules = xkb_rules;
|
||||
// 验证规则是否有效
|
||||
if (!check_keyboard_rules_validate(&rules)) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"Keyboard rules validation failed, skipping layout reset");
|
||||
rules = xkb_default_rules;
|
||||
}
|
||||
|
||||
/* Prepare an XKB keymap and assign it to the keyboard group. */
|
||||
context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!(keymap = xkb_keymap_new_from_names(context, &rules,
|
||||
if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules,
|
||||
XKB_KEYMAP_COMPILE_NO_FLAGS)))
|
||||
die("failed to compile keymap");
|
||||
|
||||
@@ -4108,7 +4100,7 @@ skip:
|
||||
wlr_output_state_finish(&pending);
|
||||
|
||||
if (need_more_frames) {
|
||||
wlr_output_schedule_frame(m->wlr_output);
|
||||
request_fresh_all_monitors();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4544,46 +4536,6 @@ void setgaps(int oh, int ov, int ih, int iv) {
|
||||
arrange(selmon, false);
|
||||
}
|
||||
|
||||
// 验证键盘规则是否有效
|
||||
bool check_keyboard_rules_validate(struct xkb_rule_names *rules) {
|
||||
if (!rules) {
|
||||
wlr_log(WLR_ERROR, "Keyboard rules are NULL");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!context) {
|
||||
wlr_log(WLR_ERROR, "Failed to create XKB context for validation");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
struct xkb_keymap *test_keymap =
|
||||
xkb_keymap_new_from_names(context, rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
if (test_keymap) {
|
||||
// 检查keymap是否至少有一个布局
|
||||
if (xkb_keymap_num_layouts(test_keymap) > 0) {
|
||||
valid = true;
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Keymap has no layouts");
|
||||
}
|
||||
xkb_keymap_unref(test_keymap);
|
||||
} else {
|
||||
wlr_log(WLR_ERROR,
|
||||
"Invalid keyboard rules: rules=%s, model=%s, layout=%s, "
|
||||
"variant=%s, options=%s",
|
||||
rules->rules ? rules->rules : "NULL",
|
||||
rules->model ? rules->model : "NULL",
|
||||
rules->layout ? rules->layout : "NULL",
|
||||
rules->variant ? rules->variant : "NULL",
|
||||
rules->options ? rules->options : "NULL");
|
||||
}
|
||||
|
||||
xkb_context_unref(context);
|
||||
return valid;
|
||||
}
|
||||
|
||||
void reset_keyboard_layout(void) {
|
||||
if (!kb_group || !kb_group->wlr_group || !seat) {
|
||||
wlr_log(WLR_ERROR, "Invalid keyboard group or seat");
|
||||
@@ -4605,16 +4557,6 @@ void reset_keyboard_layout(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep the same rules but just reapply them
|
||||
struct xkb_rule_names rules = xkb_rules;
|
||||
|
||||
// 验证规则是否有效
|
||||
if (!check_keyboard_rules_validate(&rules)) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"Keyboard rules validation failed, skipping layout reset");
|
||||
rules = xkb_default_rules;
|
||||
}
|
||||
|
||||
// Create context
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!context) {
|
||||
@@ -4623,8 +4565,8 @@ void reset_keyboard_layout(void) {
|
||||
}
|
||||
|
||||
// 现在安全地创建真正的keymap
|
||||
struct xkb_keymap *new_keymap =
|
||||
xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
struct xkb_keymap *new_keymap = xkb_keymap_new_from_names(
|
||||
context, &xkb_rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
if (!new_keymap) {
|
||||
// 理论上这里不应该失败,因为前面已经验证过了
|
||||
wlr_log(WLR_ERROR,
|
||||
|
||||
Reference in New Issue
Block a user