opt: optimize code struct

This commit is contained in:
DreamMaoMao 2025-07-17 11:47:39 +08:00
parent 3a03641e85
commit 643a9fb4b7
5 changed files with 528 additions and 532 deletions

337
src/fetch/client.h Normal file
View file

@ -0,0 +1,337 @@
bool check_hit_no_border(Client *c) {
int i;
bool hit_no_border = false;
if (!render_border) {
hit_no_border = true;
}
for (i = 0; i < config.tag_rules_count; i++) {
if (c->tags & (1 << (config.tag_rules[i].id - 1)) &&
config.tag_rules[i].no_render_border) {
hit_no_border = true;
}
}
if (no_border_when_single && c && c->mon && c->mon->visible_clients == 1) {
hit_no_border = true;
}
return hit_no_border;
}
Client *termforwin(Client *w) {
Client *c;
if (!w->pid || w->isterm || w->noswallow)
return NULL;
wl_list_for_each(c, &fstack, flink) {
if (c->isterm && !c->swallowing && c->pid &&
isdescprocess(c->pid, w->pid)) {
return c;
}
}
return NULL;
}
Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) {
Client *target_client = NULL;
const char *appid, *title;
Client *c = NULL;
wl_list_for_each(c, &clients, link) {
if (c->mon != selmon) {
continue;
}
if (!(appid = client_get_appid(c)))
appid = broken;
if (!(title = client_get_title(c)))
title = broken;
if (arg_id && strncmp(arg_id, "none", 4) == 0)
arg_id = NULL;
if (arg_title && strncmp(arg_title, "none", 4) == 0)
arg_title = NULL;
if ((arg_title && regex_match(arg_title, title) && !arg_id) ||
(arg_id && regex_match(arg_id, appid) && !arg_title) ||
(arg_id && regex_match(arg_id, appid) && arg_title &&
regex_match(arg_title, title))) {
target_client = c;
break;
}
}
return target_client;
}
struct wlr_box // 计算客户端居中坐标
setclient_coordinate_center(Client *c, struct wlr_box geom, int offsetx,
int offsety) {
struct wlr_box tempbox;
int offset = 0;
int len = 0;
Monitor *m = c->mon ? c->mon : selmon;
unsigned int cbw = check_hit_no_border(c) ? c->bw : 0;
if (!c->no_force_center) {
tempbox.x = m->w.x + (m->w.width - geom.width) / 2;
tempbox.y = m->w.y + (m->w.height - geom.height) / 2;
} else {
tempbox.x = geom.x;
tempbox.y = geom.y;
}
tempbox.width = geom.width;
tempbox.height = geom.height;
if (offsetx != 0) {
len = (m->w.width - c->geom.width - 2 * m->gappoh) / 2;
offset = len * (offsetx / 100.0);
tempbox.x += offset;
// 限制窗口在屏幕内
if (tempbox.x < m->m.x) {
tempbox.x = m->m.x - cbw;
}
if (tempbox.x + tempbox.width > m->m.x + m->m.width) {
tempbox.x = m->m.x + m->m.width - tempbox.width + cbw;
}
}
if (offsety != 0) {
len = (m->w.height - c->geom.height - 2 * m->gappov) / 2;
offset = len * (offsety / 100.0);
tempbox.y += offset;
// 限制窗口在屏幕内
if (tempbox.y < m->m.y) {
tempbox.y = m->m.y - cbw;
}
if (tempbox.y + tempbox.height > m->m.y + m->m.height) {
tempbox.y = m->m.y + m->m.height - tempbox.height + cbw;
}
}
return tempbox;
}
/* Helper: Check if rule matches client */
static bool is_window_rule_matches(const ConfigWinRule *r, const char *appid,
const char *title) {
return (r->title && regex_match(r->title, title) && !r->id) ||
(r->id && regex_match(r->id, appid) && !r->title) ||
(r->id && regex_match(r->id, appid) && r->title &&
regex_match(r->title, title));
}
Client *center_select(Monitor *m) {
Client *c = NULL;
Client *target_c = NULL;
long int mini_distance = -1;
int dirx, diry;
long int distance;
wl_list_for_each(c, &clients, link) {
if (c && VISIBLEON(c, m) && client_surface(c)->mapped &&
!c->isfloating && !client_is_unmanaged(c)) {
dirx = c->geom.x + c->geom.width / 2 - (m->w.x + m->w.width / 2);
diry = c->geom.y + c->geom.height / 2 - (m->w.y + m->w.height / 2);
distance = dirx * dirx + diry * diry;
if (distance < mini_distance || mini_distance == -1) {
mini_distance = distance;
target_c = c;
}
}
}
return target_c;
}
Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
bool align) {
Client *c;
Client **tempClients = NULL; // 初始化为 NULL
int last = -1;
// 第一次遍历,计算客户端数量
wl_list_for_each(c, &clients, link) {
if (c && (findfloating || !c->isfloating) && !c->isunglobal &&
(focus_cross_monitor || c->mon == selmon) &&
(c->tags & c->mon->tagset[c->mon->seltags])) {
last++;
}
}
if (last < 0) {
return NULL; // 没有符合条件的客户端
}
// 动态分配内存
tempClients = malloc((last + 1) * sizeof(Client *));
if (!tempClients) {
// 处理内存分配失败的情况
return NULL;
}
// 第二次遍历,填充 tempClients
last = -1;
wl_list_for_each(c, &clients, link) {
if (c && (findfloating || !c->isfloating) && !c->isunglobal &&
(focus_cross_monitor || c->mon == selmon) &&
(c->tags & c->mon->tagset[c->mon->seltags])) {
last++;
tempClients[last] = c;
}
}
int sel_x = tc->geom.x;
int sel_y = tc->geom.y;
long long int distance = LLONG_MAX;
Client *tempFocusClients = NULL;
switch (arg->i) {
case UP:
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.y < sel_y &&
tempClients[_i]->geom.x == sel_x) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
if (!tempFocusClients && !align) {
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.y < sel_y) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
}
break;
case DOWN:
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.y > sel_y &&
tempClients[_i]->geom.x == sel_x) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
if (!tempFocusClients && !align) {
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.y > sel_y) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
}
break;
case LEFT:
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.x < sel_x &&
tempClients[_i]->geom.y == sel_y) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
if (!tempFocusClients && !align) {
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.x < sel_x) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
}
break;
case RIGHT:
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.x > sel_x &&
tempClients[_i]->geom.y == sel_y) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
if (!tempFocusClients && !align) {
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.x > sel_x) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
}
break;
}
free(tempClients); // 释放内存
return tempFocusClients;
}
Client *direction_select(const Arg *arg) {
Client *tc = selmon->sel;
if (!tc)
return NULL;
if (tc && (tc->isfullscreen || tc->ismaxmizescreen)) {
// 不支持全屏窗口的焦点切换
return NULL;
}
return find_client_by_direction(tc, arg, true, false);
}
/* We probably should change the name of this, it sounds like
* will focus the topmost client of this mon, when actually will
* only return that client */
Client * // 0.5
focustop(Monitor *m) {
Client *c;
wl_list_for_each(c, &fstack, flink) {
if (c->iskilling || c->isunglobal)
continue;
if (VISIBLEON(c, m))
return c;
}
return NULL;
}

135
src/fetch/common.h Normal file
View file

@ -0,0 +1,135 @@
pid_t getparentprocess(pid_t p) {
unsigned int v = 0;
FILE *f;
char buf[256];
snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
if (!(f = fopen(buf, "r")))
return 0;
// 检查fscanf返回值确保成功读取了1个参数
if (fscanf(f, "%*u %*s %*c %u", &v) != 1) {
fclose(f);
return 0;
}
fclose(f);
return (pid_t)v;
}
char *get_autostart_path(char *autostart_path, unsigned int buf_size) {
const char *maomaoconfig = getenv("MAOMAOCONFIG");
if (maomaoconfig && maomaoconfig[0] != '\0') {
snprintf(autostart_path, buf_size, "%s/autostart.sh", maomaoconfig);
} else {
const char *homedir = getenv("HOME");
if (!homedir) {
fprintf(stderr, "Error: HOME environment variable not set.\n");
return NULL;
}
snprintf(autostart_path, buf_size, "%s/.config/maomao/autostart.sh",
homedir);
}
return autostart_path;
}
char *get_layout_abbr(const char *full_name) {
// 1. 尝试在映射表中查找
for (int i = 0; layout_mappings[i].full_name != NULL; i++) {
if (strcmp(full_name, layout_mappings[i].full_name) == 0) {
return strdup(layout_mappings[i].abbr);
}
}
// 2. 尝试从名称中提取并转换为小写
const char *open = strrchr(full_name, '(');
const char *close = strrchr(full_name, ')');
if (open && close && close > open) {
unsigned int len = close - open - 1;
if (len > 0 && len <= 4) {
char *abbr = malloc(len + 1);
if (abbr) {
// 提取并转换为小写
for (unsigned int j = 0; j < len; j++) {
abbr[j] = tolower(open[j + 1]);
}
abbr[len] = '\0';
return abbr;
}
}
}
// 3. 提取前2-3个字母并转换为小写
char *abbr = malloc(4);
if (abbr) {
unsigned int j = 0;
for (unsigned int i = 0; full_name[i] != '\0' && j < 3; i++) {
if (isalpha(full_name[i])) {
abbr[j++] = tolower(full_name[i]);
}
}
abbr[j] = '\0';
// 确保至少2个字符
if (j >= 2)
return abbr;
free(abbr);
}
// 4. 回退方案:使用首字母小写
char *fallback = malloc(3);
if (fallback) {
fallback[0] = tolower(full_name[0]);
fallback[1] = full_name[1] ? tolower(full_name[1]) : '\0';
fallback[2] = '\0';
return fallback;
}
// 5. 最终回退:返回 "xx"
return strdup("xx");
}
void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
LayerSurface **pl, double *nx, double *ny) {
struct wlr_scene_node *node, *pnode;
struct wlr_surface *surface = NULL;
Client *c = NULL;
LayerSurface *l = NULL;
int layer;
for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
// ignore text-input layer
if (layer == LyrIMPopup)
continue;
if (layer == LyrFadeOut)
continue;
if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
continue;
if (node->type == WLR_SCENE_NODE_BUFFER)
surface = wlr_scene_surface_try_from_buffer(
wlr_scene_buffer_from_node(node))
->surface;
/* Walk the tree to find a node that knows the client */
for (pnode = node; pnode && !c; pnode = &pnode->parent->node)
c = pnode->data;
if (c && c->type == LayerShell) {
c = NULL;
l = pnode->data;
}
}
if (psurface)
*psurface = surface;
if (pc)
*pc = c;
if (pl)
*pl = l;
}

3
src/fetch/fetch.h Normal file
View file

@ -0,0 +1,3 @@
#include "client.h"
#include "common.h"
#include "monitor.h"

52
src/fetch/monitor.h Normal file
View file

@ -0,0 +1,52 @@
Monitor *dirtomon(enum wlr_direction dir) {
struct wlr_output *next;
if (!wlr_output_layout_get(output_layout, selmon->wlr_output))
return selmon;
if ((next = wlr_output_layout_adjacent_output(output_layout, 1 << dir,
selmon->wlr_output,
selmon->m.x, selmon->m.y)))
return next->data;
if ((next = wlr_output_layout_farthest_output(
output_layout,
dir ^ (WLR_DIRECTION_LEFT | WLR_DIRECTION_RIGHT |
WLR_DIRECTION_UP | WLR_DIRECTION_DOWN),
selmon->wlr_output, selmon->m.x, selmon->m.y)))
return next->data;
return selmon;
}
bool is_scroller_layout(Monitor *m) {
if (strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "scroller") == 0)
return true;
if (strcmp(m->pertag->ltidxs[m->pertag->curtag]->name,
"vertical_scroller") == 0)
return true;
return false;
}
// 获取tags中最前面的tag的tagmask
unsigned int get_tags_first_tag(unsigned int source_tags) {
unsigned int i, tag;
tag = 0;
if (!source_tags) {
return selmon->pertag->curtag;
}
for (i = 0; !(tag & 1) && source_tags != 0 && i < LENGTH(tags); i++) {
tag = source_tags >> i;
}
if (i == 1) {
return 1;
} else if (i > 9) {
return 1 << 8;
} else {
return 1 << (i - 1);
}
}
Monitor *xytomon(double x, double y) {
struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
return o ? o->data : NULL;
}

View file

@ -825,6 +825,7 @@ static struct wlr_xwayland *xwayland;
#include "config/parse_config.h"
#include "dispatch/action.h"
#include "ext-protocol/all.h"
#include "fetch/fetch.h"
#include "layout/horizontal.h"
#include "layout/vertical.h"
@ -836,26 +837,6 @@ void client_change_mon(Client *c, Monitor *m) {
}
}
bool check_hit_no_border(Client *c) {
int i;
bool hit_no_border = false;
if (!render_border) {
hit_no_border = true;
}
for (i = 0; i < config.tag_rules_count; i++) {
if (c->tags & (1 << (config.tag_rules[i].id - 1)) &&
config.tag_rules[i].no_render_border) {
hit_no_border = true;
}
}
if (no_border_when_single && c && c->mon && c->mon->visible_clients == 1) {
hit_no_border = true;
}
return hit_no_border;
}
void applybounds(Client *c, struct wlr_box *bbox) {
/* set minimum possible */
c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width);
@ -926,27 +907,6 @@ void client_update_oldmonname_record(Client *c, Monitor *m) {
c->oldmonname[sizeof(c->oldmonname) - 1] = '\0';
}
pid_t getparentprocess(pid_t p) {
unsigned int v = 0;
FILE *f;
char buf[256];
snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
if (!(f = fopen(buf, "r")))
return 0;
// 检查fscanf返回值确保成功读取了1个参数
if (fscanf(f, "%*u %*s %*c %u", &v) != 1) {
fclose(f);
return 0;
}
fclose(f);
return (pid_t)v;
}
int isdescprocess(pid_t p, pid_t c) {
while (p != c && c != 0)
c = getparentprocess(c);
@ -954,22 +914,6 @@ int isdescprocess(pid_t p, pid_t c) {
return (int)c;
}
Client *termforwin(Client *w) {
Client *c;
if (!w->pid || w->isterm || w->noswallow)
return NULL;
wl_list_for_each(c, &fstack, flink) {
if (c->isterm && !c->swallowing && c->pid &&
isdescprocess(c->pid, w->pid)) {
return c;
}
}
return NULL;
}
void swallow(Client *c, Client *w) {
c->bw = w->bw;
c->isfloating = w->isfloating;
@ -1021,37 +965,6 @@ bool switch_scratchpad_client_state(Client *c) {
return false;
}
Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) {
Client *target_client = NULL;
const char *appid, *title;
Client *c = NULL;
wl_list_for_each(c, &clients, link) {
if (c->mon != selmon) {
continue;
}
if (!(appid = client_get_appid(c)))
appid = broken;
if (!(title = client_get_title(c)))
title = broken;
if (arg_id && strncmp(arg_id, "none", 4) == 0)
arg_id = NULL;
if (arg_title && strncmp(arg_title, "none", 4) == 0)
arg_title = NULL;
if ((arg_title && regex_match(arg_title, title) && !arg_id) ||
(arg_id && regex_match(arg_id, appid) && !arg_title) ||
(arg_id && regex_match(arg_id, appid) && arg_title &&
regex_match(arg_title, title))) {
target_client = c;
break;
}
}
return target_client;
}
void apply_named_scratchpad(Client *target_client) {
Client *c = NULL;
wl_list_for_each(c, &clients, link) {
@ -1132,66 +1045,6 @@ void toggle_hotarea(int x_root, int y_root) {
}
}
struct wlr_box // 计算客户端居中坐标
setclient_coordinate_center(Client *c, struct wlr_box geom, int offsetx,
int offsety) {
struct wlr_box tempbox;
int offset = 0;
int len = 0;
Monitor *m = c->mon ? c->mon : selmon;
unsigned int cbw = check_hit_no_border(c) ? c->bw : 0;
if (!c->no_force_center) {
tempbox.x = m->w.x + (m->w.width - geom.width) / 2;
tempbox.y = m->w.y + (m->w.height - geom.height) / 2;
} else {
tempbox.x = geom.x;
tempbox.y = geom.y;
}
tempbox.width = geom.width;
tempbox.height = geom.height;
if (offsetx != 0) {
len = (m->w.width - c->geom.width - 2 * m->gappoh) / 2;
offset = len * (offsetx / 100.0);
tempbox.x += offset;
// 限制窗口在屏幕内
if (tempbox.x < m->m.x) {
tempbox.x = m->m.x - cbw;
}
if (tempbox.x + tempbox.width > m->m.x + m->m.width) {
tempbox.x = m->m.x + m->m.width - tempbox.width + cbw;
}
}
if (offsety != 0) {
len = (m->w.height - c->geom.height - 2 * m->gappov) / 2;
offset = len * (offsety / 100.0);
tempbox.y += offset;
// 限制窗口在屏幕内
if (tempbox.y < m->m.y) {
tempbox.y = m->m.y - cbw;
}
if (tempbox.y + tempbox.height > m->m.y + m->m.height) {
tempbox.y = m->m.y + m->m.height - tempbox.height + cbw;
}
}
return tempbox;
}
/* Helper: Check if rule matches client */
static bool is_window_rule_matches(const ConfigWinRule *r, const char *appid,
const char *title) {
return (r->title && regex_match(r->title, title) && !r->id) ||
(r->id && regex_match(r->id, appid) && !r->title) ||
(r->id && regex_match(r->id, appid) && r->title &&
regex_match(r->title, title));
}
static void apply_rule_properties(Client *c, const ConfigWinRule *r) {
APPLY_INT_PROP(isterm);
APPLY_INT_PROP(noswallow);
@ -1380,15 +1233,6 @@ void applyrules(Client *c) {
setborder_color(c);
}
bool is_scroller_layout(Monitor *m) {
if (strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "scroller") == 0)
return true;
if (strcmp(m->pertag->ltidxs[m->pertag->curtag]->name,
"vertical_scroller") == 0)
return true;
return false;
}
void // 17
arrange(Monitor *m, bool want_animation) {
Client *c;
@ -1541,27 +1385,6 @@ void arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area,
}
}
Client *center_select(Monitor *m) {
Client *c = NULL;
Client *target_c = NULL;
long int mini_distance = -1;
int dirx, diry;
long int distance;
wl_list_for_each(c, &clients, link) {
if (c && VISIBLEON(c, m) && client_surface(c)->mapped &&
!c->isfloating && !client_is_unmanaged(c)) {
dirx = c->geom.x + c->geom.width / 2 - (m->w.x + m->w.width / 2);
diry = c->geom.y + c->geom.height / 2 - (m->w.y + m->w.height / 2);
distance = dirx * dirx + diry * diry;
if (distance < mini_distance || mini_distance == -1) {
mini_distance = distance;
target_c = c;
}
}
}
return target_c;
}
void apply_window_snap(Client *c) {
int snap_up = 99999, snap_down = 99999, snap_left = 99999,
snap_right = 99999;
@ -1665,186 +1488,6 @@ void apply_window_snap(Client *c) {
resize(c, c->geom, 0);
}
Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
bool align) {
Client *c;
Client **tempClients = NULL; // 初始化为 NULL
int last = -1;
// 第一次遍历,计算客户端数量
wl_list_for_each(c, &clients, link) {
if (c && (findfloating || !c->isfloating) && !c->isunglobal &&
(focus_cross_monitor || c->mon == selmon) &&
(c->tags & c->mon->tagset[c->mon->seltags])) {
last++;
}
}
if (last < 0) {
return NULL; // 没有符合条件的客户端
}
// 动态分配内存
tempClients = malloc((last + 1) * sizeof(Client *));
if (!tempClients) {
// 处理内存分配失败的情况
return NULL;
}
// 第二次遍历,填充 tempClients
last = -1;
wl_list_for_each(c, &clients, link) {
if (c && (findfloating || !c->isfloating) && !c->isunglobal &&
(focus_cross_monitor || c->mon == selmon) &&
(c->tags & c->mon->tagset[c->mon->seltags])) {
last++;
tempClients[last] = c;
}
}
int sel_x = tc->geom.x;
int sel_y = tc->geom.y;
long long int distance = LLONG_MAX;
Client *tempFocusClients = NULL;
switch (arg->i) {
case UP:
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.y < sel_y &&
tempClients[_i]->geom.x == sel_x) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
if (!tempFocusClients && !align) {
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.y < sel_y) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
}
break;
case DOWN:
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.y > sel_y &&
tempClients[_i]->geom.x == sel_x) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
if (!tempFocusClients && !align) {
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.y > sel_y) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
}
break;
case LEFT:
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.x < sel_x &&
tempClients[_i]->geom.y == sel_y) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
if (!tempFocusClients && !align) {
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.x < sel_x) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
}
break;
case RIGHT:
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.x > sel_x &&
tempClients[_i]->geom.y == sel_y) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
if (!tempFocusClients && !align) {
for (int _i = 0; _i <= last; _i++) {
if (tempClients[_i]->geom.x > sel_x) {
int dis_x = tempClients[_i]->geom.x - sel_x;
int dis_y = tempClients[_i]->geom.y - sel_y;
long long int tmp_distance =
dis_x * dis_x + dis_y * dis_y; // 计算距离
if (tmp_distance < distance) {
distance = tmp_distance;
tempFocusClients = tempClients[_i];
}
}
}
}
break;
}
free(tempClients); // 释放内存
return tempFocusClients;
}
Client *direction_select(const Arg *arg) {
Client *tc = selmon->sel;
if (!tc)
return NULL;
if (tc && (tc->isfullscreen || tc->ismaxmizescreen)) {
// 不支持全屏窗口的焦点切换
return NULL;
}
return find_client_by_direction(tc, arg, true, false);
}
void arrangelayers(Monitor *m) {
int i;
struct wlr_box usable_area = m->m;
@ -1887,24 +1530,6 @@ void arrangelayers(Monitor *m) {
}
}
char *get_autostart_path(char *autostart_path, unsigned int buf_size) {
const char *maomaoconfig = getenv("MAOMAOCONFIG");
if (maomaoconfig && maomaoconfig[0] != '\0') {
snprintf(autostart_path, buf_size, "%s/autostart.sh", maomaoconfig);
} else {
const char *homedir = getenv("HOME");
if (!homedir) {
fprintf(stderr, "Error: HOME environment variable not set.\n");
return NULL;
}
snprintf(autostart_path, buf_size, "%s/.config/maomao/autostart.sh",
homedir);
}
return autostart_path;
}
void // 鼠标滚轮事件
axisnotify(struct wl_listener *listener, void *data) {
@ -3184,23 +2809,6 @@ void destroykeyboardgroup(struct wl_listener *listener, void *data) {
free(group);
}
Monitor *dirtomon(enum wlr_direction dir) {
struct wlr_output *next;
if (!wlr_output_layout_get(output_layout, selmon->wlr_output))
return selmon;
if ((next = wlr_output_layout_adjacent_output(output_layout, 1 << dir,
selmon->wlr_output,
selmon->m.x, selmon->m.y)))
return next->data;
if ((next = wlr_output_layout_farthest_output(
output_layout,
dir ^ (WLR_DIRECTION_LEFT | WLR_DIRECTION_RIGHT |
WLR_DIRECTION_UP | WLR_DIRECTION_DOWN),
selmon->wlr_output, selmon->m.x, selmon->m.y)))
return next->data;
return selmon;
}
void focusclient(Client *c, int lift) {
struct wlr_surface *old_keyboard_focus_surface =
seat->keyboard_state.focused_surface;
@ -3316,21 +2924,6 @@ void focusclient(Client *c, int lift) {
client_activate_surface(client_surface(c), 1);
}
/* We probably should change the name of this, it sounds like
* will focus the topmost client of this mon, when actually will
* only return that client */
Client * // 0.5
focustop(Monitor *m) {
Client *c;
wl_list_for_each(c, &fstack, flink) {
if (c->iskilling || c->isunglobal)
continue;
if (VISIBLEON(c, m))
return c;
}
return NULL;
}
void // 0.6
fullscreennotify(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, fullscreen);
@ -4537,62 +4130,6 @@ void setgaps(int oh, int ov, int ih, int iv) {
arrange(selmon, false);
}
char *get_layout_abbr(const char *full_name) {
// 1. 尝试在映射表中查找
for (int i = 0; layout_mappings[i].full_name != NULL; i++) {
if (strcmp(full_name, layout_mappings[i].full_name) == 0) {
return strdup(layout_mappings[i].abbr);
}
}
// 2. 尝试从名称中提取并转换为小写
const char *open = strrchr(full_name, '(');
const char *close = strrchr(full_name, ')');
if (open && close && close > open) {
unsigned int len = close - open - 1;
if (len > 0 && len <= 4) {
char *abbr = malloc(len + 1);
if (abbr) {
// 提取并转换为小写
for (unsigned int j = 0; j < len; j++) {
abbr[j] = tolower(open[j + 1]);
}
abbr[len] = '\0';
return abbr;
}
}
}
// 3. 提取前2-3个字母并转换为小写
char *abbr = malloc(4);
if (abbr) {
unsigned int j = 0;
for (unsigned int i = 0; full_name[i] != '\0' && j < 3; i++) {
if (isalpha(full_name[i])) {
abbr[j++] = tolower(full_name[i]);
}
}
abbr[j] = '\0';
// 确保至少2个字符
if (j >= 2)
return abbr;
free(abbr);
}
// 4. 回退方案:使用首字母小写
char *fallback = malloc(3);
if (fallback) {
fallback[0] = tolower(full_name[0]);
fallback[1] = full_name[1] ? tolower(full_name[1]) : '\0';
fallback[2] = '\0';
return fallback;
}
// 5. 最终回退:返回 "xx"
return strdup("xx");
}
void reset_keyboard_layout(void) {
if (!kb_group || !kb_group->wlr_group || !seat) {
wlr_log(WLR_ERROR, "Invalid keyboard group or seat");
@ -4738,28 +4275,6 @@ void setsel(struct wl_listener *listener, void *data) {
wlr_seat_set_selection(seat, event->source, event->serial);
}
// 获取tags中最前面的tag的tagmask
unsigned int get_tags_first_tag(unsigned int source_tags) {
unsigned int i, tag;
tag = 0;
if (!source_tags) {
return selmon->pertag->curtag;
}
for (i = 0; !(tag & 1) && source_tags != 0 && i < LENGTH(tags); i++) {
tag = source_tags >> i;
}
if (i == 1) {
return 1;
} else if (i > 9) {
return 1 << 8;
} else {
return 1 << (i - 1);
}
}
void show_hide_client(Client *c) {
unsigned int target = get_tags_first_tag(c->oldtags);
tag_client(&(Arg){.ui = target}, c);
@ -5621,52 +5136,6 @@ void virtualpointer(struct wl_listener *listener, void *data) {
handlecursoractivity();
}
Monitor *xytomon(double x, double y) {
struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
return o ? o->data : NULL;
}
void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
LayerSurface **pl, double *nx, double *ny) {
struct wlr_scene_node *node, *pnode;
struct wlr_surface *surface = NULL;
Client *c = NULL;
LayerSurface *l = NULL;
int layer;
for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
// ignore text-input layer
if (layer == LyrIMPopup)
continue;
if (layer == LyrFadeOut)
continue;
if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
continue;
if (node->type == WLR_SCENE_NODE_BUFFER)
surface = wlr_scene_surface_try_from_buffer(
wlr_scene_buffer_from_node(node))
->surface;
/* Walk the tree to find a node that knows the client */
for (pnode = node; pnode && !c; pnode = &pnode->parent->node)
c = pnode->data;
if (c && c->type == LayerShell) {
c = NULL;
l = pnode->data;
}
}
if (psurface)
*psurface = surface;
if (pc)
*pc = c;
if (pl)
*pl = l;
}
#ifdef XWAYLAND
void activatex11(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, activate);