mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-07-11 11:05:00 -04:00
testsplit
This commit is contained in:
parent
21a492e961
commit
63276d1bee
33 changed files with 10562 additions and 10243 deletions
|
|
@ -96,7 +96,16 @@ endif
|
||||||
|
|
||||||
executable('mango',
|
executable('mango',
|
||||||
'src/mango.c',
|
'src/mango.c',
|
||||||
|
'src/animation/client.c',
|
||||||
|
'src/animation/common.c',
|
||||||
|
'src/animation/layer.c',
|
||||||
|
'src/animation/tag.c',
|
||||||
|
'src/client/client.c',
|
||||||
|
'src/layout/arrange.c',
|
||||||
|
'src/layout/layout.c',
|
||||||
'src/common/util.c',
|
'src/common/util.c',
|
||||||
|
'src/config/parse_config.c',
|
||||||
|
'src/dispatch/bind_define.c',
|
||||||
'src/ext-protocol/wlr_ext_workspace_v1.c',
|
'src/ext-protocol/wlr_ext_workspace_v1.c',
|
||||||
wayland_sources,
|
wayland_sources,
|
||||||
dependencies : [
|
dependencies : [
|
||||||
|
|
|
||||||
134
mmsg/mmsg.c
134
mmsg/mmsg.c
|
|
@ -18,71 +18,71 @@
|
||||||
|
|
||||||
char *argv0;
|
char *argv0;
|
||||||
|
|
||||||
static enum {
|
enum {
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
SET = 1 << 0,
|
SET = 1 << 0,
|
||||||
GET = 1 << 1,
|
GET = 1 << 1,
|
||||||
WATCH = 1 << 2 | GET,
|
WATCH = 1 << 2 | GET,
|
||||||
} mode = NONE;
|
} mode = NONE;
|
||||||
|
|
||||||
static int32_t Oflag;
|
int32_t Oflag;
|
||||||
static int32_t Tflag;
|
int32_t Tflag;
|
||||||
static int32_t Lflag;
|
int32_t Lflag;
|
||||||
static int32_t oflag;
|
int32_t oflag;
|
||||||
static int32_t tflag;
|
int32_t tflag;
|
||||||
static int32_t lflag;
|
int32_t lflag;
|
||||||
static int32_t cflag;
|
int32_t cflag;
|
||||||
static int32_t vflag;
|
int32_t vflag;
|
||||||
static int32_t mflag;
|
int32_t mflag;
|
||||||
static int32_t fflag;
|
int32_t fflag;
|
||||||
static int32_t qflag;
|
int32_t qflag;
|
||||||
static int32_t dflag;
|
int32_t dflag;
|
||||||
static int32_t xflag;
|
int32_t xflag;
|
||||||
static int32_t eflag;
|
int32_t eflag;
|
||||||
static int32_t kflag;
|
int32_t kflag;
|
||||||
static int32_t bflag;
|
int32_t bflag;
|
||||||
static int32_t Aflag;
|
int32_t Aflag;
|
||||||
|
|
||||||
static uint32_t occ, seltags, total_clients, urg;
|
uint32_t occ, seltags, total_clients, urg;
|
||||||
|
|
||||||
static char *output_name;
|
char *output_name;
|
||||||
static int32_t tagcount;
|
int32_t tagcount;
|
||||||
static char *tagset;
|
char *tagset;
|
||||||
static char *layout_name;
|
char *layout_name;
|
||||||
static int32_t layoutcount, layout_idx;
|
int32_t layoutcount, layout_idx;
|
||||||
static char *client_tags;
|
char *client_tags;
|
||||||
static char *dispatch_cmd;
|
char *dispatch_cmd;
|
||||||
static char *dispatch_arg1;
|
char *dispatch_arg1;
|
||||||
static char *dispatch_arg2;
|
char *dispatch_arg2;
|
||||||
static char *dispatch_arg3;
|
char *dispatch_arg3;
|
||||||
static char *dispatch_arg4;
|
char *dispatch_arg4;
|
||||||
static char *dispatch_arg5;
|
char *dispatch_arg5;
|
||||||
|
|
||||||
struct output {
|
struct output {
|
||||||
char *output_name;
|
char *output_name;
|
||||||
uint32_t name;
|
uint32_t name;
|
||||||
};
|
};
|
||||||
static DYNARR_DEF(struct output) outputs;
|
DYNARR_DEF(struct output) outputs;
|
||||||
|
|
||||||
static struct wl_display *display;
|
struct wl_display *display;
|
||||||
static struct zdwl_ipc_manager_v2 *dwl_ipc_manager;
|
struct zdwl_ipc_manager_v2 *dwl_ipc_manager;
|
||||||
|
|
||||||
// 为每个回调定义专用的空函数
|
// 为每个回调定义专用的空函数
|
||||||
static void noop_geometry(void *data, struct wl_output *wl_output, int32_t x,
|
void noop_geometry(void *data, struct wl_output *wl_output, int32_t x,
|
||||||
int32_t y, int32_t physical_width,
|
int32_t y, int32_t physical_width,
|
||||||
int32_t physical_height, int32_t subpixel,
|
int32_t physical_height, int32_t subpixel,
|
||||||
const char *make, const char *model,
|
const char *make, const char *model,
|
||||||
int32_t transform) {}
|
int32_t transform) {}
|
||||||
|
|
||||||
static void noop_mode(void *data, struct wl_output *wl_output, uint32_t flags,
|
void noop_mode(void *data, struct wl_output *wl_output, uint32_t flags,
|
||||||
int32_t width, int32_t height, int32_t refresh) {}
|
int32_t width, int32_t height, int32_t refresh) {}
|
||||||
|
|
||||||
static void noop_done(void *data, struct wl_output *wl_output) {}
|
void noop_done(void *data, struct wl_output *wl_output) {}
|
||||||
|
|
||||||
static void noop_scale(void *data, struct wl_output *wl_output,
|
void noop_scale(void *data, struct wl_output *wl_output,
|
||||||
int32_t factor) {}
|
int32_t factor) {}
|
||||||
|
|
||||||
static void noop_description(void *data, struct wl_output *wl_output,
|
void noop_description(void *data, struct wl_output *wl_output,
|
||||||
const char *description) {}
|
const char *description) {}
|
||||||
|
|
||||||
// 将 n 转换为 9 位二进制字符串,结果存入 buf(至少长度 10)
|
// 将 n 转换为 9 位二进制字符串,结果存入 buf(至少长度 10)
|
||||||
|
|
@ -93,7 +93,7 @@ void bin_str_9bits(char *buf, uint32_t n) {
|
||||||
*buf = '\0'; // 字符串结尾
|
*buf = '\0'; // 字符串结尾
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_tags(void *data,
|
void dwl_ipc_tags(void *data,
|
||||||
struct zdwl_ipc_manager_v2 *dwl_ipc_manager,
|
struct zdwl_ipc_manager_v2 *dwl_ipc_manager,
|
||||||
uint32_t count) {
|
uint32_t count) {
|
||||||
tagcount = count;
|
tagcount = count;
|
||||||
|
|
@ -101,7 +101,7 @@ static void dwl_ipc_tags(void *data,
|
||||||
printf("%d\n", tagcount);
|
printf("%d\n", tagcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_layout(void *data,
|
void dwl_ipc_layout(void *data,
|
||||||
struct zdwl_ipc_manager_v2 *dwl_ipc_manager,
|
struct zdwl_ipc_manager_v2 *dwl_ipc_manager,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
if (lflag && mode & SET && strcmp(layout_name, name) == 0)
|
if (lflag && mode & SET && strcmp(layout_name, name) == 0)
|
||||||
|
|
@ -111,10 +111,10 @@ static void dwl_ipc_layout(void *data,
|
||||||
layoutcount++;
|
layoutcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zdwl_ipc_manager_v2_listener dwl_ipc_listener = {
|
const struct zdwl_ipc_manager_v2_listener dwl_ipc_listener = {
|
||||||
.tags = dwl_ipc_tags, .layout = dwl_ipc_layout};
|
.tags = dwl_ipc_tags, .layout = dwl_ipc_layout};
|
||||||
|
|
||||||
static void
|
void
|
||||||
dwl_ipc_output_toggle_visibility(void *data,
|
dwl_ipc_output_toggle_visibility(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output) {
|
struct zdwl_ipc_output_v2 *dwl_ipc_output) {
|
||||||
if (!vflag)
|
if (!vflag)
|
||||||
|
|
@ -125,7 +125,7 @@ dwl_ipc_output_toggle_visibility(void *data,
|
||||||
printf("toggle\n");
|
printf("toggle\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_active(void *data,
|
void dwl_ipc_output_active(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
uint32_t active) {
|
uint32_t active) {
|
||||||
if (!oflag) {
|
if (!oflag) {
|
||||||
|
|
@ -139,7 +139,7 @@ static void dwl_ipc_output_active(void *data,
|
||||||
printf("selmon %u\n", active ? 1 : 0);
|
printf("selmon %u\n", active ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_tag(void *data,
|
void dwl_ipc_output_tag(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
uint32_t tag, uint32_t state, uint32_t clients,
|
uint32_t tag, uint32_t state, uint32_t clients,
|
||||||
uint32_t focused) {
|
uint32_t focused) {
|
||||||
|
|
@ -163,11 +163,11 @@ static void dwl_ipc_output_tag(void *data,
|
||||||
printf("tag %u %u %u %u\n", tag + 1, state, clients, focused);
|
printf("tag %u %u %u %u\n", tag + 1, state, clients, focused);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_layout(void *data,
|
void dwl_ipc_output_layout(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
uint32_t layout) {}
|
uint32_t layout) {}
|
||||||
|
|
||||||
static void dwl_ipc_output_layout_symbol(
|
void dwl_ipc_output_layout_symbol(
|
||||||
void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, const char *layout) {
|
void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, const char *layout) {
|
||||||
if (!(lflag && mode & GET))
|
if (!(lflag && mode & GET))
|
||||||
return;
|
return;
|
||||||
|
|
@ -177,7 +177,7 @@ static void dwl_ipc_output_layout_symbol(
|
||||||
printf("layout %s\n", layout);
|
printf("layout %s\n", layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_title(void *data,
|
void dwl_ipc_output_title(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
const char *title) {
|
const char *title) {
|
||||||
if (!(cflag && mode & GET))
|
if (!(cflag && mode & GET))
|
||||||
|
|
@ -188,7 +188,7 @@ static void dwl_ipc_output_title(void *data,
|
||||||
printf("title %s\n", title);
|
printf("title %s\n", title);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_appid(void *data,
|
void dwl_ipc_output_appid(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
const char *appid) {
|
const char *appid) {
|
||||||
if (!(cflag && mode & GET))
|
if (!(cflag && mode & GET))
|
||||||
|
|
@ -199,7 +199,7 @@ static void dwl_ipc_output_appid(void *data,
|
||||||
printf("appid %s\n", appid);
|
printf("appid %s\n", appid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_x(void *data,
|
void dwl_ipc_output_x(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
int32_t x) {
|
int32_t x) {
|
||||||
if (!xflag)
|
if (!xflag)
|
||||||
|
|
@ -210,7 +210,7 @@ static void dwl_ipc_output_x(void *data,
|
||||||
printf("x %d\n", x);
|
printf("x %d\n", x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_y(void *data,
|
void dwl_ipc_output_y(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
int32_t y) {
|
int32_t y) {
|
||||||
if (!xflag)
|
if (!xflag)
|
||||||
|
|
@ -221,7 +221,7 @@ static void dwl_ipc_output_y(void *data,
|
||||||
printf("y %d\n", y);
|
printf("y %d\n", y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_width(void *data,
|
void dwl_ipc_output_width(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
int32_t width) {
|
int32_t width) {
|
||||||
if (!xflag)
|
if (!xflag)
|
||||||
|
|
@ -232,7 +232,7 @@ static void dwl_ipc_output_width(void *data,
|
||||||
printf("width %d\n", width);
|
printf("width %d\n", width);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_height(void *data,
|
void dwl_ipc_output_height(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
int32_t height) {
|
int32_t height) {
|
||||||
if (!xflag)
|
if (!xflag)
|
||||||
|
|
@ -243,7 +243,7 @@ static void dwl_ipc_output_height(void *data,
|
||||||
printf("height %d\n", height);
|
printf("height %d\n", height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_last_layer(void *data,
|
void dwl_ipc_output_last_layer(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
const char *last_layer) {
|
const char *last_layer) {
|
||||||
if (!eflag)
|
if (!eflag)
|
||||||
|
|
@ -254,7 +254,7 @@ static void dwl_ipc_output_last_layer(void *data,
|
||||||
printf("last_layer %s\n", last_layer);
|
printf("last_layer %s\n", last_layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_kb_layout(void *data,
|
void dwl_ipc_output_kb_layout(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
const char *kb_layout) {
|
const char *kb_layout) {
|
||||||
if (!kflag)
|
if (!kflag)
|
||||||
|
|
@ -265,7 +265,7 @@ static void dwl_ipc_output_kb_layout(void *data,
|
||||||
printf("kb_layout %s\n", kb_layout);
|
printf("kb_layout %s\n", kb_layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
dwl_ipc_output_scalefactor(void *data,
|
dwl_ipc_output_scalefactor(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
const uint32_t scalefactor) {
|
const uint32_t scalefactor) {
|
||||||
|
|
@ -277,7 +277,7 @@ dwl_ipc_output_scalefactor(void *data,
|
||||||
printf("scale_factor %f\n", scalefactor / 100.0f);
|
printf("scale_factor %f\n", scalefactor / 100.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_keymode(void *data,
|
void dwl_ipc_output_keymode(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
const char *keymode) {
|
const char *keymode) {
|
||||||
if (!bflag)
|
if (!bflag)
|
||||||
|
|
@ -288,7 +288,7 @@ static void dwl_ipc_output_keymode(void *data,
|
||||||
printf("keymode %s\n", keymode);
|
printf("keymode %s\n", keymode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_fullscreen(void *data,
|
void dwl_ipc_output_fullscreen(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
uint32_t is_fullscreen) {
|
uint32_t is_fullscreen) {
|
||||||
if (!mflag)
|
if (!mflag)
|
||||||
|
|
@ -299,7 +299,7 @@ static void dwl_ipc_output_fullscreen(void *data,
|
||||||
printf("fullscreen %u\n", is_fullscreen);
|
printf("fullscreen %u\n", is_fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_floating(void *data,
|
void dwl_ipc_output_floating(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
struct zdwl_ipc_output_v2 *dwl_ipc_output,
|
||||||
uint32_t is_floating) {
|
uint32_t is_floating) {
|
||||||
if (!fflag)
|
if (!fflag)
|
||||||
|
|
@ -310,7 +310,7 @@ static void dwl_ipc_output_floating(void *data,
|
||||||
printf("floating %u\n", is_floating);
|
printf("floating %u\n", is_floating);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_frame(void *data,
|
void dwl_ipc_output_frame(void *data,
|
||||||
struct zdwl_ipc_output_v2 *dwl_ipc_output) {
|
struct zdwl_ipc_output_v2 *dwl_ipc_output) {
|
||||||
if (mode & SET) {
|
if (mode & SET) {
|
||||||
if (data && (!output_name || strcmp(output_name, (char *)data)))
|
if (data && (!output_name || strcmp(output_name, (char *)data)))
|
||||||
|
|
@ -409,7 +409,7 @@ static void dwl_ipc_output_frame(void *data,
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zdwl_ipc_output_v2_listener dwl_ipc_output_listener = {
|
const struct zdwl_ipc_output_v2_listener dwl_ipc_output_listener = {
|
||||||
.toggle_visibility = dwl_ipc_output_toggle_visibility,
|
.toggle_visibility = dwl_ipc_output_toggle_visibility,
|
||||||
.active = dwl_ipc_output_active,
|
.active = dwl_ipc_output_active,
|
||||||
.tag = dwl_ipc_output_tag,
|
.tag = dwl_ipc_output_tag,
|
||||||
|
|
@ -430,7 +430,7 @@ static const struct zdwl_ipc_output_v2_listener dwl_ipc_output_listener = {
|
||||||
.frame = dwl_ipc_output_frame,
|
.frame = dwl_ipc_output_frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void wl_output_name(void *data, struct wl_output *output,
|
void wl_output_name(void *data, struct wl_output *output,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
if (outputs.arr) {
|
if (outputs.arr) {
|
||||||
struct output *o = (struct output *)data;
|
struct output *o = (struct output *)data;
|
||||||
|
|
@ -449,7 +449,7 @@ static void wl_output_name(void *data, struct wl_output *output,
|
||||||
output_name ? NULL : strdup(name));
|
output_name ? NULL : strdup(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_output_listener output_listener = {
|
const struct wl_output_listener output_listener = {
|
||||||
.geometry = noop_geometry,
|
.geometry = noop_geometry,
|
||||||
.mode = noop_mode,
|
.mode = noop_mode,
|
||||||
.done = noop_done,
|
.done = noop_done,
|
||||||
|
|
@ -458,7 +458,7 @@ static const struct wl_output_listener output_listener = {
|
||||||
.description = noop_description,
|
.description = noop_description,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void global_add(void *data, struct wl_registry *wl_registry,
|
void global_add(void *data, struct wl_registry *wl_registry,
|
||||||
uint32_t name, const char *interface, uint32_t version) {
|
uint32_t name, const char *interface, uint32_t version) {
|
||||||
if (strcmp(interface, wl_output_interface.name) == 0) {
|
if (strcmp(interface, wl_output_interface.name) == 0) {
|
||||||
struct wl_output *o =
|
struct wl_output *o =
|
||||||
|
|
@ -479,7 +479,7 @@ static void global_add(void *data, struct wl_registry *wl_registry,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void global_remove(void *data, struct wl_registry *wl_registry,
|
void global_remove(void *data, struct wl_registry *wl_registry,
|
||||||
uint32_t name) {
|
uint32_t name) {
|
||||||
if (!outputs.arr)
|
if (!outputs.arr)
|
||||||
return;
|
return;
|
||||||
|
|
@ -493,12 +493,12 @@ static void global_remove(void *data, struct wl_registry *wl_registry,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_registry_listener registry_listener = {
|
const struct wl_registry_listener registry_listener = {
|
||||||
.global = global_add,
|
.global = global_add,
|
||||||
.global_remove = global_remove,
|
.global_remove = global_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void usage(void) {
|
void usage(void) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"usage:"
|
"usage:"
|
||||||
"\t%s [-OTLq]\n"
|
"\t%s [-OTLq]\n"
|
||||||
|
|
|
||||||
1206
src/animation/client.c
Normal file
1206
src/animation/client.c
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
270
src/animation/common.c
Normal file
270
src/animation/common.c
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
#include "../type.h"
|
||||||
|
|
||||||
|
extern Server server;
|
||||||
|
|
||||||
|
struct dvec2 calculate_animation_curve_at(double t, int32_t type) {
|
||||||
|
struct dvec2 point;
|
||||||
|
double *animation_curve;
|
||||||
|
if (type == MOVE) {
|
||||||
|
animation_curve = animation_curve_move;
|
||||||
|
} else if (type == OPEN) {
|
||||||
|
animation_curve = animation_curve_open;
|
||||||
|
} else if (type == TAG) {
|
||||||
|
animation_curve = animation_curve_tag;
|
||||||
|
} else if (type == CLOSE) {
|
||||||
|
animation_curve = animation_curve_close;
|
||||||
|
} else if (type == FOCUS) {
|
||||||
|
animation_curve = animation_curve_focus;
|
||||||
|
} else if (type == OPAFADEIN) {
|
||||||
|
animation_curve = animation_curve_opafadein;
|
||||||
|
} else if (type == OPAFADEOUT) {
|
||||||
|
animation_curve = animation_curve_opafadeout;
|
||||||
|
} else {
|
||||||
|
animation_curve = animation_curve_move;
|
||||||
|
}
|
||||||
|
|
||||||
|
point.x = 3 * t * (1 - t) * (1 - t) * animation_curve[0] +
|
||||||
|
3 * t * t * (1 - t) * animation_curve[2] + t * t * t;
|
||||||
|
|
||||||
|
point.y = 3 * t * (1 - t) * (1 - t) * animation_curve[1] +
|
||||||
|
3 * t * t * (1 - t) * animation_curve[3] + t * t * t;
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_baked_points(void) {
|
||||||
|
server.baked_points_move =
|
||||||
|
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_move));
|
||||||
|
server.baked_points_open =
|
||||||
|
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_open));
|
||||||
|
server.baked_points_tag =
|
||||||
|
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_tag));
|
||||||
|
server.baked_points_close =
|
||||||
|
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_close));
|
||||||
|
server.baked_points_focus =
|
||||||
|
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_focus));
|
||||||
|
server.baked_points_opafadein =
|
||||||
|
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_opafadein));
|
||||||
|
server.baked_points_opafadeout =
|
||||||
|
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_opafadeout));
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
|
server.baked_points_move[i] = calculate_animation_curve_at(
|
||||||
|
(double)i / (BAKED_POINTS_COUNT - 1), MOVE);
|
||||||
|
}
|
||||||
|
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
|
server.baked_points_open[i] = calculate_animation_curve_at(
|
||||||
|
(double)i / (BAKED_POINTS_COUNT - 1), OPEN);
|
||||||
|
}
|
||||||
|
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
|
server.baked_points_tag[i] = calculate_animation_curve_at(
|
||||||
|
(double)i / (BAKED_POINTS_COUNT - 1), TAG);
|
||||||
|
}
|
||||||
|
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
|
server.baked_points_close[i] = calculate_animation_curve_at(
|
||||||
|
(double)i / (BAKED_POINTS_COUNT - 1), CLOSE);
|
||||||
|
}
|
||||||
|
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
|
server.baked_points_focus[i] = calculate_animation_curve_at(
|
||||||
|
(double)i / (BAKED_POINTS_COUNT - 1), FOCUS);
|
||||||
|
}
|
||||||
|
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
|
server.baked_points_opafadein[i] = calculate_animation_curve_at(
|
||||||
|
(double)i / (BAKED_POINTS_COUNT - 1), OPAFADEIN);
|
||||||
|
}
|
||||||
|
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
|
server.baked_points_opafadeout[i] = calculate_animation_curve_at(
|
||||||
|
(double)i / (BAKED_POINTS_COUNT - 1), OPAFADEOUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double find_animation_curve_at(double t, int32_t type) {
|
||||||
|
int32_t down = 0;
|
||||||
|
int32_t up = BAKED_POINTS_COUNT - 1;
|
||||||
|
|
||||||
|
int32_t middle = (up + down) / 2;
|
||||||
|
struct dvec2 *baked_points;
|
||||||
|
if (type == MOVE) {
|
||||||
|
baked_points = server.baked_points_move;
|
||||||
|
} else if (type == OPEN) {
|
||||||
|
baked_points = server.baked_points_open;
|
||||||
|
} else if (type == TAG) {
|
||||||
|
baked_points = server.baked_points_tag;
|
||||||
|
} else if (type == CLOSE) {
|
||||||
|
baked_points = server.baked_points_close;
|
||||||
|
} else if (type == FOCUS) {
|
||||||
|
baked_points = server.baked_points_focus;
|
||||||
|
} else if (type == OPAFADEIN) {
|
||||||
|
baked_points = server.baked_points_opafadein;
|
||||||
|
} else if (type == OPAFADEOUT) {
|
||||||
|
baked_points = server.baked_points_opafadeout;
|
||||||
|
} else {
|
||||||
|
baked_points = server.baked_points_move;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (up - down != 1) {
|
||||||
|
if (baked_points[middle].x <= t) {
|
||||||
|
down = middle;
|
||||||
|
} else {
|
||||||
|
up = middle;
|
||||||
|
}
|
||||||
|
middle = (up + down) / 2;
|
||||||
|
}
|
||||||
|
return baked_points[up].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
||||||
|
int32_t ly,
|
||||||
|
struct wlr_scene_tree *snapshot_tree) {
|
||||||
|
if (!node->enabled && node->type != WLR_SCENE_NODE_TREE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
lx += node->x;
|
||||||
|
ly += node->y;
|
||||||
|
|
||||||
|
struct wlr_scene_node *snapshot_node = NULL;
|
||||||
|
switch (node->type) {
|
||||||
|
case WLR_SCENE_NODE_TREE: {
|
||||||
|
struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node);
|
||||||
|
|
||||||
|
struct wlr_scene_node *child;
|
||||||
|
wl_list_for_each(child, &scene_tree->children, link) {
|
||||||
|
scene_node_snapshot(child, lx, ly, snapshot_tree);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WLR_SCENE_NODE_RECT: {
|
||||||
|
// struct wlr_scene_rect *scene_rect = wlr_scene_rect_from_node(node);
|
||||||
|
|
||||||
|
// struct wlr_scene_rect *snapshot_rect =
|
||||||
|
// wlr_scene_rect_create(snapshot_tree, scene_rect->width,
|
||||||
|
// scene_rect->height, scene_rect->color);
|
||||||
|
// snapshot_rect->node.data = scene_rect->node.data;
|
||||||
|
// if (snapshot_rect == NULL) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// wlr_scene_rect_set_clipped_region(scene_rect,
|
||||||
|
// snapshot_rect->clipped_region);
|
||||||
|
// wlr_scene_rect_set_backdrop_blur(scene_rect, false);
|
||||||
|
// wlr_scene_rect_set_backdrop_blur_optimized(
|
||||||
|
// scene_rect, snapshot_rect->backdrop_blur_optimized);
|
||||||
|
// wlr_scene_rect_set_corner_radius(
|
||||||
|
// scene_rect, snapshot_rect->corner_radius, snapshot_rect->corners);
|
||||||
|
// wlr_scene_rect_set_color(scene_rect, snapshot_rect->color);
|
||||||
|
|
||||||
|
// snapshot_node = &snapshot_rect->node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WLR_SCENE_NODE_BUFFER: {
|
||||||
|
struct wlr_scene_buffer *scene_buffer =
|
||||||
|
wlr_scene_buffer_from_node(node);
|
||||||
|
|
||||||
|
struct wlr_scene_buffer *snapshot_buffer =
|
||||||
|
wlr_scene_buffer_create(snapshot_tree, NULL);
|
||||||
|
if (snapshot_buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
snapshot_node = &snapshot_buffer->node;
|
||||||
|
snapshot_buffer->node.data = scene_buffer->node.data;
|
||||||
|
|
||||||
|
wlr_scene_buffer_set_dest_size(snapshot_buffer, scene_buffer->dst_width,
|
||||||
|
scene_buffer->dst_height);
|
||||||
|
wlr_scene_buffer_set_opaque_region(snapshot_buffer,
|
||||||
|
&scene_buffer->opaque_region);
|
||||||
|
wlr_scene_buffer_set_source_box(snapshot_buffer,
|
||||||
|
&scene_buffer->src_box);
|
||||||
|
wlr_scene_buffer_set_transform(snapshot_buffer,
|
||||||
|
scene_buffer->transform);
|
||||||
|
wlr_scene_buffer_set_filter_mode(snapshot_buffer,
|
||||||
|
scene_buffer->filter_mode);
|
||||||
|
|
||||||
|
// 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_optimized(
|
||||||
|
// snapshot_buffer, scene_buffer->backdrop_blur_optimized);
|
||||||
|
// wlr_scene_buffer_set_backdrop_blur_ignore_transparent(
|
||||||
|
// snapshot_buffer, scene_buffer->backdrop_blur_ignore_transparent);
|
||||||
|
wlr_scene_buffer_set_backdrop_blur(snapshot_buffer, false);
|
||||||
|
|
||||||
|
snapshot_buffer->node.data = scene_buffer->node.data;
|
||||||
|
|
||||||
|
struct wlr_scene_surface *scene_surface =
|
||||||
|
wlr_scene_surface_try_from_buffer(scene_buffer);
|
||||||
|
if (scene_surface != NULL && scene_surface->surface->buffer != NULL) {
|
||||||
|
wlr_scene_buffer_set_buffer(snapshot_buffer,
|
||||||
|
&scene_surface->surface->buffer->base);
|
||||||
|
} else {
|
||||||
|
wlr_scene_buffer_set_buffer(snapshot_buffer, scene_buffer->buffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WLR_SCENE_NODE_SHADOW: {
|
||||||
|
struct wlr_scene_shadow *scene_shadow =
|
||||||
|
wlr_scene_shadow_from_node(node);
|
||||||
|
|
||||||
|
struct wlr_scene_shadow *snapshot_shadow = wlr_scene_shadow_create(
|
||||||
|
snapshot_tree, scene_shadow->width, scene_shadow->height,
|
||||||
|
scene_shadow->corner_radius, scene_shadow->blur_sigma,
|
||||||
|
scene_shadow->color);
|
||||||
|
if (snapshot_shadow == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
snapshot_node = &snapshot_shadow->node;
|
||||||
|
|
||||||
|
wlr_scene_shadow_set_clipped_region(snapshot_shadow,
|
||||||
|
scene_shadow->clipped_region);
|
||||||
|
|
||||||
|
snapshot_shadow->node.data = scene_shadow->node.data;
|
||||||
|
|
||||||
|
wlr_scene_node_set_enabled(&snapshot_shadow->node, false);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WLR_SCENE_NODE_OPTIMIZED_BLUR:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot_node != NULL) {
|
||||||
|
wlr_scene_node_set_position(snapshot_node, lx, ly);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_scene_tree *wlr_scene_tree_snapshot(struct wlr_scene_node *node,
|
||||||
|
struct wlr_scene_tree *parent) {
|
||||||
|
struct wlr_scene_tree *snapshot = wlr_scene_tree_create(parent);
|
||||||
|
if (snapshot == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable and enable the snapshot tree like so to atomically update
|
||||||
|
// the server.scene -graph. This will prevent over-damaging or other
|
||||||
|
// weirdness.
|
||||||
|
wlr_scene_node_set_enabled(&snapshot->node, false);
|
||||||
|
|
||||||
|
if (!scene_node_snapshot(node, 0, 0, snapshot)) {
|
||||||
|
wlr_scene_node_destroy(&snapshot->node);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_scene_node_set_enabled(&snapshot->node, true);
|
||||||
|
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void request_fresh_all_monitors(void) {
|
||||||
|
Monitor *m = NULL;
|
||||||
|
wl_list_for_each(m, &server.mons, link) {
|
||||||
|
if (!m->wlr_output->enabled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
wlr_output_schedule_frame(m->wlr_output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,266 +1,16 @@
|
||||||
struct dvec2 calculate_animation_curve_at(double t, int32_t type) {
|
#ifndef MANGO_ANIMATION_COMMON_H
|
||||||
struct dvec2 point;
|
#define MANGO_ANIMATION_COMMON_H
|
||||||
double *animation_curve;
|
|
||||||
if (type == MOVE) {
|
|
||||||
animation_curve = animation_curve_move;
|
|
||||||
} else if (type == OPEN) {
|
|
||||||
animation_curve = animation_curve_open;
|
|
||||||
} else if (type == TAG) {
|
|
||||||
animation_curve = animation_curve_tag;
|
|
||||||
} else if (type == CLOSE) {
|
|
||||||
animation_curve = animation_curve_close;
|
|
||||||
} else if (type == FOCUS) {
|
|
||||||
animation_curve = animation_curve_focus;
|
|
||||||
} else if (type == OPAFADEIN) {
|
|
||||||
animation_curve = animation_curve_opafadein;
|
|
||||||
} else if (type == OPAFADEOUT) {
|
|
||||||
animation_curve = animation_curve_opafadeout;
|
|
||||||
} else {
|
|
||||||
animation_curve = animation_curve_move;
|
|
||||||
}
|
|
||||||
|
|
||||||
point.x = 3 * t * (1 - t) * (1 - t) * animation_curve[0] +
|
// 动画曲线相关函数
|
||||||
3 * t * t * (1 - t) * animation_curve[2] + t * t * t;
|
struct dvec2 calculate_animation_curve_at(double t, int32_t type);
|
||||||
|
void init_baked_points(void);
|
||||||
|
double find_animation_curve_at(double t, int32_t type);
|
||||||
|
|
||||||
point.y = 3 * t * (1 - t) * (1 - t) * animation_curve[1] +
|
// 场景快照函数
|
||||||
3 * t * t * (1 - t) * animation_curve[3] + t * t * t;
|
bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx, int32_t ly, struct wlr_scene_tree *snapshot_tree);
|
||||||
|
struct wlr_scene_tree *wlr_scene_tree_snapshot(struct wlr_scene_node *node, struct wlr_scene_tree *parent);
|
||||||
|
|
||||||
return point;
|
// 屏幕刷新函数
|
||||||
}
|
void request_fresh_all_monitors(void);
|
||||||
|
|
||||||
void init_baked_points(void) {
|
#endif // MANGO_ANIMATION_COMMON_H
|
||||||
server.baked_points_move =
|
|
||||||
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_move));
|
|
||||||
server.baked_points_open =
|
|
||||||
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_open));
|
|
||||||
server.baked_points_tag =
|
|
||||||
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_tag));
|
|
||||||
server.baked_points_close =
|
|
||||||
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_close));
|
|
||||||
server.baked_points_focus =
|
|
||||||
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_focus));
|
|
||||||
server.baked_points_opafadein =
|
|
||||||
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_opafadein));
|
|
||||||
server.baked_points_opafadeout =
|
|
||||||
calloc(BAKED_POINTS_COUNT, sizeof(*server.baked_points_opafadeout));
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
|
||||||
server.baked_points_move[i] = calculate_animation_curve_at(
|
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), MOVE);
|
|
||||||
}
|
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
|
||||||
server.baked_points_open[i] = calculate_animation_curve_at(
|
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), OPEN);
|
|
||||||
}
|
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
|
||||||
server.baked_points_tag[i] = calculate_animation_curve_at(
|
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), TAG);
|
|
||||||
}
|
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
|
||||||
server.baked_points_close[i] = calculate_animation_curve_at(
|
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), CLOSE);
|
|
||||||
}
|
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
|
||||||
server.baked_points_focus[i] = calculate_animation_curve_at(
|
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), FOCUS);
|
|
||||||
}
|
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
|
||||||
server.baked_points_opafadein[i] = calculate_animation_curve_at(
|
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), OPAFADEIN);
|
|
||||||
}
|
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
|
||||||
server.baked_points_opafadeout[i] = calculate_animation_curve_at(
|
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), OPAFADEOUT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double find_animation_curve_at(double t, int32_t type) {
|
|
||||||
int32_t down = 0;
|
|
||||||
int32_t up = BAKED_POINTS_COUNT - 1;
|
|
||||||
|
|
||||||
int32_t middle = (up + down) / 2;
|
|
||||||
struct dvec2 *baked_points;
|
|
||||||
if (type == MOVE) {
|
|
||||||
baked_points = server.baked_points_move;
|
|
||||||
} else if (type == OPEN) {
|
|
||||||
baked_points = server.baked_points_open;
|
|
||||||
} else if (type == TAG) {
|
|
||||||
baked_points = server.baked_points_tag;
|
|
||||||
} else if (type == CLOSE) {
|
|
||||||
baked_points = server.baked_points_close;
|
|
||||||
} else if (type == FOCUS) {
|
|
||||||
baked_points = server.baked_points_focus;
|
|
||||||
} else if (type == OPAFADEIN) {
|
|
||||||
baked_points = server.baked_points_opafadein;
|
|
||||||
} else if (type == OPAFADEOUT) {
|
|
||||||
baked_points = server.baked_points_opafadeout;
|
|
||||||
} else {
|
|
||||||
baked_points = server.baked_points_move;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (up - down != 1) {
|
|
||||||
if (baked_points[middle].x <= t) {
|
|
||||||
down = middle;
|
|
||||||
} else {
|
|
||||||
up = middle;
|
|
||||||
}
|
|
||||||
middle = (up + down) / 2;
|
|
||||||
}
|
|
||||||
return baked_points[up].y;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
|
||||||
int32_t ly,
|
|
||||||
struct wlr_scene_tree *snapshot_tree) {
|
|
||||||
if (!node->enabled && node->type != WLR_SCENE_NODE_TREE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
lx += node->x;
|
|
||||||
ly += node->y;
|
|
||||||
|
|
||||||
struct wlr_scene_node *snapshot_node = NULL;
|
|
||||||
switch (node->type) {
|
|
||||||
case WLR_SCENE_NODE_TREE: {
|
|
||||||
struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node);
|
|
||||||
|
|
||||||
struct wlr_scene_node *child;
|
|
||||||
wl_list_for_each(child, &scene_tree->children, link) {
|
|
||||||
scene_node_snapshot(child, lx, ly, snapshot_tree);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WLR_SCENE_NODE_RECT: {
|
|
||||||
// struct wlr_scene_rect *scene_rect = wlr_scene_rect_from_node(node);
|
|
||||||
|
|
||||||
// struct wlr_scene_rect *snapshot_rect =
|
|
||||||
// wlr_scene_rect_create(snapshot_tree, scene_rect->width,
|
|
||||||
// scene_rect->height, scene_rect->color);
|
|
||||||
// snapshot_rect->node.data = scene_rect->node.data;
|
|
||||||
// if (snapshot_rect == NULL) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// wlr_scene_rect_set_clipped_region(scene_rect,
|
|
||||||
// snapshot_rect->clipped_region);
|
|
||||||
// wlr_scene_rect_set_backdrop_blur(scene_rect, false);
|
|
||||||
// wlr_scene_rect_set_backdrop_blur_optimized(
|
|
||||||
// scene_rect, snapshot_rect->backdrop_blur_optimized);
|
|
||||||
// wlr_scene_rect_set_corner_radius(
|
|
||||||
// scene_rect, snapshot_rect->corner_radius, snapshot_rect->corners);
|
|
||||||
// wlr_scene_rect_set_color(scene_rect, snapshot_rect->color);
|
|
||||||
|
|
||||||
// snapshot_node = &snapshot_rect->node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WLR_SCENE_NODE_BUFFER: {
|
|
||||||
struct wlr_scene_buffer *scene_buffer =
|
|
||||||
wlr_scene_buffer_from_node(node);
|
|
||||||
|
|
||||||
struct wlr_scene_buffer *snapshot_buffer =
|
|
||||||
wlr_scene_buffer_create(snapshot_tree, NULL);
|
|
||||||
if (snapshot_buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
snapshot_node = &snapshot_buffer->node;
|
|
||||||
snapshot_buffer->node.data = scene_buffer->node.data;
|
|
||||||
|
|
||||||
wlr_scene_buffer_set_dest_size(snapshot_buffer, scene_buffer->dst_width,
|
|
||||||
scene_buffer->dst_height);
|
|
||||||
wlr_scene_buffer_set_opaque_region(snapshot_buffer,
|
|
||||||
&scene_buffer->opaque_region);
|
|
||||||
wlr_scene_buffer_set_source_box(snapshot_buffer,
|
|
||||||
&scene_buffer->src_box);
|
|
||||||
wlr_scene_buffer_set_transform(snapshot_buffer,
|
|
||||||
scene_buffer->transform);
|
|
||||||
wlr_scene_buffer_set_filter_mode(snapshot_buffer,
|
|
||||||
scene_buffer->filter_mode);
|
|
||||||
|
|
||||||
// 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_optimized(
|
|
||||||
// snapshot_buffer, scene_buffer->backdrop_blur_optimized);
|
|
||||||
// wlr_scene_buffer_set_backdrop_blur_ignore_transparent(
|
|
||||||
// snapshot_buffer, scene_buffer->backdrop_blur_ignore_transparent);
|
|
||||||
wlr_scene_buffer_set_backdrop_blur(snapshot_buffer, false);
|
|
||||||
|
|
||||||
snapshot_buffer->node.data = scene_buffer->node.data;
|
|
||||||
|
|
||||||
struct wlr_scene_surface *scene_surface =
|
|
||||||
wlr_scene_surface_try_from_buffer(scene_buffer);
|
|
||||||
if (scene_surface != NULL && scene_surface->surface->buffer != NULL) {
|
|
||||||
wlr_scene_buffer_set_buffer(snapshot_buffer,
|
|
||||||
&scene_surface->surface->buffer->base);
|
|
||||||
} else {
|
|
||||||
wlr_scene_buffer_set_buffer(snapshot_buffer, scene_buffer->buffer);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WLR_SCENE_NODE_SHADOW: {
|
|
||||||
struct wlr_scene_shadow *scene_shadow =
|
|
||||||
wlr_scene_shadow_from_node(node);
|
|
||||||
|
|
||||||
struct wlr_scene_shadow *snapshot_shadow = wlr_scene_shadow_create(
|
|
||||||
snapshot_tree, scene_shadow->width, scene_shadow->height,
|
|
||||||
scene_shadow->corner_radius, scene_shadow->blur_sigma,
|
|
||||||
scene_shadow->color);
|
|
||||||
if (snapshot_shadow == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
snapshot_node = &snapshot_shadow->node;
|
|
||||||
|
|
||||||
wlr_scene_shadow_set_clipped_region(snapshot_shadow,
|
|
||||||
scene_shadow->clipped_region);
|
|
||||||
|
|
||||||
snapshot_shadow->node.data = scene_shadow->node.data;
|
|
||||||
|
|
||||||
wlr_scene_node_set_enabled(&snapshot_shadow->node, false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WLR_SCENE_NODE_OPTIMIZED_BLUR:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snapshot_node != NULL) {
|
|
||||||
wlr_scene_node_set_position(snapshot_node, lx, ly);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_scene_tree *wlr_scene_tree_snapshot(struct wlr_scene_node *node,
|
|
||||||
struct wlr_scene_tree *parent) {
|
|
||||||
struct wlr_scene_tree *snapshot = wlr_scene_tree_create(parent);
|
|
||||||
if (snapshot == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable and enable the snapshot tree like so to atomically update
|
|
||||||
// the server.scene -graph. This will prevent over-damaging or other
|
|
||||||
// weirdness.
|
|
||||||
wlr_scene_node_set_enabled(&snapshot->node, false);
|
|
||||||
|
|
||||||
if (!scene_node_snapshot(node, 0, 0, snapshot)) {
|
|
||||||
wlr_scene_node_destroy(&snapshot->node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_scene_node_set_enabled(&snapshot->node, true);
|
|
||||||
|
|
||||||
return snapshot;
|
|
||||||
}
|
|
||||||
|
|
||||||
void request_fresh_all_monitors(void) {
|
|
||||||
Monitor *m = NULL;
|
|
||||||
wl_list_for_each(m, &server.mons, link) {
|
|
||||||
if (!m->wlr_output->enabled) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
wlr_output_schedule_frame(m->wlr_output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
590
src/animation/layer.c
Normal file
590
src/animation/layer.c
Normal file
|
|
@ -0,0 +1,590 @@
|
||||||
|
#include "../type.h"
|
||||||
|
|
||||||
|
extern Server server;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_layer_area_bound(LayerSurface *l, struct wlr_box *bound) {
|
||||||
|
const struct wlr_layer_surface_v1_state *state = &l->layer_surface->current;
|
||||||
|
|
||||||
|
if (state->exclusive_zone > 0 || state->exclusive_zone == -1)
|
||||||
|
*bound = l->mon->m;
|
||||||
|
else
|
||||||
|
*bound = l->mon->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_layer_target_geometry(LayerSurface *l, struct wlr_box *target_box) {
|
||||||
|
|
||||||
|
if (!l || !l->mapped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const struct wlr_layer_surface_v1_state *state = &l->layer_surface->current;
|
||||||
|
|
||||||
|
// 限制区域
|
||||||
|
// waybar一般都是大于0,表示要占用多少区域,所以计算位置也要用全部区域作为基准
|
||||||
|
// 如果是-1可能表示独占所有可用空间
|
||||||
|
// 如果是0,应该是表示使用exclusive_zone外的可用区域
|
||||||
|
struct wlr_box bounds;
|
||||||
|
if (state->exclusive_zone > 0 || state->exclusive_zone == -1)
|
||||||
|
bounds = l->mon->m;
|
||||||
|
else
|
||||||
|
bounds = l->mon->w;
|
||||||
|
|
||||||
|
// 初始化几何位置
|
||||||
|
struct wlr_box box = {.width = state->desired_width,
|
||||||
|
.height = state->desired_height};
|
||||||
|
|
||||||
|
// 水平方向定位
|
||||||
|
const int32_t both_horiz =
|
||||||
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
||||||
|
if (box.width == 0) {
|
||||||
|
box.x = bounds.x;
|
||||||
|
} else if ((state->anchor & both_horiz) == both_horiz) {
|
||||||
|
box.x = bounds.x + ((bounds.width - box.width) / 2);
|
||||||
|
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT) {
|
||||||
|
box.x = bounds.x;
|
||||||
|
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) {
|
||||||
|
box.x = bounds.x + (bounds.width - box.width);
|
||||||
|
} else {
|
||||||
|
box.x = bounds.x + ((bounds.width - box.width) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 垂直方向定位
|
||||||
|
const int32_t both_vert =
|
||||||
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
||||||
|
if (box.height == 0) {
|
||||||
|
box.y = bounds.y;
|
||||||
|
} else if ((state->anchor & both_vert) == both_vert) {
|
||||||
|
box.y = bounds.y + ((bounds.height - box.height) / 2);
|
||||||
|
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) {
|
||||||
|
box.y = bounds.y;
|
||||||
|
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) {
|
||||||
|
box.y = bounds.y + (bounds.height - box.height);
|
||||||
|
} else {
|
||||||
|
box.y = bounds.y + ((bounds.height - box.height) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用边距
|
||||||
|
if (box.width == 0) {
|
||||||
|
box.x += state->margin.left;
|
||||||
|
box.width = bounds.width - (state->margin.left + state->margin.right);
|
||||||
|
} else {
|
||||||
|
if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT) {
|
||||||
|
box.x += state->margin.left;
|
||||||
|
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) {
|
||||||
|
box.x -= state->margin.right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (box.height == 0) {
|
||||||
|
box.y += state->margin.top;
|
||||||
|
box.height = bounds.height - (state->margin.top + state->margin.bottom);
|
||||||
|
} else {
|
||||||
|
if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) {
|
||||||
|
box.y += state->margin.top;
|
||||||
|
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) {
|
||||||
|
box.y -= state->margin.bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target_box->x = box.x;
|
||||||
|
target_box->y = box.y;
|
||||||
|
target_box->width = box.width;
|
||||||
|
target_box->height = box.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_layer_dir_animaiton(LayerSurface *l, struct wlr_box *geo) {
|
||||||
|
int32_t slide_direction;
|
||||||
|
int32_t horizontal, horizontal_value;
|
||||||
|
int32_t vertical, vertical_value;
|
||||||
|
int32_t center_x, center_y;
|
||||||
|
|
||||||
|
if (!l)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct wlr_box usable_area;
|
||||||
|
get_layer_area_bound(l, &usable_area);
|
||||||
|
|
||||||
|
geo->width = l->geom.width;
|
||||||
|
geo->height = l->geom.height;
|
||||||
|
|
||||||
|
center_x = l->geom.x + l->geom.width / 2;
|
||||||
|
center_y = l->geom.y + l->geom.height / 2;
|
||||||
|
horizontal =
|
||||||
|
center_x > usable_area.x + usable_area.width / 2 ? RIGHT : LEFT;
|
||||||
|
horizontal_value = horizontal == LEFT
|
||||||
|
? center_x - usable_area.x
|
||||||
|
: usable_area.x + usable_area.width - center_x;
|
||||||
|
vertical = center_y > usable_area.y + usable_area.height / 2 ? DOWN : UP;
|
||||||
|
vertical_value = vertical == UP
|
||||||
|
? center_y - l->mon->w.y
|
||||||
|
: usable_area.y + usable_area.height - center_y;
|
||||||
|
slide_direction = horizontal_value < vertical_value ? horizontal : vertical;
|
||||||
|
|
||||||
|
switch (slide_direction) {
|
||||||
|
case UP:
|
||||||
|
geo->x = l->geom.x;
|
||||||
|
geo->y = usable_area.y - l->geom.height;
|
||||||
|
break;
|
||||||
|
case DOWN:
|
||||||
|
geo->x = l->geom.x;
|
||||||
|
geo->y = usable_area.y + usable_area.height;
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
geo->x = usable_area.x - l->geom.width;
|
||||||
|
geo->y = l->geom.y;
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
geo->x = usable_area.x + usable_area.width;
|
||||||
|
geo->y = l->geom.y;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
geo->x = l->geom.x;
|
||||||
|
geo->y = 0 - l->geom.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_draw_shadow(LayerSurface *l) {
|
||||||
|
|
||||||
|
if (!l->mapped || !l->shadow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!shadows || !layer_shadows || l->noshadow) {
|
||||||
|
wlr_scene_shadow_set_size(l->shadow, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t width, height;
|
||||||
|
layer_actual_size(l, &width, &height);
|
||||||
|
|
||||||
|
int32_t delta = shadows_size;
|
||||||
|
|
||||||
|
/* we calculate where to clip the shadow */
|
||||||
|
struct wlr_box layer_box = {
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_box shadow_box = {
|
||||||
|
.x = shadows_position_x,
|
||||||
|
.y = shadows_position_y,
|
||||||
|
.width = width + 2 * delta,
|
||||||
|
.height = height + 2 * delta,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_box intersection_box;
|
||||||
|
wlr_box_intersection(&intersection_box, &layer_box, &shadow_box);
|
||||||
|
/* clipped region takes shadow relative coords, so we translate everything
|
||||||
|
* by its position */
|
||||||
|
intersection_box.x -= shadows_position_x;
|
||||||
|
intersection_box.y -= shadows_position_y;
|
||||||
|
|
||||||
|
struct clipped_region clipped_region = {
|
||||||
|
.area = intersection_box,
|
||||||
|
.corner_radius = border_radius,
|
||||||
|
.corners = border_radius_location_default,
|
||||||
|
};
|
||||||
|
|
||||||
|
wlr_scene_node_set_position(&l->shadow->node, shadow_box.x, shadow_box.y);
|
||||||
|
|
||||||
|
wlr_scene_shadow_set_size(l->shadow, shadow_box.width, shadow_box.height);
|
||||||
|
wlr_scene_shadow_set_clipped_region(l->shadow, clipped_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
||||||
|
int32_t sx, int32_t sy, void *data) {
|
||||||
|
BufferData *buffer_data = (BufferData *)data;
|
||||||
|
|
||||||
|
struct wlr_scene_surface *scene_surface =
|
||||||
|
wlr_scene_surface_try_from_buffer(buffer);
|
||||||
|
|
||||||
|
if (scene_surface == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct wlr_surface *surface = scene_surface->surface;
|
||||||
|
|
||||||
|
int32_t surface_width = surface->current.width * buffer_data->width_scale;
|
||||||
|
int32_t surface_height =
|
||||||
|
surface->current.height * buffer_data->height_scale;
|
||||||
|
|
||||||
|
if (surface_height > 0 && surface_width > 0) {
|
||||||
|
wlr_scene_buffer_set_dest_size(buffer, surface_width, surface_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_fadeout_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
||||||
|
int32_t sx, int32_t sy,
|
||||||
|
void *data) {
|
||||||
|
BufferData *buffer_data = (BufferData *)data;
|
||||||
|
wlr_scene_buffer_set_dest_size(buffer, buffer_data->width,
|
||||||
|
buffer_data->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fadeout_layer_animation_next_tick(LayerSurface *l) {
|
||||||
|
if (!l)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
|
int32_t passed_time = timespec_to_ms(&now) - l->animation.time_started;
|
||||||
|
double animation_passed =
|
||||||
|
l->animation.duration
|
||||||
|
? (double)passed_time / (double)l->animation.duration
|
||||||
|
: 1.0;
|
||||||
|
|
||||||
|
int32_t type = l->animation.action = l->animation.action;
|
||||||
|
double factor = find_animation_curve_at(animation_passed, type);
|
||||||
|
int32_t width = l->animation.initial.width +
|
||||||
|
(l->current.width - l->animation.initial.width) * factor;
|
||||||
|
int32_t height = l->animation.initial.height +
|
||||||
|
(l->current.height - l->animation.initial.height) * factor;
|
||||||
|
|
||||||
|
int32_t x = l->animation.initial.x +
|
||||||
|
(l->current.x - l->animation.initial.x) * factor;
|
||||||
|
int32_t y = l->animation.initial.y +
|
||||||
|
(l->current.y - l->animation.initial.y) * factor;
|
||||||
|
|
||||||
|
wlr_scene_node_set_position(&l->scene->node, x, y);
|
||||||
|
|
||||||
|
BufferData buffer_data;
|
||||||
|
buffer_data.width = width;
|
||||||
|
buffer_data.height = height;
|
||||||
|
|
||||||
|
if ((!l->animation_type_close &&
|
||||||
|
strcmp(layer_animation_type_close, "zoom") == 0) ||
|
||||||
|
(l->animation_type_close &&
|
||||||
|
strcmp(l->animation_type_close, "zoom") == 0)) {
|
||||||
|
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||||
|
layer_fadeout_scene_buffer_apply_effect,
|
||||||
|
&buffer_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
l->animation.current = (struct wlr_box){
|
||||||
|
.x = x,
|
||||||
|
.y = y,
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
};
|
||||||
|
|
||||||
|
double opacity_eased_progress =
|
||||||
|
find_animation_curve_at(animation_passed, OPAFADEOUT);
|
||||||
|
|
||||||
|
double percent = fadeout_begin_opacity -
|
||||||
|
(opacity_eased_progress * fadeout_begin_opacity);
|
||||||
|
|
||||||
|
double opacity = MAX(percent, 0.0f);
|
||||||
|
|
||||||
|
if (animation_fade_out)
|
||||||
|
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||||
|
scene_buffer_apply_opacity, &opacity);
|
||||||
|
|
||||||
|
if (animation_passed >= 1.0) {
|
||||||
|
wl_list_remove(&l->fadeout_link);
|
||||||
|
wlr_scene_node_destroy(&l->scene->node);
|
||||||
|
free(l);
|
||||||
|
l = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_animation_next_tick(LayerSurface *l) {
|
||||||
|
|
||||||
|
if (!l || !l->mapped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
|
int32_t passed_time = timespec_to_ms(&now) - l->animation.time_started;
|
||||||
|
double animation_passed =
|
||||||
|
l->animation.duration
|
||||||
|
? (double)passed_time / (double)l->animation.duration
|
||||||
|
: 1.0;
|
||||||
|
|
||||||
|
int32_t type = l->animation.action == NONE ? MOVE : l->animation.action;
|
||||||
|
double factor = find_animation_curve_at(animation_passed, type);
|
||||||
|
|
||||||
|
int32_t width = l->animation.initial.width +
|
||||||
|
(l->current.width - l->animation.initial.width) * factor;
|
||||||
|
int32_t height = l->animation.initial.height +
|
||||||
|
(l->current.height - l->animation.initial.height) * factor;
|
||||||
|
|
||||||
|
int32_t x = l->animation.initial.x +
|
||||||
|
(l->current.x - l->animation.initial.x) * factor;
|
||||||
|
int32_t y = l->animation.initial.y +
|
||||||
|
(l->current.y - l->animation.initial.y) * factor;
|
||||||
|
|
||||||
|
double opacity_eased_progress =
|
||||||
|
find_animation_curve_at(animation_passed, OPAFADEIN);
|
||||||
|
|
||||||
|
double opacity =
|
||||||
|
MIN(fadein_begin_opacity +
|
||||||
|
opacity_eased_progress * (1.0 - fadein_begin_opacity),
|
||||||
|
1.0f);
|
||||||
|
|
||||||
|
if (animation_fade_in)
|
||||||
|
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||||
|
scene_buffer_apply_opacity, &opacity);
|
||||||
|
|
||||||
|
wlr_scene_node_set_position(&l->scene->node, x, y);
|
||||||
|
|
||||||
|
BufferData buffer_data;
|
||||||
|
if (factor == 1.0) {
|
||||||
|
buffer_data.width_scale = 1.0f;
|
||||||
|
buffer_data.height_scale = 1.0f;
|
||||||
|
} else {
|
||||||
|
buffer_data.width_scale = (float)width / (float)l->current.width;
|
||||||
|
buffer_data.height_scale = (float)height / (float)l->current.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!l->animation_type_open &&
|
||||||
|
strcmp(layer_animation_type_open, "zoom") == 0) ||
|
||||||
|
(l->animation_type_open &&
|
||||||
|
strcmp(l->animation_type_open, "zoom") == 0)) {
|
||||||
|
wlr_scene_node_for_each_buffer(
|
||||||
|
&l->scene->node, layer_scene_buffer_apply_effect, &buffer_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
l->animation.current = (struct wlr_box){
|
||||||
|
.x = x,
|
||||||
|
.y = y,
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (animation_passed >= 1.0) {
|
||||||
|
l->animation.running = false;
|
||||||
|
l->need_output_flush = false;
|
||||||
|
l->animation.action = MOVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_fadeout_layers(LayerSurface *l) {
|
||||||
|
|
||||||
|
if (!animations || !layer_animations || l->noanim) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!l->mon || !l->scene)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((l->animation_type_close &&
|
||||||
|
strcmp(l->animation_type_close, "none") == 0) ||
|
||||||
|
(!l->animation_type_close &&
|
||||||
|
strcmp(layer_animation_type_close, "none") == 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM ||
|
||||||
|
l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LayerSurface *fadeout_layer = ecalloc(1, sizeof(*fadeout_layer));
|
||||||
|
|
||||||
|
struct wlr_box usable_area;
|
||||||
|
get_layer_area_bound(l, &usable_area);
|
||||||
|
|
||||||
|
wlr_scene_node_set_enabled(&l->scene->node, true);
|
||||||
|
fadeout_layer->scene =
|
||||||
|
wlr_scene_tree_snapshot(&l->scene->node, server.layers[LyrFadeOut]);
|
||||||
|
wlr_scene_node_set_enabled(&l->scene->node, false);
|
||||||
|
|
||||||
|
if (!fadeout_layer->scene) {
|
||||||
|
free(fadeout_layer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fadeout_layer->animation.duration = animation_duration_close;
|
||||||
|
fadeout_layer->geom = fadeout_layer->current =
|
||||||
|
fadeout_layer->animainit_geom = fadeout_layer->animation.initial =
|
||||||
|
l->animation.current;
|
||||||
|
fadeout_layer->mon = l->mon;
|
||||||
|
fadeout_layer->animation.action = CLOSE;
|
||||||
|
fadeout_layer->animation_type_close = l->animation_type_close;
|
||||||
|
fadeout_layer->animation_type_open = l->animation_type_open;
|
||||||
|
|
||||||
|
// 这里snap节点的坐标设置是使用的相对坐标,不能用绝对坐标
|
||||||
|
// 这跟普通node有区别
|
||||||
|
|
||||||
|
fadeout_layer->animation.initial.x = 0;
|
||||||
|
fadeout_layer->animation.initial.y = 0;
|
||||||
|
|
||||||
|
if ((!l->animation_type_close &&
|
||||||
|
strcmp(layer_animation_type_close, "zoom") == 0) ||
|
||||||
|
(l->animation_type_close &&
|
||||||
|
strcmp(l->animation_type_close, "zoom") == 0)) {
|
||||||
|
// 算出要设置的绝对坐标和大小
|
||||||
|
fadeout_layer->current.width =
|
||||||
|
(float)l->animation.current.width * zoom_end_ratio;
|
||||||
|
fadeout_layer->current.height =
|
||||||
|
(float)l->animation.current.height * zoom_end_ratio;
|
||||||
|
fadeout_layer->current.x = usable_area.x + usable_area.width / 2 -
|
||||||
|
fadeout_layer->current.width / 2;
|
||||||
|
fadeout_layer->current.y = usable_area.y + usable_area.height / 2 -
|
||||||
|
fadeout_layer->current.height / 2;
|
||||||
|
// 算出偏差坐标,大小不用因为后续不使用他的大小偏差去设置,而是直接缩放buffer
|
||||||
|
fadeout_layer->current.x =
|
||||||
|
fadeout_layer->current.x - l->animation.current.x;
|
||||||
|
fadeout_layer->current.y =
|
||||||
|
fadeout_layer->current.y - l->animation.current.y;
|
||||||
|
|
||||||
|
} else if ((!l->animation_type_close &&
|
||||||
|
strcmp(layer_animation_type_close, "slide") == 0) ||
|
||||||
|
(l->animation_type_close &&
|
||||||
|
strcmp(l->animation_type_close, "slide") == 0)) {
|
||||||
|
// 获取slide动画的结束绝对坐标和大小
|
||||||
|
set_layer_dir_animaiton(l, &fadeout_layer->current);
|
||||||
|
// 算出也能够有设置的偏差坐标和大小
|
||||||
|
fadeout_layer->current.x = fadeout_layer->current.x - l->geom.x;
|
||||||
|
fadeout_layer->current.y = fadeout_layer->current.y - l->geom.y;
|
||||||
|
fadeout_layer->current.width =
|
||||||
|
fadeout_layer->current.width - l->geom.width;
|
||||||
|
fadeout_layer->current.height =
|
||||||
|
fadeout_layer->current.height - l->geom.height;
|
||||||
|
} else {
|
||||||
|
// fade动画坐标大小不用变
|
||||||
|
fadeout_layer->current.x = 0;
|
||||||
|
fadeout_layer->current.y = 0;
|
||||||
|
fadeout_layer->current.width = 0;
|
||||||
|
fadeout_layer->current.height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动画开始时间
|
||||||
|
fadeout_layer->animation.time_started = get_now_in_ms();
|
||||||
|
|
||||||
|
// 将节点插入到关闭动画链表中,屏幕刷新哪里会检查链表中是否有节点可以应用于动画
|
||||||
|
wlr_scene_node_set_enabled(&fadeout_layer->scene->node, true);
|
||||||
|
wl_list_insert(&server.fadeout_layers, &fadeout_layer->fadeout_link);
|
||||||
|
|
||||||
|
// 请求刷新屏幕
|
||||||
|
if (l->mon)
|
||||||
|
wlr_output_schedule_frame(l->mon->wlr_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_set_pending_state(LayerSurface *l) {
|
||||||
|
|
||||||
|
if (!l || !l->mapped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct wlr_box usable_area;
|
||||||
|
get_layer_area_bound(l, &usable_area);
|
||||||
|
|
||||||
|
l->pending = l->geom;
|
||||||
|
|
||||||
|
if (l->animation.action == OPEN && !l->animation.running) {
|
||||||
|
|
||||||
|
if ((!l->animation_type_open &&
|
||||||
|
strcmp(layer_animation_type_open, "zoom") == 0) ||
|
||||||
|
(l->animation_type_open &&
|
||||||
|
strcmp(l->animation_type_open, "zoom") == 0)) {
|
||||||
|
l->animainit_geom.width = l->geom.width * zoom_initial_ratio;
|
||||||
|
l->animainit_geom.height = l->geom.height * zoom_initial_ratio;
|
||||||
|
l->animainit_geom.x = usable_area.x + usable_area.width / 2 -
|
||||||
|
l->animainit_geom.width / 2;
|
||||||
|
l->animainit_geom.y = usable_area.y + usable_area.height / 2 -
|
||||||
|
l->animainit_geom.height / 2;
|
||||||
|
} else if ((!l->animation_type_open &&
|
||||||
|
strcmp(layer_animation_type_open, "slide") == 0) ||
|
||||||
|
(l->animation_type_open &&
|
||||||
|
strcmp(l->animation_type_open, "slide") == 0)) {
|
||||||
|
|
||||||
|
set_layer_dir_animaiton(l, &l->animainit_geom);
|
||||||
|
} else {
|
||||||
|
l->animainit_geom.x = l->geom.x;
|
||||||
|
l->animainit_geom.y = l->geom.y;
|
||||||
|
l->animainit_geom.width = l->geom.width;
|
||||||
|
l->animainit_geom.height = l->geom.height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
l->animainit_geom = l->animation.current;
|
||||||
|
}
|
||||||
|
// 判断是否需要动画
|
||||||
|
if (!animations || !layer_animations || l->noanim ||
|
||||||
|
l->layer_surface->current.layer ==
|
||||||
|
ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ||
|
||||||
|
l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) {
|
||||||
|
l->animation.should_animate = false;
|
||||||
|
} else {
|
||||||
|
l->animation.should_animate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((l->animation_type_open &&
|
||||||
|
strcmp(l->animation_type_open, "none") == 0) ||
|
||||||
|
(!l->animation_type_open &&
|
||||||
|
strcmp(layer_animation_type_open, "none") == 0)) &&
|
||||||
|
l->animation.action == OPEN) {
|
||||||
|
l->animation.should_animate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始动画
|
||||||
|
layer_commit(l);
|
||||||
|
l->dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_commit(LayerSurface *l) {
|
||||||
|
|
||||||
|
if (!l || !l->mapped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
l->current = l->pending; // 设置动画的结束位置
|
||||||
|
|
||||||
|
if (l->animation.should_animate) {
|
||||||
|
if (!l->animation.running) {
|
||||||
|
l->animation.current = l->animainit_geom;
|
||||||
|
}
|
||||||
|
|
||||||
|
l->animation.initial = l->animainit_geom;
|
||||||
|
l->animation.time_started = get_now_in_ms();
|
||||||
|
|
||||||
|
// 标记动画开始
|
||||||
|
l->animation.running = true;
|
||||||
|
l->animation.should_animate = false;
|
||||||
|
}
|
||||||
|
// 请求刷新屏幕
|
||||||
|
if (l->mon)
|
||||||
|
wlr_output_schedule_frame(l->mon->wlr_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool layer_draw_frame(LayerSurface *l) {
|
||||||
|
|
||||||
|
if (!l || !l->mapped)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!l->need_output_flush)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (l->layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_TOP &&
|
||||||
|
l->layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animations && layer_animations && l->animation.running && !l->noanim) {
|
||||||
|
layer_animation_next_tick(l);
|
||||||
|
layer_draw_shadow(l);
|
||||||
|
} else {
|
||||||
|
layer_draw_shadow(l);
|
||||||
|
l->need_output_flush = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool layer_draw_fadeout_frame(LayerSurface *l) {
|
||||||
|
if (!l)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fadeout_layer_animation_next_tick(l);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -1,586 +1,26 @@
|
||||||
void layer_actual_size(LayerSurface *l, int32_t *width, int32_t *height) {
|
#ifndef MANGO_ANIMATION_LAYER_H
|
||||||
struct wlr_box box;
|
#define MANGO_ANIMATION_LAYER_H
|
||||||
|
|
||||||
if (l->animation.running) {
|
// 图层大小和几何计算函数
|
||||||
*width = l->animation.current.width;
|
void layer_actual_size(LayerSurface *l, int32_t *width, int32_t *height);
|
||||||
*height = l->animation.current.height;
|
void get_layer_area_bound(LayerSurface *l, struct wlr_box *bound);
|
||||||
} else {
|
void get_layer_target_geometry(LayerSurface *l, struct wlr_box *target_box);
|
||||||
get_layer_target_geometry(l, &box);
|
void set_layer_dir_animaiton(LayerSurface *l, struct wlr_box *geo);
|
||||||
*width = box.width;
|
|
||||||
*height = box.height;
|
// 图层阴影和视觉效果函数
|
||||||
}
|
void layer_draw_shadow(LayerSurface *l);
|
||||||
}
|
void layer_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx, int32_t sy, void *data);
|
||||||
|
void layer_fadeout_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx, int32_t sy, void *data);
|
||||||
void get_layer_area_bound(LayerSurface *l, struct wlr_box *bound) {
|
|
||||||
const struct wlr_layer_surface_v1_state *state = &l->layer_surface->current;
|
// 图层动画相关函数
|
||||||
|
void fadeout_layer_animation_next_tick(LayerSurface *l);
|
||||||
if (state->exclusive_zone > 0 || state->exclusive_zone == -1)
|
void layer_animation_next_tick(LayerSurface *l);
|
||||||
*bound = l->mon->m;
|
void init_fadeout_layers(LayerSurface *l);
|
||||||
else
|
void layer_set_pending_state(LayerSurface *l);
|
||||||
*bound = l->mon->w;
|
void layer_commit(LayerSurface *l);
|
||||||
}
|
|
||||||
|
// 图层绘制函数
|
||||||
void get_layer_target_geometry(LayerSurface *l, struct wlr_box *target_box) {
|
bool layer_draw_frame(LayerSurface *l);
|
||||||
|
bool layer_draw_fadeout_frame(LayerSurface *l);
|
||||||
if (!l || !l->mapped)
|
|
||||||
return;
|
#endif // MANGO_ANIMATION_LAYER_H
|
||||||
|
|
||||||
const struct wlr_layer_surface_v1_state *state = &l->layer_surface->current;
|
|
||||||
|
|
||||||
// 限制区域
|
|
||||||
// waybar一般都是大于0,表示要占用多少区域,所以计算位置也要用全部区域作为基准
|
|
||||||
// 如果是-1可能表示独占所有可用空间
|
|
||||||
// 如果是0,应该是表示使用exclusive_zone外的可用区域
|
|
||||||
struct wlr_box bounds;
|
|
||||||
if (state->exclusive_zone > 0 || state->exclusive_zone == -1)
|
|
||||||
bounds = l->mon->m;
|
|
||||||
else
|
|
||||||
bounds = l->mon->w;
|
|
||||||
|
|
||||||
// 初始化几何位置
|
|
||||||
struct wlr_box box = {.width = state->desired_width,
|
|
||||||
.height = state->desired_height};
|
|
||||||
|
|
||||||
// 水平方向定位
|
|
||||||
const int32_t both_horiz =
|
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
|
||||||
if (box.width == 0) {
|
|
||||||
box.x = bounds.x;
|
|
||||||
} else if ((state->anchor & both_horiz) == both_horiz) {
|
|
||||||
box.x = bounds.x + ((bounds.width - box.width) / 2);
|
|
||||||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT) {
|
|
||||||
box.x = bounds.x;
|
|
||||||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) {
|
|
||||||
box.x = bounds.x + (bounds.width - box.width);
|
|
||||||
} else {
|
|
||||||
box.x = bounds.x + ((bounds.width - box.width) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 垂直方向定位
|
|
||||||
const int32_t both_vert =
|
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
|
||||||
if (box.height == 0) {
|
|
||||||
box.y = bounds.y;
|
|
||||||
} else if ((state->anchor & both_vert) == both_vert) {
|
|
||||||
box.y = bounds.y + ((bounds.height - box.height) / 2);
|
|
||||||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) {
|
|
||||||
box.y = bounds.y;
|
|
||||||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) {
|
|
||||||
box.y = bounds.y + (bounds.height - box.height);
|
|
||||||
} else {
|
|
||||||
box.y = bounds.y + ((bounds.height - box.height) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 应用边距
|
|
||||||
if (box.width == 0) {
|
|
||||||
box.x += state->margin.left;
|
|
||||||
box.width = bounds.width - (state->margin.left + state->margin.right);
|
|
||||||
} else {
|
|
||||||
if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT) {
|
|
||||||
box.x += state->margin.left;
|
|
||||||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) {
|
|
||||||
box.x -= state->margin.right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (box.height == 0) {
|
|
||||||
box.y += state->margin.top;
|
|
||||||
box.height = bounds.height - (state->margin.top + state->margin.bottom);
|
|
||||||
} else {
|
|
||||||
if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) {
|
|
||||||
box.y += state->margin.top;
|
|
||||||
} else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) {
|
|
||||||
box.y -= state->margin.bottom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
target_box->x = box.x;
|
|
||||||
target_box->y = box.y;
|
|
||||||
target_box->width = box.width;
|
|
||||||
target_box->height = box.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_layer_dir_animaiton(LayerSurface *l, struct wlr_box *geo) {
|
|
||||||
int32_t slide_direction;
|
|
||||||
int32_t horizontal, horizontal_value;
|
|
||||||
int32_t vertical, vertical_value;
|
|
||||||
int32_t center_x, center_y;
|
|
||||||
|
|
||||||
if (!l)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct wlr_box usable_area;
|
|
||||||
get_layer_area_bound(l, &usable_area);
|
|
||||||
|
|
||||||
geo->width = l->geom.width;
|
|
||||||
geo->height = l->geom.height;
|
|
||||||
|
|
||||||
center_x = l->geom.x + l->geom.width / 2;
|
|
||||||
center_y = l->geom.y + l->geom.height / 2;
|
|
||||||
horizontal =
|
|
||||||
center_x > usable_area.x + usable_area.width / 2 ? RIGHT : LEFT;
|
|
||||||
horizontal_value = horizontal == LEFT
|
|
||||||
? center_x - usable_area.x
|
|
||||||
: usable_area.x + usable_area.width - center_x;
|
|
||||||
vertical = center_y > usable_area.y + usable_area.height / 2 ? DOWN : UP;
|
|
||||||
vertical_value = vertical == UP
|
|
||||||
? center_y - l->mon->w.y
|
|
||||||
: usable_area.y + usable_area.height - center_y;
|
|
||||||
slide_direction = horizontal_value < vertical_value ? horizontal : vertical;
|
|
||||||
|
|
||||||
switch (slide_direction) {
|
|
||||||
case UP:
|
|
||||||
geo->x = l->geom.x;
|
|
||||||
geo->y = usable_area.y - l->geom.height;
|
|
||||||
break;
|
|
||||||
case DOWN:
|
|
||||||
geo->x = l->geom.x;
|
|
||||||
geo->y = usable_area.y + usable_area.height;
|
|
||||||
break;
|
|
||||||
case LEFT:
|
|
||||||
geo->x = usable_area.x - l->geom.width;
|
|
||||||
geo->y = l->geom.y;
|
|
||||||
break;
|
|
||||||
case RIGHT:
|
|
||||||
geo->x = usable_area.x + usable_area.width;
|
|
||||||
geo->y = l->geom.y;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
geo->x = l->geom.x;
|
|
||||||
geo->y = 0 - l->geom.height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_draw_shadow(LayerSurface *l) {
|
|
||||||
|
|
||||||
if (!l->mapped || !l->shadow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!shadows || !layer_shadows || l->noshadow) {
|
|
||||||
wlr_scene_shadow_set_size(l->shadow, 0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t width, height;
|
|
||||||
layer_actual_size(l, &width, &height);
|
|
||||||
|
|
||||||
int32_t delta = shadows_size;
|
|
||||||
|
|
||||||
/* we calculate where to clip the shadow */
|
|
||||||
struct wlr_box layer_box = {
|
|
||||||
.x = 0,
|
|
||||||
.y = 0,
|
|
||||||
.width = width,
|
|
||||||
.height = height,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_box shadow_box = {
|
|
||||||
.x = shadows_position_x,
|
|
||||||
.y = shadows_position_y,
|
|
||||||
.width = width + 2 * delta,
|
|
||||||
.height = height + 2 * delta,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_box intersection_box;
|
|
||||||
wlr_box_intersection(&intersection_box, &layer_box, &shadow_box);
|
|
||||||
/* clipped region takes shadow relative coords, so we translate everything
|
|
||||||
* by its position */
|
|
||||||
intersection_box.x -= shadows_position_x;
|
|
||||||
intersection_box.y -= shadows_position_y;
|
|
||||||
|
|
||||||
struct clipped_region clipped_region = {
|
|
||||||
.area = intersection_box,
|
|
||||||
.corner_radius = border_radius,
|
|
||||||
.corners = border_radius_location_default,
|
|
||||||
};
|
|
||||||
|
|
||||||
wlr_scene_node_set_position(&l->shadow->node, shadow_box.x, shadow_box.y);
|
|
||||||
|
|
||||||
wlr_scene_shadow_set_size(l->shadow, shadow_box.width, shadow_box.height);
|
|
||||||
wlr_scene_shadow_set_clipped_region(l->shadow, clipped_region);
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
|
||||||
int32_t sx, int32_t sy, void *data) {
|
|
||||||
BufferData *buffer_data = (BufferData *)data;
|
|
||||||
|
|
||||||
struct wlr_scene_surface *scene_surface =
|
|
||||||
wlr_scene_surface_try_from_buffer(buffer);
|
|
||||||
|
|
||||||
if (scene_surface == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct wlr_surface *surface = scene_surface->surface;
|
|
||||||
|
|
||||||
int32_t surface_width = surface->current.width * buffer_data->width_scale;
|
|
||||||
int32_t surface_height =
|
|
||||||
surface->current.height * buffer_data->height_scale;
|
|
||||||
|
|
||||||
if (surface_height > 0 && surface_width > 0) {
|
|
||||||
wlr_scene_buffer_set_dest_size(buffer, surface_width, surface_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_fadeout_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
|
||||||
int32_t sx, int32_t sy,
|
|
||||||
void *data) {
|
|
||||||
BufferData *buffer_data = (BufferData *)data;
|
|
||||||
wlr_scene_buffer_set_dest_size(buffer, buffer_data->width,
|
|
||||||
buffer_data->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fadeout_layer_animation_next_tick(LayerSurface *l) {
|
|
||||||
if (!l)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct timespec now;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
||||||
|
|
||||||
int32_t passed_time = timespec_to_ms(&now) - l->animation.time_started;
|
|
||||||
double animation_passed =
|
|
||||||
l->animation.duration
|
|
||||||
? (double)passed_time / (double)l->animation.duration
|
|
||||||
: 1.0;
|
|
||||||
|
|
||||||
int32_t type = l->animation.action = l->animation.action;
|
|
||||||
double factor = find_animation_curve_at(animation_passed, type);
|
|
||||||
int32_t width = l->animation.initial.width +
|
|
||||||
(l->current.width - l->animation.initial.width) * factor;
|
|
||||||
int32_t height = l->animation.initial.height +
|
|
||||||
(l->current.height - l->animation.initial.height) * factor;
|
|
||||||
|
|
||||||
int32_t x = l->animation.initial.x +
|
|
||||||
(l->current.x - l->animation.initial.x) * factor;
|
|
||||||
int32_t y = l->animation.initial.y +
|
|
||||||
(l->current.y - l->animation.initial.y) * factor;
|
|
||||||
|
|
||||||
wlr_scene_node_set_position(&l->scene->node, x, y);
|
|
||||||
|
|
||||||
BufferData buffer_data;
|
|
||||||
buffer_data.width = width;
|
|
||||||
buffer_data.height = height;
|
|
||||||
|
|
||||||
if ((!l->animation_type_close &&
|
|
||||||
strcmp(layer_animation_type_close, "zoom") == 0) ||
|
|
||||||
(l->animation_type_close &&
|
|
||||||
strcmp(l->animation_type_close, "zoom") == 0)) {
|
|
||||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
|
||||||
layer_fadeout_scene_buffer_apply_effect,
|
|
||||||
&buffer_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
l->animation.current = (struct wlr_box){
|
|
||||||
.x = x,
|
|
||||||
.y = y,
|
|
||||||
.width = width,
|
|
||||||
.height = height,
|
|
||||||
};
|
|
||||||
|
|
||||||
double opacity_eased_progress =
|
|
||||||
find_animation_curve_at(animation_passed, OPAFADEOUT);
|
|
||||||
|
|
||||||
double percent = fadeout_begin_opacity -
|
|
||||||
(opacity_eased_progress * fadeout_begin_opacity);
|
|
||||||
|
|
||||||
double opacity = MAX(percent, 0.0f);
|
|
||||||
|
|
||||||
if (animation_fade_out)
|
|
||||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
|
||||||
scene_buffer_apply_opacity, &opacity);
|
|
||||||
|
|
||||||
if (animation_passed >= 1.0) {
|
|
||||||
wl_list_remove(&l->fadeout_link);
|
|
||||||
wlr_scene_node_destroy(&l->scene->node);
|
|
||||||
free(l);
|
|
||||||
l = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_animation_next_tick(LayerSurface *l) {
|
|
||||||
|
|
||||||
if (!l || !l->mapped)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct timespec now;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
||||||
|
|
||||||
int32_t passed_time = timespec_to_ms(&now) - l->animation.time_started;
|
|
||||||
double animation_passed =
|
|
||||||
l->animation.duration
|
|
||||||
? (double)passed_time / (double)l->animation.duration
|
|
||||||
: 1.0;
|
|
||||||
|
|
||||||
int32_t type = l->animation.action == NONE ? MOVE : l->animation.action;
|
|
||||||
double factor = find_animation_curve_at(animation_passed, type);
|
|
||||||
|
|
||||||
int32_t width = l->animation.initial.width +
|
|
||||||
(l->current.width - l->animation.initial.width) * factor;
|
|
||||||
int32_t height = l->animation.initial.height +
|
|
||||||
(l->current.height - l->animation.initial.height) * factor;
|
|
||||||
|
|
||||||
int32_t x = l->animation.initial.x +
|
|
||||||
(l->current.x - l->animation.initial.x) * factor;
|
|
||||||
int32_t y = l->animation.initial.y +
|
|
||||||
(l->current.y - l->animation.initial.y) * factor;
|
|
||||||
|
|
||||||
double opacity_eased_progress =
|
|
||||||
find_animation_curve_at(animation_passed, OPAFADEIN);
|
|
||||||
|
|
||||||
double opacity =
|
|
||||||
MIN(fadein_begin_opacity +
|
|
||||||
opacity_eased_progress * (1.0 - fadein_begin_opacity),
|
|
||||||
1.0f);
|
|
||||||
|
|
||||||
if (animation_fade_in)
|
|
||||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
|
||||||
scene_buffer_apply_opacity, &opacity);
|
|
||||||
|
|
||||||
wlr_scene_node_set_position(&l->scene->node, x, y);
|
|
||||||
|
|
||||||
BufferData buffer_data;
|
|
||||||
if (factor == 1.0) {
|
|
||||||
buffer_data.width_scale = 1.0f;
|
|
||||||
buffer_data.height_scale = 1.0f;
|
|
||||||
} else {
|
|
||||||
buffer_data.width_scale = (float)width / (float)l->current.width;
|
|
||||||
buffer_data.height_scale = (float)height / (float)l->current.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!l->animation_type_open &&
|
|
||||||
strcmp(layer_animation_type_open, "zoom") == 0) ||
|
|
||||||
(l->animation_type_open &&
|
|
||||||
strcmp(l->animation_type_open, "zoom") == 0)) {
|
|
||||||
wlr_scene_node_for_each_buffer(
|
|
||||||
&l->scene->node, layer_scene_buffer_apply_effect, &buffer_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
l->animation.current = (struct wlr_box){
|
|
||||||
.x = x,
|
|
||||||
.y = y,
|
|
||||||
.width = width,
|
|
||||||
.height = height,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (animation_passed >= 1.0) {
|
|
||||||
l->animation.running = false;
|
|
||||||
l->need_output_flush = false;
|
|
||||||
l->animation.action = MOVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_fadeout_layers(LayerSurface *l) {
|
|
||||||
|
|
||||||
if (!animations || !layer_animations || l->noanim) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!l->mon || !l->scene)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((l->animation_type_close &&
|
|
||||||
strcmp(l->animation_type_close, "none") == 0) ||
|
|
||||||
(!l->animation_type_close &&
|
|
||||||
strcmp(layer_animation_type_close, "none") == 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM ||
|
|
||||||
l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LayerSurface *fadeout_layer = ecalloc(1, sizeof(*fadeout_layer));
|
|
||||||
|
|
||||||
struct wlr_box usable_area;
|
|
||||||
get_layer_area_bound(l, &usable_area);
|
|
||||||
|
|
||||||
wlr_scene_node_set_enabled(&l->scene->node, true);
|
|
||||||
fadeout_layer->scene =
|
|
||||||
wlr_scene_tree_snapshot(&l->scene->node, server.layers[LyrFadeOut]);
|
|
||||||
wlr_scene_node_set_enabled(&l->scene->node, false);
|
|
||||||
|
|
||||||
if (!fadeout_layer->scene) {
|
|
||||||
free(fadeout_layer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fadeout_layer->animation.duration = animation_duration_close;
|
|
||||||
fadeout_layer->geom = fadeout_layer->current =
|
|
||||||
fadeout_layer->animainit_geom = fadeout_layer->animation.initial =
|
|
||||||
l->animation.current;
|
|
||||||
fadeout_layer->mon = l->mon;
|
|
||||||
fadeout_layer->animation.action = CLOSE;
|
|
||||||
fadeout_layer->animation_type_close = l->animation_type_close;
|
|
||||||
fadeout_layer->animation_type_open = l->animation_type_open;
|
|
||||||
|
|
||||||
// 这里snap节点的坐标设置是使用的相对坐标,不能用绝对坐标
|
|
||||||
// 这跟普通node有区别
|
|
||||||
|
|
||||||
fadeout_layer->animation.initial.x = 0;
|
|
||||||
fadeout_layer->animation.initial.y = 0;
|
|
||||||
|
|
||||||
if ((!l->animation_type_close &&
|
|
||||||
strcmp(layer_animation_type_close, "zoom") == 0) ||
|
|
||||||
(l->animation_type_close &&
|
|
||||||
strcmp(l->animation_type_close, "zoom") == 0)) {
|
|
||||||
// 算出要设置的绝对坐标和大小
|
|
||||||
fadeout_layer->current.width =
|
|
||||||
(float)l->animation.current.width * zoom_end_ratio;
|
|
||||||
fadeout_layer->current.height =
|
|
||||||
(float)l->animation.current.height * zoom_end_ratio;
|
|
||||||
fadeout_layer->current.x = usable_area.x + usable_area.width / 2 -
|
|
||||||
fadeout_layer->current.width / 2;
|
|
||||||
fadeout_layer->current.y = usable_area.y + usable_area.height / 2 -
|
|
||||||
fadeout_layer->current.height / 2;
|
|
||||||
// 算出偏差坐标,大小不用因为后续不使用他的大小偏差去设置,而是直接缩放buffer
|
|
||||||
fadeout_layer->current.x =
|
|
||||||
fadeout_layer->current.x - l->animation.current.x;
|
|
||||||
fadeout_layer->current.y =
|
|
||||||
fadeout_layer->current.y - l->animation.current.y;
|
|
||||||
|
|
||||||
} else if ((!l->animation_type_close &&
|
|
||||||
strcmp(layer_animation_type_close, "slide") == 0) ||
|
|
||||||
(l->animation_type_close &&
|
|
||||||
strcmp(l->animation_type_close, "slide") == 0)) {
|
|
||||||
// 获取slide动画的结束绝对坐标和大小
|
|
||||||
set_layer_dir_animaiton(l, &fadeout_layer->current);
|
|
||||||
// 算出也能够有设置的偏差坐标和大小
|
|
||||||
fadeout_layer->current.x = fadeout_layer->current.x - l->geom.x;
|
|
||||||
fadeout_layer->current.y = fadeout_layer->current.y - l->geom.y;
|
|
||||||
fadeout_layer->current.width =
|
|
||||||
fadeout_layer->current.width - l->geom.width;
|
|
||||||
fadeout_layer->current.height =
|
|
||||||
fadeout_layer->current.height - l->geom.height;
|
|
||||||
} else {
|
|
||||||
// fade动画坐标大小不用变
|
|
||||||
fadeout_layer->current.x = 0;
|
|
||||||
fadeout_layer->current.y = 0;
|
|
||||||
fadeout_layer->current.width = 0;
|
|
||||||
fadeout_layer->current.height = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 动画开始时间
|
|
||||||
fadeout_layer->animation.time_started = get_now_in_ms();
|
|
||||||
|
|
||||||
// 将节点插入到关闭动画链表中,屏幕刷新哪里会检查链表中是否有节点可以应用于动画
|
|
||||||
wlr_scene_node_set_enabled(&fadeout_layer->scene->node, true);
|
|
||||||
wl_list_insert(&server.fadeout_layers, &fadeout_layer->fadeout_link);
|
|
||||||
|
|
||||||
// 请求刷新屏幕
|
|
||||||
if (l->mon)
|
|
||||||
wlr_output_schedule_frame(l->mon->wlr_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_set_pending_state(LayerSurface *l) {
|
|
||||||
|
|
||||||
if (!l || !l->mapped)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct wlr_box usable_area;
|
|
||||||
get_layer_area_bound(l, &usable_area);
|
|
||||||
|
|
||||||
l->pending = l->geom;
|
|
||||||
|
|
||||||
if (l->animation.action == OPEN && !l->animation.running) {
|
|
||||||
|
|
||||||
if ((!l->animation_type_open &&
|
|
||||||
strcmp(layer_animation_type_open, "zoom") == 0) ||
|
|
||||||
(l->animation_type_open &&
|
|
||||||
strcmp(l->animation_type_open, "zoom") == 0)) {
|
|
||||||
l->animainit_geom.width = l->geom.width * zoom_initial_ratio;
|
|
||||||
l->animainit_geom.height = l->geom.height * zoom_initial_ratio;
|
|
||||||
l->animainit_geom.x = usable_area.x + usable_area.width / 2 -
|
|
||||||
l->animainit_geom.width / 2;
|
|
||||||
l->animainit_geom.y = usable_area.y + usable_area.height / 2 -
|
|
||||||
l->animainit_geom.height / 2;
|
|
||||||
} else if ((!l->animation_type_open &&
|
|
||||||
strcmp(layer_animation_type_open, "slide") == 0) ||
|
|
||||||
(l->animation_type_open &&
|
|
||||||
strcmp(l->animation_type_open, "slide") == 0)) {
|
|
||||||
|
|
||||||
set_layer_dir_animaiton(l, &l->animainit_geom);
|
|
||||||
} else {
|
|
||||||
l->animainit_geom.x = l->geom.x;
|
|
||||||
l->animainit_geom.y = l->geom.y;
|
|
||||||
l->animainit_geom.width = l->geom.width;
|
|
||||||
l->animainit_geom.height = l->geom.height;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
l->animainit_geom = l->animation.current;
|
|
||||||
}
|
|
||||||
// 判断是否需要动画
|
|
||||||
if (!animations || !layer_animations || l->noanim ||
|
|
||||||
l->layer_surface->current.layer ==
|
|
||||||
ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ||
|
|
||||||
l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) {
|
|
||||||
l->animation.should_animate = false;
|
|
||||||
} else {
|
|
||||||
l->animation.should_animate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((l->animation_type_open &&
|
|
||||||
strcmp(l->animation_type_open, "none") == 0) ||
|
|
||||||
(!l->animation_type_open &&
|
|
||||||
strcmp(layer_animation_type_open, "none") == 0)) &&
|
|
||||||
l->animation.action == OPEN) {
|
|
||||||
l->animation.should_animate = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始动画
|
|
||||||
layer_commit(l);
|
|
||||||
l->dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_commit(LayerSurface *l) {
|
|
||||||
|
|
||||||
if (!l || !l->mapped)
|
|
||||||
return;
|
|
||||||
|
|
||||||
l->current = l->pending; // 设置动画的结束位置
|
|
||||||
|
|
||||||
if (l->animation.should_animate) {
|
|
||||||
if (!l->animation.running) {
|
|
||||||
l->animation.current = l->animainit_geom;
|
|
||||||
}
|
|
||||||
|
|
||||||
l->animation.initial = l->animainit_geom;
|
|
||||||
l->animation.time_started = get_now_in_ms();
|
|
||||||
|
|
||||||
// 标记动画开始
|
|
||||||
l->animation.running = true;
|
|
||||||
l->animation.should_animate = false;
|
|
||||||
}
|
|
||||||
// 请求刷新屏幕
|
|
||||||
if (l->mon)
|
|
||||||
wlr_output_schedule_frame(l->mon->wlr_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool layer_draw_frame(LayerSurface *l) {
|
|
||||||
|
|
||||||
if (!l || !l->mapped)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!l->need_output_flush)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (l->layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_TOP &&
|
|
||||||
l->layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (animations && layer_animations && l->animation.running && !l->noanim) {
|
|
||||||
layer_animation_next_tick(l);
|
|
||||||
layer_draw_shadow(l);
|
|
||||||
} else {
|
|
||||||
layer_draw_shadow(l);
|
|
||||||
l->need_output_flush = false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool layer_draw_fadeout_frame(LayerSurface *l) {
|
|
||||||
if (!l)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
fadeout_layer_animation_next_tick(l);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
98
src/animation/tag.c
Normal file
98
src/animation/tag.c
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
#include "../type.h"
|
||||||
|
#include "../client/client.h"
|
||||||
|
|
||||||
|
extern Server server;
|
||||||
|
|
||||||
|
void set_tagin_animation(Monitor *m, Client *c) {
|
||||||
|
if (c->animation.running) {
|
||||||
|
c->animainit_geom.x = c->animation.current.x;
|
||||||
|
c->animainit_geom.y = c->animation.current.y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->pertag->curtag > m->pertag->prevtag) {
|
||||||
|
|
||||||
|
c->animainit_geom.x = tag_animation_direction == VERTICAL
|
||||||
|
? c->animation.current.x
|
||||||
|
: MAX(c->mon->m.x + c->mon->m.width,
|
||||||
|
c->geom.x + c->mon->m.width);
|
||||||
|
c->animainit_geom.y = tag_animation_direction == VERTICAL
|
||||||
|
? MAX(c->mon->m.y + c->mon->m.height,
|
||||||
|
c->geom.y + c->mon->m.height)
|
||||||
|
: c->animation.current.y;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
c->animainit_geom.x =
|
||||||
|
tag_animation_direction == VERTICAL
|
||||||
|
? c->animation.current.x
|
||||||
|
: MIN(m->m.x - c->geom.width, c->geom.x - c->mon->m.width);
|
||||||
|
c->animainit_geom.y =
|
||||||
|
tag_animation_direction == VERTICAL
|
||||||
|
? MIN(m->m.y - c->geom.height, c->geom.y - c->mon->m.height)
|
||||||
|
: c->animation.current.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_arrange_visible(Monitor *m, Client *c, bool want_animation) {
|
||||||
|
|
||||||
|
if (!c->is_clip_to_hide || !ISTILED(c) || !is_scroller_layout(c->mon)) {
|
||||||
|
c->is_clip_to_hide = false;
|
||||||
|
wlr_scene_node_set_enabled(&c->scene->node, true);
|
||||||
|
wlr_scene_node_set_enabled(&c->scene_surface->node, true);
|
||||||
|
}
|
||||||
|
client_set_suspended(c, false);
|
||||||
|
|
||||||
|
if (!c->animation.tag_from_rule && want_animation &&
|
||||||
|
m->pertag->prevtag != 0 && m->pertag->curtag != 0 && animations) {
|
||||||
|
c->animation.tagining = true;
|
||||||
|
set_tagin_animation(m, c);
|
||||||
|
} else {
|
||||||
|
c->animainit_geom.x = c->animation.current.x;
|
||||||
|
c->animainit_geom.y = c->animation.current.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->animation.tag_from_rule = false;
|
||||||
|
c->animation.tagouting = false;
|
||||||
|
c->animation.tagouted = false;
|
||||||
|
resize(c, c->geom, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_tagout_animation(Monitor *m, Client *c) {
|
||||||
|
if (m->pertag->curtag > m->pertag->prevtag) {
|
||||||
|
c->pending = c->geom;
|
||||||
|
c->pending.x =
|
||||||
|
tag_animation_direction == VERTICAL
|
||||||
|
? c->animation.current.x
|
||||||
|
: MIN(c->mon->m.x - c->geom.width, c->geom.x - c->mon->m.width);
|
||||||
|
c->pending.y = tag_animation_direction == VERTICAL
|
||||||
|
? MIN(c->mon->m.y - c->geom.height,
|
||||||
|
c->geom.y - c->mon->m.height)
|
||||||
|
: c->animation.current.y;
|
||||||
|
|
||||||
|
resize(c, c->geom, 0);
|
||||||
|
} else {
|
||||||
|
c->pending = c->geom;
|
||||||
|
c->pending.x = tag_animation_direction == VERTICAL
|
||||||
|
? c->animation.current.x
|
||||||
|
: MAX(c->mon->m.x + c->mon->m.width,
|
||||||
|
c->geom.x + c->mon->m.width);
|
||||||
|
c->pending.y = tag_animation_direction == VERTICAL
|
||||||
|
? MAX(c->mon->m.y + c->mon->m.height,
|
||||||
|
c->geom.y + c->mon->m.height)
|
||||||
|
: c->animation.current.y;
|
||||||
|
resize(c, c->geom, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_arrange_hidden(Monitor *m, Client *c, bool want_animation) {
|
||||||
|
if ((c->tags & (1 << (m->pertag->prevtag - 1))) &&
|
||||||
|
m->pertag->prevtag != 0 && m->pertag->curtag != 0 && animations) {
|
||||||
|
c->animation.tagouting = true;
|
||||||
|
c->animation.tagining = false;
|
||||||
|
set_tagout_animation(m, c);
|
||||||
|
} else {
|
||||||
|
wlr_scene_node_set_enabled(&c->scene->node, false);
|
||||||
|
client_set_suspended(c, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,93 +1,10 @@
|
||||||
void set_tagin_animation(Monitor *m, Client *c) {
|
#ifndef MANGO_ANIMATION_TAG_H
|
||||||
if (c->animation.running) {
|
#define MANGO_ANIMATION_TAG_H
|
||||||
c->animainit_geom.x = c->animation.current.x;
|
|
||||||
c->animainit_geom.y = c->animation.current.y;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m->pertag->curtag > m->pertag->prevtag) {
|
// 标签切换动画函数
|
||||||
|
void set_tagin_animation(Monitor *m, Client *c);
|
||||||
|
void set_arrange_visible(Monitor *m, Client *c, bool want_animation);
|
||||||
|
void set_tagout_animation(Monitor *m, Client *c);
|
||||||
|
void set_arrange_hidden(Monitor *m, Client *c, bool want_animation);
|
||||||
|
|
||||||
c->animainit_geom.x = tag_animation_direction == VERTICAL
|
#endif // MANGO_ANIMATION_TAG_H
|
||||||
? c->animation.current.x
|
|
||||||
: MAX(c->mon->m.x + c->mon->m.width,
|
|
||||||
c->geom.x + c->mon->m.width);
|
|
||||||
c->animainit_geom.y = tag_animation_direction == VERTICAL
|
|
||||||
? MAX(c->mon->m.y + c->mon->m.height,
|
|
||||||
c->geom.y + c->mon->m.height)
|
|
||||||
: c->animation.current.y;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
c->animainit_geom.x =
|
|
||||||
tag_animation_direction == VERTICAL
|
|
||||||
? c->animation.current.x
|
|
||||||
: MIN(m->m.x - c->geom.width, c->geom.x - c->mon->m.width);
|
|
||||||
c->animainit_geom.y =
|
|
||||||
tag_animation_direction == VERTICAL
|
|
||||||
? MIN(m->m.y - c->geom.height, c->geom.y - c->mon->m.height)
|
|
||||||
: c->animation.current.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_arrange_visible(Monitor *m, Client *c, bool want_animation) {
|
|
||||||
|
|
||||||
if (!c->is_clip_to_hide || !ISTILED(c) || !is_scroller_layout(c->mon)) {
|
|
||||||
c->is_clip_to_hide = false;
|
|
||||||
wlr_scene_node_set_enabled(&c->scene->node, true);
|
|
||||||
wlr_scene_node_set_enabled(&c->scene_surface->node, true);
|
|
||||||
}
|
|
||||||
client_set_suspended(c, false);
|
|
||||||
|
|
||||||
if (!c->animation.tag_from_rule && want_animation &&
|
|
||||||
m->pertag->prevtag != 0 && m->pertag->curtag != 0 && animations) {
|
|
||||||
c->animation.tagining = true;
|
|
||||||
set_tagin_animation(m, c);
|
|
||||||
} else {
|
|
||||||
c->animainit_geom.x = c->animation.current.x;
|
|
||||||
c->animainit_geom.y = c->animation.current.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->animation.tag_from_rule = false;
|
|
||||||
c->animation.tagouting = false;
|
|
||||||
c->animation.tagouted = false;
|
|
||||||
resize(c, c->geom, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_tagout_animation(Monitor *m, Client *c) {
|
|
||||||
if (m->pertag->curtag > m->pertag->prevtag) {
|
|
||||||
c->pending = c->geom;
|
|
||||||
c->pending.x =
|
|
||||||
tag_animation_direction == VERTICAL
|
|
||||||
? c->animation.current.x
|
|
||||||
: MIN(c->mon->m.x - c->geom.width, c->geom.x - c->mon->m.width);
|
|
||||||
c->pending.y = tag_animation_direction == VERTICAL
|
|
||||||
? MIN(c->mon->m.y - c->geom.height,
|
|
||||||
c->geom.y - c->mon->m.height)
|
|
||||||
: c->animation.current.y;
|
|
||||||
|
|
||||||
resize(c, c->geom, 0);
|
|
||||||
} else {
|
|
||||||
c->pending = c->geom;
|
|
||||||
c->pending.x = tag_animation_direction == VERTICAL
|
|
||||||
? c->animation.current.x
|
|
||||||
: MAX(c->mon->m.x + c->mon->m.width,
|
|
||||||
c->geom.x + c->mon->m.width);
|
|
||||||
c->pending.y = tag_animation_direction == VERTICAL
|
|
||||||
? MAX(c->mon->m.y + c->mon->m.height,
|
|
||||||
c->geom.y + c->mon->m.height)
|
|
||||||
: c->animation.current.y;
|
|
||||||
resize(c, c->geom, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_arrange_hidden(Monitor *m, Client *c, bool want_animation) {
|
|
||||||
if ((c->tags & (1 << (m->pertag->prevtag - 1))) &&
|
|
||||||
m->pertag->prevtag != 0 && m->pertag->curtag != 0 && animations) {
|
|
||||||
c->animation.tagouting = true;
|
|
||||||
c->animation.tagining = false;
|
|
||||||
set_tagout_animation(m, c);
|
|
||||||
} else {
|
|
||||||
wlr_scene_node_set_enabled(&c->scene->node, false);
|
|
||||||
client_set_suspended(c, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
546
src/client/client.c
Normal file
546
src/client/client.c
Normal file
|
|
@ -0,0 +1,546 @@
|
||||||
|
#include "../type.h"
|
||||||
|
|
||||||
|
extern Server server;
|
||||||
|
|
||||||
|
int32_t client_is_x11(Client *c) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
return c->type == X11;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_surface *client_surface(Client *c) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->surface;
|
||||||
|
#endif
|
||||||
|
return c->surface.xdg->surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t toplevel_from_wlr_surface(struct wlr_surface *s,
|
||||||
|
Client **pc,
|
||||||
|
LayerSurface **pl) {
|
||||||
|
struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface;
|
||||||
|
struct wlr_surface *root_surface;
|
||||||
|
struct wlr_layer_surface_v1 *layer_surface;
|
||||||
|
Client *c = NULL;
|
||||||
|
LayerSurface *l = NULL;
|
||||||
|
int32_t type = -1;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
struct wlr_xwayland_surface *xsurface;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
return -1;
|
||||||
|
root_surface = wlr_surface_get_root_surface(s);
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(root_surface))) {
|
||||||
|
c = xsurface->data;
|
||||||
|
type = c->type;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((layer_surface =
|
||||||
|
wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) {
|
||||||
|
l = layer_surface->data;
|
||||||
|
type = LayerShell;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
xdg_surface = wlr_xdg_surface_try_from_wlr_surface(root_surface);
|
||||||
|
while (xdg_surface) {
|
||||||
|
tmp_xdg_surface = NULL;
|
||||||
|
switch (xdg_surface->role) {
|
||||||
|
case WLR_XDG_SURFACE_ROLE_POPUP:
|
||||||
|
if (!xdg_surface->popup || !xdg_surface->popup->parent)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
tmp_xdg_surface = wlr_xdg_surface_try_from_wlr_surface(
|
||||||
|
xdg_surface->popup->parent);
|
||||||
|
|
||||||
|
if (!tmp_xdg_surface)
|
||||||
|
return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc,
|
||||||
|
pl);
|
||||||
|
|
||||||
|
xdg_surface = tmp_xdg_surface;
|
||||||
|
break;
|
||||||
|
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
|
||||||
|
c = xdg_surface->data;
|
||||||
|
type = c->type;
|
||||||
|
goto end;
|
||||||
|
case WLR_XDG_SURFACE_ROLE_NONE:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (pl)
|
||||||
|
*pl = l;
|
||||||
|
if (pc)
|
||||||
|
*pc = c;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The others */
|
||||||
|
void client_activate_surface(struct wlr_surface *s,
|
||||||
|
int32_t activated) {
|
||||||
|
struct wlr_xdg_toplevel *toplevel;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
struct wlr_xwayland_surface *xsurface;
|
||||||
|
if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) {
|
||||||
|
if (activated && xsurface->minimized)
|
||||||
|
wlr_xwayland_surface_set_minimized(xsurface, false);
|
||||||
|
wlr_xwayland_surface_activate(xsurface, activated);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if ((toplevel = wlr_xdg_toplevel_try_from_wlr_surface(s)))
|
||||||
|
wlr_xdg_toplevel_set_activated(toplevel, activated);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *client_get_appid(Client *c) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->class ? c->surface.xwayland->class
|
||||||
|
: "broken";
|
||||||
|
#endif
|
||||||
|
return c->surface.xdg->toplevel->app_id ? c->surface.xdg->toplevel->app_id
|
||||||
|
: "broken";
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_get_pid(Client *c) {
|
||||||
|
pid_t pid;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->pid;
|
||||||
|
#endif
|
||||||
|
wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_get_clip(Client *c, struct wlr_box *clip) {
|
||||||
|
*clip = (struct wlr_box){
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = c->geom.width - 2 * c->bw,
|
||||||
|
.height = c->geom.height - 2 * c->bw,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
clip->x = c->surface.xdg->geometry.x;
|
||||||
|
clip->y = c->surface.xdg->geometry.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_get_geometry(Client *c, struct wlr_box *geom) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
geom->x = c->surface.xwayland->x;
|
||||||
|
geom->y = c->surface.xwayland->y;
|
||||||
|
geom->width = c->surface.xwayland->width;
|
||||||
|
geom->height = c->surface.xwayland->height;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
*geom = c->surface.xdg->geometry;
|
||||||
|
}
|
||||||
|
|
||||||
|
Client *client_get_parent(Client *c) {
|
||||||
|
Client *p = NULL;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
if (c->surface.xwayland->parent)
|
||||||
|
toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p,
|
||||||
|
NULL);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (c->surface.xdg->toplevel->parent)
|
||||||
|
toplevel_from_wlr_surface(
|
||||||
|
c->surface.xdg->toplevel->parent->base->surface, &p, NULL);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_has_children(Client *c) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return !wl_list_empty(&c->surface.xwayland->children);
|
||||||
|
#endif
|
||||||
|
/* surface.xdg->link is never empty because it always contains at least the
|
||||||
|
* surface itself. */
|
||||||
|
return wl_list_length(&c->surface.xdg->link) > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *client_get_title(Client *c) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->title ? c->surface.xwayland->title
|
||||||
|
: "broken";
|
||||||
|
#endif
|
||||||
|
return c->surface.xdg->toplevel->title ? c->surface.xdg->toplevel->title
|
||||||
|
: "broken";
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_is_float_type(Client *c) {
|
||||||
|
struct wlr_xdg_toplevel *toplevel;
|
||||||
|
struct wlr_xdg_toplevel_state state;
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
||||||
|
xcb_size_hints_t *size_hints = surface->size_hints;
|
||||||
|
|
||||||
|
if (!size_hints)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (surface->modal)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (wlr_xwayland_surface_has_window_type(
|
||||||
|
surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DIALOG) ||
|
||||||
|
wlr_xwayland_surface_has_window_type(
|
||||||
|
surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH) ||
|
||||||
|
wlr_xwayland_surface_has_window_type(
|
||||||
|
surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLBAR) ||
|
||||||
|
wlr_xwayland_surface_has_window_type(
|
||||||
|
surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size_hints && size_hints->min_width > 0 &&
|
||||||
|
size_hints->min_height > 0 &&
|
||||||
|
(size_hints->max_width == size_hints->min_width ||
|
||||||
|
size_hints->max_height == size_hints->min_height);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
toplevel = c->surface.xdg->toplevel;
|
||||||
|
state = toplevel->current;
|
||||||
|
return toplevel->parent || (state.min_width != 0 && state.min_height != 0 &&
|
||||||
|
(state.min_width == state.max_width ||
|
||||||
|
state.min_height == state.max_height));
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_is_rendered_on_mon(Client *c, Monitor *m) {
|
||||||
|
/* This is needed for when you don't want to check formal assignment,
|
||||||
|
* but rather actual displaying of the pixels.
|
||||||
|
* Usually VISIBLEON suffices and is also faster. */
|
||||||
|
struct wlr_surface_output *s;
|
||||||
|
int32_t unused_lx, unused_ly;
|
||||||
|
if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly))
|
||||||
|
return 0;
|
||||||
|
wl_list_for_each(s, &client_surface(c)->current_outputs,
|
||||||
|
link) if (s->output == m->wlr_output) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_is_stopped(Client *c) {
|
||||||
|
int32_t pid;
|
||||||
|
siginfo_t in = {0};
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);
|
||||||
|
if (waitid(P_PID, pid, &in, WNOHANG | WCONTINUED | WSTOPPED | WNOWAIT) <
|
||||||
|
0) {
|
||||||
|
/* This process is not our child process, while is very unluckely that
|
||||||
|
* it is stopped, in order to do not skip frames assume that it is. */
|
||||||
|
if (errno == ECHILD)
|
||||||
|
return 1;
|
||||||
|
} else if (in.si_pid) {
|
||||||
|
if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED)
|
||||||
|
return 1;
|
||||||
|
if (in.si_code == CLD_CONTINUED)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_is_unmanaged(Client *c) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->override_redirect;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_notify_enter(struct wlr_surface *s,
|
||||||
|
struct wlr_keyboard *kb) {
|
||||||
|
if (kb)
|
||||||
|
wlr_seat_keyboard_notify_enter(server.seat, s, kb->keycodes,
|
||||||
|
kb->num_keycodes, &kb->modifiers);
|
||||||
|
else
|
||||||
|
wlr_seat_keyboard_notify_enter(server.seat, s, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_send_close(Client *c) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
wlr_xwayland_surface_close(c->surface.xwayland);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
wlr_xdg_toplevel_send_close(c->surface.xdg->toplevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_border_color(Client *c,
|
||||||
|
const float color[4]) {
|
||||||
|
wlr_scene_rect_set_color(c->border, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_fullscreen(Client *c, int32_t fullscreen) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_scale(struct wlr_surface *s, float scale) {
|
||||||
|
wlr_fractional_scale_v1_notify_scale(s, scale);
|
||||||
|
wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t client_set_size(Client *c, uint32_t width,
|
||||||
|
uint32_t height) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x + c->bw,
|
||||||
|
c->geom.y + c->bw, width, height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if ((int32_t)width == c->surface.xdg->toplevel->current.width &&
|
||||||
|
(int32_t)height == c->surface.xdg->toplevel->current.height)
|
||||||
|
return 0;
|
||||||
|
return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width,
|
||||||
|
(int32_t)height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_minimized(Client *c, bool minimized) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
wlr_xwayland_surface_set_minimized(c->surface.xwayland, minimized);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_maximized(Client *c, bool maximized) {
|
||||||
|
struct wlr_xdg_toplevel *toplevel;
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
wlr_xwayland_surface_set_maximized(c->surface.xwayland, maximized,
|
||||||
|
maximized);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
toplevel = c->surface.xdg->toplevel;
|
||||||
|
wlr_xdg_toplevel_set_maximized(toplevel, maximized);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_tiled(Client *c, uint32_t edges) {
|
||||||
|
struct wlr_xdg_toplevel *toplevel;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c) && c->force_maximize) {
|
||||||
|
wlr_xwayland_surface_set_maximized(c->surface.xwayland,
|
||||||
|
edges != WLR_EDGE_NONE,
|
||||||
|
edges != WLR_EDGE_NONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
toplevel = c->surface.xdg->toplevel;
|
||||||
|
|
||||||
|
if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >=
|
||||||
|
XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
|
||||||
|
wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->force_maximize) {
|
||||||
|
wlr_xdg_toplevel_set_maximized(toplevel, edges != WLR_EDGE_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_suspended(Client *c, int32_t suspended) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_should_ignore_focus(Client *c) {
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
||||||
|
|
||||||
|
if (!surface->hints)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return !surface->hints->input;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_is_x11_popup(Client *c) {
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
||||||
|
// 处理不需要焦点的窗口类型
|
||||||
|
const uint32_t no_focus_types[] = {
|
||||||
|
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_COMBO,
|
||||||
|
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DND,
|
||||||
|
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
|
||||||
|
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_MENU,
|
||||||
|
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_NOTIFICATION,
|
||||||
|
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_POPUP_MENU,
|
||||||
|
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH,
|
||||||
|
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLTIP,
|
||||||
|
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY};
|
||||||
|
// 检查窗口类型是否需要禁止焦点
|
||||||
|
for (size_t i = 0;
|
||||||
|
i < sizeof(no_focus_types) / sizeof(no_focus_types[0]); ++i) {
|
||||||
|
if (wlr_xwayland_surface_has_window_type(surface,
|
||||||
|
no_focus_types[i])) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_should_global(Client *c) {
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
||||||
|
|
||||||
|
if (surface->sticky)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_should_overtop(Client *c) {
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
||||||
|
if (surface->above)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_wants_focus(Client *c) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
return client_is_unmanaged(c) &&
|
||||||
|
wlr_xwayland_surface_override_redirect_wants_focus(
|
||||||
|
c->surface.xwayland) &&
|
||||||
|
wlr_xwayland_surface_icccm_input_model(c->surface.xwayland) !=
|
||||||
|
WLR_ICCCM_INPUT_MODEL_NONE;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t client_wants_fullscreen(Client *c) {
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->fullscreen;
|
||||||
|
#endif
|
||||||
|
return c->surface.xdg->toplevel->requested.fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool client_request_minimize(Client *c, void *data) {
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
struct wlr_xwayland_minimize_event *event = data;
|
||||||
|
return event->minimize;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return c->surface.xdg->toplevel->requested.minimized;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool client_request_maximize(Client *c, void *data) {
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
||||||
|
return surface->maximized_vert || surface->maximized_horz;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return c->surface.xdg->toplevel->requested.maximized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_size_bound(Client *c) {
|
||||||
|
struct wlr_xdg_toplevel *toplevel;
|
||||||
|
struct wlr_xdg_toplevel_state state;
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
||||||
|
xcb_size_hints_t *size_hints = surface->size_hints;
|
||||||
|
|
||||||
|
if (!size_hints)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((uint32_t)c->geom.width - 2 * c->bw < size_hints->min_width &&
|
||||||
|
size_hints->min_width > 0)
|
||||||
|
c->geom.width = size_hints->min_width + 2 * c->bw;
|
||||||
|
if ((uint32_t)c->geom.height - 2 * c->bw < size_hints->min_height &&
|
||||||
|
size_hints->min_height > 0)
|
||||||
|
c->geom.height = size_hints->min_height + 2 * c->bw;
|
||||||
|
if ((uint32_t)c->geom.width - 2 * c->bw > size_hints->max_width &&
|
||||||
|
size_hints->max_width > 0)
|
||||||
|
c->geom.width = size_hints->max_width + 2 * c->bw;
|
||||||
|
if ((uint32_t)c->geom.height - 2 * c->bw > size_hints->max_height &&
|
||||||
|
size_hints->max_height > 0)
|
||||||
|
c->geom.height = size_hints->max_height + 2 * c->bw;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
toplevel = c->surface.xdg->toplevel;
|
||||||
|
state = toplevel->current;
|
||||||
|
if ((uint32_t)c->geom.width - 2 * c->bw < state.min_width &&
|
||||||
|
state.min_width > 0) {
|
||||||
|
c->geom.width = state.min_width + 2 * c->bw;
|
||||||
|
}
|
||||||
|
if ((uint32_t)c->geom.height - 2 * c->bw < state.min_height &&
|
||||||
|
state.min_height > 0) {
|
||||||
|
c->geom.height = state.min_height + 2 * c->bw;
|
||||||
|
}
|
||||||
|
if ((uint32_t)c->geom.width - 2 * c->bw > state.max_width &&
|
||||||
|
state.max_width > 0) {
|
||||||
|
c->geom.width = state.max_width + 2 * c->bw;
|
||||||
|
}
|
||||||
|
if ((uint32_t)c->geom.height - 2 * c->bw > state.max_height &&
|
||||||
|
state.max_height > 0) {
|
||||||
|
c->geom.height = state.max_height + 2 * c->bw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,550 +1,50 @@
|
||||||
/*
|
#ifndef MANGO_CLIENT_CLIENT_H
|
||||||
* Attempt to consolidate unavoidable suck into one file, away from dwl.c. This
|
#define MANGO_CLIENT_CLIENT_H
|
||||||
* file is not meant to be pretty. We use a .h file with static inline
|
|
||||||
* functions instead of a separate .c module, or function pointers like sway, so
|
/* 基础客户端类型检测和表面处理 */
|
||||||
* that they will simply compile out if the chosen #defines leave them unused.
|
int32_t client_is_x11(Client *c);
|
||||||
*/
|
struct wlr_surface *client_surface(Client *c);
|
||||||
|
int32_t toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl);
|
||||||
/* Leave these functions first; they're used in the others */
|
|
||||||
static inline int32_t client_is_x11(Client *c) {
|
/* 客户端激活和焦点控制 */
|
||||||
#ifdef XWAYLAND
|
void client_activate_surface(struct wlr_surface *s, int32_t activated);
|
||||||
return c->type == X11;
|
void client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb);
|
||||||
#endif
|
int32_t client_should_ignore_focus(Client *c);
|
||||||
return 0;
|
int32_t client_is_x11_popup(Client *c);
|
||||||
}
|
int32_t client_wants_focus(Client *c);
|
||||||
|
|
||||||
static inline struct wlr_surface *client_surface(Client *c) {
|
/* 客户端信息获取 */
|
||||||
#ifdef XWAYLAND
|
const char *client_get_appid(Client *c);
|
||||||
if (client_is_x11(c))
|
int32_t client_get_pid(Client *c);
|
||||||
return c->surface.xwayland->surface;
|
const char *client_get_title(Client *c);
|
||||||
#endif
|
Client *client_get_parent(Client *c);
|
||||||
return c->surface.xdg->surface;
|
int32_t client_has_children(Client *c);
|
||||||
}
|
int32_t client_is_float_type(Client *c);
|
||||||
|
int32_t client_is_rendered_on_mon(Client *c, Monitor *m);
|
||||||
static inline int32_t toplevel_from_wlr_surface(struct wlr_surface *s,
|
int32_t client_is_stopped(Client *c);
|
||||||
Client **pc,
|
int32_t client_is_unmanaged(Client *c);
|
||||||
LayerSurface **pl) {
|
int32_t client_wants_fullscreen(Client *c);
|
||||||
struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface;
|
bool client_request_minimize(Client *c, void *data);
|
||||||
struct wlr_surface *root_surface;
|
bool client_request_maximize(Client *c, void *data);
|
||||||
struct wlr_layer_surface_v1 *layer_surface;
|
|
||||||
Client *c = NULL;
|
/* 客户端几何和布局 */
|
||||||
LayerSurface *l = NULL;
|
void client_get_clip(Client *c, struct wlr_box *clip);
|
||||||
int32_t type = -1;
|
void client_get_geometry(Client *c, struct wlr_box *geom);
|
||||||
#ifdef XWAYLAND
|
void client_set_size_bound(Client *c);
|
||||||
struct wlr_xwayland_surface *xsurface;
|
|
||||||
#endif
|
/* 客户端状态设置 */
|
||||||
|
void client_send_close(Client *c);
|
||||||
if (!s)
|
void client_set_border_color(Client *c, const float color[4]);
|
||||||
return -1;
|
void client_set_fullscreen(Client *c, int32_t fullscreen);
|
||||||
root_surface = wlr_surface_get_root_surface(s);
|
void client_set_scale(struct wlr_surface *s, float scale);
|
||||||
|
uint32_t client_set_size(Client *c, uint32_t width, uint32_t height);
|
||||||
#ifdef XWAYLAND
|
void client_set_minimized(Client *c, bool minimized);
|
||||||
if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(root_surface))) {
|
void client_set_maximized(Client *c, bool maximized);
|
||||||
c = xsurface->data;
|
void client_set_tiled(Client *c, uint32_t edges);
|
||||||
type = c->type;
|
void client_set_suspended(Client *c, int32_t suspended);
|
||||||
goto end;
|
|
||||||
}
|
/* 特殊客户端行为 */
|
||||||
#endif
|
int32_t client_should_global(Client *c);
|
||||||
|
int32_t client_should_overtop(Client *c);
|
||||||
if ((layer_surface =
|
|
||||||
wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) {
|
#endif // MANGO_CLIENT_CLIENT_H
|
||||||
l = layer_surface->data;
|
|
||||||
type = LayerShell;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
xdg_surface = wlr_xdg_surface_try_from_wlr_surface(root_surface);
|
|
||||||
while (xdg_surface) {
|
|
||||||
tmp_xdg_surface = NULL;
|
|
||||||
switch (xdg_surface->role) {
|
|
||||||
case WLR_XDG_SURFACE_ROLE_POPUP:
|
|
||||||
if (!xdg_surface->popup || !xdg_surface->popup->parent)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
tmp_xdg_surface = wlr_xdg_surface_try_from_wlr_surface(
|
|
||||||
xdg_surface->popup->parent);
|
|
||||||
|
|
||||||
if (!tmp_xdg_surface)
|
|
||||||
return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc,
|
|
||||||
pl);
|
|
||||||
|
|
||||||
xdg_surface = tmp_xdg_surface;
|
|
||||||
break;
|
|
||||||
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
|
|
||||||
c = xdg_surface->data;
|
|
||||||
type = c->type;
|
|
||||||
goto end;
|
|
||||||
case WLR_XDG_SURFACE_ROLE_NONE:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
if (pl)
|
|
||||||
*pl = l;
|
|
||||||
if (pc)
|
|
||||||
*pc = c;
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The others */
|
|
||||||
static inline void client_activate_surface(struct wlr_surface *s,
|
|
||||||
int32_t activated) {
|
|
||||||
struct wlr_xdg_toplevel *toplevel;
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
struct wlr_xwayland_surface *xsurface;
|
|
||||||
if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) {
|
|
||||||
if (activated && xsurface->minimized)
|
|
||||||
wlr_xwayland_surface_set_minimized(xsurface, false);
|
|
||||||
wlr_xwayland_surface_activate(xsurface, activated);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ((toplevel = wlr_xdg_toplevel_try_from_wlr_surface(s)))
|
|
||||||
wlr_xdg_toplevel_set_activated(toplevel, activated);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline const char *client_get_appid(Client *c) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c))
|
|
||||||
return c->surface.xwayland->class ? c->surface.xwayland->class
|
|
||||||
: "broken";
|
|
||||||
#endif
|
|
||||||
return c->surface.xdg->toplevel->app_id ? c->surface.xdg->toplevel->app_id
|
|
||||||
: "broken";
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_get_pid(Client *c) {
|
|
||||||
pid_t pid;
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c))
|
|
||||||
return c->surface.xwayland->pid;
|
|
||||||
#endif
|
|
||||||
wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_get_clip(Client *c, struct wlr_box *clip) {
|
|
||||||
*clip = (struct wlr_box){
|
|
||||||
.x = 0,
|
|
||||||
.y = 0,
|
|
||||||
.width = c->geom.width - 2 * c->bw,
|
|
||||||
.height = c->geom.height - 2 * c->bw,
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c))
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
clip->x = c->surface.xdg->geometry.x;
|
|
||||||
clip->y = c->surface.xdg->geometry.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_get_geometry(Client *c, struct wlr_box *geom) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
geom->x = c->surface.xwayland->x;
|
|
||||||
geom->y = c->surface.xwayland->y;
|
|
||||||
geom->width = c->surface.xwayland->width;
|
|
||||||
geom->height = c->surface.xwayland->height;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
*geom = c->surface.xdg->geometry;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Client *client_get_parent(Client *c) {
|
|
||||||
Client *p = NULL;
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
if (c->surface.xwayland->parent)
|
|
||||||
toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p,
|
|
||||||
NULL);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (c->surface.xdg->toplevel->parent)
|
|
||||||
toplevel_from_wlr_surface(
|
|
||||||
c->surface.xdg->toplevel->parent->base->surface, &p, NULL);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_has_children(Client *c) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c))
|
|
||||||
return !wl_list_empty(&c->surface.xwayland->children);
|
|
||||||
#endif
|
|
||||||
/* surface.xdg->link is never empty because it always contains at least the
|
|
||||||
* surface itself. */
|
|
||||||
return wl_list_length(&c->surface.xdg->link) > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline const char *client_get_title(Client *c) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c))
|
|
||||||
return c->surface.xwayland->title ? c->surface.xwayland->title
|
|
||||||
: "broken";
|
|
||||||
#endif
|
|
||||||
return c->surface.xdg->toplevel->title ? c->surface.xdg->toplevel->title
|
|
||||||
: "broken";
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_is_float_type(Client *c) {
|
|
||||||
struct wlr_xdg_toplevel *toplevel;
|
|
||||||
struct wlr_xdg_toplevel_state state;
|
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
|
||||||
xcb_size_hints_t *size_hints = surface->size_hints;
|
|
||||||
|
|
||||||
if (!size_hints)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (surface->modal)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (wlr_xwayland_surface_has_window_type(
|
|
||||||
surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DIALOG) ||
|
|
||||||
wlr_xwayland_surface_has_window_type(
|
|
||||||
surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH) ||
|
|
||||||
wlr_xwayland_surface_has_window_type(
|
|
||||||
surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLBAR) ||
|
|
||||||
wlr_xwayland_surface_has_window_type(
|
|
||||||
surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return size_hints && size_hints->min_width > 0 &&
|
|
||||||
size_hints->min_height > 0 &&
|
|
||||||
(size_hints->max_width == size_hints->min_width ||
|
|
||||||
size_hints->max_height == size_hints->min_height);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
toplevel = c->surface.xdg->toplevel;
|
|
||||||
state = toplevel->current;
|
|
||||||
return toplevel->parent || (state.min_width != 0 && state.min_height != 0 &&
|
|
||||||
(state.min_width == state.max_width ||
|
|
||||||
state.min_height == state.max_height));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_is_rendered_on_mon(Client *c, Monitor *m) {
|
|
||||||
/* This is needed for when you don't want to check formal assignment,
|
|
||||||
* but rather actual displaying of the pixels.
|
|
||||||
* Usually VISIBLEON suffices and is also faster. */
|
|
||||||
struct wlr_surface_output *s;
|
|
||||||
int32_t unused_lx, unused_ly;
|
|
||||||
if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly))
|
|
||||||
return 0;
|
|
||||||
wl_list_for_each(s, &client_surface(c)->current_outputs,
|
|
||||||
link) if (s->output == m->wlr_output) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_is_stopped(Client *c) {
|
|
||||||
int32_t pid;
|
|
||||||
siginfo_t in = {0};
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c))
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);
|
|
||||||
if (waitid(P_PID, pid, &in, WNOHANG | WCONTINUED | WSTOPPED | WNOWAIT) <
|
|
||||||
0) {
|
|
||||||
/* This process is not our child process, while is very unluckely that
|
|
||||||
* it is stopped, in order to do not skip frames assume that it is. */
|
|
||||||
if (errno == ECHILD)
|
|
||||||
return 1;
|
|
||||||
} else if (in.si_pid) {
|
|
||||||
if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED)
|
|
||||||
return 1;
|
|
||||||
if (in.si_code == CLD_CONTINUED)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_is_unmanaged(Client *c) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c))
|
|
||||||
return c->surface.xwayland->override_redirect;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_notify_enter(struct wlr_surface *s,
|
|
||||||
struct wlr_keyboard *kb) {
|
|
||||||
if (kb)
|
|
||||||
wlr_seat_keyboard_notify_enter(server.seat, s, kb->keycodes,
|
|
||||||
kb->num_keycodes, &kb->modifiers);
|
|
||||||
else
|
|
||||||
wlr_seat_keyboard_notify_enter(server.seat, s, NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_send_close(Client *c) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
wlr_xwayland_surface_close(c->surface.xwayland);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
wlr_xdg_toplevel_send_close(c->surface.xdg->toplevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_set_border_color(Client *c,
|
|
||||||
const float color[static 4]) {
|
|
||||||
wlr_scene_rect_set_color(c->border, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_set_fullscreen(Client *c, int32_t fullscreen) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_set_scale(struct wlr_surface *s, float scale) {
|
|
||||||
wlr_fractional_scale_v1_notify_scale(s, scale);
|
|
||||||
wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t client_set_size(Client *c, uint32_t width,
|
|
||||||
uint32_t height) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x + c->bw,
|
|
||||||
c->geom.y + c->bw, width, height);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ((int32_t)width == c->surface.xdg->toplevel->current.width &&
|
|
||||||
(int32_t)height == c->surface.xdg->toplevel->current.height)
|
|
||||||
return 0;
|
|
||||||
return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width,
|
|
||||||
(int32_t)height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_set_minimized(Client *c, bool minimized) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
wlr_xwayland_surface_set_minimized(c->surface.xwayland, minimized);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_set_maximized(Client *c, bool maximized) {
|
|
||||||
struct wlr_xdg_toplevel *toplevel;
|
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
wlr_xwayland_surface_set_maximized(c->surface.xwayland, maximized,
|
|
||||||
maximized);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
toplevel = c->surface.xdg->toplevel;
|
|
||||||
wlr_xdg_toplevel_set_maximized(toplevel, maximized);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
wlr_xwayland_surface_set_maximized(c->surface.xwayland,
|
|
||||||
edges != WLR_EDGE_NONE,
|
|
||||||
edges != WLR_EDGE_NONE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
toplevel = c->surface.xdg->toplevel;
|
|
||||||
|
|
||||||
if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >=
|
|
||||||
XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
|
|
||||||
wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->force_maximize) {
|
|
||||||
wlr_xdg_toplevel_set_maximized(toplevel, edges != WLR_EDGE_NONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_set_suspended(Client *c, int32_t suspended) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c))
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_should_ignore_focus(Client *c) {
|
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
|
||||||
|
|
||||||
if (!surface->hints)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return !surface->hints->input;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_is_x11_popup(Client *c) {
|
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
|
||||||
// 处理不需要焦点的窗口类型
|
|
||||||
const uint32_t no_focus_types[] = {
|
|
||||||
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_COMBO,
|
|
||||||
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DND,
|
|
||||||
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
|
|
||||||
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_MENU,
|
|
||||||
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_NOTIFICATION,
|
|
||||||
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_POPUP_MENU,
|
|
||||||
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH,
|
|
||||||
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLTIP,
|
|
||||||
WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY};
|
|
||||||
// 检查窗口类型是否需要禁止焦点
|
|
||||||
for (size_t i = 0;
|
|
||||||
i < sizeof(no_focus_types) / sizeof(no_focus_types[0]); ++i) {
|
|
||||||
if (wlr_xwayland_surface_has_window_type(surface,
|
|
||||||
no_focus_types[i])) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_should_global(Client *c) {
|
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
|
||||||
|
|
||||||
if (surface->sticky)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_should_overtop(Client *c) {
|
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
|
||||||
if (surface->above)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_wants_focus(Client *c) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
return client_is_unmanaged(c) &&
|
|
||||||
wlr_xwayland_surface_override_redirect_wants_focus(
|
|
||||||
c->surface.xwayland) &&
|
|
||||||
wlr_xwayland_surface_icccm_input_model(c->surface.xwayland) !=
|
|
||||||
WLR_ICCCM_INPUT_MODEL_NONE;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t client_wants_fullscreen(Client *c) {
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c))
|
|
||||||
return c->surface.xwayland->fullscreen;
|
|
||||||
#endif
|
|
||||||
return c->surface.xdg->toplevel->requested.fullscreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool client_request_minimize(Client *c, void *data) {
|
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
struct wlr_xwayland_minimize_event *event = data;
|
|
||||||
return event->minimize;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return c->surface.xdg->toplevel->requested.minimized;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool client_request_maximize(Client *c, void *data) {
|
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
|
||||||
return surface->maximized_vert || surface->maximized_horz;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return c->surface.xdg->toplevel->requested.maximized;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void client_set_size_bound(Client *c) {
|
|
||||||
struct wlr_xdg_toplevel *toplevel;
|
|
||||||
struct wlr_xdg_toplevel_state state;
|
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
if (client_is_x11(c)) {
|
|
||||||
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
|
||||||
xcb_size_hints_t *size_hints = surface->size_hints;
|
|
||||||
|
|
||||||
if (!size_hints)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((uint32_t)c->geom.width - 2 * c->bw < size_hints->min_width &&
|
|
||||||
size_hints->min_width > 0)
|
|
||||||
c->geom.width = size_hints->min_width + 2 * c->bw;
|
|
||||||
if ((uint32_t)c->geom.height - 2 * c->bw < size_hints->min_height &&
|
|
||||||
size_hints->min_height > 0)
|
|
||||||
c->geom.height = size_hints->min_height + 2 * c->bw;
|
|
||||||
if ((uint32_t)c->geom.width - 2 * c->bw > size_hints->max_width &&
|
|
||||||
size_hints->max_width > 0)
|
|
||||||
c->geom.width = size_hints->max_width + 2 * c->bw;
|
|
||||||
if ((uint32_t)c->geom.height - 2 * c->bw > size_hints->max_height &&
|
|
||||||
size_hints->max_height > 0)
|
|
||||||
c->geom.height = size_hints->max_height + 2 * c->bw;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
toplevel = c->surface.xdg->toplevel;
|
|
||||||
state = toplevel->current;
|
|
||||||
if ((uint32_t)c->geom.width - 2 * c->bw < state.min_width &&
|
|
||||||
state.min_width > 0) {
|
|
||||||
c->geom.width = state.min_width + 2 * c->bw;
|
|
||||||
}
|
|
||||||
if ((uint32_t)c->geom.height - 2 * c->bw < state.min_height &&
|
|
||||||
state.min_height > 0) {
|
|
||||||
c->geom.height = state.min_height + 2 * c->bw;
|
|
||||||
}
|
|
||||||
if ((uint32_t)c->geom.width - 2 * c->bw > state.max_width &&
|
|
||||||
state.max_width > 0) {
|
|
||||||
c->geom.width = state.max_width + 2 * c->bw;
|
|
||||||
}
|
|
||||||
if ((uint32_t)c->geom.height - 2 * c->bw > state.max_height &&
|
|
||||||
state.max_height > 0) {
|
|
||||||
c->geom.height = state.max_height + 2 * c->bw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3403
src/config/parse_config.c
Normal file
3403
src/config/parse_config.c
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -126,7 +126,7 @@ char xkb_rules_variant[256];
|
||||||
char xkb_rules_options[256];
|
char xkb_rules_options[256];
|
||||||
|
|
||||||
/* keyboard */
|
/* keyboard */
|
||||||
static const struct xkb_rule_names xkb_fallback_rules = {
|
const struct xkb_rule_names xkb_fallback_rules = {
|
||||||
.layout = "us",
|
.layout = "us",
|
||||||
.variant = NULL,
|
.variant = NULL,
|
||||||
.model = NULL,
|
.model = NULL,
|
||||||
|
|
@ -134,7 +134,7 @@ static const struct xkb_rule_names xkb_fallback_rules = {
|
||||||
.options = NULL,
|
.options = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct xkb_rule_names xkb_default_rules = {
|
const struct xkb_rule_names xkb_default_rules = {
|
||||||
.options = NULL,
|
.options = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -206,7 +206,7 @@ enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
|
||||||
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
|
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
|
||||||
#define MODKEY WLR_MODIFIER_ALT
|
#define MODKEY WLR_MODIFIER_ALT
|
||||||
|
|
||||||
static const char *tags[] = {
|
const char *tags[] = {
|
||||||
"1", "2", "3", "4", "5", "6", "7", "8", "9",
|
"1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ typedef struct {
|
||||||
const char *abbr; // 全部使用小写
|
const char *abbr; // 全部使用小写
|
||||||
} LayoutMapping;
|
} LayoutMapping;
|
||||||
|
|
||||||
static const LayoutMapping layout_mappings[] = {
|
const LayoutMapping layout_mappings[] = {
|
||||||
{"English (US)", "us"},
|
{"English (US)", "us"},
|
||||||
{"English (UK)", "gb"},
|
{"English (UK)", "gb"},
|
||||||
{"Russian", "ru"},
|
{"Russian", "ru"},
|
||||||
|
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
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 toggleoverview(const Arg *arg);
|
|
||||||
int32_t set_proportion(const Arg *arg);
|
|
||||||
int32_t switch_proportion_preset(const Arg *arg);
|
|
||||||
int32_t zoom(const Arg *arg);
|
|
||||||
int32_t tagsilent(const Arg *arg);
|
|
||||||
int32_t tagtoleft(const Arg *arg);
|
|
||||||
int32_t tagtoright(const Arg *arg);
|
|
||||||
int32_t tagcrossmon(const Arg *arg);
|
|
||||||
int32_t viewtoleft(const Arg *arg);
|
|
||||||
int32_t viewtoright(const Arg *arg);
|
|
||||||
int32_t viewtoleft_have_client(const Arg *arg);
|
|
||||||
int32_t viewtoright_have_client(const Arg *arg);
|
|
||||||
int32_t viewcrossmon(const Arg *arg);
|
|
||||||
int32_t togglefloating(const Arg *arg);
|
|
||||||
int32_t togglefullscreen(const Arg *arg);
|
|
||||||
int32_t togglemaximizescreen(const Arg *arg);
|
|
||||||
int32_t togglegaps(const Arg *arg);
|
|
||||||
int32_t tagmon(const Arg *arg);
|
|
||||||
int32_t spawn(const Arg *arg);
|
|
||||||
int32_t spawn_shell(const Arg *arg);
|
|
||||||
int32_t spawn_on_empty(const Arg *arg);
|
|
||||||
int32_t setkeymode(const Arg *arg);
|
|
||||||
int32_t switch_keyboard_layout(const Arg *arg);
|
|
||||||
int32_t setlayout(const Arg *arg);
|
|
||||||
int32_t switch_layout(const Arg *arg);
|
|
||||||
int32_t setmfact(const Arg *arg);
|
|
||||||
int32_t quit(const Arg *arg);
|
|
||||||
int32_t moveresize(const Arg *arg);
|
|
||||||
int32_t exchange_client(const Arg *arg);
|
|
||||||
int32_t exchange_stack_client(const Arg *arg);
|
|
||||||
int32_t killclient(const Arg *arg);
|
|
||||||
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 chvt(const Arg *arg);
|
|
||||||
int32_t reload_config(const Arg *arg);
|
|
||||||
int32_t smartmovewin(const Arg *arg);
|
|
||||||
int32_t smartresizewin(const Arg *arg);
|
|
||||||
int32_t centerwin(const Arg *arg);
|
|
||||||
int32_t bind_to_view(const Arg *arg);
|
|
||||||
int32_t toggletag(const Arg *arg);
|
|
||||||
int32_t toggleview(const Arg *arg);
|
|
||||||
int32_t tag(const Arg *arg);
|
|
||||||
int32_t comboview(const Arg *arg);
|
|
||||||
int32_t incgaps(const Arg *arg);
|
|
||||||
int32_t incigaps(const Arg *arg);
|
|
||||||
int32_t incihgaps(const Arg *arg);
|
|
||||||
int32_t incivgaps(const Arg *arg);
|
|
||||||
int32_t incogaps(const Arg *arg);
|
|
||||||
int32_t incohgaps(const Arg *arg);
|
|
||||||
int32_t incovgaps(const Arg *arg);
|
|
||||||
int32_t defaultgaps(const Arg *arg);
|
|
||||||
int32_t togglefakefullscreen(const Arg *arg);
|
|
||||||
int32_t toggleoverlay(const Arg *arg);
|
|
||||||
int32_t movewin(const Arg *arg);
|
|
||||||
int32_t resizewin(const Arg *arg);
|
|
||||||
int32_t toggle_named_scratchpad(const Arg *arg);
|
|
||||||
int32_t toggle_render_border(const Arg *arg);
|
|
||||||
int32_t create_virtual_output(const Arg *arg);
|
|
||||||
int32_t destroy_all_virtual_output(const Arg *arg);
|
|
||||||
int32_t focuslast(const Arg *arg);
|
|
||||||
int32_t toggle_trackpad_enable(const Arg *arg);
|
|
||||||
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 scroller_stack(const Arg *arg);
|
|
||||||
1795
src/dispatch/bind_define.c
Normal file
1795
src/dispatch/bind_define.c
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +0,0 @@
|
||||||
#include "dwl-ipc.h"
|
|
||||||
#include "ext-workspace.h"
|
|
||||||
#include "foreign-toplevel.h"
|
|
||||||
#include "tearing.h"
|
|
||||||
#include "text-input.h"
|
|
||||||
|
|
@ -1,41 +1,41 @@
|
||||||
#include "dwl-ipc-unstable-v2-protocol.h"
|
#include "dwl-ipc-unstable-v2-protocol.h"
|
||||||
|
|
||||||
static void dwl_ipc_manager_bind(struct wl_client *client, void *data,
|
void dwl_ipc_manager_bind(struct wl_client *client, void *data,
|
||||||
uint32_t version, uint32_t id);
|
uint32_t version, uint32_t id);
|
||||||
static void dwl_ipc_manager_destroy(struct wl_resource *resource);
|
void dwl_ipc_manager_destroy(struct wl_resource *resource);
|
||||||
static void dwl_ipc_manager_get_output(struct wl_client *client,
|
void dwl_ipc_manager_get_output(struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
struct wl_resource *resource,
|
||||||
uint32_t id, struct wl_resource *output);
|
uint32_t id, struct wl_resource *output);
|
||||||
static void dwl_ipc_manager_release(struct wl_client *client,
|
void dwl_ipc_manager_release(struct wl_client *client,
|
||||||
struct wl_resource *resource);
|
struct wl_resource *resource);
|
||||||
static void dwl_ipc_output_destroy(struct wl_resource *resource);
|
void dwl_ipc_output_destroy(struct wl_resource *resource);
|
||||||
static void dwl_ipc_output_printstatus(Monitor *monitor);
|
void dwl_ipc_output_printstatus(Monitor *monitor);
|
||||||
static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output);
|
void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output);
|
||||||
static void dwl_ipc_output_set_client_tags(struct wl_client *client,
|
void dwl_ipc_output_set_client_tags(struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
struct wl_resource *resource,
|
||||||
uint32_t and_tags,
|
uint32_t and_tags,
|
||||||
uint32_t xor_tags);
|
uint32_t xor_tags);
|
||||||
static void dwl_ipc_output_set_layout(struct wl_client *client,
|
void dwl_ipc_output_set_layout(struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
struct wl_resource *resource,
|
||||||
uint32_t index);
|
uint32_t index);
|
||||||
static void dwl_ipc_output_set_tags(struct wl_client *client,
|
void dwl_ipc_output_set_tags(struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
struct wl_resource *resource,
|
||||||
uint32_t tagmask, uint32_t toggle_tagset);
|
uint32_t tagmask, uint32_t toggle_tagset);
|
||||||
static void dwl_ipc_output_quit(struct wl_client *client,
|
void dwl_ipc_output_quit(struct wl_client *client,
|
||||||
struct wl_resource *resource);
|
struct wl_resource *resource);
|
||||||
static void dwl_ipc_output_dispatch(struct wl_client *client,
|
void dwl_ipc_output_dispatch(struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
struct wl_resource *resource,
|
||||||
const char *dispatch, const char *arg1,
|
const char *dispatch, const char *arg1,
|
||||||
const char *arg2, const char *arg3,
|
const char *arg2, const char *arg3,
|
||||||
const char *arg4, const char *arg5);
|
const char *arg4, const char *arg5);
|
||||||
static void dwl_ipc_output_release(struct wl_client *client,
|
void dwl_ipc_output_release(struct wl_client *client,
|
||||||
struct wl_resource *resource);
|
struct wl_resource *resource);
|
||||||
|
|
||||||
/* global event handlers */
|
/* global event handlers */
|
||||||
static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {
|
struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {
|
||||||
.release = dwl_ipc_manager_release,
|
.release = dwl_ipc_manager_release,
|
||||||
.get_output = dwl_ipc_manager_get_output};
|
.get_output = dwl_ipc_manager_get_output};
|
||||||
static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {
|
struct zdwl_ipc_output_v2_interface dwl_output_implementation = {
|
||||||
.release = dwl_ipc_output_release,
|
.release = dwl_ipc_output_release,
|
||||||
.set_tags = dwl_ipc_output_set_tags,
|
.set_tags = dwl_ipc_output_set_tags,
|
||||||
.quit = dwl_ipc_output_quit,
|
.quit = dwl_ipc_output_quit,
|
||||||
|
|
@ -57,7 +57,7 @@ void dwl_ipc_manager_bind(struct wl_client *client, void *data,
|
||||||
|
|
||||||
zdwl_ipc_manager_v2_send_tags(manager_resource, LENGTH(tags));
|
zdwl_ipc_manager_v2_send_tags(manager_resource, LENGTH(tags));
|
||||||
|
|
||||||
for (uint32_t i = 0; i < LENGTH(layouts); i++)
|
for (uint32_t i = 0; i < layouts_len; i++) {
|
||||||
zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol);
|
zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,7 +93,7 @@ void dwl_ipc_manager_release(struct wl_client *client,
|
||||||
wl_resource_destroy(resource);
|
wl_resource_destroy(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_ipc_output_destroy(struct wl_resource *resource) {
|
void dwl_ipc_output_destroy(struct wl_resource *resource) {
|
||||||
DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource);
|
DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource);
|
||||||
wl_list_remove(&ipc_output->link);
|
wl_list_remove(&ipc_output->link);
|
||||||
free(ipc_output);
|
free(ipc_output);
|
||||||
|
|
@ -254,7 +254,7 @@ void dwl_ipc_output_set_layout(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
monitor = ipc_output->mon;
|
monitor = ipc_output->mon;
|
||||||
if (index >= LENGTH(layouts))
|
if (index >= layouts_len)
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
monitor->pertag->ltidxs[monitor->pertag->curtag] = &layouts[index];
|
monitor->pertag->ltidxs[monitor->pertag->curtag] = &layouts[index];
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ void toggle_workspace(struct workspace *target) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_ext_workspace_activate(struct wl_listener *listener,
|
void handle_ext_workspace_activate(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct workspace *workspace =
|
struct workspace *workspace =
|
||||||
wl_container_of(listener, workspace, activate);
|
wl_container_of(listener, workspace, activate);
|
||||||
|
|
@ -56,7 +56,7 @@ static void handle_ext_workspace_activate(struct wl_listener *listener,
|
||||||
wlr_log(WLR_INFO, "ext activating workspace %d", workspace->tag);
|
wlr_log(WLR_INFO, "ext activating workspace %d", workspace->tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_ext_workspace_deactivate(struct wl_listener *listener,
|
void handle_ext_workspace_deactivate(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct workspace *workspace =
|
struct workspace *workspace =
|
||||||
wl_container_of(listener, workspace, deactivate);
|
wl_container_of(listener, workspace, deactivate);
|
||||||
|
|
@ -69,8 +69,8 @@ static void handle_ext_workspace_deactivate(struct wl_listener *listener,
|
||||||
wlr_log(WLR_INFO, "ext deactivating workspace %d", workspace->tag);
|
wlr_log(WLR_INFO, "ext deactivating workspace %d", workspace->tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *get_name_from_tag(uint32_t tag) {
|
const char *get_name_from_tag(uint32_t tag) {
|
||||||
static const char *names[] = {"overview", "1", "2", "3", "4",
|
const char *names[] = {"overview", "1", "2", "3", "4",
|
||||||
"5", "6", "7", "8", "9"};
|
"5", "6", "7", "8", "9"};
|
||||||
return (tag < sizeof(names) / sizeof(names[0])) ? names[tag] : NULL;
|
return (tag < sizeof(names) / sizeof(names[0])) ? names[tag] : NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@ void cleanup_workspaces_by_monitor(Monitor *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_workspace_by_tag(uint32_t tag, Monitor *m) {
|
void remove_workspace_by_tag(uint32_t tag, Monitor *m) {
|
||||||
struct workspace *workspace, *tmp;
|
struct workspace *workspace, *tmp;
|
||||||
wl_list_for_each_safe(workspace, tmp, &workspaces, link) {
|
wl_list_for_each_safe(workspace, tmp, &workspaces, link) {
|
||||||
if (workspace->tag == tag && workspace->m == m) {
|
if (workspace->tag == tag && workspace->m == m) {
|
||||||
|
|
@ -102,7 +102,7 @@ static void remove_workspace_by_tag(uint32_t tag, Monitor *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_workspace_by_tag(int32_t tag, Monitor *m) {
|
void add_workspace_by_tag(int32_t tag, Monitor *m) {
|
||||||
const char *name = get_name_from_tag(tag);
|
const char *name = get_name_from_tag(tag);
|
||||||
|
|
||||||
struct workspace *workspace = ecalloc(1, sizeof(*workspace));
|
struct workspace *workspace = ecalloc(1, sizeof(*workspace));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||||
|
|
||||||
static struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
|
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
|
||||||
|
|
||||||
void handle_foreign_activate_request(struct wl_listener *listener, void *data) {
|
void handle_foreign_activate_request(struct wl_listener *listener, void *data) {
|
||||||
Client *c = wl_container_of(listener, c, foreign_activate_request);
|
Client *c = wl_container_of(listener, c, foreign_activate_request);
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ struct tearing_controller {
|
||||||
struct wlr_tearing_control_manager_v1 *tearing_control;
|
struct wlr_tearing_control_manager_v1 *tearing_control;
|
||||||
struct wl_listener tearing_new_object;
|
struct wl_listener tearing_new_object;
|
||||||
|
|
||||||
static void handle_controller_set_hint(struct wl_listener *listener,
|
void handle_controller_set_hint(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct tearing_controller *controller =
|
struct tearing_controller *controller =
|
||||||
wl_container_of(listener, controller, set_hint);
|
wl_container_of(listener, controller, set_hint);
|
||||||
|
|
@ -29,7 +29,7 @@ static void handle_controller_set_hint(struct wl_listener *listener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_controller_destroy(struct wl_listener *listener,
|
void handle_controller_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct tearing_controller *controller =
|
struct tearing_controller *controller =
|
||||||
wl_container_of(listener, controller, destroy);
|
wl_container_of(listener, controller, destroy);
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ Monitor *output_nearest_to(int32_t lx, int32_t ly) {
|
||||||
|
|
||||||
bool output_is_usable(Monitor *m) { return m && m->wlr_output->enabled; }
|
bool output_is_usable(Monitor *m) { return m && m->wlr_output->enabled; }
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
is_keyboard_emulated_by_input_method(struct wlr_keyboard *keyboard,
|
is_keyboard_emulated_by_input_method(struct wlr_keyboard *keyboard,
|
||||||
struct wlr_input_method_v2 *input_method) {
|
struct wlr_input_method_v2 *input_method) {
|
||||||
struct wlr_virtual_keyboard_v1 *virtual_keyboard;
|
struct wlr_virtual_keyboard_v1 *virtual_keyboard;
|
||||||
|
|
@ -103,7 +103,7 @@ is_keyboard_emulated_by_input_method(struct wlr_keyboard *keyboard,
|
||||||
wl_resource_get_client(input_method->resource);
|
wl_resource_get_client(input_method->resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_input_method_keyboard_grab_v2 *
|
struct wlr_input_method_keyboard_grab_v2 *
|
||||||
get_keyboard_grab(KeyboardGroup *keyboard) {
|
get_keyboard_grab(KeyboardGroup *keyboard) {
|
||||||
struct wlr_input_method_v2 *input_method =
|
struct wlr_input_method_v2 *input_method =
|
||||||
dwl_input_method_relay->input_method;
|
dwl_input_method_relay->input_method;
|
||||||
|
|
@ -157,7 +157,7 @@ bool dwl_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct text_input *
|
struct text_input *
|
||||||
get_active_text_input(struct dwl_input_method_relay *relay) {
|
get_active_text_input(struct dwl_input_method_relay *relay) {
|
||||||
struct text_input *text_input;
|
struct text_input *text_input;
|
||||||
|
|
||||||
|
|
@ -173,7 +173,7 @@ get_active_text_input(struct dwl_input_method_relay *relay) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_active_text_input(struct dwl_input_method_relay *relay) {
|
void update_active_text_input(struct dwl_input_method_relay *relay) {
|
||||||
struct text_input *active_text_input = get_active_text_input(relay);
|
struct text_input *active_text_input = get_active_text_input(relay);
|
||||||
|
|
||||||
if (relay->input_method && relay->active_text_input != active_text_input) {
|
if (relay->input_method && relay->active_text_input != active_text_input) {
|
||||||
|
|
@ -188,7 +188,7 @@ static void update_active_text_input(struct dwl_input_method_relay *relay) {
|
||||||
relay->active_text_input = active_text_input;
|
relay->active_text_input = active_text_input;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
update_text_inputs_focused_surface(struct dwl_input_method_relay *relay) {
|
update_text_inputs_focused_surface(struct dwl_input_method_relay *relay) {
|
||||||
struct text_input *text_input;
|
struct text_input *text_input;
|
||||||
wl_list_for_each(text_input, &relay->text_inputs, link) {
|
wl_list_for_each(text_input, &relay->text_inputs, link) {
|
||||||
|
|
@ -215,7 +215,7 @@ update_text_inputs_focused_surface(struct dwl_input_method_relay *relay) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_popup_position(struct dwl_input_method_popup *popup) {
|
void update_popup_position(struct dwl_input_method_popup *popup) {
|
||||||
struct dwl_input_method_relay *relay = popup->relay;
|
struct dwl_input_method_relay *relay = popup->relay;
|
||||||
struct text_input *text_input = relay->active_text_input;
|
struct text_input *text_input = relay->active_text_input;
|
||||||
struct wlr_box cursor_rect;
|
struct wlr_box cursor_rect;
|
||||||
|
|
@ -291,14 +291,14 @@ static void update_popup_position(struct dwl_input_method_popup *popup) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_popups_position(struct dwl_input_method_relay *relay) {
|
void update_popups_position(struct dwl_input_method_relay *relay) {
|
||||||
struct dwl_input_method_popup *popup;
|
struct dwl_input_method_popup *popup;
|
||||||
wl_list_for_each(popup, &relay->popups, link) {
|
wl_list_for_each(popup, &relay->popups, link) {
|
||||||
update_popup_position(popup);
|
update_popup_position(popup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_input_method_commit(struct wl_listener *listener,
|
void handle_input_method_commit(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, input_method_commit);
|
wl_container_of(listener, relay, input_method_commit);
|
||||||
|
|
@ -330,7 +330,7 @@ static void handle_input_method_commit(struct wl_listener *listener,
|
||||||
wlr_text_input_v3_send_done(text_input->input);
|
wlr_text_input_v3_send_done(text_input->input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_keyboard_grab_destroy(struct wl_listener *listener,
|
void handle_keyboard_grab_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, keyboard_grab_destroy);
|
wl_container_of(listener, relay, keyboard_grab_destroy);
|
||||||
|
|
@ -343,7 +343,7 @@ static void handle_keyboard_grab_destroy(struct wl_listener *listener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_input_method_grab_keyboard(struct wl_listener *listener,
|
void handle_input_method_grab_keyboard(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, input_method_grab_keyboard);
|
wl_container_of(listener, relay, input_method_grab_keyboard);
|
||||||
|
|
@ -362,7 +362,7 @@ static void handle_input_method_grab_keyboard(struct wl_listener *listener,
|
||||||
&relay->keyboard_grab_destroy);
|
&relay->keyboard_grab_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_input_method_destroy(struct wl_listener *listener,
|
void handle_input_method_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, input_method_destroy);
|
wl_container_of(listener, relay, input_method_destroy);
|
||||||
|
|
@ -377,7 +377,7 @@ static void handle_input_method_destroy(struct wl_listener *listener,
|
||||||
update_active_text_input(relay);
|
update_active_text_input(relay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_popup_surface_destroy(struct wl_listener *listener,
|
void handle_popup_surface_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_popup *popup =
|
struct dwl_input_method_popup *popup =
|
||||||
wl_container_of(listener, popup, destroy);
|
wl_container_of(listener, popup, destroy);
|
||||||
|
|
@ -388,14 +388,14 @@ static void handle_popup_surface_destroy(struct wl_listener *listener,
|
||||||
free(popup);
|
free(popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_popup_surface_commit(struct wl_listener *listener,
|
void handle_popup_surface_commit(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_popup *popup =
|
struct dwl_input_method_popup *popup =
|
||||||
wl_container_of(listener, popup, commit);
|
wl_container_of(listener, popup, commit);
|
||||||
update_popup_position(popup);
|
update_popup_position(popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_input_method_new_popup_surface(struct wl_listener *listener,
|
void handle_input_method_new_popup_surface(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, input_method_new_popup_surface);
|
wl_container_of(listener, relay, input_method_new_popup_surface);
|
||||||
|
|
@ -422,7 +422,7 @@ static void handle_input_method_new_popup_surface(struct wl_listener *listener,
|
||||||
update_popup_position(popup);
|
update_popup_position(popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_new_input_method(struct wl_listener *listener, void *data) {
|
void handle_new_input_method(struct wl_listener *listener, void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, new_input_method);
|
wl_container_of(listener, relay, new_input_method);
|
||||||
struct wlr_input_method_v2 *input_method = data;
|
struct wlr_input_method_v2 *input_method = data;
|
||||||
|
|
@ -459,7 +459,7 @@ static void handle_new_input_method(struct wl_listener *listener, void *data) {
|
||||||
update_active_text_input(relay);
|
update_active_text_input(relay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_state_to_input_method(struct dwl_input_method_relay *relay) {
|
void send_state_to_input_method(struct dwl_input_method_relay *relay) {
|
||||||
|
|
||||||
struct wlr_input_method_v2 *input_method = relay->input_method;
|
struct wlr_input_method_v2 *input_method = relay->input_method;
|
||||||
struct wlr_text_input_v3 *input = relay->active_text_input->input;
|
struct wlr_text_input_v3 *input = relay->active_text_input->input;
|
||||||
|
|
@ -481,7 +481,7 @@ static void send_state_to_input_method(struct dwl_input_method_relay *relay) {
|
||||||
wlr_input_method_v2_send_done(input_method);
|
wlr_input_method_v2_send_done(input_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_text_input_enable(struct wl_listener *listener, void *data) {
|
void handle_text_input_enable(struct wl_listener *listener, void *data) {
|
||||||
struct text_input *text_input =
|
struct text_input *text_input =
|
||||||
wl_container_of(listener, text_input, enable);
|
wl_container_of(listener, text_input, enable);
|
||||||
struct dwl_input_method_relay *relay = text_input->relay;
|
struct dwl_input_method_relay *relay = text_input->relay;
|
||||||
|
|
@ -494,7 +494,7 @@ static void handle_text_input_enable(struct wl_listener *listener, void *data) {
|
||||||
wlr_text_input_v3_send_done(text_input->input);
|
wlr_text_input_v3_send_done(text_input->input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_text_input_disable(struct wl_listener *listener,
|
void handle_text_input_disable(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct text_input *text_input =
|
struct text_input *text_input =
|
||||||
wl_container_of(listener, text_input, disable);
|
wl_container_of(listener, text_input, disable);
|
||||||
|
|
@ -502,7 +502,7 @@ static void handle_text_input_disable(struct wl_listener *listener,
|
||||||
update_active_text_input(text_input->relay);
|
update_active_text_input(text_input->relay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_text_input_commit(struct wl_listener *listener, void *data) {
|
void handle_text_input_commit(struct wl_listener *listener, void *data) {
|
||||||
struct text_input *text_input =
|
struct text_input *text_input =
|
||||||
wl_container_of(listener, text_input, commit);
|
wl_container_of(listener, text_input, commit);
|
||||||
struct dwl_input_method_relay *relay = text_input->relay;
|
struct dwl_input_method_relay *relay = text_input->relay;
|
||||||
|
|
@ -513,7 +513,7 @@ static void handle_text_input_commit(struct wl_listener *listener, void *data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_text_input_destroy(struct wl_listener *listener,
|
void handle_text_input_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct text_input *text_input =
|
struct text_input *text_input =
|
||||||
wl_container_of(listener, text_input, destroy);
|
wl_container_of(listener, text_input, destroy);
|
||||||
|
|
@ -526,7 +526,7 @@ static void handle_text_input_destroy(struct wl_listener *listener,
|
||||||
free(text_input);
|
free(text_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_new_text_input(struct wl_listener *listener, void *data) {
|
void handle_new_text_input(struct wl_listener *listener, void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, new_text_input);
|
wl_container_of(listener, relay, new_text_input);
|
||||||
struct wlr_text_input_v3 *wlr_text_input = data;
|
struct wlr_text_input_v3 *wlr_text_input = data;
|
||||||
|
|
@ -555,7 +555,7 @@ static void handle_new_text_input(struct wl_listener *listener, void *data) {
|
||||||
update_text_inputs_focused_surface(relay);
|
update_text_inputs_focused_surface(relay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_focused_surface_destroy(struct wl_listener *listener,
|
void handle_focused_surface_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct dwl_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, focused_surface_destroy);
|
wl_container_of(listener, relay, focused_surface_destroy);
|
||||||
|
|
|
||||||
|
|
@ -71,39 +71,39 @@ struct wlr_ext_workspace_v1_resource {
|
||||||
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.workspace_resources
|
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.workspace_resources
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ext_workspace_group_handle_v1_interface group_impl;
|
const struct ext_workspace_group_handle_v1_interface group_impl;
|
||||||
|
|
||||||
static struct wlr_ext_workspace_group_v1_resource *
|
struct wlr_ext_workspace_group_v1_resource *
|
||||||
group_resource_from_resource(struct wl_resource *resource) {
|
group_resource_from_resource(struct wl_resource *resource) {
|
||||||
assert(wl_resource_instance_of(
|
assert(wl_resource_instance_of(
|
||||||
resource, &ext_workspace_group_handle_v1_interface, &group_impl));
|
resource, &ext_workspace_group_handle_v1_interface, &group_impl));
|
||||||
return wl_resource_get_user_data(resource);
|
return wl_resource_get_user_data(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ext_workspace_handle_v1_interface workspace_impl;
|
const struct ext_workspace_handle_v1_interface workspace_impl;
|
||||||
|
|
||||||
static struct wlr_ext_workspace_v1_resource *
|
struct wlr_ext_workspace_v1_resource *
|
||||||
workspace_resource_from_resource(struct wl_resource *resource) {
|
workspace_resource_from_resource(struct wl_resource *resource) {
|
||||||
assert(wl_resource_instance_of(resource, &ext_workspace_handle_v1_interface,
|
assert(wl_resource_instance_of(resource, &ext_workspace_handle_v1_interface,
|
||||||
&workspace_impl));
|
&workspace_impl));
|
||||||
return wl_resource_get_user_data(resource);
|
return wl_resource_get_user_data(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ext_workspace_manager_v1_interface manager_impl;
|
const struct ext_workspace_manager_v1_interface manager_impl;
|
||||||
|
|
||||||
static struct wlr_ext_workspace_manager_v1_resource *
|
struct wlr_ext_workspace_manager_v1_resource *
|
||||||
manager_resource_from_resource(struct wl_resource *resource) {
|
manager_resource_from_resource(struct wl_resource *resource) {
|
||||||
assert(wl_resource_instance_of(
|
assert(wl_resource_instance_of(
|
||||||
resource, &ext_workspace_manager_v1_interface, &manager_impl));
|
resource, &ext_workspace_manager_v1_interface, &manager_impl));
|
||||||
return wl_resource_get_user_data(resource);
|
return wl_resource_get_user_data(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_handle_destroy(struct wl_client *client,
|
void workspace_handle_destroy(struct wl_client *client,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
wl_resource_destroy(resource);
|
wl_resource_destroy(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_handle_activate(struct wl_client *client,
|
void workspace_handle_activate(struct wl_client *client,
|
||||||
struct wl_resource *workspace_resource) {
|
struct wl_resource *workspace_resource) {
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||||
workspace_resource_from_resource(workspace_resource);
|
workspace_resource_from_resource(workspace_resource);
|
||||||
|
|
@ -121,7 +121,7 @@ static void workspace_handle_activate(struct wl_client *client,
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
workspace_handle_deactivate(struct wl_client *client,
|
workspace_handle_deactivate(struct wl_client *client,
|
||||||
struct wl_resource *workspace_resource) {
|
struct wl_resource *workspace_resource) {
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||||
|
|
@ -140,7 +140,7 @@ workspace_handle_deactivate(struct wl_client *client,
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_handle_assign(struct wl_client *client,
|
void workspace_handle_assign(struct wl_client *client,
|
||||||
struct wl_resource *workspace_resource,
|
struct wl_resource *workspace_resource,
|
||||||
struct wl_resource *group_resource) {
|
struct wl_resource *group_resource) {
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||||
|
|
@ -162,7 +162,7 @@ static void workspace_handle_assign(struct wl_client *client,
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_handle_remove(struct wl_client *client,
|
void workspace_handle_remove(struct wl_client *client,
|
||||||
struct wl_resource *workspace_resource) {
|
struct wl_resource *workspace_resource) {
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||||
workspace_resource_from_resource(workspace_resource);
|
workspace_resource_from_resource(workspace_resource);
|
||||||
|
|
@ -180,7 +180,7 @@ static void workspace_handle_remove(struct wl_client *client,
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ext_workspace_handle_v1_interface workspace_impl = {
|
const struct ext_workspace_handle_v1_interface workspace_impl = {
|
||||||
.destroy = workspace_handle_destroy,
|
.destroy = workspace_handle_destroy,
|
||||||
.activate = workspace_handle_activate,
|
.activate = workspace_handle_activate,
|
||||||
.deactivate = workspace_handle_deactivate,
|
.deactivate = workspace_handle_deactivate,
|
||||||
|
|
@ -188,7 +188,7 @@ static const struct ext_workspace_handle_v1_interface workspace_impl = {
|
||||||
.remove = workspace_handle_remove,
|
.remove = workspace_handle_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void group_handle_create_workspace(struct wl_client *client,
|
void group_handle_create_workspace(struct wl_client *client,
|
||||||
struct wl_resource *group_resource,
|
struct wl_resource *group_resource,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||||
|
|
@ -213,17 +213,17 @@ static void group_handle_create_workspace(struct wl_client *client,
|
||||||
wl_list_insert(group_res->manager->requests.prev, &req->link);
|
wl_list_insert(group_res->manager->requests.prev, &req->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void group_handle_destroy(struct wl_client *client,
|
void group_handle_destroy(struct wl_client *client,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
wl_resource_destroy(resource);
|
wl_resource_destroy(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ext_workspace_group_handle_v1_interface group_impl = {
|
const struct ext_workspace_group_handle_v1_interface group_impl = {
|
||||||
.create_workspace = group_handle_create_workspace,
|
.create_workspace = group_handle_create_workspace,
|
||||||
.destroy = group_handle_destroy,
|
.destroy = group_handle_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void destroy_workspace_resource(
|
void destroy_workspace_resource(
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res) {
|
struct wlr_ext_workspace_v1_resource *workspace_res) {
|
||||||
wl_list_remove(&workspace_res->link);
|
wl_list_remove(&workspace_res->link);
|
||||||
wl_list_remove(&workspace_res->manager_resource_link);
|
wl_list_remove(&workspace_res->manager_resource_link);
|
||||||
|
|
@ -231,7 +231,7 @@ static void destroy_workspace_resource(
|
||||||
free(workspace_res);
|
free(workspace_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_resource_destroy(struct wl_resource *resource) {
|
void workspace_resource_destroy(struct wl_resource *resource) {
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||||
workspace_resource_from_resource(resource);
|
workspace_resource_from_resource(resource);
|
||||||
if (workspace_res) {
|
if (workspace_res) {
|
||||||
|
|
@ -239,7 +239,7 @@ static void workspace_resource_destroy(struct wl_resource *resource) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_ext_workspace_v1_resource *create_workspace_resource(
|
struct wlr_ext_workspace_v1_resource *create_workspace_resource(
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
struct wlr_ext_workspace_handle_v1 *workspace,
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
struct wlr_ext_workspace_v1_resource *workspace_res =
|
||||||
|
|
@ -268,7 +268,7 @@ static struct wlr_ext_workspace_v1_resource *create_workspace_resource(
|
||||||
return workspace_res;
|
return workspace_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
destroy_group_resource(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
destroy_group_resource(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
||||||
wl_list_remove(&group_res->link);
|
wl_list_remove(&group_res->link);
|
||||||
wl_list_remove(&group_res->manager_resource_link);
|
wl_list_remove(&group_res->manager_resource_link);
|
||||||
|
|
@ -276,7 +276,7 @@ destroy_group_resource(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
||||||
free(group_res);
|
free(group_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void group_handle_resource_destroy(struct wl_resource *resource) {
|
void group_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||||
group_resource_from_resource(resource);
|
group_resource_from_resource(resource);
|
||||||
if (group_res) {
|
if (group_res) {
|
||||||
|
|
@ -284,7 +284,7 @@ static void group_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_ext_workspace_group_v1_resource *create_group_resource(
|
struct wlr_ext_workspace_group_v1_resource *create_group_resource(
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
struct wlr_ext_workspace_group_v1_resource *group_res =
|
||||||
|
|
@ -313,13 +313,13 @@ static struct wlr_ext_workspace_group_v1_resource *create_group_resource(
|
||||||
return group_res;
|
return group_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroy_request(struct wlr_ext_workspace_v1_request *req) {
|
void destroy_request(struct wlr_ext_workspace_v1_request *req) {
|
||||||
wl_list_remove(&req->link);
|
wl_list_remove(&req->link);
|
||||||
free(req->name);
|
free(req->name);
|
||||||
free(req);
|
free(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_handle_commit(struct wl_client *client,
|
void manager_handle_commit(struct wl_client *client,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
||||||
manager_resource_from_resource(resource);
|
manager_resource_from_resource(resource);
|
||||||
|
|
@ -355,7 +355,7 @@ static void manager_handle_commit(struct wl_client *client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_idle(void *data) {
|
void handle_idle(void *data) {
|
||||||
struct wlr_ext_workspace_manager_v1 *manager = data;
|
struct wlr_ext_workspace_manager_v1 *manager = data;
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||||
|
|
@ -365,7 +365,7 @@ static void handle_idle(void *data) {
|
||||||
manager->idle_source = NULL;
|
manager->idle_source = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
manager_schedule_done(struct wlr_ext_workspace_manager_v1 *manager) {
|
manager_schedule_done(struct wlr_ext_workspace_manager_v1 *manager) {
|
||||||
if (!manager->idle_source) {
|
if (!manager->idle_source) {
|
||||||
manager->idle_source =
|
manager->idle_source =
|
||||||
|
|
@ -373,7 +373,7 @@ manager_schedule_done(struct wlr_ext_workspace_manager_v1 *manager) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
workspace_send_details(struct wlr_ext_workspace_v1_resource *workspace_res) {
|
workspace_send_details(struct wlr_ext_workspace_v1_resource *workspace_res) {
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace = workspace_res->workspace;
|
struct wlr_ext_workspace_handle_v1 *workspace = workspace_res->workspace;
|
||||||
struct wl_resource *resource = workspace_res->resource;
|
struct wl_resource *resource = workspace_res->resource;
|
||||||
|
|
@ -393,18 +393,18 @@ workspace_send_details(struct wlr_ext_workspace_v1_resource *workspace_res) {
|
||||||
manager_schedule_done(workspace->manager);
|
manager_schedule_done(workspace->manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_handle_stop(struct wl_client *client,
|
void manager_handle_stop(struct wl_client *client,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
ext_workspace_manager_v1_send_finished(resource);
|
ext_workspace_manager_v1_send_finished(resource);
|
||||||
wl_resource_destroy(resource);
|
wl_resource_destroy(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ext_workspace_manager_v1_interface manager_impl = {
|
const struct ext_workspace_manager_v1_interface manager_impl = {
|
||||||
.commit = manager_handle_commit,
|
.commit = manager_handle_commit,
|
||||||
.stop = manager_handle_stop,
|
.stop = manager_handle_stop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void destroy_manager_resource(
|
void destroy_manager_resource(
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
struct wlr_ext_workspace_v1_request *req, *tmp;
|
||||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
||||||
|
|
@ -427,7 +427,7 @@ static void destroy_manager_resource(
|
||||||
free(manager_res);
|
free(manager_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_resource_destroy(struct wl_resource *resource) {
|
void manager_resource_destroy(struct wl_resource *resource) {
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
||||||
manager_resource_from_resource(resource);
|
manager_resource_from_resource(resource);
|
||||||
if (manager_res) {
|
if (manager_res) {
|
||||||
|
|
@ -435,7 +435,7 @@ static void manager_resource_destroy(struct wl_resource *resource) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
group_send_details(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
group_send_details(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group = group_res->group;
|
struct wlr_ext_workspace_group_handle_v1 *group = group_res->group;
|
||||||
struct wl_resource *resource = group_res->resource;
|
struct wl_resource *resource = group_res->resource;
|
||||||
|
|
@ -458,7 +458,7 @@ group_send_details(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
||||||
manager_schedule_done(group->manager);
|
manager_schedule_done(group->manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_bind(struct wl_client *client, void *data, uint32_t version,
|
void manager_bind(struct wl_client *client, void *data, uint32_t version,
|
||||||
uint32_t id) {
|
uint32_t id) {
|
||||||
struct wlr_ext_workspace_manager_v1 *manager = data;
|
struct wlr_ext_workspace_manager_v1 *manager = data;
|
||||||
|
|
||||||
|
|
@ -525,7 +525,7 @@ static void manager_bind(struct wl_client *client, void *data, uint32_t version,
|
||||||
ext_workspace_manager_v1_send_done(manager_res->resource);
|
ext_workspace_manager_v1_send_done(manager_res->resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_handle_display_destroy(struct wl_listener *listener,
|
void manager_handle_display_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct wlr_ext_workspace_manager_v1 *manager =
|
struct wlr_ext_workspace_manager_v1 *manager =
|
||||||
wl_container_of(listener, manager, display_destroy);
|
wl_container_of(listener, manager, display_destroy);
|
||||||
|
|
@ -623,7 +623,7 @@ wlr_ext_workspace_group_handle_v1_create(
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
workspace_send_group(struct wlr_ext_workspace_handle_v1 *workspace,
|
workspace_send_group(struct wlr_ext_workspace_handle_v1 *workspace,
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||||
bool enter) {
|
bool enter) {
|
||||||
|
|
@ -648,7 +648,7 @@ workspace_send_group(struct wlr_ext_workspace_handle_v1 *workspace,
|
||||||
manager_schedule_done(workspace->manager);
|
manager_schedule_done(workspace->manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
destroy_group_output(struct wlr_ext_workspace_v1_group_output *group_output) {
|
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_bind.link);
|
||||||
wl_list_remove(&group_output->output_destroy.link);
|
wl_list_remove(&group_output->output_destroy.link);
|
||||||
|
|
@ -656,7 +656,7 @@ destroy_group_output(struct wlr_ext_workspace_v1_group_output *group_output) {
|
||||||
free(group_output);
|
free(group_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
||||||
struct wlr_output *output, bool enter) {
|
struct wlr_output *output, bool enter) {
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
struct wlr_ext_workspace_group_v1_resource *group_res;
|
||||||
|
|
@ -728,7 +728,7 @@ void wlr_ext_workspace_group_handle_v1_destroy(
|
||||||
free(group);
|
free(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_output_bind(struct wl_listener *listener, void *data) {
|
void handle_output_bind(struct wl_listener *listener, void *data) {
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
struct wlr_ext_workspace_v1_group_output *group_output =
|
||||||
wl_container_of(listener, group_output, output_bind);
|
wl_container_of(listener, group_output, output_bind);
|
||||||
struct wlr_output_event_bind *event = data;
|
struct wlr_output_event_bind *event = data;
|
||||||
|
|
@ -745,14 +745,14 @@ static void handle_output_bind(struct wl_listener *listener, void *data) {
|
||||||
manager_schedule_done(group_output->group->manager);
|
manager_schedule_done(group_output->group->manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
void handle_output_destroy(struct wl_listener *listener, void *data) {
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
struct wlr_ext_workspace_v1_group_output *group_output =
|
||||||
wl_container_of(listener, group_output, output_destroy);
|
wl_container_of(listener, group_output, output_destroy);
|
||||||
group_send_output(group_output->group, group_output->output, false);
|
group_send_output(group_output->group, group_output->output, false);
|
||||||
destroy_group_output(group_output);
|
destroy_group_output(group_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_ext_workspace_v1_group_output *
|
struct wlr_ext_workspace_v1_group_output *
|
||||||
get_group_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
get_group_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
||||||
struct wlr_output *output) {
|
struct wlr_output *output) {
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output;
|
struct wlr_ext_workspace_v1_group_output *group_output;
|
||||||
|
|
@ -929,7 +929,7 @@ void wlr_ext_workspace_handle_v1_set_name(
|
||||||
manager_schedule_done(workspace->manager);
|
manager_schedule_done(workspace->manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool array_equal(struct wl_array *a, struct wl_array *b) {
|
bool array_equal(struct wl_array *a, struct wl_array *b) {
|
||||||
return (a->size == b->size) &&
|
return (a->size == b->size) &&
|
||||||
(a->size == 0 || memcmp(a->data, b->data, a->size) == 0);
|
(a->size == 0 || memcmp(a->data, b->data, a->size) == 0);
|
||||||
}
|
}
|
||||||
|
|
@ -956,7 +956,7 @@ void wlr_ext_workspace_handle_v1_set_coordinates(
|
||||||
manager_schedule_done(workspace->manager);
|
manager_schedule_done(workspace->manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_set_state(struct wlr_ext_workspace_handle_v1 *workspace,
|
void workspace_set_state(struct wlr_ext_workspace_handle_v1 *workspace,
|
||||||
enum ext_workspace_handle_v1_state state,
|
enum ext_workspace_handle_v1_state state,
|
||||||
bool enabled) {
|
bool enabled) {
|
||||||
uint32_t old_state = workspace->state;
|
uint32_t old_state = workspace->state;
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ setclient_coordinate_center(Client *c, Monitor *tm, struct wlr_box geom,
|
||||||
return tempbox;
|
return tempbox;
|
||||||
}
|
}
|
||||||
/* Helper: Check if rule matches client */
|
/* Helper: Check if rule matches client */
|
||||||
static bool is_window_rule_matches(const ConfigWinRule *r, const char *appid,
|
bool is_window_rule_matches(const ConfigWinRule *r, const char *appid,
|
||||||
const char *title) {
|
const char *title) {
|
||||||
return (r->title && regex_match(r->title, title) && !r->id) ||
|
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) ||
|
||||||
|
|
|
||||||
844
src/layout/arrange.c
Normal file
844
src/layout/arrange.c
Normal file
|
|
@ -0,0 +1,844 @@
|
||||||
|
#include "../type.h"
|
||||||
|
#include "layout.h"
|
||||||
|
#include "../animation/tag.h"
|
||||||
|
|
||||||
|
extern Server server;
|
||||||
|
extern Layout layouts[];
|
||||||
|
extern Layout overviewlayout;
|
||||||
|
|
||||||
|
void set_size_per(Monitor *m, Client *c) {
|
||||||
|
Client *fc = NULL;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
if (!m || !c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wl_list_for_each(fc, &server.clients, link) {
|
||||||
|
if (VISIBLEON(fc, m) && ISTILED(fc) && fc != c) {
|
||||||
|
c->master_mfact_per = fc->master_mfact_per;
|
||||||
|
c->master_inner_per = fc->master_inner_per;
|
||||||
|
c->stack_inner_per = fc->stack_inner_per;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
c->master_mfact_per = m->pertag->mfacts[m->pertag->curtag];
|
||||||
|
c->master_inner_per = 1.0f;
|
||||||
|
c->stack_inner_per = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize_tile_master_horizontal(Client *rec, bool isdrag, int32_t offsetx,
|
||||||
|
int32_t offsety, uint32_t time,
|
||||||
|
int32_t type) {
|
||||||
|
Client *tc = NULL;
|
||||||
|
float delta_x, delta_y;
|
||||||
|
Client *next = NULL;
|
||||||
|
Client *prev = NULL;
|
||||||
|
Client *nextnext = NULL;
|
||||||
|
Client *prevprev = NULL;
|
||||||
|
struct wl_list *node;
|
||||||
|
bool begin_find_nextnext = false;
|
||||||
|
bool begin_find_prevprev = false;
|
||||||
|
|
||||||
|
// 从当前节点的下一个开始遍历
|
||||||
|
for (node = rec->link.next; node != &server.clients;
|
||||||
|
node = node->next) {
|
||||||
|
tc = wl_container_of(node, tc, link);
|
||||||
|
if (begin_find_nextnext && VISIBLEON(tc, rec->mon) &&
|
||||||
|
ISTILED(tc)) {
|
||||||
|
nextnext = tc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!begin_find_nextnext && VISIBLEON(tc, rec->mon) &&
|
||||||
|
ISTILED(tc)) { // 根据你的实际字段名调整
|
||||||
|
next = tc;
|
||||||
|
begin_find_nextnext = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从当前节点的上一个开始遍历
|
||||||
|
for (node = rec->link.prev; node != &server.clients;
|
||||||
|
node = node->prev) {
|
||||||
|
tc = wl_container_of(node, tc, link);
|
||||||
|
|
||||||
|
if (begin_find_prevprev && VISIBLEON(tc, rec->mon) &&
|
||||||
|
ISTILED(tc)) {
|
||||||
|
prevprev = tc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!begin_find_prevprev && VISIBLEON(tc, rec->mon) &&
|
||||||
|
ISTILED(tc)) { // 根据你的实际字段名调整
|
||||||
|
prev = tc;
|
||||||
|
begin_find_prevprev = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!server.start_drag_window && isdrag) {
|
||||||
|
server.drag_begin_cursorx = server.cursor->x;
|
||||||
|
server.drag_begin_cursory = server.cursor->y;
|
||||||
|
server.start_drag_window = true;
|
||||||
|
// 记录初始状态
|
||||||
|
rec->old_master_mfact_per = rec->master_mfact_per;
|
||||||
|
rec->old_master_inner_per = rec->master_inner_per;
|
||||||
|
rec->old_stack_inner_per = rec->stack_inner_per;
|
||||||
|
rec->cursor_in_upper_half =
|
||||||
|
server.cursor->y <
|
||||||
|
rec->geom.y + rec->geom.height / 2;
|
||||||
|
rec->cursor_in_left_half =
|
||||||
|
server.cursor->x <
|
||||||
|
rec->geom.x + rec->geom.width / 2;
|
||||||
|
// 记录初始几何信息
|
||||||
|
rec->drag_begin_geom = rec->geom;
|
||||||
|
} else {
|
||||||
|
// 计算相对于屏幕尺寸的比例变化
|
||||||
|
if (isdrag) {
|
||||||
|
|
||||||
|
offsetx = server.cursor->x - server.drag_begin_cursorx;
|
||||||
|
offsety = server.cursor->y - server.drag_begin_cursory;
|
||||||
|
} else {
|
||||||
|
rec->old_master_mfact_per = rec->master_mfact_per;
|
||||||
|
rec->old_master_inner_per = rec->master_inner_per;
|
||||||
|
rec->old_stack_inner_per = rec->stack_inner_per;
|
||||||
|
rec->drag_begin_geom = rec->geom;
|
||||||
|
rec->cursor_in_upper_half = true;
|
||||||
|
rec->cursor_in_left_half = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec->ismaster) {
|
||||||
|
delta_x = (float)(offsetx) * (rec->old_master_mfact_per) /
|
||||||
|
rec->drag_begin_geom.width;
|
||||||
|
delta_y = (float)(offsety) * (rec->old_master_inner_per) /
|
||||||
|
rec->drag_begin_geom.height;
|
||||||
|
} else {
|
||||||
|
delta_x = (float)(offsetx) *
|
||||||
|
(1 - rec->old_master_mfact_per) /
|
||||||
|
rec->drag_begin_geom.width;
|
||||||
|
delta_y = (float)(offsety) * (rec->old_stack_inner_per) /
|
||||||
|
rec->drag_begin_geom.height;
|
||||||
|
}
|
||||||
|
bool moving_up;
|
||||||
|
bool moving_down;
|
||||||
|
|
||||||
|
if (!isdrag) {
|
||||||
|
moving_up = offsety < 0 ? true : false;
|
||||||
|
moving_down = offsety > 0 ? true : false;
|
||||||
|
} else {
|
||||||
|
moving_up = server.cursor->y < server.drag_begin_cursory;
|
||||||
|
moving_down = server.cursor->y > server.drag_begin_cursory;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec->ismaster && !prev) {
|
||||||
|
if (moving_up) {
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
} else {
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
}
|
||||||
|
} else if (rec->ismaster && next && !next->ismaster) {
|
||||||
|
if (moving_up) {
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
} else {
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
}
|
||||||
|
} else if (!rec->ismaster && prev && prev->ismaster) {
|
||||||
|
if (moving_up) {
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
} else {
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
}
|
||||||
|
} else if (!rec->ismaster && !next) {
|
||||||
|
if (moving_up) {
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
} else {
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
}
|
||||||
|
} else if (type == CENTER_TILE && !rec->ismaster &&
|
||||||
|
!nextnext) {
|
||||||
|
if (moving_up) {
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
} else {
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
}
|
||||||
|
} else if (type == CENTER_TILE && !rec->ismaster && prevprev &&
|
||||||
|
prevprev->ismaster) {
|
||||||
|
if (moving_up) {
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
} else {
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
}
|
||||||
|
} else if ((rec->cursor_in_upper_half && moving_up) ||
|
||||||
|
(!rec->cursor_in_upper_half && moving_down)) {
|
||||||
|
// 光标在窗口上方且向上移动,或在窗口下方且向下移动 → 增加高度
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
delta_y = delta_y * 2;
|
||||||
|
} else {
|
||||||
|
// 其他情况 → 减小高度
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
delta_y = delta_y * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rec->ismaster && rec->isleftstack &&
|
||||||
|
type == CENTER_TILE) {
|
||||||
|
delta_x = delta_x * -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec->ismaster && type == CENTER_TILE &&
|
||||||
|
rec->cursor_in_left_half) {
|
||||||
|
delta_x = delta_x * -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec->ismaster && type == CENTER_TILE) {
|
||||||
|
delta_x = delta_x * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == RIGHT_TILE) {
|
||||||
|
delta_x = delta_x * -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接设置新的比例,基于初始值 + 变化量
|
||||||
|
float new_master_mfact_per =
|
||||||
|
rec->old_master_mfact_per + delta_x;
|
||||||
|
float new_master_inner_per =
|
||||||
|
rec->old_master_inner_per + delta_y;
|
||||||
|
float new_stack_inner_per = rec->old_stack_inner_per + delta_y;
|
||||||
|
|
||||||
|
// 应用限制,确保比例在合理范围内
|
||||||
|
new_master_mfact_per = fmaxf(0.1f, fminf(0.9f, new_master_mfact_per));
|
||||||
|
new_master_inner_per = fmaxf(0.1f, fminf(0.9f, new_master_inner_per));
|
||||||
|
new_stack_inner_per = fmaxf(0.1f, fminf(0.9f, new_stack_inner_per));
|
||||||
|
|
||||||
|
// 应用到所有平铺窗口
|
||||||
|
wl_list_for_each(tc, &server.clients, link) {
|
||||||
|
if (VISIBLEON(tc, rec->mon) && ISTILED(tc)) {
|
||||||
|
tc->master_mfact_per = new_master_mfact_per;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rec->master_inner_per = new_master_inner_per;
|
||||||
|
rec->stack_inner_per = new_stack_inner_per;
|
||||||
|
|
||||||
|
if (!isdrag) {
|
||||||
|
arrange(rec->mon, false, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.last_apply_drag_time == 0 ||
|
||||||
|
time - server.last_apply_drag_time > drag_tile_refresh_interval) {
|
||||||
|
arrange(rec->mon, false, false);
|
||||||
|
server.last_apply_drag_time = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize_tile_master_vertical(Client *rec, bool isdrag, int32_t offsetx,
|
||||||
|
int32_t offsety, uint32_t time, int32_t type) {
|
||||||
|
Client *tc = NULL;
|
||||||
|
float delta_x, delta_y;
|
||||||
|
Client *next = NULL;
|
||||||
|
Client *prev = NULL;
|
||||||
|
struct wl_list *node;
|
||||||
|
|
||||||
|
// 从当前节点的下一个开始遍历
|
||||||
|
for (node = rec->link.next; node != &server.clients;
|
||||||
|
node = node->next) {
|
||||||
|
tc = wl_container_of(node, tc, link);
|
||||||
|
|
||||||
|
if (VISIBLEON(tc, rec->mon) &&
|
||||||
|
ISTILED(tc)) { // 根据你的实际字段名调整
|
||||||
|
next = tc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从当前节点的上一个开始遍历
|
||||||
|
for (node = rec->link.prev; node != &server.clients;
|
||||||
|
node = node->prev) {
|
||||||
|
tc = wl_container_of(node, tc, link);
|
||||||
|
|
||||||
|
if (VISIBLEON(tc, rec->mon) &&
|
||||||
|
ISTILED(tc)) { // 根据你的实际字段名调整
|
||||||
|
prev = tc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!server.start_drag_window && isdrag) {
|
||||||
|
server.drag_begin_cursorx = server.cursor->x;
|
||||||
|
server.drag_begin_cursory = server.cursor->y;
|
||||||
|
server.start_drag_window = true;
|
||||||
|
|
||||||
|
// 记录初始状态
|
||||||
|
rec->old_master_mfact_per = rec->master_mfact_per;
|
||||||
|
rec->old_master_inner_per = rec->master_inner_per;
|
||||||
|
rec->old_stack_inner_per = rec->stack_inner_per;
|
||||||
|
rec->cursor_in_upper_half =
|
||||||
|
server.cursor->y <
|
||||||
|
rec->geom.y + rec->geom.height / 2;
|
||||||
|
rec->cursor_in_left_half =
|
||||||
|
server.cursor->x <
|
||||||
|
rec->geom.x + rec->geom.width / 2;
|
||||||
|
// 记录初始几何信息
|
||||||
|
rec->drag_begin_geom = rec->geom;
|
||||||
|
} else {
|
||||||
|
// 计算相对于屏幕尺寸的比例变化
|
||||||
|
// 计算相对于屏幕尺寸的比例变化
|
||||||
|
if (isdrag) {
|
||||||
|
|
||||||
|
offsetx = server.cursor->x - server.drag_begin_cursorx;
|
||||||
|
offsety = server.cursor->y - server.drag_begin_cursory;
|
||||||
|
} else {
|
||||||
|
rec->old_master_mfact_per = rec->master_mfact_per;
|
||||||
|
rec->old_master_inner_per = rec->master_inner_per;
|
||||||
|
rec->old_stack_inner_per = rec->stack_inner_per;
|
||||||
|
rec->drag_begin_geom = rec->geom;
|
||||||
|
rec->cursor_in_upper_half = true;
|
||||||
|
rec->cursor_in_left_half = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec->ismaster) {
|
||||||
|
// 垂直版本:左右移动调整高度比例,上下移动调整宽度比例
|
||||||
|
delta_x = (float)(offsetx) * (rec->old_master_inner_per) /
|
||||||
|
rec->drag_begin_geom.width;
|
||||||
|
delta_y = (float)(offsety) * (rec->old_master_mfact_per) /
|
||||||
|
rec->drag_begin_geom.height;
|
||||||
|
} else {
|
||||||
|
delta_x = (float)(offsetx) * (rec->old_stack_inner_per) /
|
||||||
|
rec->drag_begin_geom.width;
|
||||||
|
delta_y = (float)(offsety) *
|
||||||
|
(1 - rec->old_master_mfact_per) /
|
||||||
|
rec->drag_begin_geom.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool moving_left;
|
||||||
|
bool moving_right;
|
||||||
|
|
||||||
|
if (!isdrag) {
|
||||||
|
moving_left = offsetx < 0 ? true : false;
|
||||||
|
moving_right = offsetx > 0 ? true : false;
|
||||||
|
} else {
|
||||||
|
moving_left = server.cursor->x < server.drag_begin_cursorx;
|
||||||
|
moving_right = server.cursor->x > server.drag_begin_cursorx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调整主区域和栈区域的高度比例(垂直分割)
|
||||||
|
if (rec->ismaster && !prev) {
|
||||||
|
if (moving_left) {
|
||||||
|
delta_x = -fabsf(delta_x); // 向上移动减少主区域高度
|
||||||
|
} else {
|
||||||
|
delta_x = fabsf(delta_x); // 向下移动增加主区域高度
|
||||||
|
}
|
||||||
|
} else if (rec->ismaster && next && !next->ismaster) {
|
||||||
|
if (moving_left) {
|
||||||
|
delta_x = fabsf(delta_x); // 向上移动增加主区域高度
|
||||||
|
} else {
|
||||||
|
delta_x = -fabsf(delta_x); // 向下移动减少主区域高度
|
||||||
|
}
|
||||||
|
} else if (!rec->ismaster && prev && prev->ismaster) {
|
||||||
|
if (moving_left) {
|
||||||
|
delta_x = -fabsf(delta_x); // 向上移动减少栈区域高度
|
||||||
|
} else {
|
||||||
|
delta_x = fabsf(delta_x); // 向下移动增加栈区域高度
|
||||||
|
}
|
||||||
|
} else if (!rec->ismaster && !next) {
|
||||||
|
if (moving_left) {
|
||||||
|
delta_x = fabsf(delta_x); // 向上移动增加栈区域高度
|
||||||
|
} else {
|
||||||
|
delta_x = -fabsf(delta_x); // 向下移动减少栈区域高度
|
||||||
|
}
|
||||||
|
} else if ((rec->cursor_in_left_half && moving_left) ||
|
||||||
|
(!rec->cursor_in_left_half && moving_right)) {
|
||||||
|
// 光标在窗口左侧且向左移动,或在窗口右侧且向右移动 → 增加宽度
|
||||||
|
delta_x = fabsf(delta_x);
|
||||||
|
delta_x = delta_x * 2;
|
||||||
|
} else {
|
||||||
|
// 其他情况 → 减小宽度
|
||||||
|
delta_x = -fabsf(delta_x);
|
||||||
|
delta_x = delta_x * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接设置新的比例,基于初始值 + 变化量
|
||||||
|
float new_master_mfact_per = rec->old_master_mfact_per +
|
||||||
|
delta_y; // 垂直:delta_y调整主区域高度
|
||||||
|
float new_master_inner_per = rec->old_master_inner_per +
|
||||||
|
delta_x; // 垂直:delta_x调整主区域内部宽度
|
||||||
|
float new_stack_inner_per = rec->old_stack_inner_per +
|
||||||
|
delta_x; // 垂直:delta_x调整栈区域内部宽度
|
||||||
|
|
||||||
|
// 应用限制,确保比例在合理范围内
|
||||||
|
new_master_mfact_per = fmaxf(0.1f, fminf(0.9f, new_master_mfact_per));
|
||||||
|
new_master_inner_per = fmaxf(0.1f, fminf(0.9f, new_master_inner_per));
|
||||||
|
new_stack_inner_per = fmaxf(0.1f, fminf(0.9f, new_stack_inner_per));
|
||||||
|
|
||||||
|
// 应用到所有平铺窗口
|
||||||
|
wl_list_for_each(tc, &server.clients, link) {
|
||||||
|
if (VISIBLEON(tc, rec->mon) && ISTILED(tc)) {
|
||||||
|
tc->master_mfact_per = new_master_mfact_per;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rec->master_inner_per = new_master_inner_per;
|
||||||
|
rec->stack_inner_per = new_stack_inner_per;
|
||||||
|
|
||||||
|
if (!isdrag) {
|
||||||
|
arrange(rec->mon, false, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.last_apply_drag_time == 0 ||
|
||||||
|
time - server.last_apply_drag_time > drag_tile_refresh_interval) {
|
||||||
|
arrange(rec->mon, false, false);
|
||||||
|
server.last_apply_drag_time = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize_tile_scroller(Client *rec, bool isdrag, int32_t offsetx,
|
||||||
|
int32_t offsety, uint32_t time, bool isvertical) {
|
||||||
|
float delta_x, delta_y;
|
||||||
|
float new_scroller_proportion;
|
||||||
|
float new_stack_proportion;
|
||||||
|
Client *stack_head = get_scroll_stack_head(rec);
|
||||||
|
|
||||||
|
if (rec && rec->mon->visible_tiling_clients == 1 &&
|
||||||
|
!scroller_ignore_proportion_single)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!server.start_drag_window && isdrag) {
|
||||||
|
server.drag_begin_cursorx = server.cursor->x;
|
||||||
|
server.drag_begin_cursory = server.cursor->y;
|
||||||
|
server.start_drag_window = true;
|
||||||
|
|
||||||
|
// 记录初始状态
|
||||||
|
stack_head->old_scroller_pproportion = stack_head->scroller_proportion;
|
||||||
|
rec->old_stack_proportion = rec->stack_proportion;
|
||||||
|
|
||||||
|
rec->cursor_in_left_half =
|
||||||
|
server.cursor->x <
|
||||||
|
rec->geom.x + rec->geom.width / 2;
|
||||||
|
rec->cursor_in_upper_half =
|
||||||
|
server.cursor->y <
|
||||||
|
rec->geom.y + rec->geom.height / 2;
|
||||||
|
// 记录初始几何信息
|
||||||
|
rec->drag_begin_geom = rec->geom;
|
||||||
|
} else {
|
||||||
|
// 计算相对于屏幕尺寸的比例变化
|
||||||
|
// 计算相对于屏幕尺寸的比例变化
|
||||||
|
if (isdrag) {
|
||||||
|
|
||||||
|
offsetx = server.cursor->x - server.drag_begin_cursorx;
|
||||||
|
offsety = server.cursor->y - server.drag_begin_cursory;
|
||||||
|
} else {
|
||||||
|
rec->old_master_mfact_per = rec->master_mfact_per;
|
||||||
|
rec->old_master_inner_per = rec->master_inner_per;
|
||||||
|
rec->old_stack_inner_per = rec->stack_inner_per;
|
||||||
|
rec->drag_begin_geom = rec->geom;
|
||||||
|
stack_head->old_scroller_pproportion =
|
||||||
|
stack_head->scroller_proportion;
|
||||||
|
rec->old_stack_proportion = rec->stack_proportion;
|
||||||
|
rec->cursor_in_upper_half = false;
|
||||||
|
rec->cursor_in_left_half = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isvertical) {
|
||||||
|
delta_y = (float)(offsety) *
|
||||||
|
(stack_head->old_scroller_pproportion) /
|
||||||
|
rec->drag_begin_geom.height;
|
||||||
|
delta_x = (float)(offsetx) * (rec->old_stack_proportion) /
|
||||||
|
rec->drag_begin_geom.width;
|
||||||
|
} else {
|
||||||
|
delta_x = (float)(offsetx) *
|
||||||
|
(stack_head->old_scroller_pproportion) /
|
||||||
|
rec->drag_begin_geom.width;
|
||||||
|
delta_y = (float)(offsety) * (rec->old_stack_proportion) /
|
||||||
|
rec->drag_begin_geom.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool moving_up;
|
||||||
|
bool moving_down;
|
||||||
|
bool moving_left;
|
||||||
|
bool moving_right;
|
||||||
|
|
||||||
|
if (!isdrag) {
|
||||||
|
moving_up = offsety < 0 ? true : false;
|
||||||
|
moving_down = offsety > 0 ? true : false;
|
||||||
|
moving_left = offsetx < 0 ? true : false;
|
||||||
|
moving_right = offsetx > 0 ? true : false;
|
||||||
|
} else {
|
||||||
|
moving_up = server.cursor->y < server.drag_begin_cursory;
|
||||||
|
moving_down = server.cursor->y > server.drag_begin_cursory;
|
||||||
|
moving_left = server.cursor->x < server.drag_begin_cursorx;
|
||||||
|
moving_right = server.cursor->x > server.drag_begin_cursorx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rec->cursor_in_upper_half && moving_up) ||
|
||||||
|
(!rec->cursor_in_upper_half && moving_down)) {
|
||||||
|
// 光标在窗口上方且向上移动,或在窗口下方且向下移动 → 增加高度
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
} else {
|
||||||
|
// 其他情况 → 减小高度
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rec->cursor_in_left_half && moving_left) ||
|
||||||
|
(!rec->cursor_in_left_half && moving_right)) {
|
||||||
|
delta_x = fabsf(delta_x);
|
||||||
|
} else {
|
||||||
|
delta_x = -fabsf(delta_x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isvertical) {
|
||||||
|
if (!rec->next_in_stack && rec->prev_in_stack &&
|
||||||
|
!isdrag) {
|
||||||
|
delta_x = delta_x * -1.0f;
|
||||||
|
}
|
||||||
|
if (!rec->next_in_stack && rec->prev_in_stack &&
|
||||||
|
isdrag) {
|
||||||
|
if (moving_right) {
|
||||||
|
delta_x = -fabsf(delta_x);
|
||||||
|
} else {
|
||||||
|
delta_x = fabsf(delta_x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!rec->prev_in_stack && rec->next_in_stack &&
|
||||||
|
isdrag) {
|
||||||
|
if (moving_left) {
|
||||||
|
delta_x = -fabsf(delta_x);
|
||||||
|
} else {
|
||||||
|
delta_x = fabsf(delta_x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isdrag) {
|
||||||
|
if (moving_up) {
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
} else {
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (!rec->next_in_stack && rec->prev_in_stack &&
|
||||||
|
!isdrag) {
|
||||||
|
delta_y = delta_y * -1.0f;
|
||||||
|
}
|
||||||
|
if (!rec->next_in_stack && rec->prev_in_stack &&
|
||||||
|
isdrag) {
|
||||||
|
if (moving_down) {
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
} else {
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!rec->prev_in_stack && rec->next_in_stack &&
|
||||||
|
isdrag) {
|
||||||
|
if (moving_up) {
|
||||||
|
delta_y = -fabsf(delta_y);
|
||||||
|
} else {
|
||||||
|
delta_y = fabsf(delta_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isdrag) {
|
||||||
|
if (moving_left) {
|
||||||
|
delta_x = -fabsf(delta_x);
|
||||||
|
} else {
|
||||||
|
delta_x = fabsf(delta_x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接设置新的比例,基于初始值 + 变化量
|
||||||
|
if (isvertical) {
|
||||||
|
new_scroller_proportion =
|
||||||
|
stack_head->old_scroller_pproportion + delta_y;
|
||||||
|
new_stack_proportion = rec->old_stack_proportion + delta_x;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
new_scroller_proportion =
|
||||||
|
stack_head->old_scroller_pproportion + delta_x;
|
||||||
|
new_stack_proportion = rec->old_stack_proportion + delta_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用限制,确保比例在合理范围内
|
||||||
|
new_scroller_proportion =
|
||||||
|
fmaxf(0.1f, fminf(1.0f, new_scroller_proportion));
|
||||||
|
new_stack_proportion = fmaxf(0.1f, fminf(1.0f, new_stack_proportion));
|
||||||
|
|
||||||
|
rec->stack_proportion = new_stack_proportion;
|
||||||
|
|
||||||
|
stack_head->scroller_proportion = new_scroller_proportion;
|
||||||
|
|
||||||
|
if (!isdrag) {
|
||||||
|
arrange(rec->mon, false, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.last_apply_drag_time == 0 ||
|
||||||
|
time - server.last_apply_drag_time > drag_tile_refresh_interval) {
|
||||||
|
arrange(rec->mon, false, false);
|
||||||
|
server.last_apply_drag_time = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize_tile_client(Client *rec, bool isdrag, int32_t offsetx,
|
||||||
|
int32_t offsety, uint32_t time) {
|
||||||
|
|
||||||
|
if (!rec || rec->isfullscreen ||
|
||||||
|
rec->ismaximizescreen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (rec->mon->isoverview)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Layout *current_layout =
|
||||||
|
rec->mon->pertag->ltidxs[rec->mon->pertag->curtag];
|
||||||
|
if (current_layout->id == TILE || current_layout->id == DECK ||
|
||||||
|
current_layout->id == CENTER_TILE || current_layout->id == RIGHT_TILE ||
|
||||||
|
(current_layout->id == TGMIX &&
|
||||||
|
rec->mon->visible_tiling_clients <= 3)
|
||||||
|
|
||||||
|
) {
|
||||||
|
resize_tile_master_horizontal(rec, isdrag, offsetx, offsety,
|
||||||
|
time, current_layout->id);
|
||||||
|
} else if (current_layout->id == VERTICAL_TILE ||
|
||||||
|
current_layout->id == VERTICAL_DECK) {
|
||||||
|
resize_tile_master_vertical(rec, isdrag, offsetx, offsety,
|
||||||
|
time, current_layout->id);
|
||||||
|
} else if (current_layout->id == SCROLLER) {
|
||||||
|
resize_tile_scroller(rec, isdrag, offsetx, offsety, time,
|
||||||
|
false);
|
||||||
|
} else if (current_layout->id == VERTICAL_SCROLLER) {
|
||||||
|
resize_tile_scroller(rec, isdrag, offsetx, offsety, time,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_size_per_mon(Monitor *m, int32_t tile_cilent_num,
|
||||||
|
double total_left_stack_hight_percent,
|
||||||
|
double total_right_stack_hight_percent,
|
||||||
|
double total_stack_hight_percent,
|
||||||
|
double total_master_inner_percent, int32_t master_num,
|
||||||
|
int32_t stack_num) {
|
||||||
|
Client *c = NULL;
|
||||||
|
int32_t i = 0;
|
||||||
|
uint32_t stack_index = 0;
|
||||||
|
uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
|
||||||
|
|
||||||
|
if (m->pertag->ltidxs[m->pertag->curtag]->id != CENTER_TILE) {
|
||||||
|
|
||||||
|
wl_list_for_each(c, &server.clients, link) {
|
||||||
|
if (VISIBLEON(c, m) && ISTILED(c)) {
|
||||||
|
if (total_master_inner_percent > 0.0 && i < nmasters) {
|
||||||
|
c->ismaster = true;
|
||||||
|
c->stack_inner_per = stack_num ? 1.0f / stack_num : 1.0f;
|
||||||
|
c->master_inner_per =
|
||||||
|
c->master_inner_per / total_master_inner_percent;
|
||||||
|
} else {
|
||||||
|
c->ismaster = false;
|
||||||
|
c->master_inner_per =
|
||||||
|
master_num > 0 ? 1.0f / master_num : 1.0f;
|
||||||
|
c->stack_inner_per =
|
||||||
|
total_stack_hight_percent
|
||||||
|
? c->stack_inner_per / total_stack_hight_percent
|
||||||
|
: 1.0f;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wl_list_for_each(c, &server.clients, link) {
|
||||||
|
if (VISIBLEON(c, m) && ISTILED(c)) {
|
||||||
|
if (total_master_inner_percent > 0.0 && i < nmasters) {
|
||||||
|
c->ismaster = true;
|
||||||
|
if ((stack_index % 2) ^ (tile_cilent_num % 2 == 0)) {
|
||||||
|
c->stack_inner_per =
|
||||||
|
stack_num > 1 ? 1.0f / ((stack_num - 1) / 2) : 1.0f;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
c->stack_inner_per =
|
||||||
|
stack_num > 1 ? 2.0f / stack_num : 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->master_inner_per =
|
||||||
|
c->master_inner_per / total_master_inner_percent;
|
||||||
|
} else {
|
||||||
|
stack_index = i - nmasters;
|
||||||
|
|
||||||
|
c->ismaster = false;
|
||||||
|
c->master_inner_per =
|
||||||
|
master_num > 0 ? 1.0f / master_num : 1.0f;
|
||||||
|
if ((stack_index % 2) ^ (tile_cilent_num % 2 == 0)) {
|
||||||
|
c->stack_inner_per =
|
||||||
|
total_right_stack_hight_percent
|
||||||
|
? c->stack_inner_per /
|
||||||
|
total_right_stack_hight_percent
|
||||||
|
: 1.0f;
|
||||||
|
} else {
|
||||||
|
c->stack_inner_per =
|
||||||
|
total_left_stack_hight_percent
|
||||||
|
? c->stack_inner_per /
|
||||||
|
total_left_stack_hight_percent
|
||||||
|
: 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize_floating_window(Client *rec) {
|
||||||
|
int cdx = (int)round(server.cursor->x) - server.grabcx;
|
||||||
|
int cdy = (int)round(server.cursor->y) - server.grabcy;
|
||||||
|
|
||||||
|
cdx = !(server.rzcorner & 1) &&
|
||||||
|
rec->geom.width - 2 * (int)rec->bw - cdx < 1
|
||||||
|
? 0
|
||||||
|
: cdx;
|
||||||
|
cdy =
|
||||||
|
!(server.rzcorner & 2) &&
|
||||||
|
rec->geom.height - 2 * (int)rec->bw - cdy < 1
|
||||||
|
? 0
|
||||||
|
: cdy;
|
||||||
|
|
||||||
|
const struct wlr_box box = {
|
||||||
|
.x = rec->geom.x + (server.rzcorner & 1 ? 0 : cdx),
|
||||||
|
.y = rec->geom.y + (server.rzcorner & 2 ? 0 : cdy),
|
||||||
|
.width = rec->geom.width + (server.rzcorner & 1 ? cdx : -cdx),
|
||||||
|
.height =
|
||||||
|
rec->geom.height + (server.rzcorner & 2 ? cdy : -cdy)};
|
||||||
|
|
||||||
|
rec->float_geom = box;
|
||||||
|
|
||||||
|
resize(rec, box, 1);
|
||||||
|
server.grabcx += cdx;
|
||||||
|
server.grabcy += cdy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void // 17
|
||||||
|
arrange(Monitor *m, bool want_animation, bool from_view) {
|
||||||
|
Client *c = NULL;
|
||||||
|
double total_stack_inner_percent = 0;
|
||||||
|
double total_master_inner_percent = 0;
|
||||||
|
double total_right_stack_hight_percent = 0;
|
||||||
|
double total_left_stack_hight_percent = 0;
|
||||||
|
int32_t i = 0;
|
||||||
|
int32_t nmasters = 0;
|
||||||
|
int32_t stack_index = 0;
|
||||||
|
int32_t master_num = 0;
|
||||||
|
int32_t stack_num = 0;
|
||||||
|
|
||||||
|
if (!m)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m->wlr_output->enabled)
|
||||||
|
return;
|
||||||
|
m->visible_clients = 0;
|
||||||
|
m->visible_tiling_clients = 0;
|
||||||
|
m->visible_scroll_tiling_clients = 0;
|
||||||
|
|
||||||
|
wl_list_for_each(c, &server.clients, link) {
|
||||||
|
|
||||||
|
if (!client_only_in_one_tag(c) || c->isglobal || c->isunglobal) {
|
||||||
|
exit_scroller_stack(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from_view && (c->isglobal || c->isunglobal)) {
|
||||||
|
set_size_per(m, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->mon == m && (c->isglobal || c->isunglobal)) {
|
||||||
|
c->tags = m->tagset[m->seltags];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from_view && m->sel == NULL && c->isglobal && VISIBLEON(c, m)) {
|
||||||
|
focusclient(c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VISIBLEON(c, m)) {
|
||||||
|
if (from_view && !client_only_in_one_tag(c)) {
|
||||||
|
set_size_per(m, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c->isunglobal)
|
||||||
|
m->visible_clients++;
|
||||||
|
|
||||||
|
if (ISTILED(c)) {
|
||||||
|
m->visible_tiling_clients++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ISSCROLLTILED(c) && !c->prev_in_stack) {
|
||||||
|
m->visible_scroll_tiling_clients++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nmasters = m->pertag->nmasters[m->pertag->curtag];
|
||||||
|
|
||||||
|
wl_list_for_each(c, &server.clients, link) {
|
||||||
|
if (c->iskilling)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (c->mon == m) {
|
||||||
|
if (VISIBLEON(c, m)) {
|
||||||
|
if (ISTILED(c)) {
|
||||||
|
|
||||||
|
if (i < nmasters) {
|
||||||
|
master_num++;
|
||||||
|
total_master_inner_percent += c->master_inner_per;
|
||||||
|
} else {
|
||||||
|
stack_num++;
|
||||||
|
total_stack_inner_percent += c->stack_inner_per;
|
||||||
|
stack_index = i - nmasters;
|
||||||
|
if ((stack_index % 2) ^
|
||||||
|
(m->visible_tiling_clients % 2 == 0)) {
|
||||||
|
c->isleftstack = false;
|
||||||
|
total_right_stack_hight_percent +=
|
||||||
|
c->stack_inner_per;
|
||||||
|
} else {
|
||||||
|
c->isleftstack = true;
|
||||||
|
total_left_stack_hight_percent +=
|
||||||
|
c->stack_inner_per;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_arrange_visible(m, c, want_animation);
|
||||||
|
} else {
|
||||||
|
set_arrange_hidden(m, c, want_animation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->mon == m && c->ismaximizescreen && !c->animation.tagouted &&
|
||||||
|
!c->animation.tagouting && VISIBLEON(c, m)) {
|
||||||
|
reset_maximizescreen_size(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_size_per_mon(
|
||||||
|
m, m->visible_tiling_clients, total_left_stack_hight_percent,
|
||||||
|
total_right_stack_hight_percent, total_stack_inner_percent,
|
||||||
|
total_master_inner_percent, master_num, stack_num);
|
||||||
|
|
||||||
|
if (m->isoverview) {
|
||||||
|
overviewlayout.arrange(m);
|
||||||
|
} else {
|
||||||
|
m->pertag->ltidxs[m->pertag->curtag]->arrange(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!server.start_drag_window) {
|
||||||
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||||
|
checkidleinhibitor(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
printstatus();
|
||||||
|
}
|
||||||
|
|
@ -1,836 +1,37 @@
|
||||||
void set_size_per(Monitor *m, Client *c) {
|
#ifndef TILE_RESIZE_H
|
||||||
Client *fc = NULL;
|
#define TILE_RESIZE_H
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
if (!m || !c)
|
/* 平铺窗口大小比例设置 */
|
||||||
return;
|
void set_size_per(Monitor *m, Client *c);
|
||||||
|
|
||||||
wl_list_for_each(fc, &server.clients, link) {
|
|
||||||
if (VISIBLEON(fc, m) && ISTILED(fc) && fc != c) {
|
|
||||||
c->master_mfact_per = fc->master_mfact_per;
|
|
||||||
c->master_inner_per = fc->master_inner_per;
|
|
||||||
c->stack_inner_per = fc->stack_inner_per;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
c->master_mfact_per = m->pertag->mfacts[m->pertag->curtag];
|
|
||||||
c->master_inner_per = 1.0f;
|
|
||||||
c->stack_inner_per = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 水平布局平铺窗口调整 */
|
||||||
void resize_tile_master_horizontal(Client *rec, bool isdrag, int32_t offsetx,
|
void resize_tile_master_horizontal(Client *rec, bool isdrag, int32_t offsetx,
|
||||||
int32_t offsety, uint32_t time,
|
int32_t offsety, uint32_t time, int32_t type);
|
||||||
int32_t type) {
|
|
||||||
Client *tc = NULL;
|
|
||||||
float delta_x, delta_y;
|
|
||||||
Client *next = NULL;
|
|
||||||
Client *prev = NULL;
|
|
||||||
Client *nextnext = NULL;
|
|
||||||
Client *prevprev = NULL;
|
|
||||||
struct wl_list *node;
|
|
||||||
bool begin_find_nextnext = false;
|
|
||||||
bool begin_find_prevprev = false;
|
|
||||||
|
|
||||||
// 从当前节点的下一个开始遍历
|
|
||||||
for (node = rec->link.next; node != &server.clients;
|
|
||||||
node = node->next) {
|
|
||||||
tc = wl_container_of(node, tc, link);
|
|
||||||
if (begin_find_nextnext && VISIBLEON(tc, rec->mon) &&
|
|
||||||
ISTILED(tc)) {
|
|
||||||
nextnext = tc;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!begin_find_nextnext && VISIBLEON(tc, rec->mon) &&
|
|
||||||
ISTILED(tc)) { // 根据你的实际字段名调整
|
|
||||||
next = tc;
|
|
||||||
begin_find_nextnext = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从当前节点的上一个开始遍历
|
|
||||||
for (node = rec->link.prev; node != &server.clients;
|
|
||||||
node = node->prev) {
|
|
||||||
tc = wl_container_of(node, tc, link);
|
|
||||||
|
|
||||||
if (begin_find_prevprev && VISIBLEON(tc, rec->mon) &&
|
|
||||||
ISTILED(tc)) {
|
|
||||||
prevprev = tc;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!begin_find_prevprev && VISIBLEON(tc, rec->mon) &&
|
|
||||||
ISTILED(tc)) { // 根据你的实际字段名调整
|
|
||||||
prev = tc;
|
|
||||||
begin_find_prevprev = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!server.start_drag_window && isdrag) {
|
|
||||||
server.drag_begin_cursorx = server.cursor->x;
|
|
||||||
server.drag_begin_cursory = server.cursor->y;
|
|
||||||
server.start_drag_window = true;
|
|
||||||
// 记录初始状态
|
|
||||||
rec->old_master_mfact_per = rec->master_mfact_per;
|
|
||||||
rec->old_master_inner_per = rec->master_inner_per;
|
|
||||||
rec->old_stack_inner_per = rec->stack_inner_per;
|
|
||||||
rec->cursor_in_upper_half =
|
|
||||||
server.cursor->y <
|
|
||||||
rec->geom.y + rec->geom.height / 2;
|
|
||||||
rec->cursor_in_left_half =
|
|
||||||
server.cursor->x <
|
|
||||||
rec->geom.x + rec->geom.width / 2;
|
|
||||||
// 记录初始几何信息
|
|
||||||
rec->drag_begin_geom = rec->geom;
|
|
||||||
} else {
|
|
||||||
// 计算相对于屏幕尺寸的比例变化
|
|
||||||
if (isdrag) {
|
|
||||||
|
|
||||||
offsetx = server.cursor->x - server.drag_begin_cursorx;
|
|
||||||
offsety = server.cursor->y - server.drag_begin_cursory;
|
|
||||||
} else {
|
|
||||||
rec->old_master_mfact_per = rec->master_mfact_per;
|
|
||||||
rec->old_master_inner_per = rec->master_inner_per;
|
|
||||||
rec->old_stack_inner_per = rec->stack_inner_per;
|
|
||||||
rec->drag_begin_geom = rec->geom;
|
|
||||||
rec->cursor_in_upper_half = true;
|
|
||||||
rec->cursor_in_left_half = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rec->ismaster) {
|
|
||||||
delta_x = (float)(offsetx) * (rec->old_master_mfact_per) /
|
|
||||||
rec->drag_begin_geom.width;
|
|
||||||
delta_y = (float)(offsety) * (rec->old_master_inner_per) /
|
|
||||||
rec->drag_begin_geom.height;
|
|
||||||
} else {
|
|
||||||
delta_x = (float)(offsetx) *
|
|
||||||
(1 - rec->old_master_mfact_per) /
|
|
||||||
rec->drag_begin_geom.width;
|
|
||||||
delta_y = (float)(offsety) * (rec->old_stack_inner_per) /
|
|
||||||
rec->drag_begin_geom.height;
|
|
||||||
}
|
|
||||||
bool moving_up;
|
|
||||||
bool moving_down;
|
|
||||||
|
|
||||||
if (!isdrag) {
|
|
||||||
moving_up = offsety < 0 ? true : false;
|
|
||||||
moving_down = offsety > 0 ? true : false;
|
|
||||||
} else {
|
|
||||||
moving_up = server.cursor->y < server.drag_begin_cursory;
|
|
||||||
moving_down = server.cursor->y > server.drag_begin_cursory;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rec->ismaster && !prev) {
|
|
||||||
if (moving_up) {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
}
|
|
||||||
} else if (rec->ismaster && next && !next->ismaster) {
|
|
||||||
if (moving_up) {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
}
|
|
||||||
} else if (!rec->ismaster && prev && prev->ismaster) {
|
|
||||||
if (moving_up) {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
}
|
|
||||||
} else if (!rec->ismaster && !next) {
|
|
||||||
if (moving_up) {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
}
|
|
||||||
} else if (type == CENTER_TILE && !rec->ismaster &&
|
|
||||||
!nextnext) {
|
|
||||||
if (moving_up) {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
}
|
|
||||||
} else if (type == CENTER_TILE && !rec->ismaster && prevprev &&
|
|
||||||
prevprev->ismaster) {
|
|
||||||
if (moving_up) {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
}
|
|
||||||
} else if ((rec->cursor_in_upper_half && moving_up) ||
|
|
||||||
(!rec->cursor_in_upper_half && moving_down)) {
|
|
||||||
// 光标在窗口上方且向上移动,或在窗口下方且向下移动 → 增加高度
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
delta_y = delta_y * 2;
|
|
||||||
} else {
|
|
||||||
// 其他情况 → 减小高度
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
delta_y = delta_y * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rec->ismaster && rec->isleftstack &&
|
|
||||||
type == CENTER_TILE) {
|
|
||||||
delta_x = delta_x * -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rec->ismaster && type == CENTER_TILE &&
|
|
||||||
rec->cursor_in_left_half) {
|
|
||||||
delta_x = delta_x * -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rec->ismaster && type == CENTER_TILE) {
|
|
||||||
delta_x = delta_x * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == RIGHT_TILE) {
|
|
||||||
delta_x = delta_x * -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直接设置新的比例,基于初始值 + 变化量
|
|
||||||
float new_master_mfact_per =
|
|
||||||
rec->old_master_mfact_per + delta_x;
|
|
||||||
float new_master_inner_per =
|
|
||||||
rec->old_master_inner_per + delta_y;
|
|
||||||
float new_stack_inner_per = rec->old_stack_inner_per + delta_y;
|
|
||||||
|
|
||||||
// 应用限制,确保比例在合理范围内
|
|
||||||
new_master_mfact_per = fmaxf(0.1f, fminf(0.9f, new_master_mfact_per));
|
|
||||||
new_master_inner_per = fmaxf(0.1f, fminf(0.9f, new_master_inner_per));
|
|
||||||
new_stack_inner_per = fmaxf(0.1f, fminf(0.9f, new_stack_inner_per));
|
|
||||||
|
|
||||||
// 应用到所有平铺窗口
|
|
||||||
wl_list_for_each(tc, &server.clients, link) {
|
|
||||||
if (VISIBLEON(tc, rec->mon) && ISTILED(tc)) {
|
|
||||||
tc->master_mfact_per = new_master_mfact_per;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rec->master_inner_per = new_master_inner_per;
|
|
||||||
rec->stack_inner_per = new_stack_inner_per;
|
|
||||||
|
|
||||||
if (!isdrag) {
|
|
||||||
arrange(rec->mon, false, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server.last_apply_drag_time == 0 ||
|
|
||||||
time - server.last_apply_drag_time > drag_tile_refresh_interval) {
|
|
||||||
arrange(rec->mon, false, false);
|
|
||||||
server.last_apply_drag_time = time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 垂直布局平铺窗口调整 */
|
||||||
void resize_tile_master_vertical(Client *rec, bool isdrag, int32_t offsetx,
|
void resize_tile_master_vertical(Client *rec, bool isdrag, int32_t offsetx,
|
||||||
int32_t offsety, uint32_t time, int32_t type) {
|
int32_t offsety, uint32_t time, int32_t type);
|
||||||
Client *tc = NULL;
|
|
||||||
float delta_x, delta_y;
|
|
||||||
Client *next = NULL;
|
|
||||||
Client *prev = NULL;
|
|
||||||
struct wl_list *node;
|
|
||||||
|
|
||||||
// 从当前节点的下一个开始遍历
|
|
||||||
for (node = rec->link.next; node != &server.clients;
|
|
||||||
node = node->next) {
|
|
||||||
tc = wl_container_of(node, tc, link);
|
|
||||||
|
|
||||||
if (VISIBLEON(tc, rec->mon) &&
|
|
||||||
ISTILED(tc)) { // 根据你的实际字段名调整
|
|
||||||
next = tc;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从当前节点的上一个开始遍历
|
|
||||||
for (node = rec->link.prev; node != &server.clients;
|
|
||||||
node = node->prev) {
|
|
||||||
tc = wl_container_of(node, tc, link);
|
|
||||||
|
|
||||||
if (VISIBLEON(tc, rec->mon) &&
|
|
||||||
ISTILED(tc)) { // 根据你的实际字段名调整
|
|
||||||
prev = tc;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!server.start_drag_window && isdrag) {
|
|
||||||
server.drag_begin_cursorx = server.cursor->x;
|
|
||||||
server.drag_begin_cursory = server.cursor->y;
|
|
||||||
server.start_drag_window = true;
|
|
||||||
|
|
||||||
// 记录初始状态
|
|
||||||
rec->old_master_mfact_per = rec->master_mfact_per;
|
|
||||||
rec->old_master_inner_per = rec->master_inner_per;
|
|
||||||
rec->old_stack_inner_per = rec->stack_inner_per;
|
|
||||||
rec->cursor_in_upper_half =
|
|
||||||
server.cursor->y <
|
|
||||||
rec->geom.y + rec->geom.height / 2;
|
|
||||||
rec->cursor_in_left_half =
|
|
||||||
server.cursor->x <
|
|
||||||
rec->geom.x + rec->geom.width / 2;
|
|
||||||
// 记录初始几何信息
|
|
||||||
rec->drag_begin_geom = rec->geom;
|
|
||||||
} else {
|
|
||||||
// 计算相对于屏幕尺寸的比例变化
|
|
||||||
// 计算相对于屏幕尺寸的比例变化
|
|
||||||
if (isdrag) {
|
|
||||||
|
|
||||||
offsetx = server.cursor->x - server.drag_begin_cursorx;
|
|
||||||
offsety = server.cursor->y - server.drag_begin_cursory;
|
|
||||||
} else {
|
|
||||||
rec->old_master_mfact_per = rec->master_mfact_per;
|
|
||||||
rec->old_master_inner_per = rec->master_inner_per;
|
|
||||||
rec->old_stack_inner_per = rec->stack_inner_per;
|
|
||||||
rec->drag_begin_geom = rec->geom;
|
|
||||||
rec->cursor_in_upper_half = true;
|
|
||||||
rec->cursor_in_left_half = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rec->ismaster) {
|
|
||||||
// 垂直版本:左右移动调整高度比例,上下移动调整宽度比例
|
|
||||||
delta_x = (float)(offsetx) * (rec->old_master_inner_per) /
|
|
||||||
rec->drag_begin_geom.width;
|
|
||||||
delta_y = (float)(offsety) * (rec->old_master_mfact_per) /
|
|
||||||
rec->drag_begin_geom.height;
|
|
||||||
} else {
|
|
||||||
delta_x = (float)(offsetx) * (rec->old_stack_inner_per) /
|
|
||||||
rec->drag_begin_geom.width;
|
|
||||||
delta_y = (float)(offsety) *
|
|
||||||
(1 - rec->old_master_mfact_per) /
|
|
||||||
rec->drag_begin_geom.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool moving_left;
|
|
||||||
bool moving_right;
|
|
||||||
|
|
||||||
if (!isdrag) {
|
|
||||||
moving_left = offsetx < 0 ? true : false;
|
|
||||||
moving_right = offsetx > 0 ? true : false;
|
|
||||||
} else {
|
|
||||||
moving_left = server.cursor->x < server.drag_begin_cursorx;
|
|
||||||
moving_right = server.cursor->x > server.drag_begin_cursorx;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调整主区域和栈区域的高度比例(垂直分割)
|
|
||||||
if (rec->ismaster && !prev) {
|
|
||||||
if (moving_left) {
|
|
||||||
delta_x = -fabsf(delta_x); // 向上移动减少主区域高度
|
|
||||||
} else {
|
|
||||||
delta_x = fabsf(delta_x); // 向下移动增加主区域高度
|
|
||||||
}
|
|
||||||
} else if (rec->ismaster && next && !next->ismaster) {
|
|
||||||
if (moving_left) {
|
|
||||||
delta_x = fabsf(delta_x); // 向上移动增加主区域高度
|
|
||||||
} else {
|
|
||||||
delta_x = -fabsf(delta_x); // 向下移动减少主区域高度
|
|
||||||
}
|
|
||||||
} else if (!rec->ismaster && prev && prev->ismaster) {
|
|
||||||
if (moving_left) {
|
|
||||||
delta_x = -fabsf(delta_x); // 向上移动减少栈区域高度
|
|
||||||
} else {
|
|
||||||
delta_x = fabsf(delta_x); // 向下移动增加栈区域高度
|
|
||||||
}
|
|
||||||
} else if (!rec->ismaster && !next) {
|
|
||||||
if (moving_left) {
|
|
||||||
delta_x = fabsf(delta_x); // 向上移动增加栈区域高度
|
|
||||||
} else {
|
|
||||||
delta_x = -fabsf(delta_x); // 向下移动减少栈区域高度
|
|
||||||
}
|
|
||||||
} else if ((rec->cursor_in_left_half && moving_left) ||
|
|
||||||
(!rec->cursor_in_left_half && moving_right)) {
|
|
||||||
// 光标在窗口左侧且向左移动,或在窗口右侧且向右移动 → 增加宽度
|
|
||||||
delta_x = fabsf(delta_x);
|
|
||||||
delta_x = delta_x * 2;
|
|
||||||
} else {
|
|
||||||
// 其他情况 → 减小宽度
|
|
||||||
delta_x = -fabsf(delta_x);
|
|
||||||
delta_x = delta_x * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直接设置新的比例,基于初始值 + 变化量
|
|
||||||
float new_master_mfact_per = rec->old_master_mfact_per +
|
|
||||||
delta_y; // 垂直:delta_y调整主区域高度
|
|
||||||
float new_master_inner_per = rec->old_master_inner_per +
|
|
||||||
delta_x; // 垂直:delta_x调整主区域内部宽度
|
|
||||||
float new_stack_inner_per = rec->old_stack_inner_per +
|
|
||||||
delta_x; // 垂直:delta_x调整栈区域内部宽度
|
|
||||||
|
|
||||||
// 应用限制,确保比例在合理范围内
|
|
||||||
new_master_mfact_per = fmaxf(0.1f, fminf(0.9f, new_master_mfact_per));
|
|
||||||
new_master_inner_per = fmaxf(0.1f, fminf(0.9f, new_master_inner_per));
|
|
||||||
new_stack_inner_per = fmaxf(0.1f, fminf(0.9f, new_stack_inner_per));
|
|
||||||
|
|
||||||
// 应用到所有平铺窗口
|
|
||||||
wl_list_for_each(tc, &server.clients, link) {
|
|
||||||
if (VISIBLEON(tc, rec->mon) && ISTILED(tc)) {
|
|
||||||
tc->master_mfact_per = new_master_mfact_per;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rec->master_inner_per = new_master_inner_per;
|
|
||||||
rec->stack_inner_per = new_stack_inner_per;
|
|
||||||
|
|
||||||
if (!isdrag) {
|
|
||||||
arrange(rec->mon, false, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server.last_apply_drag_time == 0 ||
|
|
||||||
time - server.last_apply_drag_time > drag_tile_refresh_interval) {
|
|
||||||
arrange(rec->mon, false, false);
|
|
||||||
server.last_apply_drag_time = time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 滚动布局平铺窗口调整 */
|
||||||
void resize_tile_scroller(Client *rec, bool isdrag, int32_t offsetx,
|
void resize_tile_scroller(Client *rec, bool isdrag, int32_t offsetx,
|
||||||
int32_t offsety, uint32_t time, bool isvertical) {
|
int32_t offsety, uint32_t time, bool isvertical);
|
||||||
float delta_x, delta_y;
|
|
||||||
float new_scroller_proportion;
|
|
||||||
float new_stack_proportion;
|
|
||||||
Client *stack_head = get_scroll_stack_head(rec);
|
|
||||||
|
|
||||||
if (rec && rec->mon->visible_tiling_clients == 1 &&
|
|
||||||
!scroller_ignore_proportion_single)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!server.start_drag_window && isdrag) {
|
|
||||||
server.drag_begin_cursorx = server.cursor->x;
|
|
||||||
server.drag_begin_cursory = server.cursor->y;
|
|
||||||
server.start_drag_window = true;
|
|
||||||
|
|
||||||
// 记录初始状态
|
|
||||||
stack_head->old_scroller_pproportion = stack_head->scroller_proportion;
|
|
||||||
rec->old_stack_proportion = rec->stack_proportion;
|
|
||||||
|
|
||||||
rec->cursor_in_left_half =
|
|
||||||
server.cursor->x <
|
|
||||||
rec->geom.x + rec->geom.width / 2;
|
|
||||||
rec->cursor_in_upper_half =
|
|
||||||
server.cursor->y <
|
|
||||||
rec->geom.y + rec->geom.height / 2;
|
|
||||||
// 记录初始几何信息
|
|
||||||
rec->drag_begin_geom = rec->geom;
|
|
||||||
} else {
|
|
||||||
// 计算相对于屏幕尺寸的比例变化
|
|
||||||
// 计算相对于屏幕尺寸的比例变化
|
|
||||||
if (isdrag) {
|
|
||||||
|
|
||||||
offsetx = server.cursor->x - server.drag_begin_cursorx;
|
|
||||||
offsety = server.cursor->y - server.drag_begin_cursory;
|
|
||||||
} else {
|
|
||||||
rec->old_master_mfact_per = rec->master_mfact_per;
|
|
||||||
rec->old_master_inner_per = rec->master_inner_per;
|
|
||||||
rec->old_stack_inner_per = rec->stack_inner_per;
|
|
||||||
rec->drag_begin_geom = rec->geom;
|
|
||||||
stack_head->old_scroller_pproportion =
|
|
||||||
stack_head->scroller_proportion;
|
|
||||||
rec->old_stack_proportion = rec->stack_proportion;
|
|
||||||
rec->cursor_in_upper_half = false;
|
|
||||||
rec->cursor_in_left_half = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isvertical) {
|
|
||||||
delta_y = (float)(offsety) *
|
|
||||||
(stack_head->old_scroller_pproportion) /
|
|
||||||
rec->drag_begin_geom.height;
|
|
||||||
delta_x = (float)(offsetx) * (rec->old_stack_proportion) /
|
|
||||||
rec->drag_begin_geom.width;
|
|
||||||
} else {
|
|
||||||
delta_x = (float)(offsetx) *
|
|
||||||
(stack_head->old_scroller_pproportion) /
|
|
||||||
rec->drag_begin_geom.width;
|
|
||||||
delta_y = (float)(offsety) * (rec->old_stack_proportion) /
|
|
||||||
rec->drag_begin_geom.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool moving_up;
|
|
||||||
bool moving_down;
|
|
||||||
bool moving_left;
|
|
||||||
bool moving_right;
|
|
||||||
|
|
||||||
if (!isdrag) {
|
|
||||||
moving_up = offsety < 0 ? true : false;
|
|
||||||
moving_down = offsety > 0 ? true : false;
|
|
||||||
moving_left = offsetx < 0 ? true : false;
|
|
||||||
moving_right = offsetx > 0 ? true : false;
|
|
||||||
} else {
|
|
||||||
moving_up = server.cursor->y < server.drag_begin_cursory;
|
|
||||||
moving_down = server.cursor->y > server.drag_begin_cursory;
|
|
||||||
moving_left = server.cursor->x < server.drag_begin_cursorx;
|
|
||||||
moving_right = server.cursor->x > server.drag_begin_cursorx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((rec->cursor_in_upper_half && moving_up) ||
|
|
||||||
(!rec->cursor_in_upper_half && moving_down)) {
|
|
||||||
// 光标在窗口上方且向上移动,或在窗口下方且向下移动 → 增加高度
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
// 其他情况 → 减小高度
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((rec->cursor_in_left_half && moving_left) ||
|
|
||||||
(!rec->cursor_in_left_half && moving_right)) {
|
|
||||||
delta_x = fabsf(delta_x);
|
|
||||||
} else {
|
|
||||||
delta_x = -fabsf(delta_x);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isvertical) {
|
|
||||||
if (!rec->next_in_stack && rec->prev_in_stack &&
|
|
||||||
!isdrag) {
|
|
||||||
delta_x = delta_x * -1.0f;
|
|
||||||
}
|
|
||||||
if (!rec->next_in_stack && rec->prev_in_stack &&
|
|
||||||
isdrag) {
|
|
||||||
if (moving_right) {
|
|
||||||
delta_x = -fabsf(delta_x);
|
|
||||||
} else {
|
|
||||||
delta_x = fabsf(delta_x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!rec->prev_in_stack && rec->next_in_stack &&
|
|
||||||
isdrag) {
|
|
||||||
if (moving_left) {
|
|
||||||
delta_x = -fabsf(delta_x);
|
|
||||||
} else {
|
|
||||||
delta_x = fabsf(delta_x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isdrag) {
|
|
||||||
if (moving_up) {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (!rec->next_in_stack && rec->prev_in_stack &&
|
|
||||||
!isdrag) {
|
|
||||||
delta_y = delta_y * -1.0f;
|
|
||||||
}
|
|
||||||
if (!rec->next_in_stack && rec->prev_in_stack &&
|
|
||||||
isdrag) {
|
|
||||||
if (moving_down) {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!rec->prev_in_stack && rec->next_in_stack &&
|
|
||||||
isdrag) {
|
|
||||||
if (moving_up) {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isdrag) {
|
|
||||||
if (moving_left) {
|
|
||||||
delta_x = -fabsf(delta_x);
|
|
||||||
} else {
|
|
||||||
delta_x = fabsf(delta_x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直接设置新的比例,基于初始值 + 变化量
|
|
||||||
if (isvertical) {
|
|
||||||
new_scroller_proportion =
|
|
||||||
stack_head->old_scroller_pproportion + delta_y;
|
|
||||||
new_stack_proportion = rec->old_stack_proportion + delta_x;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
new_scroller_proportion =
|
|
||||||
stack_head->old_scroller_pproportion + delta_x;
|
|
||||||
new_stack_proportion = rec->old_stack_proportion + delta_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 应用限制,确保比例在合理范围内
|
|
||||||
new_scroller_proportion =
|
|
||||||
fmaxf(0.1f, fminf(1.0f, new_scroller_proportion));
|
|
||||||
new_stack_proportion = fmaxf(0.1f, fminf(1.0f, new_stack_proportion));
|
|
||||||
|
|
||||||
rec->stack_proportion = new_stack_proportion;
|
|
||||||
|
|
||||||
stack_head->scroller_proportion = new_scroller_proportion;
|
|
||||||
|
|
||||||
if (!isdrag) {
|
|
||||||
arrange(rec->mon, false, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server.last_apply_drag_time == 0 ||
|
|
||||||
time - server.last_apply_drag_time > drag_tile_refresh_interval) {
|
|
||||||
arrange(rec->mon, false, false);
|
|
||||||
server.last_apply_drag_time = time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 通用平铺窗口调整入口函数 */
|
||||||
void resize_tile_client(Client *rec, bool isdrag, int32_t offsetx,
|
void resize_tile_client(Client *rec, bool isdrag, int32_t offsetx,
|
||||||
int32_t offsety, uint32_t time) {
|
int32_t offsety, uint32_t time);
|
||||||
|
|
||||||
if (!rec || rec->isfullscreen ||
|
|
||||||
rec->ismaximizescreen)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (rec->mon->isoverview)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const Layout *current_layout =
|
|
||||||
rec->mon->pertag->ltidxs[rec->mon->pertag->curtag];
|
|
||||||
if (current_layout->id == TILE || current_layout->id == DECK ||
|
|
||||||
current_layout->id == CENTER_TILE || current_layout->id == RIGHT_TILE ||
|
|
||||||
(current_layout->id == TGMIX &&
|
|
||||||
rec->mon->visible_tiling_clients <= 3)
|
|
||||||
|
|
||||||
) {
|
|
||||||
resize_tile_master_horizontal(rec, isdrag, offsetx, offsety,
|
|
||||||
time, current_layout->id);
|
|
||||||
} else if (current_layout->id == VERTICAL_TILE ||
|
|
||||||
current_layout->id == VERTICAL_DECK) {
|
|
||||||
resize_tile_master_vertical(rec, isdrag, offsetx, offsety,
|
|
||||||
time, current_layout->id);
|
|
||||||
} else if (current_layout->id == SCROLLER) {
|
|
||||||
resize_tile_scroller(rec, isdrag, offsetx, offsety, time,
|
|
||||||
false);
|
|
||||||
} else if (current_layout->id == VERTICAL_SCROLLER) {
|
|
||||||
resize_tile_scroller(rec, isdrag, offsetx, offsety, time,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 重置显示器上所有平铺窗口的比例 */
|
||||||
void reset_size_per_mon(Monitor *m, int32_t tile_cilent_num,
|
void reset_size_per_mon(Monitor *m, int32_t tile_cilent_num,
|
||||||
double total_left_stack_hight_percent,
|
double total_left_stack_hight_percent,
|
||||||
double total_right_stack_hight_percent,
|
double total_right_stack_hight_percent,
|
||||||
double total_stack_hight_percent,
|
double total_stack_hight_percent,
|
||||||
double total_master_inner_percent, int32_t master_num,
|
double total_master_inner_percent, int32_t master_num,
|
||||||
int32_t stack_num) {
|
int32_t stack_num);
|
||||||
Client *c = NULL;
|
|
||||||
int32_t i = 0;
|
|
||||||
uint32_t stack_index = 0;
|
|
||||||
uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
|
|
||||||
|
|
||||||
if (m->pertag->ltidxs[m->pertag->curtag]->id != CENTER_TILE) {
|
/* 浮动窗口调整大小 */
|
||||||
|
void resize_floating_window(Client *rec);
|
||||||
|
|
||||||
wl_list_for_each(c, &server.clients, link) {
|
/* 排列显示器上的所有窗口 */
|
||||||
if (VISIBLEON(c, m) && ISTILED(c)) {
|
void arrange(Monitor *m, bool want_animation, bool from_view);
|
||||||
if (total_master_inner_percent > 0.0 && i < nmasters) {
|
|
||||||
c->ismaster = true;
|
|
||||||
c->stack_inner_per = stack_num ? 1.0f / stack_num : 1.0f;
|
|
||||||
c->master_inner_per =
|
|
||||||
c->master_inner_per / total_master_inner_percent;
|
|
||||||
} else {
|
|
||||||
c->ismaster = false;
|
|
||||||
c->master_inner_per =
|
|
||||||
master_num > 0 ? 1.0f / master_num : 1.0f;
|
|
||||||
c->stack_inner_per =
|
|
||||||
total_stack_hight_percent
|
|
||||||
? c->stack_inner_per / total_stack_hight_percent
|
|
||||||
: 1.0f;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wl_list_for_each(c, &server.clients, link) {
|
|
||||||
if (VISIBLEON(c, m) && ISTILED(c)) {
|
|
||||||
if (total_master_inner_percent > 0.0 && i < nmasters) {
|
|
||||||
c->ismaster = true;
|
|
||||||
if ((stack_index % 2) ^ (tile_cilent_num % 2 == 0)) {
|
|
||||||
c->stack_inner_per =
|
|
||||||
stack_num > 1 ? 1.0f / ((stack_num - 1) / 2) : 1.0f;
|
|
||||||
|
|
||||||
} else {
|
#endif // TILE_RESIZE_H
|
||||||
c->stack_inner_per =
|
|
||||||
stack_num > 1 ? 2.0f / stack_num : 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->master_inner_per =
|
|
||||||
c->master_inner_per / total_master_inner_percent;
|
|
||||||
} else {
|
|
||||||
stack_index = i - nmasters;
|
|
||||||
|
|
||||||
c->ismaster = false;
|
|
||||||
c->master_inner_per =
|
|
||||||
master_num > 0 ? 1.0f / master_num : 1.0f;
|
|
||||||
if ((stack_index % 2) ^ (tile_cilent_num % 2 == 0)) {
|
|
||||||
c->stack_inner_per =
|
|
||||||
total_right_stack_hight_percent
|
|
||||||
? c->stack_inner_per /
|
|
||||||
total_right_stack_hight_percent
|
|
||||||
: 1.0f;
|
|
||||||
} else {
|
|
||||||
c->stack_inner_per =
|
|
||||||
total_left_stack_hight_percent
|
|
||||||
? c->stack_inner_per /
|
|
||||||
total_left_stack_hight_percent
|
|
||||||
: 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize_floating_window(Client *rec) {
|
|
||||||
int cdx = (int)round(server.cursor->x) - server.grabcx;
|
|
||||||
int cdy = (int)round(server.cursor->y) - server.grabcy;
|
|
||||||
|
|
||||||
cdx = !(server.rzcorner & 1) &&
|
|
||||||
rec->geom.width - 2 * (int)rec->bw - cdx < 1
|
|
||||||
? 0
|
|
||||||
: cdx;
|
|
||||||
cdy =
|
|
||||||
!(server.rzcorner & 2) &&
|
|
||||||
rec->geom.height - 2 * (int)rec->bw - cdy < 1
|
|
||||||
? 0
|
|
||||||
: cdy;
|
|
||||||
|
|
||||||
const struct wlr_box box = {
|
|
||||||
.x = rec->geom.x + (server.rzcorner & 1 ? 0 : cdx),
|
|
||||||
.y = rec->geom.y + (server.rzcorner & 2 ? 0 : cdy),
|
|
||||||
.width = rec->geom.width + (server.rzcorner & 1 ? cdx : -cdx),
|
|
||||||
.height =
|
|
||||||
rec->geom.height + (server.rzcorner & 2 ? cdy : -cdy)};
|
|
||||||
|
|
||||||
rec->float_geom = box;
|
|
||||||
|
|
||||||
resize(rec, box, 1);
|
|
||||||
server.grabcx += cdx;
|
|
||||||
server.grabcy += cdy;
|
|
||||||
}
|
|
||||||
|
|
||||||
void // 17
|
|
||||||
arrange(Monitor *m, bool want_animation, bool from_view) {
|
|
||||||
Client *c = NULL;
|
|
||||||
double total_stack_inner_percent = 0;
|
|
||||||
double total_master_inner_percent = 0;
|
|
||||||
double total_right_stack_hight_percent = 0;
|
|
||||||
double total_left_stack_hight_percent = 0;
|
|
||||||
int32_t i = 0;
|
|
||||||
int32_t nmasters = 0;
|
|
||||||
int32_t stack_index = 0;
|
|
||||||
int32_t master_num = 0;
|
|
||||||
int32_t stack_num = 0;
|
|
||||||
|
|
||||||
if (!m)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!m->wlr_output->enabled)
|
|
||||||
return;
|
|
||||||
m->visible_clients = 0;
|
|
||||||
m->visible_tiling_clients = 0;
|
|
||||||
m->visible_scroll_tiling_clients = 0;
|
|
||||||
|
|
||||||
wl_list_for_each(c, &server.clients, link) {
|
|
||||||
|
|
||||||
if (!client_only_in_one_tag(c) || c->isglobal || c->isunglobal) {
|
|
||||||
exit_scroller_stack(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from_view && (c->isglobal || c->isunglobal)) {
|
|
||||||
set_size_per(m, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->mon == m && (c->isglobal || c->isunglobal)) {
|
|
||||||
c->tags = m->tagset[m->seltags];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from_view && m->sel == NULL && c->isglobal && VISIBLEON(c, m)) {
|
|
||||||
focusclient(c, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VISIBLEON(c, m)) {
|
|
||||||
if (from_view && !client_only_in_one_tag(c)) {
|
|
||||||
set_size_per(m, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!c->isunglobal)
|
|
||||||
m->visible_clients++;
|
|
||||||
|
|
||||||
if (ISTILED(c)) {
|
|
||||||
m->visible_tiling_clients++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ISSCROLLTILED(c) && !c->prev_in_stack) {
|
|
||||||
m->visible_scroll_tiling_clients++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nmasters = m->pertag->nmasters[m->pertag->curtag];
|
|
||||||
|
|
||||||
wl_list_for_each(c, &server.clients, link) {
|
|
||||||
if (c->iskilling)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (c->mon == m) {
|
|
||||||
if (VISIBLEON(c, m)) {
|
|
||||||
if (ISTILED(c)) {
|
|
||||||
|
|
||||||
if (i < nmasters) {
|
|
||||||
master_num++;
|
|
||||||
total_master_inner_percent += c->master_inner_per;
|
|
||||||
} else {
|
|
||||||
stack_num++;
|
|
||||||
total_stack_inner_percent += c->stack_inner_per;
|
|
||||||
stack_index = i - nmasters;
|
|
||||||
if ((stack_index % 2) ^
|
|
||||||
(m->visible_tiling_clients % 2 == 0)) {
|
|
||||||
c->isleftstack = false;
|
|
||||||
total_right_stack_hight_percent +=
|
|
||||||
c->stack_inner_per;
|
|
||||||
} else {
|
|
||||||
c->isleftstack = true;
|
|
||||||
total_left_stack_hight_percent +=
|
|
||||||
c->stack_inner_per;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_arrange_visible(m, c, want_animation);
|
|
||||||
} else {
|
|
||||||
set_arrange_hidden(m, c, want_animation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->mon == m && c->ismaximizescreen && !c->animation.tagouted &&
|
|
||||||
!c->animation.tagouting && VISIBLEON(c, m)) {
|
|
||||||
reset_maximizescreen_size(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_size_per_mon(
|
|
||||||
m, m->visible_tiling_clients, total_left_stack_hight_percent,
|
|
||||||
total_right_stack_hight_percent, total_stack_inner_percent,
|
|
||||||
total_master_inner_percent, master_num, stack_num);
|
|
||||||
|
|
||||||
if (m->isoverview) {
|
|
||||||
overviewlayout.arrange(m);
|
|
||||||
} else {
|
|
||||||
m->pertag->ltidxs[m->pertag->curtag]->arrange(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!server.start_drag_window) {
|
|
||||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
|
||||||
checkidleinhibitor(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
printstatus();
|
|
||||||
}
|
|
||||||
26
src/layout/layout.c
Normal file
26
src/layout/layout.c
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#include "../type.h"
|
||||||
|
#include "layout.h"
|
||||||
|
|
||||||
|
Layout overviewlayout = {"", overview, "overview"};
|
||||||
|
|
||||||
|
|
||||||
|
Layout layouts[] = {
|
||||||
|
// 最少两个,不能删除少于两个
|
||||||
|
/* symbol arrange function name */
|
||||||
|
{"T", tile, "tile", TILE}, // 平铺布局
|
||||||
|
{"S", scroller, "scroller", SCROLLER}, // 滚动布局
|
||||||
|
{"G", grid, "grid", GRID}, // 格子布局
|
||||||
|
{"M", monocle, "monocle", MONOCLE}, // 单屏布局
|
||||||
|
{"K", deck, "deck", DECK}, // 卡片布局
|
||||||
|
{"CT", center_tile, "center_tile", CENTER_TILE}, // 居中布局
|
||||||
|
{"RT", right_tile, "right_tile", RIGHT_TILE}, // 右布局
|
||||||
|
{"VS", vertical_scroller, "vertical_scroller",
|
||||||
|
VERTICAL_SCROLLER}, // 垂直滚动布局
|
||||||
|
{"VT", vertical_tile, "vertical_tile", VERTICAL_TILE}, // 垂直平铺布局
|
||||||
|
{"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局
|
||||||
|
{"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局
|
||||||
|
{"TG", tgmix, "tgmix", TGMIX}, // 混合布局
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t layouts_len = sizeof(layouts) / sizeof(layouts[0]);
|
||||||
|
|
@ -1,20 +1,17 @@
|
||||||
static void tile(Monitor *m);
|
void tile(Monitor *m);
|
||||||
static void center_tile(Monitor *m);
|
void center_tile(Monitor *m);
|
||||||
static void right_tile(Monitor *m);
|
void right_tile(Monitor *m);
|
||||||
static void overview(Monitor *m);
|
void overview(Monitor *m);
|
||||||
static void grid(Monitor *m);
|
void grid(Monitor *m);
|
||||||
static void scroller(Monitor *m);
|
void scroller(Monitor *m);
|
||||||
static void deck(Monitor *mon);
|
void deck(Monitor *mon);
|
||||||
static void monocle(Monitor *m);
|
void monocle(Monitor *m);
|
||||||
static void vertical_tile(Monitor *m);
|
void vertical_tile(Monitor *m);
|
||||||
static void vertical_overview(Monitor *m);
|
void vertical_overview(Monitor *m);
|
||||||
static void vertical_grid(Monitor *m);
|
void vertical_grid(Monitor *m);
|
||||||
static void vertical_scroller(Monitor *m);
|
void vertical_scroller(Monitor *m);
|
||||||
static void vertical_deck(Monitor *mon);
|
void vertical_deck(Monitor *mon);
|
||||||
static void tgmix(Monitor *m);
|
void tgmix(Monitor *m);
|
||||||
|
|
||||||
/* layout(s) */
|
|
||||||
Layout overviewlayout = {"", overview, "overview"};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TILE,
|
TILE,
|
||||||
|
|
@ -30,21 +27,3 @@ enum {
|
||||||
RIGHT_TILE,
|
RIGHT_TILE,
|
||||||
TGMIX,
|
TGMIX,
|
||||||
};
|
};
|
||||||
|
|
||||||
Layout layouts[] = {
|
|
||||||
// 最少两个,不能删除少于两个
|
|
||||||
/* symbol arrange function name */
|
|
||||||
{"T", tile, "tile", TILE}, // 平铺布局
|
|
||||||
{"S", scroller, "scroller", SCROLLER}, // 滚动布局
|
|
||||||
{"G", grid, "grid", GRID}, // 格子布局
|
|
||||||
{"M", monocle, "monocle", MONOCLE}, // 单屏布局
|
|
||||||
{"K", deck, "deck", DECK}, // 卡片布局
|
|
||||||
{"CT", center_tile, "center_tile", CENTER_TILE}, // 居中布局
|
|
||||||
{"RT", right_tile, "right_tile", RIGHT_TILE}, // 右布局
|
|
||||||
{"VS", vertical_scroller, "vertical_scroller",
|
|
||||||
VERTICAL_SCROLLER}, // 垂直滚动布局
|
|
||||||
{"VT", vertical_tile, "vertical_tile", VERTICAL_TILE}, // 垂直平铺布局
|
|
||||||
{"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局
|
|
||||||
{"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局
|
|
||||||
{"TG", tgmix, "tgmix", TGMIX}, // 混合布局
|
|
||||||
};
|
|
||||||
1032
src/mango.c
1032
src/mango.c
File diff suppressed because it is too large
Load diff
916
src/type.h
Normal file
916
src/type.h
Normal file
|
|
@ -0,0 +1,916 @@
|
||||||
|
/*
|
||||||
|
* See LICENSE file for copyright and license details.
|
||||||
|
*/
|
||||||
|
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||||
|
#include "wlr/util/box.h"
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <libinput.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
#include <scenefx/render/fx_renderer/fx_renderer.h>
|
||||||
|
#include <scenefx/types/fx/blur_data.h>
|
||||||
|
#include <scenefx/types/fx/clipped_region.h>
|
||||||
|
#include <scenefx/types/fx/corner_location.h>
|
||||||
|
#include <scenefx/types/wlr_scene.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
#include <wlr/backend.h>
|
||||||
|
#include <wlr/backend/headless.h>
|
||||||
|
#include <wlr/backend/libinput.h>
|
||||||
|
#include <wlr/backend/multi.h>
|
||||||
|
#include <wlr/backend/wayland.h>
|
||||||
|
#include <wlr/interfaces/wlr_keyboard.h>
|
||||||
|
#include <wlr/render/allocator.h>
|
||||||
|
#include <wlr/render/wlr_renderer.h>
|
||||||
|
#include <wlr/types/wlr_alpha_modifier_v1.h>
|
||||||
|
#include <wlr/types/wlr_compositor.h>
|
||||||
|
#include <wlr/types/wlr_cursor.h>
|
||||||
|
#include <wlr/types/wlr_cursor_shape_v1.h>
|
||||||
|
#include <wlr/types/wlr_data_control_v1.h>
|
||||||
|
#include <wlr/types/wlr_data_device.h>
|
||||||
|
#include <wlr/types/wlr_drm.h>
|
||||||
|
#include <wlr/types/wlr_drm_lease_v1.h>
|
||||||
|
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||||
|
#include <wlr/types/wlr_ext_data_control_v1.h>
|
||||||
|
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
||||||
|
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
||||||
|
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||||
|
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||||
|
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||||
|
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||||
|
#include <wlr/types/wlr_input_device.h>
|
||||||
|
#include <wlr/types/wlr_keyboard.h>
|
||||||
|
#include <wlr/types/wlr_keyboard_group.h>
|
||||||
|
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
|
||||||
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
|
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||||
|
#include <wlr/types/wlr_linux_drm_syncobj_v1.h>
|
||||||
|
#include <wlr/types/wlr_output.h>
|
||||||
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
|
#include <wlr/types/wlr_output_management_v1.h>
|
||||||
|
#include <wlr/types/wlr_output_power_management_v1.h>
|
||||||
|
#include <wlr/types/wlr_pointer.h>
|
||||||
|
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||||
|
#include <wlr/types/wlr_pointer_gestures_v1.h>
|
||||||
|
#include <wlr/types/wlr_presentation_time.h>
|
||||||
|
#include <wlr/types/wlr_primary_selection.h>
|
||||||
|
#include <wlr/types/wlr_primary_selection_v1.h>
|
||||||
|
#include <wlr/types/wlr_relative_pointer_v1.h>
|
||||||
|
#include <wlr/types/wlr_screencopy_v1.h>
|
||||||
|
#include <wlr/types/wlr_seat.h>
|
||||||
|
#include <wlr/types/wlr_server_decoration.h>
|
||||||
|
#include <wlr/types/wlr_session_lock_v1.h>
|
||||||
|
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
|
||||||
|
#include <wlr/types/wlr_subcompositor.h>
|
||||||
|
#include <wlr/types/wlr_switch.h>
|
||||||
|
#include <wlr/types/wlr_viewporter.h>
|
||||||
|
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||||
|
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||||
|
#include <wlr/types/wlr_xcursor_manager.h>
|
||||||
|
#include <wlr/types/wlr_xdg_activation_v1.h>
|
||||||
|
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
||||||
|
#include <wlr/types/wlr_xdg_foreign_registry.h>
|
||||||
|
#include <wlr/types/wlr_xdg_foreign_v1.h>
|
||||||
|
#include <wlr/types/wlr_xdg_foreign_v2.h>
|
||||||
|
#include <wlr/types/wlr_xdg_output_v1.h>
|
||||||
|
#include <wlr/types/wlr_xdg_shell.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
|
#include <wlr/util/region.h>
|
||||||
|
#include <wordexp.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <wlr/xwayland.h>
|
||||||
|
#include <xcb/xcb_icccm.h>
|
||||||
|
#endif
|
||||||
|
#include "common/util.h"
|
||||||
|
|
||||||
|
/* macros */
|
||||||
|
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
|
#define GEZERO(A) ((A) >= 0 ? (A) : 0)
|
||||||
|
#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS)
|
||||||
|
#define INSIDEMON(A) \
|
||||||
|
(A->geom.x >= A->mon->m.x && A->geom.y >= A->mon->m.y && \
|
||||||
|
A->geom.x + A->geom.width <= A->mon->m.x + A->mon->m.width && \
|
||||||
|
A->geom.y + A->geom.height <= A->mon->m.y + A->mon->m.height)
|
||||||
|
#define GEOMINSIDEMON(A, M) \
|
||||||
|
(A->x >= M->m.x && A->y >= M->m.y && \
|
||||||
|
A->x + A->width <= M->m.x + M->m.width && \
|
||||||
|
A->y + A->height <= M->m.y + M->m.height)
|
||||||
|
#define ISTILED(A) \
|
||||||
|
(A && !(A)->isfloating && !(A)->isminimized && !(A)->iskilling && \
|
||||||
|
!(A)->ismaximizescreen && !(A)->isfullscreen && !(A)->isunglobal)
|
||||||
|
#define ISSCROLLTILED(A) \
|
||||||
|
(A && !(A)->isfloating && !(A)->isminimized && !(A)->iskilling && \
|
||||||
|
!(A)->isunglobal)
|
||||||
|
#define VISIBLEON(C, M) \
|
||||||
|
((C) && (M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
|
||||||
|
#define LENGTH(X) (sizeof X / sizeof X[0])
|
||||||
|
#define END(A) ((A) + LENGTH(A))
|
||||||
|
#define TAGMASK ((1 << LENGTH(tags)) - 1)
|
||||||
|
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
|
||||||
|
#define ISFULLSCREEN(A) \
|
||||||
|
((A)->isfullscreen || (A)->ismaximizescreen || \
|
||||||
|
(A)->overview_ismaximizescreenbak || (A)->overview_isfullscreenbak)
|
||||||
|
#define LISTEN_STATIC(E, H) \
|
||||||
|
do { \
|
||||||
|
struct wl_listener *_l = ecalloc(1, sizeof(*_l)); \
|
||||||
|
_l->notify = (H); \
|
||||||
|
wl_signal_add((E), _l); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define APPLY_INT_PROP(obj, rule, prop) \
|
||||||
|
if (rule->prop >= 0) \
|
||||||
|
obj->prop = rule->prop
|
||||||
|
|
||||||
|
#define APPLY_FLOAT_PROP(obj, rule, prop) \
|
||||||
|
if (rule->prop > 0.0f) \
|
||||||
|
obj->prop = rule->prop
|
||||||
|
|
||||||
|
#define APPLY_STRING_PROP(obj, rule, prop) \
|
||||||
|
if (rule->prop != NULL) \
|
||||||
|
obj->prop = rule->prop
|
||||||
|
|
||||||
|
#define BAKED_POINTS_COUNT 256
|
||||||
|
|
||||||
|
/* enums */
|
||||||
|
enum { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT };
|
||||||
|
|
||||||
|
enum { VERTICAL, HORIZONTAL };
|
||||||
|
enum { SWIPE_UP, SWIPE_DOWN, SWIPE_LEFT, SWIPE_RIGHT };
|
||||||
|
enum { CurNormal, CurPressed, CurMove, CurResize }; /* server.cursor */
|
||||||
|
enum { XDGShell, LayerShell, X11 }; /* client types */
|
||||||
|
enum { AxisUp, AxisDown, AxisLeft, AxisRight }; // 滚轮滚动的方向
|
||||||
|
enum {
|
||||||
|
LyrBg,
|
||||||
|
LyrBlur,
|
||||||
|
LyrBottom,
|
||||||
|
LyrTile,
|
||||||
|
LyrTop,
|
||||||
|
LyrFadeOut,
|
||||||
|
LyrOverlay,
|
||||||
|
LyrIMPopup, // text-input layer
|
||||||
|
LyrBlock,
|
||||||
|
NUM_LAYERS
|
||||||
|
}; /* server.scene server.layers */
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
enum {
|
||||||
|
NetWMWindowTypeDialog,
|
||||||
|
NetWMWindowTypeSplash,
|
||||||
|
NetWMWindowTypeToolbar,
|
||||||
|
NetWMWindowTypeUtility,
|
||||||
|
NetLast
|
||||||
|
}; /* EWMH atoms */
|
||||||
|
#endif
|
||||||
|
enum { UP, DOWN, LEFT, RIGHT, UNDIR }; /* smartmovewin */
|
||||||
|
enum { NONE, OPEN, MOVE, CLOSE, TAG, FOCUS, OPAFADEIN, OPAFADEOUT };
|
||||||
|
enum { UNFOLD, FOLD, INVALIDFOLD };
|
||||||
|
enum { PREV, NEXT };
|
||||||
|
enum { STATE_UNSPECIFIED = 0, STATE_ENABLED, STATE_DISABLED };
|
||||||
|
|
||||||
|
enum tearing_mode {
|
||||||
|
TEARING_DISABLED = 0,
|
||||||
|
TEARING_ENABLED,
|
||||||
|
TEARING_FULLSCREEN_ONLY,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum seat_config_shortcuts_inhibit {
|
||||||
|
SHORTCUTS_INHIBIT_DISABLE,
|
||||||
|
SHORTCUTS_INHIBIT_ENABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 事件掩码枚举
|
||||||
|
enum print_event_type {
|
||||||
|
PRINT_ACTIVE = 1 << 0,
|
||||||
|
PRINT_TAG = 1 << 1,
|
||||||
|
PRINT_LAYOUT = 1 << 2,
|
||||||
|
PRINT_TITLE = 1 << 3,
|
||||||
|
PRINT_APPID = 1 << 4,
|
||||||
|
PRINT_LAYOUT_SYMBOL = 1 << 5,
|
||||||
|
PRINT_FULLSCREEN = 1 << 6,
|
||||||
|
PRINT_FLOATING = 1 << 7,
|
||||||
|
PRINT_X = 1 << 8,
|
||||||
|
PRINT_Y = 1 << 9,
|
||||||
|
PRINT_WIDTH = 1 << 10,
|
||||||
|
PRINT_HEIGHT = 1 << 11,
|
||||||
|
PRINT_LAST_LAYER = 1 << 12,
|
||||||
|
PRINT_KB_LAYOUT = 1 << 13,
|
||||||
|
PRINT_KEYMODE = 1 << 14,
|
||||||
|
PRINT_SCALEFACTOR = 1 << 15,
|
||||||
|
PRINT_FRAME = 1 << 16,
|
||||||
|
PRINT_ALL = (1 << 17) - 1 // 所有位都设为1
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Pertag Pertag;
|
||||||
|
typedef struct Monitor Monitor;
|
||||||
|
typedef struct Client Client;
|
||||||
|
|
||||||
|
struct dvec2 {
|
||||||
|
double x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ivec2 {
|
||||||
|
int32_t x, y, width, height;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t i;
|
||||||
|
int32_t i2;
|
||||||
|
float f;
|
||||||
|
float f2;
|
||||||
|
char *v;
|
||||||
|
char *v2;
|
||||||
|
char *v3;
|
||||||
|
uint32_t ui;
|
||||||
|
uint32_t ui2;
|
||||||
|
} Arg;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name; // keymode名称
|
||||||
|
bool is_default; // 是否为默认模式
|
||||||
|
bool is_common; // 是否为公共模式
|
||||||
|
} KeyMode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t mod;
|
||||||
|
uint32_t button;
|
||||||
|
int32_t (*func)(const Arg *);
|
||||||
|
const Arg arg;
|
||||||
|
} Button; // 鼠标按键
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t mod;
|
||||||
|
uint32_t dir;
|
||||||
|
int32_t (*func)(const Arg *);
|
||||||
|
const Arg arg;
|
||||||
|
} Axis;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct wl_list link;
|
||||||
|
struct wlr_input_device *wlr_device;
|
||||||
|
struct libinput_device *libinput_device;
|
||||||
|
struct wl_listener destroy_listener; // 用于监听设备销毁事件
|
||||||
|
void *device_data; // 新增:指向设备特定数据(如 Switch)
|
||||||
|
} InputDevice;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct wl_list link;
|
||||||
|
struct wlr_switch *wlr_switch;
|
||||||
|
struct wl_listener toggle;
|
||||||
|
InputDevice *input_dev;
|
||||||
|
} Switch;
|
||||||
|
|
||||||
|
struct dwl_animation {
|
||||||
|
bool should_animate;
|
||||||
|
bool running;
|
||||||
|
bool tagining;
|
||||||
|
bool tagouted;
|
||||||
|
bool tagouting;
|
||||||
|
bool begin_fade_in;
|
||||||
|
bool tag_from_rule;
|
||||||
|
uint32_t time_started;
|
||||||
|
uint32_t duration;
|
||||||
|
struct wlr_box initial;
|
||||||
|
struct wlr_box current;
|
||||||
|
int32_t action;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dwl_opacity_animation {
|
||||||
|
bool running;
|
||||||
|
float current_opacity;
|
||||||
|
float target_opacity;
|
||||||
|
float initial_opacity;
|
||||||
|
uint32_t time_started;
|
||||||
|
uint32_t duration;
|
||||||
|
float current_border_color[4];
|
||||||
|
float target_border_color[4];
|
||||||
|
float initial_border_color[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float width_scale;
|
||||||
|
float height_scale;
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
|
enum corner_location corner_location;
|
||||||
|
bool should_scale;
|
||||||
|
} BufferData;
|
||||||
|
|
||||||
|
struct Client {
|
||||||
|
/* Must keep these three elements in this order */
|
||||||
|
uint32_t type; /* XDGShell or X11* */
|
||||||
|
struct wlr_box geom, pending, float_geom, animainit_geom,
|
||||||
|
overview_backup_geom, current,
|
||||||
|
drag_begin_geom; /* layout-relative, includes border */
|
||||||
|
Monitor *mon;
|
||||||
|
struct wlr_scene_tree *scene;
|
||||||
|
struct wlr_scene_rect *border; /* top, bottom, left, right */
|
||||||
|
struct wlr_scene_shadow *shadow;
|
||||||
|
struct wlr_scene_tree *scene_surface;
|
||||||
|
struct wl_list link;
|
||||||
|
struct wl_list flink;
|
||||||
|
struct wl_list fadeout_link;
|
||||||
|
union {
|
||||||
|
struct wlr_xdg_surface *xdg;
|
||||||
|
struct wlr_xwayland_surface *xwayland;
|
||||||
|
} surface;
|
||||||
|
struct wl_listener commit;
|
||||||
|
struct wl_listener map;
|
||||||
|
struct wl_listener maximize;
|
||||||
|
struct wl_listener minimize;
|
||||||
|
struct wl_listener unmap;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
struct wl_listener set_title;
|
||||||
|
struct wl_listener fullscreen;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
struct wl_listener activate;
|
||||||
|
struct wl_listener associate;
|
||||||
|
struct wl_listener dissociate;
|
||||||
|
struct wl_listener configure;
|
||||||
|
struct wl_listener set_hints;
|
||||||
|
struct wl_listener set_geometry;
|
||||||
|
#endif
|
||||||
|
uint32_t bw;
|
||||||
|
uint32_t tags, oldtags, mini_restore_tag;
|
||||||
|
bool dirty;
|
||||||
|
uint32_t configure_serial;
|
||||||
|
struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel;
|
||||||
|
int32_t isfloating, isurgent, isfullscreen, isfakefullscreen,
|
||||||
|
need_float_size_reduce, isminimized, isoverlay, isnosizehint,
|
||||||
|
ignore_maximize, ignore_minimize;
|
||||||
|
int32_t ismaximizescreen;
|
||||||
|
int32_t overview_backup_bw;
|
||||||
|
int32_t fullscreen_backup_x, fullscreen_backup_y, fullscreen_backup_w,
|
||||||
|
fullscreen_backup_h;
|
||||||
|
int32_t overview_isfullscreenbak, overview_ismaximizescreenbak,
|
||||||
|
overview_isfloatingbak;
|
||||||
|
|
||||||
|
struct wlr_xdg_toplevel_decoration_v1 *decoration;
|
||||||
|
struct wl_listener foreign_activate_request;
|
||||||
|
struct wl_listener foreign_fullscreen_request;
|
||||||
|
struct wl_listener foreign_close_request;
|
||||||
|
struct wl_listener foreign_destroy;
|
||||||
|
struct wl_listener foreign_minimize_request;
|
||||||
|
struct wl_listener foreign_maximize_request;
|
||||||
|
struct wl_listener set_decoration_mode;
|
||||||
|
struct wl_listener destroy_decoration;
|
||||||
|
|
||||||
|
const char *animation_type_open;
|
||||||
|
const char *animation_type_close;
|
||||||
|
int32_t is_in_scratchpad;
|
||||||
|
int32_t iscustomsize;
|
||||||
|
int32_t iscustompos;
|
||||||
|
int32_t is_scratchpad_show;
|
||||||
|
int32_t isglobal;
|
||||||
|
int32_t isnoborder;
|
||||||
|
int32_t isnoshadow;
|
||||||
|
int32_t isnoradius;
|
||||||
|
int32_t isnoanimation;
|
||||||
|
int32_t isopensilent;
|
||||||
|
int32_t istagsilent;
|
||||||
|
int32_t iskilling;
|
||||||
|
int32_t istagswitching;
|
||||||
|
int32_t isnamedscratchpad;
|
||||||
|
bool is_pending_open_animation;
|
||||||
|
bool is_restoring_from_ov;
|
||||||
|
float scroller_proportion;
|
||||||
|
float stack_proportion;
|
||||||
|
float old_stack_proportion;
|
||||||
|
bool need_output_flush;
|
||||||
|
struct dwl_animation animation;
|
||||||
|
struct dwl_opacity_animation opacity_animation;
|
||||||
|
int32_t isterm, noswallow;
|
||||||
|
int32_t allow_csd;
|
||||||
|
int32_t force_maximize;
|
||||||
|
pid_t pid;
|
||||||
|
Client *swallowing, *swallowedby;
|
||||||
|
bool is_clip_to_hide;
|
||||||
|
bool drag_to_tile;
|
||||||
|
bool scratchpad_switching_mon;
|
||||||
|
bool fake_no_border;
|
||||||
|
int32_t nofocus;
|
||||||
|
int32_t nofadein;
|
||||||
|
int32_t nofadeout;
|
||||||
|
int32_t no_force_center;
|
||||||
|
int32_t isunglobal;
|
||||||
|
float focused_opacity;
|
||||||
|
float unfocused_opacity;
|
||||||
|
char oldmonname[128];
|
||||||
|
int32_t noblur;
|
||||||
|
double master_mfact_per, master_inner_per, stack_inner_per;
|
||||||
|
double old_master_mfact_per, old_master_inner_per, old_stack_inner_per;
|
||||||
|
double old_scroller_pproportion;
|
||||||
|
bool ismaster;
|
||||||
|
bool cursor_in_upper_half, cursor_in_left_half;
|
||||||
|
bool isleftstack;
|
||||||
|
int32_t tearing_hint;
|
||||||
|
int32_t force_tearing;
|
||||||
|
int32_t allow_shortcuts_inhibit;
|
||||||
|
float scroller_proportion_single;
|
||||||
|
bool isfocusing;
|
||||||
|
struct Client *next_in_stack;
|
||||||
|
struct Client *prev_in_stack;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct wl_list link;
|
||||||
|
struct wl_resource *resource;
|
||||||
|
Monitor *mon;
|
||||||
|
} DwlIpcOutput;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t mod;
|
||||||
|
xkb_keysym_t keysym;
|
||||||
|
int32_t (*func)(const Arg *);
|
||||||
|
const Arg arg;
|
||||||
|
} Key;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct wlr_keyboard_group *wlr_group;
|
||||||
|
|
||||||
|
int32_t nsyms;
|
||||||
|
const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */
|
||||||
|
uint32_t mods; /* invalid if nsyms == 0 */
|
||||||
|
uint32_t keycode;
|
||||||
|
struct wl_event_source *key_repeat_source;
|
||||||
|
|
||||||
|
struct wl_listener modifiers;
|
||||||
|
struct wl_listener key;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
} KeyboardGroup;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct wlr_keyboard_shortcuts_inhibitor_v1 *inhibitor;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
struct wl_list link;
|
||||||
|
} KeyboardShortcutsInhibitor;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* Must keep these three elements in this order */
|
||||||
|
uint32_t type; /* LayerShell */
|
||||||
|
struct wlr_box geom, current, pending, animainit_geom;
|
||||||
|
Monitor *mon;
|
||||||
|
struct wlr_scene_tree *scene;
|
||||||
|
struct wlr_scene_tree *popups;
|
||||||
|
struct wlr_scene_shadow *shadow;
|
||||||
|
struct wlr_scene_layer_surface_v1 *scene_layer;
|
||||||
|
struct wl_list link;
|
||||||
|
struct wl_list fadeout_link;
|
||||||
|
int32_t mapped;
|
||||||
|
struct wlr_layer_surface_v1 *layer_surface;
|
||||||
|
|
||||||
|
struct wl_listener destroy;
|
||||||
|
struct wl_listener map;
|
||||||
|
struct wl_listener unmap;
|
||||||
|
struct wl_listener surface_commit;
|
||||||
|
|
||||||
|
struct dwl_animation animation;
|
||||||
|
bool dirty;
|
||||||
|
int32_t noblur;
|
||||||
|
int32_t noanim;
|
||||||
|
int32_t noshadow;
|
||||||
|
char *animation_type_open;
|
||||||
|
char *animation_type_close;
|
||||||
|
bool need_output_flush;
|
||||||
|
bool being_unmapped;
|
||||||
|
} LayerSurface;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *symbol;
|
||||||
|
void (*arrange)(Monitor *);
|
||||||
|
const char *name;
|
||||||
|
uint32_t id;
|
||||||
|
} Layout;
|
||||||
|
|
||||||
|
struct Monitor {
|
||||||
|
struct wl_list link;
|
||||||
|
struct wlr_output *wlr_output;
|
||||||
|
struct wlr_scene_output *scene_output;
|
||||||
|
struct wlr_output_state pending;
|
||||||
|
struct wl_listener frame;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
struct wl_listener request_state;
|
||||||
|
struct wl_listener destroy_lock_surface;
|
||||||
|
struct wlr_session_lock_surface_v1 *lock_surface;
|
||||||
|
struct wlr_box m; /* monitor area, layout-relative */
|
||||||
|
struct wlr_box w; /* window area, layout-relative */
|
||||||
|
struct wl_list layers[4]; /* LayerSurface::link */
|
||||||
|
uint32_t seltags;
|
||||||
|
uint32_t tagset[2];
|
||||||
|
|
||||||
|
struct wl_list dwl_ipc_outputs;
|
||||||
|
int32_t gappih; /* horizontal gap between windows */
|
||||||
|
int32_t gappiv; /* vertical gap between windows */
|
||||||
|
int32_t gappoh; /* horizontal outer gaps */
|
||||||
|
int32_t gappov; /* vertical outer gaps */
|
||||||
|
Pertag *pertag;
|
||||||
|
Client *sel, *prevsel;
|
||||||
|
int32_t isoverview;
|
||||||
|
int32_t is_in_hotarea;
|
||||||
|
int32_t asleep;
|
||||||
|
uint32_t visible_clients;
|
||||||
|
uint32_t visible_tiling_clients;
|
||||||
|
uint32_t visible_scroll_tiling_clients;
|
||||||
|
struct wlr_scene_optimized_blur *blur;
|
||||||
|
char last_surface_ws_name[256];
|
||||||
|
struct wlr_ext_workspace_group_handle_v1 *ext_group;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct wlr_pointer_constraint_v1 *constraint;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
} PointerConstraint;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct wlr_scene_tree *scene;
|
||||||
|
|
||||||
|
struct wlr_session_lock_v1 *lock;
|
||||||
|
struct wl_listener new_surface;
|
||||||
|
struct wl_listener unlock;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
} SessionLock;
|
||||||
|
|
||||||
|
// 在你的头文件中(比如 server.h)
|
||||||
|
// 在你的头文件中(比如 server.h)
|
||||||
|
typedef struct {
|
||||||
|
// 键盘模式相关
|
||||||
|
KeyMode keymode;
|
||||||
|
|
||||||
|
// 核心 Wayland/WLRoots 对象
|
||||||
|
struct wl_display *dpy;
|
||||||
|
struct wl_event_loop *event_loop;
|
||||||
|
struct wlr_backend *backend;
|
||||||
|
struct wlr_backend *headless_backend;
|
||||||
|
struct wlr_scene *scene;
|
||||||
|
struct wlr_scene_tree *layers[NUM_LAYERS];
|
||||||
|
struct wlr_renderer *drw;
|
||||||
|
struct wlr_allocator *alloc;
|
||||||
|
struct wlr_compositor *compositor;
|
||||||
|
|
||||||
|
// Shell 相关
|
||||||
|
struct wlr_xdg_shell *xdg_shell;
|
||||||
|
struct wlr_xdg_activation_v1 *activation;
|
||||||
|
struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr;
|
||||||
|
struct wl_list clients; /* tiling order */
|
||||||
|
struct wl_list fstack; /* focus order */
|
||||||
|
struct wl_list fadeout_clients;
|
||||||
|
struct wl_list fadeout_layers;
|
||||||
|
struct wlr_idle_notifier_v1 *idle_notifier;
|
||||||
|
struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr;
|
||||||
|
struct wlr_layer_shell_v1 *layer_shell;
|
||||||
|
struct wlr_output_manager_v1 *output_mgr;
|
||||||
|
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr;
|
||||||
|
struct wlr_keyboard_shortcuts_inhibit_manager_v1
|
||||||
|
*keyboard_shortcuts_inhibit;
|
||||||
|
struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
|
||||||
|
struct wlr_output_power_manager_v1 *power_mgr;
|
||||||
|
struct wlr_pointer_gestures_v1 *pointer_gestures;
|
||||||
|
struct wlr_drm_lease_v1_manager *drm_lease_manager;
|
||||||
|
struct mango_print_status_manager *print_status_manager;
|
||||||
|
|
||||||
|
// 光标和输入相关
|
||||||
|
struct wlr_cursor *cursor;
|
||||||
|
struct wlr_xcursor_manager *cursor_mgr;
|
||||||
|
struct wlr_session *session;
|
||||||
|
|
||||||
|
// 界面元素
|
||||||
|
struct wlr_scene_rect *root_bg;
|
||||||
|
struct wlr_session_lock_manager_v1 *session_lock_mgr;
|
||||||
|
struct wlr_scene_rect *locked_bg;
|
||||||
|
struct wlr_session_lock_v1 *cur_lock;
|
||||||
|
struct wlr_scene_tree *drag_icon;
|
||||||
|
struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr;
|
||||||
|
struct wlr_pointer_constraints_v1 *pointer_constraints;
|
||||||
|
struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr;
|
||||||
|
struct wlr_pointer_constraint_v1 *active_constraint;
|
||||||
|
|
||||||
|
// 座位和键盘
|
||||||
|
struct wlr_seat *seat;
|
||||||
|
KeyboardGroup *kb_group;
|
||||||
|
struct wl_list inputdevices;
|
||||||
|
struct wl_list keyboard_shortcut_inhibitors;
|
||||||
|
|
||||||
|
// 布局相关
|
||||||
|
struct wlr_output_layout *output_layout;
|
||||||
|
struct wl_list mons;
|
||||||
|
Monitor *selmon;
|
||||||
|
struct wlr_box sgeom;
|
||||||
|
|
||||||
|
// 动画曲线数据
|
||||||
|
struct dvec2 *baked_points_move;
|
||||||
|
struct dvec2 *baked_points_open;
|
||||||
|
struct dvec2 *baked_points_tag;
|
||||||
|
struct dvec2 *baked_points_close;
|
||||||
|
struct dvec2 *baked_points_focus;
|
||||||
|
struct dvec2 *baked_points_opafadein;
|
||||||
|
struct dvec2 *baked_points_opafadeout;
|
||||||
|
|
||||||
|
// 事件源
|
||||||
|
struct wl_event_source *hide_source;
|
||||||
|
|
||||||
|
// 光标状态
|
||||||
|
struct {
|
||||||
|
enum wp_cursor_shape_device_v1_shape shape;
|
||||||
|
struct wlr_surface *surface;
|
||||||
|
int32_t hotspot_x;
|
||||||
|
int32_t hotspot_y;
|
||||||
|
} last_cursor;
|
||||||
|
|
||||||
|
// 各种状态变量
|
||||||
|
pid_t child_pid;
|
||||||
|
int32_t locked;
|
||||||
|
uint32_t locked_mods;
|
||||||
|
void *exclusive_focus;
|
||||||
|
uint32_t cursor_mode;
|
||||||
|
Client *grabc;
|
||||||
|
int32_t rzcorner;
|
||||||
|
int32_t grabcx, grabcy;
|
||||||
|
int32_t drag_begin_cursorx, drag_begin_cursory;
|
||||||
|
bool start_drag_window;
|
||||||
|
int32_t last_apply_drag_time;
|
||||||
|
|
||||||
|
int32_t enablegaps;
|
||||||
|
int32_t axis_apply_time;
|
||||||
|
int32_t axis_apply_dir;
|
||||||
|
int32_t scroller_focus_lock;
|
||||||
|
|
||||||
|
uint32_t swipe_fingers;
|
||||||
|
double swipe_dx;
|
||||||
|
double swipe_dy;
|
||||||
|
|
||||||
|
bool render_border;
|
||||||
|
uint32_t chvt_backup_tag;
|
||||||
|
bool allow_frame_scheduling;
|
||||||
|
char chvt_backup_selmon[32];
|
||||||
|
|
||||||
|
bool cursor_hidden;
|
||||||
|
bool tag_combo;
|
||||||
|
|
||||||
|
// 配置路径
|
||||||
|
const char *cli_config_path;
|
||||||
|
} Server;
|
||||||
|
|
||||||
|
|
||||||
|
/* function declarations */
|
||||||
|
void init_server(void);
|
||||||
|
void free_server(void);
|
||||||
|
void applybounds(
|
||||||
|
Client *c,
|
||||||
|
struct wlr_box *bbox); // 设置边界规则,能让一些窗口拥有比较适合的大小
|
||||||
|
void applyrules(Client *c); // 窗口规则应用,应用config.h中定义的窗口规则
|
||||||
|
void arrange(Monitor *m, bool want_animation,
|
||||||
|
bool from_view); // 布局函数,让窗口俺平铺规则移动和重置大小
|
||||||
|
void arrangelayer(Monitor *m, struct wl_list *list,
|
||||||
|
struct wlr_box *usable_area, int32_t exclusive);
|
||||||
|
void arrangelayers(Monitor *m);
|
||||||
|
void handle_print_status(struct wl_listener *listener, void *data);
|
||||||
|
void axisnotify(struct wl_listener *listener,
|
||||||
|
void *data); // 滚轮事件处理
|
||||||
|
void buttonpress(struct wl_listener *listener,
|
||||||
|
void *data); // 鼠标按键事件处理
|
||||||
|
int32_t ongesture(struct wlr_pointer_swipe_end_event *event);
|
||||||
|
void swipe_begin(struct wl_listener *listener, void *data);
|
||||||
|
void swipe_update(struct wl_listener *listener, void *data);
|
||||||
|
void swipe_end(struct wl_listener *listener, void *data);
|
||||||
|
void pinch_begin(struct wl_listener *listener, void *data);
|
||||||
|
void pinch_update(struct wl_listener *listener, void *data);
|
||||||
|
void pinch_end(struct wl_listener *listener, void *data);
|
||||||
|
void hold_begin(struct wl_listener *listener, void *data);
|
||||||
|
void hold_end(struct wl_listener *listener, void *data);
|
||||||
|
void checkidleinhibitor(struct wlr_surface *exclude);
|
||||||
|
void cleanup(void); // 退出清理
|
||||||
|
void cleanupmon(struct wl_listener *listener, void *data); // 退出清理
|
||||||
|
void closemon(Monitor *m);
|
||||||
|
void cleanuplisteners(void);
|
||||||
|
void toggle_hotarea(int32_t x_root, int32_t y_root); // 触发热区
|
||||||
|
void maplayersurfacenotify(struct wl_listener *listener, void *data);
|
||||||
|
void commitlayersurfacenotify(struct wl_listener *listener, void *data);
|
||||||
|
void commitnotify(struct wl_listener *listener, void *data);
|
||||||
|
void createdecoration(struct wl_listener *listener, void *data);
|
||||||
|
void createidleinhibitor(struct wl_listener *listener, void *data);
|
||||||
|
void createkeyboard(struct wlr_keyboard *keyboard);
|
||||||
|
void requestmonstate(struct wl_listener *listener, void *data);
|
||||||
|
void createlayersurface(struct wl_listener *listener, void *data);
|
||||||
|
void createlocksurface(struct wl_listener *listener, void *data);
|
||||||
|
void createmon(struct wl_listener *listener, void *data);
|
||||||
|
void createnotify(struct wl_listener *listener, void *data);
|
||||||
|
void createpointer(struct wlr_pointer *pointer);
|
||||||
|
void configure_pointer(struct libinput_device *device);
|
||||||
|
void destroyinputdevice(struct wl_listener *listener, void *data);
|
||||||
|
void createswitch(struct wlr_switch *switch_device);
|
||||||
|
void switch_toggle(struct wl_listener *listener, void *data);
|
||||||
|
void createpointerconstraint(struct wl_listener *listener, void *data);
|
||||||
|
void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
|
||||||
|
void commitpopup(struct wl_listener *listener, void *data);
|
||||||
|
void createpopup(struct wl_listener *listener, void *data);
|
||||||
|
void cursorframe(struct wl_listener *listener, void *data);
|
||||||
|
void cursorwarptohint(void);
|
||||||
|
void destroydecoration(struct wl_listener *listener, void *data);
|
||||||
|
void destroydragicon(struct wl_listener *listener, void *data);
|
||||||
|
void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
||||||
|
void destroylayernodenotify(struct wl_listener *listener, void *data);
|
||||||
|
void destroylock(SessionLock *lock, int32_t unlocked);
|
||||||
|
void destroylocksurface(struct wl_listener *listener, void *data);
|
||||||
|
void destroynotify(struct wl_listener *listener, void *data);
|
||||||
|
void destroypointerconstraint(struct wl_listener *listener, void *data);
|
||||||
|
void destroysessionlock(struct wl_listener *listener, void *data);
|
||||||
|
void destroykeyboardgroup(struct wl_listener *listener, void *data);
|
||||||
|
Monitor *dirtomon(enum wlr_direction dir);
|
||||||
|
void setcursorshape(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
|
void focusclient(Client *c, int32_t lift);
|
||||||
|
|
||||||
|
void setborder_color(Client *c);
|
||||||
|
Client *focustop(Monitor *m);
|
||||||
|
void fullscreennotify(struct wl_listener *listener, void *data);
|
||||||
|
void gpureset(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
|
int32_t keyrepeat(void *data);
|
||||||
|
|
||||||
|
void inputdevice(struct wl_listener *listener, void *data);
|
||||||
|
int32_t keybinding(uint32_t state, bool locked, uint32_t mods,
|
||||||
|
xkb_keysym_t sym, uint32_t keycode);
|
||||||
|
void keypress(struct wl_listener *listener, void *data);
|
||||||
|
void keypressmod(struct wl_listener *listener, void *data);
|
||||||
|
bool keypressglobal(struct wlr_surface *last_surface,
|
||||||
|
struct wlr_keyboard *keyboard,
|
||||||
|
struct wlr_keyboard_key_event *event, uint32_t mods,
|
||||||
|
xkb_keysym_t keysym, uint32_t keycode);
|
||||||
|
void locksession(struct wl_listener *listener, void *data);
|
||||||
|
void mapnotify(struct wl_listener *listener, void *data);
|
||||||
|
void maximizenotify(struct wl_listener *listener, void *data);
|
||||||
|
void minimizenotify(struct wl_listener *listener, void *data);
|
||||||
|
void motionabsolute(struct wl_listener *listener, void *data);
|
||||||
|
void motionnotify(uint32_t time, struct wlr_input_device *device,
|
||||||
|
double sx, double sy, double sx_unaccel,
|
||||||
|
double sy_unaccel);
|
||||||
|
void motionrelative(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
|
void reset_foreign_tolevel(Client *c);
|
||||||
|
void remove_foreign_topleve(Client *c);
|
||||||
|
void add_foreign_topleve(Client *c);
|
||||||
|
void exchange_two_client(Client *c1, Client *c2);
|
||||||
|
void outputmgrapply(struct wl_listener *listener, void *data);
|
||||||
|
void outputmgrapplyortest(struct wlr_output_configuration_v1 *config,
|
||||||
|
int32_t test);
|
||||||
|
void outputmgrtest(struct wl_listener *listener, void *data);
|
||||||
|
void pointerfocus(Client *c, struct wlr_surface *surface, double sx,
|
||||||
|
double sy, uint32_t time);
|
||||||
|
void printstatus(void);
|
||||||
|
void quitsignal(int32_t signo);
|
||||||
|
void powermgrsetmode(struct wl_listener *listener, void *data);
|
||||||
|
void rendermon(struct wl_listener *listener, void *data);
|
||||||
|
void requestdecorationmode(struct wl_listener *listener, void *data);
|
||||||
|
void requestdrmlease(struct wl_listener *listener, void *data);
|
||||||
|
void requeststartdrag(struct wl_listener *listener, void *data);
|
||||||
|
void resize(Client *c, struct wlr_box geo, int32_t interact);
|
||||||
|
void run(char *startup_cmd);
|
||||||
|
void setcursor(struct wl_listener *listener, void *data);
|
||||||
|
void setfloating(Client *c, int32_t floating);
|
||||||
|
void setfakefullscreen(Client *c, int32_t fakefullscreen);
|
||||||
|
void setfullscreen(Client *c, int32_t fullscreen);
|
||||||
|
void setmaximizescreen(Client *c, int32_t maximizescreen);
|
||||||
|
void reset_maximizescreen_size(Client *c);
|
||||||
|
void setgaps(int32_t oh, int32_t ov, int32_t ih, int32_t iv);
|
||||||
|
|
||||||
|
void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus);
|
||||||
|
void setpsel(struct wl_listener *listener, void *data);
|
||||||
|
void setsel(struct wl_listener *listener, void *data);
|
||||||
|
void setup(void);
|
||||||
|
void startdrag(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
|
void unlocksession(struct wl_listener *listener, void *data);
|
||||||
|
void unmaplayersurfacenotify(struct wl_listener *listener, void *data);
|
||||||
|
void unmapnotify(struct wl_listener *listener, void *data);
|
||||||
|
void updatemons(struct wl_listener *listener, void *data);
|
||||||
|
void updatetitle(struct wl_listener *listener, void *data);
|
||||||
|
void urgent(struct wl_listener *listener, void *data);
|
||||||
|
void view(const Arg *arg, bool want_animation);
|
||||||
|
|
||||||
|
void handlesig(int32_t signo);
|
||||||
|
void
|
||||||
|
handle_keyboard_shortcuts_inhibit_new_inhibitor(struct wl_listener *listener,
|
||||||
|
void *data);
|
||||||
|
void virtualkeyboard(struct wl_listener *listener, void *data);
|
||||||
|
void virtualpointer(struct wl_listener *listener, void *data);
|
||||||
|
void warp_cursor(const Client *c);
|
||||||
|
Monitor *xytomon(double x, double y);
|
||||||
|
void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||||
|
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||||
|
void clear_fullscreen_flag(Client *c);
|
||||||
|
pid_t getparentprocess(pid_t p);
|
||||||
|
int32_t isdescprocess(pid_t p, pid_t c);
|
||||||
|
Client *termforwin(Client *w);
|
||||||
|
void swallow(Client *c, Client *w);
|
||||||
|
|
||||||
|
void warp_cursor_to_selmon(Monitor *m);
|
||||||
|
uint32_t want_restore_fullscreen(Client *target_client);
|
||||||
|
void overview_restore(Client *c, const Arg *arg);
|
||||||
|
void overview_backup(Client *c);
|
||||||
|
void set_minimized(Client *c);
|
||||||
|
|
||||||
|
void show_scratchpad(Client *c);
|
||||||
|
void show_hide_client(Client *c);
|
||||||
|
void tag_client(const Arg *arg, Client *target_client);
|
||||||
|
|
||||||
|
struct wlr_box setclient_coordinate_center(Client *c, Monitor *m,
|
||||||
|
struct wlr_box geom,
|
||||||
|
int32_t offsetx,
|
||||||
|
int32_t offsety);
|
||||||
|
uint32_t get_tags_first_tag(uint32_t tags);
|
||||||
|
|
||||||
|
struct wlr_output_mode *
|
||||||
|
get_nearest_output_mode(struct wlr_output *output, int32_t width,
|
||||||
|
int32_t height, float refresh);
|
||||||
|
|
||||||
|
void client_commit(Client *c);
|
||||||
|
void layer_commit(LayerSurface *l);
|
||||||
|
void apply_border(Client *c);
|
||||||
|
void client_set_opacity(Client *c, double opacity);
|
||||||
|
void init_baked_points(void);
|
||||||
|
void scene_buffer_apply_opacity(struct wlr_scene_buffer *buffer,
|
||||||
|
int32_t sx, int32_t sy, void *data);
|
||||||
|
|
||||||
|
Client *direction_select(const Arg *arg);
|
||||||
|
void view_in_mon(const Arg *arg, bool want_animation, Monitor *m,
|
||||||
|
bool changefocus);
|
||||||
|
|
||||||
|
void buffer_set_effect(Client *c, BufferData buffer_data);
|
||||||
|
void snap_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
||||||
|
int32_t sx, int32_t sy, void *data);
|
||||||
|
void client_set_pending_state(Client *c);
|
||||||
|
void layer_set_pending_state(LayerSurface *l);
|
||||||
|
void set_rect_size(struct wlr_scene_rect *rect, int32_t width,
|
||||||
|
int32_t height);
|
||||||
|
Client *center_tiled_select(Monitor *m);
|
||||||
|
void handlecursoractivity(void);
|
||||||
|
int32_t hidecursor(void *data);
|
||||||
|
bool check_hit_no_border(Client *c);
|
||||||
|
void reset_keyboard_layout(void);
|
||||||
|
void client_update_oldmonname_record(Client *c, Monitor *m);
|
||||||
|
void pending_kill_client(Client *c);
|
||||||
|
uint32_t get_tags_first_tag_num(uint32_t source_tags);
|
||||||
|
void set_layer_open_animaiton(LayerSurface *l, struct wlr_box geo);
|
||||||
|
void init_fadeout_layers(LayerSurface *l);
|
||||||
|
void layer_actual_size(LayerSurface *l, int32_t *width, int32_t *height);
|
||||||
|
void get_layer_target_geometry(LayerSurface *l,
|
||||||
|
struct wlr_box *target_box);
|
||||||
|
void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
||||||
|
int32_t sx, int32_t sy, void *data);
|
||||||
|
double find_animation_curve_at(double t, int32_t type);
|
||||||
|
|
||||||
|
void apply_opacity_to_rect_nodes(Client *c, struct wlr_scene_node *node,
|
||||||
|
double animation_passed);
|
||||||
|
enum corner_location set_client_corner_location(Client *c);
|
||||||
|
double all_output_frame_duration_ms();
|
||||||
|
struct wlr_scene_tree *
|
||||||
|
wlr_scene_tree_snapshot(struct wlr_scene_node *node,
|
||||||
|
struct wlr_scene_tree *parent);
|
||||||
|
bool is_scroller_layout(Monitor *m);
|
||||||
|
bool is_centertile_layout(Monitor *m);
|
||||||
|
void create_output(struct wlr_backend *backend, void *data);
|
||||||
|
void get_layout_abbr(char *abbr, const char *full_name);
|
||||||
|
void apply_named_scratchpad(Client *target_client);
|
||||||
|
Client *get_client_by_id_or_title(const char *arg_id,
|
||||||
|
const char *arg_title);
|
||||||
|
bool switch_scratchpad_client_state(Client *c);
|
||||||
|
bool check_trackpad_disabled(struct wlr_pointer *pointer);
|
||||||
|
uint32_t get_tag_status(uint32_t tag, Monitor *m);
|
||||||
|
void enable_adaptive_sync(Monitor *m, struct wlr_output_state *state);
|
||||||
|
Client *get_next_stack_client(Client *c, bool reverse);
|
||||||
|
void set_float_malposition(Client *tc);
|
||||||
|
void set_size_per(Monitor *m, Client *c);
|
||||||
|
void resize_tile_client(Client *rec, bool isdrag, int32_t offsetx,
|
||||||
|
int32_t offsety, uint32_t time);
|
||||||
|
void refresh_monitors_workspaces_status(Monitor *m);
|
||||||
|
void init_client_properties(Client *c);
|
||||||
|
float *get_border_color(Client *c);
|
||||||
|
void clear_fullscreen_and_maximized_state(Monitor *m);
|
||||||
|
void request_fresh_all_monitors(void);
|
||||||
|
Client *find_client_by_direction(Client *tc, const Arg *arg,
|
||||||
|
bool findfloating, bool ignore_align);
|
||||||
|
void exit_scroller_stack(Client *c);
|
||||||
|
Client *get_scroll_stack_head(Client *c);
|
||||||
|
bool client_only_in_one_tag(Client *c);
|
||||||
|
Client *get_focused_stack_client(Client *sc);
|
||||||
|
bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc);
|
||||||
|
|
||||||
|
#include "config/preset.h"
|
||||||
|
struct Pertag {
|
||||||
|
uint32_t curtag, prevtag; /* current and previous tag */
|
||||||
|
int32_t nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
|
||||||
|
float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
|
||||||
|
bool no_hide[LENGTH(tags) + 1]; /* no_hide per tag */
|
||||||
|
bool no_render_border[LENGTH(tags) + 1]; /* no_render_border per tag */
|
||||||
|
const Layout
|
||||||
|
*ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue