Compare commits

..

34 Commits

Author SHA1 Message Date
a1f4cbb282 Merge branch 'main' into feature/dual-row-scroller 2025-12-22 14:55:39 +01:00
DreamMaoMao
471c71f65c feat: add windowrule option isnoradius 2025-12-20 11:39:53 +08:00
DreamMaoMao
df0e18481b opt: reduce cursor resize request 2025-12-19 23:08:19 +08:00
DreamMaoMao
a67083bdb4 opt: no force center x11 window when map 2025-12-19 22:55:26 +08:00
DreamMaoMao
9aa8dab8ac opt: reset float geom record when remap 2025-12-19 17:34:29 +08:00
DreamMaoMao
e26e477d6b Merge pull request #523 from meeeee3/scroll-factor
feat: add wheel scroll factor
2025-12-19 16:43:50 +08:00
meeeee3
a8f7dc3e68 feat: add wheel scroll factor 2025-12-19 16:43:21 +08:00
DreamMaoMao
f54d7b3483 break change: inhibit_regardless_of_visibility rename to idleinhibit_ignore_visible 2025-12-19 14:40:32 +08:00
DreamMaoMao
bce6c0498e fix: inhibit_regardless_of_visibility not apply in some case 2025-12-19 14:36:23 +08:00
DreamMaoMao
5f884bdf51 opt: opt optimize idleinhibit check 2025-12-18 10:51:53 +08:00
DreamMaoMao
ff35c7afe9 bump version to 0.10.8 2025-12-17 11:04:13 +08:00
DreamMaoMao
0212ee7177 opt: remove useless code 2025-12-16 12:02:34 +08:00
DreamMaoMao
b5848f38b4 fix: crash when use focusstack 2025-12-16 11:57:56 +08:00
DreamMaoMao
db2151af64 fix: crash when focusmon to invalid monitor 2025-12-16 11:34:52 +08:00
DreamMaoMao
acb3fc2a2a Merge pull request #511 from andycandy-dev/fix-rouded-corners
fix: rounded corners on off-screen window edges
2025-12-14 22:28:18 +08:00
Andrej Novikov
a1a7cf5a7a fix: rounded corners being drawn on windows that extend out of screen 2025-12-14 15:15:21 +02:00
DreamMaoMao
3e9f437e85 Merge pull request #510 from andycandy-dev/fix-scroller-overlap
fix: scroller layout window overlap caused by uint
2025-12-14 21:01:07 +08:00
Andrej Novikov
75407c9727 fix: scroller layout window overlap caused by uint 2025-12-14 14:26:01 +02:00
DreamMaoMao
50b9de6f80 Merge pull request #507 from Rexcrazy804/nix-patches
Improvements to nix derrivation
2025-12-13 21:54:10 +08:00
DreamMaoMao
0f861e79a0 fix: avoid using old cursor_mgr in cursor timer 2025-12-13 18:21:58 +08:00
Rexiel Scarlet
20a0905ba7 feat(nix): support debug override for setting asan opt 2025-12-13 11:40:23 +04:00
Rexiel Scarlet
1d79b10437 refactor(nix): removed redundandt let in + formatting 2025-12-13 11:40:20 +04:00
Rexiel Scarlet
5b0c2d834f fix(nix): correctly set meson opt for enableXwayland flag 2025-12-13 11:40:16 +04:00
DreamMaoMao
c151ad46e6 feat: add layout tgmix 2025-12-13 11:43:39 +08:00
DreamMaoMao
06dd3423a1 opt: optimize ws module 2025-12-13 09:50:36 +08:00
DreamMaoMao
d696b763e8 Merge pull request #503 from hsdcc/main
fix typo in 'layer animation' section
2025-12-12 22:01:04 +08:00
hsd_
47ad3b7c2b fix typo in 'layer animation' section 2025-12-12 13:31:47 +00:00
DreamMaoMao
fa4eb322b6 fix: crash when reload_config 2025-12-12 15:41:26 +08:00
DreamMaoMao
91f4604199 feat: add fadein fadeout curve 2025-12-12 12:14:18 +08:00
DreamMaoMao
ddc2448d1c fix: fix typo 2025-12-11 15:45:05 +08:00
DreamMaoMao
bbc5ee19a8 Merge pull request #358 from 4zv4l/main
feat: allow to build using Guix
2025-12-11 09:41:09 +08:00
4zv4l
2c893c3345 guix: not pin hash in repo 2025-12-11 09:41:09 +08:00
4zv4l
840f3fb403 Merge branch 'DreamMaoMao:main' into main 2025-11-30 23:16:09 +08:00
4zv4l
3e6d8c6a18 feat: allow to build using Guix 2025-10-29 21:34:22 +08:00
20 changed files with 695 additions and 444 deletions

View File

@@ -32,7 +32,7 @@ Scroller Layout
https://github.com/user-attachments/assets/c9bf9415-fad1-4400-bcdc-3ad2d76de85a
Layer animaiton
Layer animation
https://github.com/user-attachments/assets/014c893f-115c-4ae9-8342-f9ae3e9a0df0

View File

@@ -48,6 +48,8 @@ animation_curve_move=0.46,1.0,0.29,1
animation_curve_tag=0.46,1.0,0.29,1
animation_curve_close=0.08,0.92,0,1
animation_curve_focus=0.46,1.0,0.29,1
animation_curve_opafadeout=0.5,0.5,0.5,0.5
animation_curve_opafadein=0.46,1.0,0.29,1
# Scroller Layout Setting
scroller_structs=20
@@ -76,7 +78,7 @@ overviewgappo=30
no_border_when_single=0
axis_bind_apply_timeout=100
focus_on_activate=1
inhibit_regardless_of_visibility=0
idleinhibit_ignore_visible=0
sloppyfocus=1
warpcursor=1
focus_cross_monitor=0

64
mangowc.scm Normal file
View File

@@ -0,0 +1,64 @@
(define-module (mangowc)
#:use-module (guix download)
#:use-module (guix git-download)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (guix utils)
#:use-module (gnu packages wm)
#:use-module (gnu packages freedesktop)
#:use-module (gnu packages xdisorg)
#:use-module (gnu packages pciutils)
#:use-module (gnu packages admin)
#:use-module (gnu packages pcre)
#:use-module (gnu packages xorg)
#:use-module (gnu packages build-tools)
#:use-module (gnu packages ninja)
#:use-module (gnu packages pkg-config)
#:use-module (guix build-system meson)
#:use-module (guix licenses))
(define-public mangowc-git
(package
(name "mangowc")
(version "git")
(source (local-file "." "mangowc-checkout"
#:recursive? #t
#:select? (or (git-predicate (current-source-directory))
(const #t))))
(build-system meson-build-system)
(arguments
(list
#:configure-flags
#~(list (string-append "-Dsysconfdir=" #$output "/etc"))
#:phases
#~(modify-phases %standard-phases
(add-before 'configure 'patch-meson
(lambda _
(substitute* "meson.build"
(("'-DSYSCONFDIR=\\\"@0@\\\"'.format\\('/etc'\\)")
"'-DSYSCONFDIR=\"@0@\"'.format(sysconfdir)")
(("sysconfdir = sysconfdir.substring\\(prefix.length\\(\\)\\)")
"")))))))
(inputs (list wayland
libinput
libdrm
libxkbcommon
pixman
libdisplay-info
libliftoff
hwdata
seatd
pcre2
libxcb
xcb-util-wm
wlroots
scenefx))
(native-inputs (list pkg-config wayland-protocols))
(home-page "https://github.com/DreamMaoMao/mangowc")
(synopsis "Wayland compositor based on wlroots and scenefx")
(description "A Wayland compositor based on wlroots and scenefx,
inspired by dwl but aiming to be more feature-rich.")
(license gpl3)))
mangowc-git

View File

@@ -1,5 +1,5 @@
project('mango', ['c', 'cpp'],
version : '0.10.7',
version : '0.10.8',
)
subdir('protocols')

View File

@@ -13,60 +13,64 @@
wayland-scanner,
xcbutilwm,
xwayland,
enableXWayland ? true,
meson,
ninja,
scenefx,
wlroots_0_19,
libGL,
}: let
enableXWayland ? true,
debug ? false,
}:
stdenv.mkDerivation {
pname = "mango";
in
stdenv.mkDerivation {
inherit pname;
version = "nightly";
version = "nightly";
src = builtins.path {
path = ../.;
name = "source";
};
src = builtins.path {
path = ../.;
name = "source";
};
nativeBuildInputs = [
meson
ninja
pkg-config
wayland-scanner
mesonFlags = [
(lib.mesonEnable "xwayland" enableXWayland)
(lib.mesonBool "asan" debug)
];
nativeBuildInputs = [
meson
ninja
pkg-config
wayland-scanner
];
buildInputs =
[
libinput
libxcb
libxkbcommon
pcre2
pixman
wayland
wayland-protocols
wlroots_0_19
scenefx
libGL
]
++ lib.optionals enableXWayland [
libX11
xcbutilwm
xwayland
];
buildInputs =
[
libinput
libxcb
libxkbcommon
pcre2
pixman
wayland
wayland-protocols
wlroots_0_19
scenefx
libGL
]
++ lib.optionals enableXWayland [
libX11
xcbutilwm
xwayland
];
passthru = {
providedSessions = ["mango"];
};
passthru = {
providedSessions = ["mango"];
};
meta = {
mainProgram = "mango";
description = "A streamlined but feature-rich Wayland compositor";
homepage = "https://github.com/DreamMaoMao/mango";
license = lib.licenses.gpl3Plus;
maintainers = [];
platforms = lib.platforms.unix;
};
}
meta = {
mainProgram = "mango";
description = "A streamlined but feature-rich Wayland compositor";
homepage = "https://github.com/DreamMaoMao/mango";
license = lib.licenses.gpl3Plus;
maintainers = [];
platforms = lib.platforms.unix;
};
}

View File

@@ -240,8 +240,9 @@ void buffer_set_effect(Client *c, BufferData data) {
if (c == grabc)
data.should_scale = false;
if (c->isfullscreen || (no_radius_when_single && c->mon &&
c->mon->visible_tiling_clients == 1)) {
if (c->isnoradius || c->isfullscreen ||
(no_radius_when_single && c->mon &&
c->mon->visible_tiling_clients == 1)) {
data.corner_location = CORNER_LOCATION_NONE;
}
@@ -354,11 +355,13 @@ void apply_border(Client *c) {
return;
bool hit_no_border = check_hit_no_border(c);
enum corner_location current_corner_location =
c->isfullscreen || (no_radius_when_single && c->mon &&
c->mon->visible_tiling_clients == 1)
? CORNER_LOCATION_NONE
: CORNER_LOCATION_ALL;
enum corner_location current_corner_location;
if (c->isfullscreen || (no_radius_when_single && c->mon &&
c->mon->visible_tiling_clients == 1)) {
current_corner_location = CORNER_LOCATION_NONE;
} else {
current_corner_location = set_client_corner_location(c);
}
// Handle no-border cases
if (hit_no_border && smartgaps) {
@@ -630,6 +633,7 @@ void fadeout_client_animation_next_tick(Client *c) {
int type = c->animation.action = c->animation.action;
double factor = find_animation_curve_at(animation_passed, type);
uint32_t width = c->animation.initial.width +
(c->current.width - c->animation.initial.width) * factor;
uint32_t height =
@@ -650,7 +654,13 @@ void fadeout_client_animation_next_tick(Client *c) {
.height = height,
};
double opacity = MAX(fadeout_begin_opacity - animation_passed, 0);
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);
if (animation_fade_out && !c->nofadeout)
wlr_scene_node_for_each_buffer(&c->scene->node,
@@ -701,10 +711,10 @@ void client_animation_next_tick(Client *c) {
c->animation.initial.height +
(c->current.height - c->animation.initial.height) * factor;
uint32_t x = c->animation.initial.x +
(c->current.x - c->animation.initial.x) * factor;
uint32_t y = c->animation.initial.y +
(c->current.y - c->animation.initial.y) * factor;
int32_t x = c->animation.initial.x +
(c->current.x - c->animation.initial.x) * factor;
int32_t y = c->animation.initial.y +
(c->current.y - c->animation.initial.y) * factor;
wlr_scene_node_set_position(&c->scene->node, x, y);
c->animation.current = (struct wlr_box){
@@ -1109,8 +1119,11 @@ bool client_apply_focus_opacity(Client *c) {
? (double)passed_time / (double)c->animation.duration
: 1.0;
double opacity_eased_progress =
find_animation_curve_at(linear_progress, OPAFADEIN);
float percent =
animation_fade_in && !c->nofadein ? linear_progress : 1.0;
animation_fade_in && !c->nofadein ? opacity_eased_progress : 1.0;
float opacity =
c == selmon->sel ? c->focused_opacity : c->unfocused_opacity;

View File

@@ -11,6 +11,10 @@ struct dvec2 calculate_animation_curve_at(double t, int type) {
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;
}
@@ -32,6 +36,10 @@ void init_baked_points(void) {
calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_close));
baked_points_focus =
calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_focus));
baked_points_opafadein =
calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_opafadein));
baked_points_opafadeout =
calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_opafadeout));
for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
baked_points_move[i] = calculate_animation_curve_at(
@@ -53,6 +61,14 @@ void init_baked_points(void) {
baked_points_focus[i] = calculate_animation_curve_at(
(double)i / (BAKED_POINTS_COUNT - 1), FOCUS);
}
for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
baked_points_opafadein[i] = calculate_animation_curve_at(
(double)i / (BAKED_POINTS_COUNT - 1), OPAFADEIN);
}
for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
baked_points_opafadeout[i] = calculate_animation_curve_at(
(double)i / (BAKED_POINTS_COUNT - 1), OPAFADEOUT);
}
}
double find_animation_curve_at(double t, int type) {
@@ -71,6 +87,10 @@ double find_animation_curve_at(double t, int type) {
baked_points = baked_points_close;
} else if (type == FOCUS) {
baked_points = baked_points_focus;
} else if (type == OPAFADEIN) {
baked_points = baked_points_opafadein;
} else if (type == OPAFADEOUT) {
baked_points = baked_points_opafadeout;
} else {
baked_points = baked_points_move;
}

View File

@@ -276,7 +276,13 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) {
.height = height,
};
double opacity = MAX(fadeout_begin_opacity - animation_passed, 0.0f);
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,
@@ -318,9 +324,13 @@ void layer_animation_next_tick(LayerSurface *l) {
uint32_t y = l->animation.initial.y +
(l->current.y - l->animation.initial.y) * factor;
double opacity = MIN(fadein_begin_opacity +
animation_passed * (1.0 - fadein_begin_opacity),
1.0f);
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,

View File

@@ -64,6 +64,7 @@ typedef struct {
const char *layer_animation_type_close;
int isnoborder;
int isnoshadow;
int isnoradius;
int isnoanimation;
int isopensilent;
int istagsilent;
@@ -194,6 +195,8 @@ typedef struct {
double animation_curve_tag[4];
double animation_curve_close[4];
double animation_curve_focus[4];
double animation_curve_opafadein[4];
double animation_curve_opafadeout[4];
int scroller_structs;
float scroller_default_proportion;
@@ -237,7 +240,7 @@ typedef struct {
uint32_t axis_bind_apply_timeout;
uint32_t focus_on_activate;
int inhibit_regardless_of_visibility;
int idleinhibit_ignore_visible;
int sloppyfocus;
int warpcursor;
@@ -264,6 +267,8 @@ typedef struct {
uint32_t send_events_mode;
uint32_t button_map;
double axis_scroll_factor;
int blur;
int blur_layer;
int blur_optimized;
@@ -1187,6 +1192,22 @@ void parse_option(Config *config, char *key, char *value) {
"Error: Failed to parse animation_curve_focus: %s\n",
value);
}
} else if (strcmp(key, "animation_curve_opafadein") == 0) {
int num =
parse_double_array(value, config->animation_curve_opafadein, 4);
if (num != 4) {
fprintf(stderr,
"Error: Failed to parse animation_curve_opafadein: %s\n",
value);
}
} else if (strcmp(key, "animation_curve_opafadeout") == 0) {
int num =
parse_double_array(value, config->animation_curve_opafadeout, 4);
if (num != 4) {
fprintf(stderr,
"Error: Failed to parse animation_curve_opafadeout: %s\n",
value);
}
} else if (strcmp(key, "scroller_structs") == 0) {
config->scroller_structs = atoi(value);
} else if (strcmp(key, "scroller_default_proportion") == 0) {
@@ -1446,8 +1467,8 @@ void parse_option(Config *config, char *key, char *value) {
config->focus_on_activate = atoi(value);
} else if (strcmp(key, "numlockon") == 0) {
config->numlockon = atoi(value);
} else if (strcmp(key, "inhibit_regardless_of_visibility") == 0) {
config->inhibit_regardless_of_visibility = atoi(value);
} else if (strcmp(key, "idleinhibit_ignore_visible") == 0) {
config->idleinhibit_ignore_visible = atoi(value);
} else if (strcmp(key, "sloppyfocus") == 0) {
config->sloppyfocus = atoi(value);
} else if (strcmp(key, "warpcursor") == 0) {
@@ -1494,6 +1515,8 @@ void parse_option(Config *config, char *key, char *value) {
config->send_events_mode = atoi(value);
} else if (strcmp(key, "button_map") == 0) {
config->button_map = atoi(value);
} else if (strcmp(key, "axis_scroll_factor") == 0) {
config->axis_scroll_factor = atof(value);
} else if (strcmp(key, "gappih") == 0) {
config->gappih = atoi(value);
} else if (strcmp(key, "gappiv") == 0) {
@@ -1691,6 +1714,7 @@ void parse_option(Config *config, char *key, char *value) {
rule->isfullscreen = -1;
rule->isnoborder = -1;
rule->isnoshadow = -1;
rule->isnoradius = -1;
rule->isnoanimation = -1;
rule->isopensilent = -1;
rule->istagsilent = -1;
@@ -1780,6 +1804,8 @@ void parse_option(Config *config, char *key, char *value) {
rule->isnoborder = atoi(val);
} else if (strcmp(key, "isnoshadow") == 0) {
rule->isnoshadow = atoi(val);
} else if (strcmp(key, "isnoradius") == 0) {
rule->isnoradius = atoi(val);
} else if (strcmp(key, "isnoanimation") == 0) {
rule->isnoanimation = atoi(val);
} else if (strcmp(key, "isopensilent") == 0) {
@@ -2406,6 +2432,14 @@ void free_baked_points(void) {
free(baked_points_focus);
baked_points_focus = NULL;
}
if (baked_points_opafadein) {
free(baked_points_opafadein);
baked_points_opafadein = NULL;
}
if (baked_points_opafadeout) {
free(baked_points_opafadeout);
baked_points_opafadeout = NULL;
}
}
void free_config(void) {
@@ -2719,8 +2753,8 @@ void override_config(void) {
axis_bind_apply_timeout =
CLAMP_INT(config.axis_bind_apply_timeout, 0, 1000);
focus_on_activate = CLAMP_INT(config.focus_on_activate, 0, 1);
inhibit_regardless_of_visibility =
CLAMP_INT(config.inhibit_regardless_of_visibility, 0, 1);
idleinhibit_ignore_visible =
CLAMP_INT(config.idleinhibit_ignore_visible, 0, 1);
sloppyfocus = CLAMP_INT(config.sloppyfocus, 0, 1);
warpcursor = CLAMP_INT(config.warpcursor, 0, 1);
focus_cross_monitor = CLAMP_INT(config.focus_cross_monitor, 0, 1);
@@ -2764,6 +2798,7 @@ void override_config(void) {
click_method = CLAMP_INT(config.click_method, 0, 2);
send_events_mode = CLAMP_INT(config.send_events_mode, 0, 2);
button_map = CLAMP_INT(config.button_map, 0, 1);
axis_scroll_factor = CLAMP_FLOAT(config.axis_scroll_factor, 0.1f, 10.0f);
// 外观设置
gappih = CLAMP_INT(config.gappih, 0, 1000);
@@ -2820,6 +2855,10 @@ void override_config(void) {
sizeof(animation_curve_close));
memcpy(animation_curve_focus, config.animation_curve_focus,
sizeof(animation_curve_focus));
memcpy(animation_curve_opafadein, config.animation_curve_opafadein,
sizeof(animation_curve_opafadein));
memcpy(animation_curve_opafadeout, config.animation_curve_opafadeout,
sizeof(animation_curve_opafadeout));
}
void set_value_default() {
@@ -2888,6 +2927,7 @@ void set_value_default() {
config.exchange_cross_monitor = exchange_cross_monitor;
config.scratchpad_cross_monitor = scratchpad_cross_monitor;
config.focus_cross_tag = focus_cross_tag;
config.axis_scroll_factor = axis_scroll_factor;
config.view_current_to_back = view_current_to_back;
config.single_scratchpad = single_scratchpad;
config.xwayland_persistence = xwayland_persistence;
@@ -2903,8 +2943,8 @@ void set_value_default() {
config.enable_floating_snap = enable_floating_snap;
config.swipe_min_threshold = swipe_min_threshold;
config.inhibit_regardless_of_visibility =
inhibit_regardless_of_visibility; /* 1 means idle inhibitors will
config.idleinhibit_ignore_visible =
idleinhibit_ignore_visible; /* 1 means idle inhibitors will
disable idle tracking even if it's
surface isn't visible
*/
@@ -2969,6 +3009,10 @@ void set_value_default() {
sizeof(animation_curve_close));
memcpy(config.animation_curve_focus, animation_curve_focus,
sizeof(animation_curve_focus));
memcpy(config.animation_curve_opafadein, animation_curve_opafadein,
sizeof(animation_curve_opafadein));
memcpy(config.animation_curve_opafadeout, animation_curve_opafadeout,
sizeof(animation_curve_opafadeout));
memcpy(config.rootcolor, rootcolor, sizeof(rootcolor));
memcpy(config.bordercolor, bordercolor, sizeof(bordercolor));
@@ -3171,9 +3215,37 @@ void reapply_monitor_rules(void) {
}
void reapply_cursor_style(void) {
if (cursor_mgr)
if (hide_source) {
wl_event_source_timer_update(hide_source, 0);
wl_event_source_remove(hide_source);
hide_source = NULL;
}
wlr_cursor_unset_image(cursor);
wlr_cursor_set_surface(cursor, NULL, 0, 0);
if (cursor_mgr) {
wlr_xcursor_manager_destroy(cursor_mgr);
cursor_mgr = NULL;
}
cursor_mgr = wlr_xcursor_manager_create(config.cursor_theme, cursor_size);
Monitor *m = NULL;
wl_list_for_each(m, &mons, link) {
wlr_xcursor_manager_load(cursor_mgr, m->wlr_output->scale);
}
wlr_cursor_set_xcursor(cursor, cursor_mgr, "left_ptr");
hide_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy),
hidecursor, cursor);
if (cursor_hidden) {
wlr_cursor_unset_image(cursor);
} else {
wl_event_source_timer_update(hide_source, cursor_hide_timeout * 1000);
}
}
void reapply_border(void) {
@@ -3293,5 +3365,5 @@ int reload_config(const Arg *arg) {
parse_config();
reset_option();
printstatus();
return 0;
return 1;
}

View File

@@ -26,11 +26,13 @@ uint32_t animation_duration_open = 400; // Animation open speed
uint32_t animation_duration_tag = 300; // Animation tag speed
uint32_t animation_duration_close = 300; // Animation close speed
uint32_t animation_duration_focus = 0; // Animation focus opacity speed
double animation_curve_move[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_open[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_tag[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_close[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_focus[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_move[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_open[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_tag[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_close[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_focus[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_opafadein[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
double animation_curve_opafadeout[4] = {0.5, 0.5, 0.5, 0.5}; // 动画曲线
/* appearance */
uint32_t axis_bind_apply_timeout = 100; // 滚轮绑定动作的触发的时间间隔
@@ -79,7 +81,7 @@ uint32_t cursor_hide_timeout = 0;
uint32_t swipe_min_threshold = 1;
int inhibit_regardless_of_visibility =
int idleinhibit_ignore_visible =
0; /* 1 means idle inhibitors will disable idle tracking even if it's
surface isn't visible */
uint32_t borderpx = 4; /* border pixel of windows */
@@ -105,7 +107,7 @@ int xwayland_persistence = 1; /* xwayland persistence */
int syncobj_enable = 0;
int adaptive_sync = 0;
int allow_lock_transparent = 0;
double drag_refresh_interval = 30.0;
double drag_refresh_interval = 16.0;
int allow_tearing = TEARING_DISABLED;
int allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
@@ -177,6 +179,8 @@ LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER
enum libinput_config_click_method click_method =
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
double axis_scroll_factor = 1.0;
/* You can choose between:
LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED

View File

@@ -196,15 +196,17 @@ int toggle_trackpad_enable(const Arg *arg) {
int focusmon(const Arg *arg) {
Client *c = NULL;
Monitor *m = NULL;
Monitor *tm = NULL;
if (arg->i != UNDIR) {
m = dirtomon(arg->i);
tm = dirtomon(arg->i);
} else if (arg->v) {
wl_list_for_each(m, &mons, link) {
if (!m->wlr_output->enabled) {
continue;
}
if (regex_match(arg->v, m->wlr_output->name)) {
tm = m;
break;
}
}
@@ -212,10 +214,10 @@ int focusmon(const Arg *arg) {
return 0;
}
if (!m || !m->wlr_output->enabled || m == selmon)
if (!tm || !tm->wlr_output->enabled || tm == selmon)
return 0;
selmon = m;
selmon = tm;
if (warpcursor) {
warp_cursor_to_selmon(selmon);
}

View File

@@ -1,8 +1,8 @@
#include "wlr_ext_workspace_v1.h"
#define EXT_WORKSPACE_ENABLE_CAPS \
WLR_EXT_WORKSPACE_HANDLE_V1_CAP_ACTIVATE | \
WLR_EXT_WORKSPACE_HANDLE_V1_CAP_DEACTIVATE
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_DEACTIVATE
typedef struct Monitor Monitor;

View File

@@ -29,7 +29,7 @@ struct wlr_ext_workspace_v1_request {
// ACTIVATE / DEACTIVATE / ASSIGN / REMOVE
struct wlr_ext_workspace_handle_v1 *workspace;
struct wl_list link; // wlr_ext_workspace_manager_client_v1.requests
struct wl_list link; // wlr_ext_workspace_manager_v1_resource.requests
};
struct wlr_ext_workspace_v1_group_output {
@@ -41,33 +41,40 @@ struct wlr_ext_workspace_v1_group_output {
};
// These structs wrap wl_resource of each interface to access the request queue
// (wlr_ext_workspace_manager_client_v1.requests) assigned per manager resource
// (wlr_ext_workspace_manager_v1_resource.requests) assigned per manager
// resource
struct wlr_ext_workspace_manager_client_v1 {
struct wlr_ext_workspace_manager_v1_resource {
struct wl_resource *resource;
struct wlr_ext_workspace_manager_v1 *manager;
struct wl_list requests; // wlr_ext_workspace_v1_request.link
struct wl_list link; // wlr_ext_workspace_manager_v1.clients
struct wl_list requests; // wlr_ext_workspace_v1_request.link
struct wl_list workspace_resources; // wlr_ext_workspace_v1_resource.link
struct wl_list group_resources; // wlr_ext_workspace_group_v1_resource.link
struct wl_list link; // wlr_ext_workspace_manager_v1.resources
};
struct wlr_ext_workspace_group_client_v1 {
struct wlr_ext_workspace_group_v1_resource {
struct wl_resource *resource;
struct wlr_ext_workspace_group_handle_v1 *group;
struct wlr_ext_workspace_manager_client_v1 *manager;
struct wl_list link; // wlr_ext_workspace_group_v1.clients
struct wlr_ext_workspace_manager_v1_resource *manager;
struct wl_list link; // wlr_ext_workspace_group_v1.resources
struct wl_list
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.group_resources
};
struct wlr_ext_workspace_client_v1 {
struct wlr_ext_workspace_v1_resource {
struct wl_resource *resource;
struct wlr_ext_workspace_handle_v1 *workspace;
struct wlr_ext_workspace_manager_client_v1 *manager;
struct wl_list link; // wlr_ext_workspace_v1.clients
struct wlr_ext_workspace_manager_v1_resource *manager;
struct wl_list link; // wlr_ext_workspace_v1.resources
struct wl_list
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.workspace_resources
};
static const struct ext_workspace_group_handle_v1_interface group_impl;
static struct wlr_ext_workspace_group_client_v1 *
group_client_from_resource(struct wl_resource *resource) {
static struct wlr_ext_workspace_group_v1_resource *
group_resource_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(
resource, &ext_workspace_group_handle_v1_interface, &group_impl));
return wl_resource_get_user_data(resource);
@@ -75,8 +82,8 @@ group_client_from_resource(struct wl_resource *resource) {
static const struct ext_workspace_handle_v1_interface workspace_impl;
static struct wlr_ext_workspace_client_v1 *
workspace_client_from_resource(struct wl_resource *resource) {
static struct wlr_ext_workspace_v1_resource *
workspace_resource_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &ext_workspace_handle_v1_interface,
&workspace_impl));
return wl_resource_get_user_data(resource);
@@ -84,8 +91,8 @@ workspace_client_from_resource(struct wl_resource *resource) {
static const struct ext_workspace_manager_v1_interface manager_impl;
static struct wlr_ext_workspace_manager_client_v1 *
manager_client_from_resource(struct wl_resource *resource) {
static struct wlr_ext_workspace_manager_v1_resource *
manager_resource_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(
resource, &ext_workspace_manager_v1_interface, &manager_impl));
return wl_resource_get_user_data(resource);
@@ -98,9 +105,9 @@ static void workspace_handle_destroy(struct wl_client *client,
static void workspace_handle_activate(struct wl_client *client,
struct wl_resource *workspace_resource) {
struct wlr_ext_workspace_client_v1 *workspace =
workspace_client_from_resource(workspace_resource);
if (!workspace) {
struct wlr_ext_workspace_v1_resource *workspace_res =
workspace_resource_from_resource(workspace_resource);
if (!workspace_res) {
return;
}
@@ -110,16 +117,16 @@ static void workspace_handle_activate(struct wl_client *client,
return;
}
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE;
req->workspace = workspace->workspace;
wl_list_insert(workspace->manager->requests.prev, &req->link);
req->workspace = workspace_res->workspace;
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
}
static void
workspace_handle_deactivate(struct wl_client *client,
struct wl_resource *workspace_resource) {
struct wlr_ext_workspace_client_v1 *workspace =
workspace_client_from_resource(workspace_resource);
if (!workspace) {
struct wlr_ext_workspace_v1_resource *workspace_res =
workspace_resource_from_resource(workspace_resource);
if (!workspace_res) {
return;
}
@@ -129,18 +136,18 @@ workspace_handle_deactivate(struct wl_client *client,
return;
}
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE;
req->workspace = workspace->workspace;
wl_list_insert(workspace->manager->requests.prev, &req->link);
req->workspace = workspace_res->workspace;
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
}
static void workspace_handle_assign(struct wl_client *client,
struct wl_resource *workspace_resource,
struct wl_resource *group_resource) {
struct wlr_ext_workspace_client_v1 *workspace =
workspace_client_from_resource(workspace_resource);
struct wlr_ext_workspace_group_client_v1 *group =
group_client_from_resource(group_resource);
if (!workspace || !group) {
struct wlr_ext_workspace_v1_resource *workspace_res =
workspace_resource_from_resource(workspace_resource);
struct wlr_ext_workspace_group_v1_resource *group_res =
group_resource_from_resource(group_resource);
if (!workspace_res || !group_res) {
return;
}
@@ -150,16 +157,16 @@ static void workspace_handle_assign(struct wl_client *client,
return;
}
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN;
req->group = group->group;
req->workspace = workspace->workspace;
wl_list_insert(workspace->manager->requests.prev, &req->link);
req->group = group_res->group;
req->workspace = workspace_res->workspace;
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
}
static void workspace_handle_remove(struct wl_client *client,
struct wl_resource *workspace_resource) {
struct wlr_ext_workspace_client_v1 *workspace =
workspace_client_from_resource(workspace_resource);
if (!workspace) {
struct wlr_ext_workspace_v1_resource *workspace_res =
workspace_resource_from_resource(workspace_resource);
if (!workspace_res) {
return;
}
@@ -169,8 +176,8 @@ static void workspace_handle_remove(struct wl_client *client,
return;
}
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE;
req->workspace = workspace->workspace;
wl_list_insert(workspace->manager->requests.prev, &req->link);
req->workspace = workspace_res->workspace;
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
}
static const struct ext_workspace_handle_v1_interface workspace_impl = {
@@ -184,9 +191,9 @@ static const struct ext_workspace_handle_v1_interface workspace_impl = {
static void group_handle_create_workspace(struct wl_client *client,
struct wl_resource *group_resource,
const char *name) {
struct wlr_ext_workspace_group_client_v1 *group =
group_client_from_resource(group_resource);
if (!group) {
struct wlr_ext_workspace_group_v1_resource *group_res =
group_resource_from_resource(group_resource);
if (!group_res) {
return;
}
@@ -195,9 +202,15 @@ static void group_handle_create_workspace(struct wl_client *client,
wl_resource_post_no_memory(group_resource);
return;
}
req->name = strdup(name);
if (!req->name) {
free(req);
wl_resource_post_no_memory(group_resource);
return;
}
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE;
req->group = group->group;
wl_list_insert(group->manager->requests.prev, &req->link);
req->group = group_res->group;
wl_list_insert(group_res->manager->requests.prev, &req->link);
}
static void group_handle_destroy(struct wl_client *client,
@@ -210,89 +223,94 @@ static const struct ext_workspace_group_handle_v1_interface group_impl = {
.destroy = group_handle_destroy,
};
static void
destroy_workspace_client(struct wlr_ext_workspace_client_v1 *workspace_client) {
wl_list_remove(&workspace_client->link);
wl_resource_set_user_data(workspace_client->resource, NULL);
free(workspace_client);
static void destroy_workspace_resource(
struct wlr_ext_workspace_v1_resource *workspace_res) {
wl_list_remove(&workspace_res->link);
wl_list_remove(&workspace_res->manager_resource_link);
wl_resource_set_user_data(workspace_res->resource, NULL);
free(workspace_res);
}
static void workspace_resource_destroy(struct wl_resource *resource) {
struct wlr_ext_workspace_client_v1 *workspace_client =
workspace_client_from_resource(resource);
if (workspace_client) {
destroy_workspace_client(workspace_client);
struct wlr_ext_workspace_v1_resource *workspace_res =
workspace_resource_from_resource(resource);
if (workspace_res) {
destroy_workspace_resource(workspace_res);
}
}
static struct wlr_ext_workspace_client_v1 *create_workspace_client(
static struct wlr_ext_workspace_v1_resource *create_workspace_resource(
struct wlr_ext_workspace_handle_v1 *workspace,
struct wlr_ext_workspace_manager_client_v1 *manager_client) {
struct wlr_ext_workspace_client_v1 *workspace_client =
calloc(1, sizeof(*workspace_client));
if (!workspace_client) {
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
struct wlr_ext_workspace_v1_resource *workspace_res =
calloc(1, sizeof(*workspace_res));
if (!workspace_res) {
return NULL;
}
struct wl_client *client = wl_resource_get_client(manager_client->resource);
workspace_client->resource = wl_resource_create(
client, &ext_workspace_handle_v1_interface,
wl_resource_get_version(manager_client->resource), 0);
if (!workspace_client->resource) {
free(workspace_client);
struct wl_client *client = wl_resource_get_client(manager_res->resource);
workspace_res->resource =
wl_resource_create(client, &ext_workspace_handle_v1_interface,
wl_resource_get_version(manager_res->resource), 0);
if (!workspace_res->resource) {
free(workspace_res);
return NULL;
}
wl_resource_set_implementation(workspace_client->resource, &workspace_impl,
workspace_client,
workspace_resource_destroy);
wl_resource_set_implementation(workspace_res->resource, &workspace_impl,
workspace_res, workspace_resource_destroy);
workspace_client->workspace = workspace;
workspace_client->manager = manager_client;
wl_list_insert(&workspace->clients, &workspace_client->link);
workspace_res->workspace = workspace;
workspace_res->manager = manager_res;
wl_list_insert(&workspace->resources, &workspace_res->link);
wl_list_insert(&manager_res->workspace_resources,
&workspace_res->manager_resource_link);
return workspace_client;
return workspace_res;
}
static void
destroy_group_client(struct wlr_ext_workspace_group_client_v1 *group_client) {
wl_list_remove(&group_client->link);
wl_resource_set_user_data(group_client->resource, NULL);
free(group_client);
destroy_group_resource(struct wlr_ext_workspace_group_v1_resource *group_res) {
wl_list_remove(&group_res->link);
wl_list_remove(&group_res->manager_resource_link);
wl_resource_set_user_data(group_res->resource, NULL);
free(group_res);
}
static void group_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_ext_workspace_group_client_v1 *group_client =
group_client_from_resource(resource);
if (group_client) {
destroy_group_client(group_client);
struct wlr_ext_workspace_group_v1_resource *group_res =
group_resource_from_resource(resource);
if (group_res) {
destroy_group_resource(group_res);
}
}
static struct wlr_ext_workspace_group_client_v1 *create_group_client(
static struct wlr_ext_workspace_group_v1_resource *create_group_resource(
struct wlr_ext_workspace_group_handle_v1 *group,
struct wlr_ext_workspace_manager_client_v1 *manager_client) {
struct wlr_ext_workspace_group_client_v1 *group_client =
calloc(1, sizeof(*group_client));
if (!group_client) {
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
struct wlr_ext_workspace_group_v1_resource *group_res =
calloc(1, sizeof(*group_res));
if (!group_res) {
return NULL;
}
struct wl_client *client = wl_resource_get_client(manager_client->resource);
uint32_t version = wl_resource_get_version(manager_client->resource);
group_client->resource = wl_resource_create(
struct wl_client *client = wl_resource_get_client(manager_res->resource);
uint32_t version = wl_resource_get_version(manager_res->resource);
group_res->resource = wl_resource_create(
client, &ext_workspace_group_handle_v1_interface, version, 0);
if (group_client->resource == NULL) {
free(group_client);
if (group_res->resource == NULL) {
free(group_res);
return NULL;
}
wl_resource_set_implementation(group_client->resource, &group_impl,
group_client, group_handle_resource_destroy);
wl_resource_set_implementation(group_res->resource, &group_impl, group_res,
group_handle_resource_destroy);
group_client->group = group;
group_client->manager = manager_client;
wl_list_insert(&group->clients, &group_client->link);
group_res->group = group;
group_res->manager = manager_res;
wl_list_insert(&group->resources, &group_res->link);
wl_list_insert(&manager_res->group_resources,
&group_res->manager_resource_link);
return group_client;
return group_res;
}
static void destroy_request(struct wlr_ext_workspace_v1_request *req) {
@@ -303,18 +321,22 @@ static void destroy_request(struct wlr_ext_workspace_v1_request *req) {
static void manager_handle_commit(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_ext_workspace_manager_client_v1 *manager =
manager_client_from_resource(resource);
if (!manager) {
struct wlr_ext_workspace_manager_v1_resource *manager_res =
manager_resource_from_resource(resource);
if (!manager_res) {
return;
}
struct wlr_ext_workspace_v1_request *req, *tmp;
wl_list_for_each_safe(req, tmp, &manager->requests, link) {
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
switch (req->type) {
case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE:
case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE:;
struct wlr_ext_workspace_group_handle_v1_create_workspace_event
event = {
.name = req->name,
};
wl_signal_emit_mutable(&req->group->events.create_workspace,
req->name);
&event);
break;
case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE:
wl_signal_emit_mutable(&req->workspace->events.activate, NULL);
@@ -323,13 +345,11 @@ static void manager_handle_commit(struct wl_client *client,
wl_signal_emit_mutable(&req->workspace->events.deactivate, NULL);
break;
case WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN:
wl_signal_emit_mutable(&req->workspace->events.assign, &req->group);
wl_signal_emit_mutable(&req->workspace->events.assign, req->group);
break;
case WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE:
wl_signal_emit_mutable(&req->workspace->events.remove, NULL);
break;
default:
abort();
}
destroy_request(req);
}
@@ -338,9 +358,9 @@ static void manager_handle_commit(struct wl_client *client,
static void handle_idle(void *data) {
struct wlr_ext_workspace_manager_v1 *manager = data;
struct wlr_ext_workspace_manager_client_v1 *manager_client;
wl_list_for_each(manager_client, &manager->clients, link) {
ext_workspace_manager_v1_send_done(manager_client->resource);
struct wlr_ext_workspace_manager_v1_resource *manager_res;
wl_list_for_each(manager_res, &manager->resources, link) {
ext_workspace_manager_v1_send_done(manager_res->resource);
}
manager->idle_source = NULL;
}
@@ -354,9 +374,9 @@ manager_schedule_done(struct wlr_ext_workspace_manager_v1 *manager) {
}
static void
workspace_send_details(struct wlr_ext_workspace_client_v1 *workspace_client) {
struct wlr_ext_workspace_handle_v1 *workspace = workspace_client->workspace;
struct wl_resource *resource = workspace_client->resource;
workspace_send_details(struct wlr_ext_workspace_v1_resource *workspace_res) {
struct wlr_ext_workspace_handle_v1 *workspace = workspace_res->workspace;
struct wl_resource *resource = workspace_res->resource;
ext_workspace_handle_v1_send_capabilities(resource, workspace->caps);
if (workspace->coordinates.size > 0) {
@@ -384,29 +404,41 @@ static const struct ext_workspace_manager_v1_interface manager_impl = {
.stop = manager_handle_stop,
};
static void destroy_manager_client(
struct wlr_ext_workspace_manager_client_v1 *manager_client) {
static void destroy_manager_resource(
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
struct wlr_ext_workspace_v1_request *req, *tmp;
wl_list_for_each_safe(req, tmp, &manager_client->requests, link) {
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
destroy_request(req);
}
wl_list_remove(&manager_client->link);
wl_resource_set_user_data(manager_client->resource, NULL);
free(manager_client);
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp2;
wl_list_for_each_safe(workspace_res, tmp2,
&manager_res->workspace_resources,
manager_resource_link) {
destroy_workspace_resource(workspace_res);
}
struct wlr_ext_workspace_group_v1_resource *group_res, *tmp3;
wl_list_for_each_safe(group_res, tmp3, &manager_res->group_resources,
manager_resource_link) {
destroy_group_resource(group_res);
}
wl_list_remove(&manager_res->link);
wl_resource_set_user_data(manager_res->resource, NULL);
free(manager_res);
}
static void manager_resource_destroy(struct wl_resource *resource) {
struct wlr_ext_workspace_manager_client_v1 *manager_client =
manager_client_from_resource(resource);
if (manager_client) {
destroy_manager_client(manager_client);
struct wlr_ext_workspace_manager_v1_resource *manager_res =
manager_resource_from_resource(resource);
if (manager_res) {
destroy_manager_resource(manager_res);
}
}
static void
group_send_details(struct wlr_ext_workspace_group_client_v1 *group_client) {
struct wlr_ext_workspace_group_handle_v1 *group = group_client->group;
struct wl_resource *resource = group_client->resource;
group_send_details(struct wlr_ext_workspace_group_v1_resource *group_res) {
struct wlr_ext_workspace_group_handle_v1 *group = group_res->group;
struct wl_resource *resource = group_res->resource;
struct wl_client *client = wl_resource_get_client(resource);
ext_workspace_group_handle_v1_send_capabilities(resource, group->caps);
@@ -430,65 +462,67 @@ static void manager_bind(struct wl_client *client, void *data, uint32_t version,
uint32_t id) {
struct wlr_ext_workspace_manager_v1 *manager = data;
struct wlr_ext_workspace_manager_client_v1 *manager_client =
calloc(1, sizeof(*manager_client));
if (!manager_client) {
struct wlr_ext_workspace_manager_v1_resource *manager_res =
calloc(1, sizeof(*manager_res));
if (!manager_res) {
wl_client_post_no_memory(client);
return;
}
manager_client->manager = manager;
wl_list_init(&manager_client->requests);
wl_list_insert(&manager->clients, &manager_client->link);
manager_res->manager = manager;
wl_list_init(&manager_res->requests);
wl_list_init(&manager_res->workspace_resources);
wl_list_init(&manager_res->group_resources);
manager_client->resource = wl_resource_create(
manager_res->resource = wl_resource_create(
client, &ext_workspace_manager_v1_interface, version, id);
if (!manager_client->resource) {
free(manager_client);
if (!manager_res->resource) {
free(manager_res);
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(manager_client->resource, &manager_impl,
manager_client, manager_resource_destroy);
wl_resource_set_implementation(manager_res->resource, &manager_impl,
manager_res, manager_resource_destroy);
wl_list_insert(&manager->resources, &manager_res->link);
struct wlr_ext_workspace_group_handle_v1 *group;
wl_list_for_each(group, &manager->groups, link) {
struct wlr_ext_workspace_group_client_v1 *group_client =
create_group_client(group, manager_client);
if (!group_client) {
wl_resource_post_no_memory(manager_client->resource);
struct wlr_ext_workspace_group_v1_resource *group_res =
create_group_resource(group, manager_res);
if (!group_res) {
wl_resource_post_no_memory(manager_res->resource);
continue;
}
ext_workspace_manager_v1_send_workspace_group(manager_client->resource,
group_client->resource);
group_send_details(group_client);
ext_workspace_manager_v1_send_workspace_group(manager_res->resource,
group_res->resource);
group_send_details(group_res);
}
struct wlr_ext_workspace_handle_v1 *workspace;
wl_list_for_each(workspace, &manager->workspaces, link) {
struct wlr_ext_workspace_client_v1 *workspace_client =
create_workspace_client(workspace, manager_client);
if (!workspace) {
wl_client_post_no_memory(client);
struct wlr_ext_workspace_v1_resource *workspace_res =
create_workspace_resource(workspace, manager_res);
if (!workspace_res) {
wl_resource_post_no_memory(manager_res->resource);
continue;
}
ext_workspace_manager_v1_send_workspace(manager_client->resource,
workspace_client->resource);
workspace_send_details(workspace_client);
ext_workspace_manager_v1_send_workspace(manager_res->resource,
workspace_res->resource);
workspace_send_details(workspace_res);
if (!workspace->group) {
continue;
}
struct wlr_ext_workspace_group_client_v1 *group_client;
wl_list_for_each(group_client, &workspace->group->clients, link) {
if (group_client->manager == manager_client) {
struct wlr_ext_workspace_group_v1_resource *group_res;
wl_list_for_each(group_res, &workspace->group->resources, link) {
if (group_res->manager == manager_res) {
ext_workspace_group_handle_v1_send_workspace_enter(
group_client->resource, workspace_client->resource);
group_res->resource, workspace_res->resource);
}
}
}
manager_schedule_done(manager);
ext_workspace_manager_v1_send_done(manager_res->resource);
}
static void manager_handle_display_destroy(struct wl_listener *listener,
@@ -509,9 +543,9 @@ static void manager_handle_display_destroy(struct wl_listener *listener,
wlr_ext_workspace_handle_v1_destroy(workspace);
}
struct wlr_ext_workspace_manager_client_v1 *manager_client, *tmp3;
wl_list_for_each_safe(manager_client, tmp3, &manager->clients, link) {
destroy_manager_client(manager_client);
struct wlr_ext_workspace_manager_v1_resource *manager_res, *tmp3;
wl_list_for_each_safe(manager_res, tmp3, &manager->resources, link) {
destroy_manager_resource(manager_res);
}
if (manager->idle_source) {
@@ -548,7 +582,7 @@ wlr_ext_workspace_manager_v1_create(struct wl_display *display,
wl_list_init(&manager->groups);
wl_list_init(&manager->workspaces);
wl_list_init(&manager->clients);
wl_list_init(&manager->resources);
wl_signal_init(&manager->events.destroy);
return manager;
@@ -566,22 +600,22 @@ wlr_ext_workspace_group_handle_v1_create(
group->caps = caps;
wl_list_init(&group->outputs);
wl_list_init(&group->clients);
wl_list_init(&group->resources);
wl_signal_init(&group->events.create_workspace);
wl_signal_init(&group->events.destroy);
wl_list_insert(manager->groups.prev, &group->link);
struct wlr_ext_workspace_manager_client_v1 *manager_client;
wl_list_for_each(manager_client, &manager->clients, link) {
struct wlr_ext_workspace_group_client_v1 *group_client =
create_group_client(group, manager_client);
if (!group_client) {
struct wlr_ext_workspace_manager_v1_resource *manager_res;
wl_list_for_each(manager_res, &manager->resources, link) {
struct wlr_ext_workspace_group_v1_resource *group_res =
create_group_resource(group, manager_res);
if (!group_res) {
continue;
}
ext_workspace_manager_v1_send_workspace_group(manager_client->resource,
group_client->resource);
group_send_details(group_client);
ext_workspace_manager_v1_send_workspace_group(manager_res->resource,
group_res->resource);
group_send_details(group_res);
}
manager_schedule_done(manager);
@@ -594,19 +628,19 @@ workspace_send_group(struct wlr_ext_workspace_handle_v1 *workspace,
struct wlr_ext_workspace_group_handle_v1 *group,
bool enter) {
struct wlr_ext_workspace_client_v1 *workspace_client;
wl_list_for_each(workspace_client, &workspace->clients, link) {
struct wlr_ext_workspace_group_client_v1 *group_client;
wl_list_for_each(group_client, &group->clients, link) {
if (group_client->manager != workspace_client->manager) {
struct wlr_ext_workspace_v1_resource *workspace_res;
wl_list_for_each(workspace_res, &workspace->resources, link) {
struct wlr_ext_workspace_group_v1_resource *group_res;
wl_list_for_each(group_res, &group->resources, link) {
if (group_res->manager != workspace_res->manager) {
continue;
}
if (enter) {
ext_workspace_group_handle_v1_send_workspace_enter(
group_client->resource, workspace_client->resource);
group_res->resource, workspace_res->resource);
} else {
ext_workspace_group_handle_v1_send_workspace_leave(
group_client->resource, workspace_client->resource);
group_res->resource, workspace_res->resource);
}
}
}
@@ -625,10 +659,9 @@ destroy_group_output(struct wlr_ext_workspace_v1_group_output *group_output) {
static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group,
struct wlr_output *output, bool enter) {
struct wlr_ext_workspace_group_client_v1 *group_client;
wl_list_for_each(group_client, &group->clients, link) {
struct wl_client *client =
wl_resource_get_client(group_client->resource);
struct wlr_ext_workspace_group_v1_resource *group_res;
wl_list_for_each(group_res, &group->resources, link) {
struct wl_client *client = wl_resource_get_client(group_res->resource);
struct wl_resource *output_resource;
wl_resource_for_each(output_resource, &output->resources) {
@@ -637,10 +670,10 @@ static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group,
}
if (enter) {
ext_workspace_group_handle_v1_send_output_enter(
group_client->resource, output_resource);
group_res->resource, output_resource);
} else {
ext_workspace_group_handle_v1_send_output_leave(
group_client->resource, output_resource);
group_res->resource, output_resource);
}
}
}
@@ -650,6 +683,10 @@ static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group,
void wlr_ext_workspace_group_handle_v1_destroy(
struct wlr_ext_workspace_group_handle_v1 *group) {
if (!group) {
return;
}
wl_signal_emit_mutable(&group->events.destroy, NULL);
assert(wl_list_empty(&group->events.create_workspace.listener_list));
@@ -663,16 +700,16 @@ void wlr_ext_workspace_group_handle_v1_destroy(
}
}
struct wlr_ext_workspace_group_client_v1 *group_client, *tmp;
wl_list_for_each_safe(group_client, tmp, &group->clients, link) {
ext_workspace_group_handle_v1_send_removed(group_client->resource);
destroy_group_client(group_client);
struct wlr_ext_workspace_group_v1_resource *group_res, *tmp;
wl_list_for_each_safe(group_res, tmp, &group->resources, link) {
ext_workspace_group_handle_v1_send_removed(group_res->resource);
destroy_group_resource(group_res);
}
struct wlr_ext_workspace_manager_client_v1 *manager_client;
wl_list_for_each(manager_client, &group->manager->clients, link) {
struct wlr_ext_workspace_manager_v1_resource *manager_res;
wl_list_for_each(manager_res, &group->manager->resources, link) {
struct wlr_ext_workspace_v1_request *req, *tmp2;
wl_list_for_each_safe(req, tmp2, &manager_client->requests, link) {
wl_list_for_each_safe(req, tmp2, &manager_res->requests, link) {
if (req->group == group) {
destroy_request(req);
}
@@ -697,11 +734,11 @@ static void handle_output_bind(struct wl_listener *listener, void *data) {
struct wlr_output_event_bind *event = data;
struct wl_client *client = wl_resource_get_client(event->resource);
struct wlr_ext_workspace_group_client_v1 *group_client;
wl_list_for_each(group_client, &group_output->group->clients, link) {
if (wl_resource_get_client(group_client->resource) == client) {
ext_workspace_group_handle_v1_send_output_enter(
group_client->resource, event->resource);
struct wlr_ext_workspace_group_v1_resource *group_res;
wl_list_for_each(group_res, &group_output->group->resources, link) {
if (wl_resource_get_client(group_res->resource) == client) {
ext_workspace_group_handle_v1_send_output_enter(group_res->resource,
event->resource);
}
}
@@ -778,11 +815,12 @@ wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
if (id) {
workspace->id = strdup(id);
if (!workspace->id) {
free(workspace);
return NULL;
}
}
wl_list_init(&workspace->clients);
wl_list_init(&workspace->resources);
wl_array_init(&workspace->coordinates);
wl_signal_init(&workspace->events.activate);
wl_signal_init(&workspace->events.deactivate);
@@ -792,16 +830,16 @@ wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
wl_list_insert(&manager->workspaces, &workspace->link);
struct wlr_ext_workspace_manager_client_v1 *manager_client;
wl_list_for_each(manager_client, &manager->clients, link) {
struct wlr_ext_workspace_client_v1 *workspace_client =
create_workspace_client(workspace, manager_client);
if (!workspace_client) {
struct wlr_ext_workspace_manager_v1_resource *manager_res;
wl_list_for_each(manager_res, &manager->resources, link) {
struct wlr_ext_workspace_v1_resource *workspace_res =
create_workspace_resource(workspace, manager_res);
if (!workspace_res) {
continue;
}
ext_workspace_manager_v1_send_workspace(manager_client->resource,
workspace_client->resource);
workspace_send_details(workspace_client);
ext_workspace_manager_v1_send_workspace(manager_res->resource,
workspace_res->resource);
workspace_send_details(workspace_res);
}
manager_schedule_done(manager);
@@ -811,6 +849,10 @@ wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
void wlr_ext_workspace_handle_v1_destroy(
struct wlr_ext_workspace_handle_v1 *workspace) {
if (!workspace) {
return;
}
wl_signal_emit_mutable(&workspace->events.destroy, NULL);
assert(wl_list_empty(&workspace->events.activate.listener_list));
@@ -823,16 +865,16 @@ void wlr_ext_workspace_handle_v1_destroy(
workspace_send_group(workspace, workspace->group, false);
}
struct wlr_ext_workspace_client_v1 *workspace_client, *tmp;
wl_list_for_each_safe(workspace_client, tmp, &workspace->clients, link) {
ext_workspace_handle_v1_send_removed(workspace_client->resource);
destroy_workspace_client(workspace_client);
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp;
wl_list_for_each_safe(workspace_res, tmp, &workspace->resources, link) {
ext_workspace_handle_v1_send_removed(workspace_res->resource);
destroy_workspace_resource(workspace_res);
}
struct wlr_ext_workspace_manager_client_v1 *manager_client;
wl_list_for_each(manager_client, &workspace->manager->clients, link) {
struct wlr_ext_workspace_manager_v1_resource *manager_res;
wl_list_for_each(manager_res, &workspace->manager->resources, link) {
struct wlr_ext_workspace_v1_request *req, *tmp2;
wl_list_for_each_safe(req, tmp2, &manager_client->requests, link) {
wl_list_for_each_safe(req, tmp2, &manager_res->requests, link) {
if (req->workspace == workspace) {
destroy_request(req);
}
@@ -856,7 +898,7 @@ void wlr_ext_workspace_handle_v1_set_group(
}
if (workspace->group) {
workspace_send_group(workspace, group, false);
workspace_send_group(workspace, workspace->group, false);
}
workspace->group = group;
if (group) {
@@ -878,9 +920,9 @@ void wlr_ext_workspace_handle_v1_set_name(
return;
}
struct wlr_ext_workspace_client_v1 *workspace_client;
wl_list_for_each(workspace_client, &workspace->clients, link) {
ext_workspace_handle_v1_send_name(workspace_client->resource,
struct wlr_ext_workspace_v1_resource *workspace_res;
wl_list_for_each(workspace_res, &workspace->resources, link) {
ext_workspace_handle_v1_send_name(workspace_res->resource,
workspace->name);
}
@@ -905,9 +947,9 @@ void wlr_ext_workspace_handle_v1_set_coordinates(
wl_array_init(&workspace->coordinates);
wl_array_copy(&workspace->coordinates, coordinates);
struct wlr_ext_workspace_client_v1 *workspace_client;
wl_list_for_each(workspace_client, &workspace->clients, link) {
ext_workspace_handle_v1_send_coordinates(workspace_client->resource,
struct wlr_ext_workspace_v1_resource *workspace_res;
wl_list_for_each(workspace_res, &workspace->resources, link) {
ext_workspace_handle_v1_send_coordinates(workspace_res->resource,
&workspace->coordinates);
}
@@ -927,9 +969,9 @@ static void workspace_set_state(struct wlr_ext_workspace_handle_v1 *workspace,
return;
}
struct wlr_ext_workspace_client_v1 *workspace_client;
wl_list_for_each(workspace_client, &workspace->clients, link) {
ext_workspace_handle_v1_send_state(workspace_client->resource,
struct wlr_ext_workspace_v1_resource *workspace_res;
wl_list_for_each(workspace_res, &workspace->resources, link) {
ext_workspace_handle_v1_send_state(workspace_res->resource,
workspace->state);
}

View File

@@ -2,32 +2,11 @@
// TODO: remove this file
// refer: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5115
/*
* This an unstable interface of wlroots. No guarantees are made regarding the
* future consistency of this API.
*/
#ifndef WLR_USE_UNSTABLE
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
#endif
#ifndef WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
#define WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
#include <wayland-protocols/ext-workspace-v1-enum.h>
#include <wayland-server-core.h>
struct wlr_output;
enum wlr_ext_workspace_group_handle_v1_cap {
WLR_EXT_WORKSPACE_GROUP_HANDLE_V1_CAP_CREATE_WORKSPACE = 1 << 0,
};
enum wlr_ext_workspace_handle_v1_cap {
WLR_EXT_WORKSPACE_HANDLE_V1_CAP_ACTIVATE = 1 << 0,
WLR_EXT_WORKSPACE_HANDLE_V1_CAP_DEACTIVATE = 1 << 1,
WLR_EXT_WORKSPACE_HANDLE_V1_CAP_REMOVE = 1 << 2,
WLR_EXT_WORKSPACE_HANDLE_V1_CAP_ASSIGN = 1 << 3,
};
struct wlr_ext_workspace_manager_v1 {
struct wl_global *global;
struct wl_list groups; // wlr_ext_workspace_group_handle_v1.link
@@ -37,24 +16,33 @@ struct wlr_ext_workspace_manager_v1 {
struct wl_signal destroy;
} events;
struct wl_list clients; // wlr_ext_workspace_manager_client_v1.link
struct wl_event_source *idle_source;
struct wl_event_loop *event_loop;
struct wl_listener display_destroy;
struct {
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
struct wl_event_source *idle_source;
struct wl_event_loop *event_loop;
struct wl_listener display_destroy;
};
};
struct wlr_ext_workspace_group_handle_v1_create_workspace_event {
const char *name;
};
struct wlr_ext_workspace_group_handle_v1 {
struct wlr_ext_workspace_manager_v1 *manager;
uint32_t caps; // wlr_ext_workspace_group_handle_v1_cap
uint32_t caps; // ext_workspace_group_handle_v1_group_capabilities
struct {
struct wl_signal create_workspace; // const char *
struct wl_signal
create_workspace; // wlr_ext_workspace_group_handle_v1_create_workspace_event
struct wl_signal destroy;
} events;
struct wl_list link; // wlr_ext_workspace_manager_v1.groups
struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link
struct wl_list clients; // wlr_ext_workspace_manager_client_v1.link
struct {
struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
};
};
struct wlr_ext_workspace_handle_v1 {
@@ -63,7 +51,7 @@ struct wlr_ext_workspace_handle_v1 {
char *id;
char *name;
struct wl_array coordinates;
uint32_t caps; // wlr_ext_workspace_handle_v1_cap
uint32_t caps; // ext_workspace_handle_v1_workspace_capabilities
uint32_t state; // ext_workspace_handle_v1_state
struct {
@@ -74,9 +62,11 @@ struct wlr_ext_workspace_handle_v1 {
struct wl_signal destroy;
} events;
struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces;
struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces
struct wl_list clients;
struct {
struct wl_list resources; // wlr_ext_workspace_v1_resource.link
};
};
struct wlr_ext_workspace_manager_v1 *
@@ -114,5 +104,3 @@ void wlr_ext_workspace_handle_v1_set_urgent(
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
void wlr_ext_workspace_handle_v1_set_hidden(
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
#endif

View File

@@ -389,30 +389,21 @@ Client *focustop(Monitor *m) {
Client *get_next_stack_client(Client *c, bool reverse) {
if (!c || !c->mon)
return NULL; // 添加输入检查
return NULL;
Client *next = NULL;
if (reverse) {
wl_list_for_each_reverse(next, &c->link, link) {
if (!next)
continue; // 安全检查
if (&next->link == &clients)
continue; /* wrap past the sentinel node */
if (c->mon->has_visible_fullscreen_client && !next->isfloating &&
!next->isfullscreen)
continue;
// 添加更安全的 VISIBLEON 检查
if (next != c && next->mon && VISIBLEON(next, c->mon))
return next;
}
} else {
wl_list_for_each(next, &c->link, link) {
if (!next)
continue; // 安全检查
if (c->mon->has_visible_fullscreen_client && !next->isfloating &&
!next->isfullscreen)
continue;
if (&next->link == &clients)
continue; /* wrap past the sentinel node */
if (next != c && next->mon && VISIBLEON(next, c->mon))
return next;

View File

@@ -5,7 +5,7 @@ void set_size_per(Monitor *m, Client *c) {
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_innder_per = fc->stack_innder_per;
c->stack_inner_per = fc->stack_inner_per;
found = true;
break;
}
@@ -14,7 +14,7 @@ void set_size_per(Monitor *m, Client *c) {
if (!found) {
c->master_mfact_per = m->pertag->mfacts[m->pertag->curtag];
c->master_inner_per = 1.0f;
c->stack_innder_per = 1.0f;
c->stack_inner_per = 1.0f;
}
}
@@ -70,7 +70,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx,
// 记录初始状态
grabc->old_master_mfact_per = grabc->master_mfact_per;
grabc->old_master_inner_per = grabc->master_inner_per;
grabc->old_stack_innder_per = grabc->stack_innder_per;
grabc->old_stack_inner_per = grabc->stack_inner_per;
grabc->cursor_in_upper_half =
cursor->y < grabc->geom.y + grabc->geom.height / 2;
grabc->cursor_in_left_half =
@@ -86,7 +86,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx,
} else {
grabc->old_master_mfact_per = grabc->master_mfact_per;
grabc->old_master_inner_per = grabc->master_inner_per;
grabc->old_stack_innder_per = grabc->stack_innder_per;
grabc->old_stack_inner_per = grabc->stack_inner_per;
grabc->drag_begin_geom = grabc->geom;
grabc->cursor_in_upper_half = true;
grabc->cursor_in_left_half = false;
@@ -100,7 +100,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx,
} else {
delta_x = (float)(offsetx) * (1 - grabc->old_master_mfact_per) /
grabc->drag_begin_geom.width;
delta_y = (float)(offsety) * (grabc->old_stack_innder_per) /
delta_y = (float)(offsety) * (grabc->old_stack_inner_per) /
grabc->drag_begin_geom.height;
}
bool moving_up;
@@ -182,12 +182,12 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx,
// 直接设置新的比例,基于初始值 + 变化量
float new_master_mfact_per = grabc->old_master_mfact_per + delta_x;
float new_master_inner_per = grabc->old_master_inner_per + delta_y;
float new_stack_innder_per = grabc->old_stack_innder_per + delta_y;
float new_stack_inner_per = grabc->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_innder_per = fmaxf(0.1f, fminf(0.9f, new_stack_innder_per));
new_stack_inner_per = fmaxf(0.1f, fminf(0.9f, new_stack_inner_per));
// 应用到所有平铺窗口
wl_list_for_each(tc, &clients, link) {
@@ -197,7 +197,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx,
}
grabc->master_inner_per = new_master_inner_per;
grabc->stack_innder_per = new_stack_innder_per;
grabc->stack_inner_per = new_stack_inner_per;
if (!isdrag) {
arrange(grabc->mon, false);
@@ -250,7 +250,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx,
// 记录初始状态
grabc->old_master_mfact_per = grabc->master_mfact_per;
grabc->old_master_inner_per = grabc->master_inner_per;
grabc->old_stack_innder_per = grabc->stack_innder_per;
grabc->old_stack_inner_per = grabc->stack_inner_per;
grabc->cursor_in_upper_half =
cursor->y < grabc->geom.y + grabc->geom.height / 2;
grabc->cursor_in_left_half =
@@ -267,7 +267,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx,
} else {
grabc->old_master_mfact_per = grabc->master_mfact_per;
grabc->old_master_inner_per = grabc->master_inner_per;
grabc->old_stack_innder_per = grabc->stack_innder_per;
grabc->old_stack_inner_per = grabc->stack_inner_per;
grabc->drag_begin_geom = grabc->geom;
grabc->cursor_in_upper_half = true;
grabc->cursor_in_left_half = false;
@@ -280,7 +280,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx,
delta_y = (float)(offsety) * (grabc->old_master_mfact_per) /
grabc->drag_begin_geom.height;
} else {
delta_x = (float)(offsetx) * (grabc->old_stack_innder_per) /
delta_x = (float)(offsetx) * (grabc->old_stack_inner_per) /
grabc->drag_begin_geom.width;
delta_y = (float)(offsety) * (1 - grabc->old_master_mfact_per) /
grabc->drag_begin_geom.height;
@@ -338,13 +338,13 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx,
delta_y; // 垂直delta_y调整主区域高度
float new_master_inner_per = grabc->old_master_inner_per +
delta_x; // 垂直delta_x调整主区域内部宽度
float new_stack_innder_per = grabc->old_stack_innder_per +
delta_x; // 垂直delta_x调整栈区域内部宽度
float new_stack_inner_per = grabc->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_innder_per = fmaxf(0.1f, fminf(0.9f, new_stack_innder_per));
new_stack_inner_per = fmaxf(0.1f, fminf(0.9f, new_stack_inner_per));
// 应用到所有平铺窗口
wl_list_for_each(tc, &clients, link) {
@@ -354,7 +354,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx,
}
grabc->master_inner_per = new_master_inner_per;
grabc->stack_innder_per = new_stack_innder_per;
grabc->stack_inner_per = new_stack_inner_per;
if (!isdrag) {
arrange(grabc->mon, false);
@@ -402,7 +402,7 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int offsetx, int offsety,
} else {
grabc->old_master_mfact_per = grabc->master_mfact_per;
grabc->old_master_inner_per = grabc->master_inner_per;
grabc->old_stack_innder_per = grabc->stack_innder_per;
grabc->old_stack_inner_per = grabc->stack_inner_per;
grabc->drag_begin_geom = grabc->geom;
grabc->old_scroller_pproportion = grabc->scroller_proportion;
grabc->cursor_in_upper_half = false;
@@ -485,7 +485,8 @@ void resize_tile_client(Client *grabc, bool isdrag, int offsetx, int offsety,
const Layout *current_layout =
grabc->mon->pertag->ltidxs[grabc->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 == CENTER_TILE || current_layout->id == RIGHT_TILE ||
(current_layout->id == TGMIX && grabc->mon->visible_tiling_clients <= 3)
) {
resize_tile_master_horizontal(grabc, isdrag, offsetx, offsety, time,
@@ -520,16 +521,16 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num,
if (VISIBLEON(c, m) && ISTILED(c)) {
if (total_master_inner_percent > 0.0 && i < nmasters) {
c->ismaster = true;
c->stack_innder_per = stack_num ? 1.0f / stack_num : 1.0f;
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_innder_per =
c->stack_inner_per =
total_stack_hight_percent
? c->stack_innder_per / total_stack_hight_percent
? c->stack_inner_per / total_stack_hight_percent
: 1.0f;
}
i++;
@@ -541,11 +542,11 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num,
if (total_master_inner_percent > 0.0 && i < nmasters) {
c->ismaster = true;
if ((stack_index % 2) ^ (tile_cilent_num % 2 == 0)) {
c->stack_innder_per =
c->stack_inner_per =
stack_num > 1 ? 1.0f / ((stack_num - 1) / 2) : 1.0f;
} else {
c->stack_innder_per =
c->stack_inner_per =
stack_num > 1 ? 2.0f / stack_num : 1.0f;
}
@@ -558,15 +559,15 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num,
c->master_inner_per =
master_num > 0 ? 1.0f / master_num : 1.0f;
if ((stack_index % 2) ^ (tile_cilent_num % 2 == 0)) {
c->stack_innder_per =
c->stack_inner_per =
total_right_stack_hight_percent
? c->stack_innder_per /
? c->stack_inner_per /
total_right_stack_hight_percent
: 1.0f;
} else {
c->stack_innder_per =
c->stack_inner_per =
total_left_stack_hight_percent
? c->stack_innder_per /
? c->stack_inner_per /
total_left_stack_hight_percent
: 1.0f;
}
@@ -580,7 +581,7 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num,
void // 17
arrange(Monitor *m, bool want_animation) {
Client *c = NULL;
double total_stack_innder_percent = 0;
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;
@@ -598,7 +599,6 @@ arrange(Monitor *m, bool want_animation) {
m->visible_clients = 0;
m->visible_tiling_clients = 0;
m->visible_scroll_tiling_clients = 0;
m->has_visible_fullscreen_client = false;
wl_list_for_each(c, &clients, link) {
@@ -612,9 +612,6 @@ arrange(Monitor *m, bool want_animation) {
if (!c->isunglobal)
m->visible_clients++;
if (c->isfullscreen)
m->has_visible_fullscreen_client = true;
if (ISTILED(c)) {
m->visible_tiling_clients++;
}
@@ -640,17 +637,17 @@ arrange(Monitor *m, bool want_animation) {
total_master_inner_percent += c->master_inner_per;
} else {
stack_num++;
total_stack_innder_percent += c->stack_innder_per;
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_innder_per;
c->stack_inner_per;
} else {
c->isleftstack = true;
total_left_stack_hight_percent +=
c->stack_innder_per;
c->stack_inner_per;
}
}
@@ -671,7 +668,7 @@ arrange(Monitor *m, bool want_animation) {
reset_size_per_mon(
m, m->visible_tiling_clients, total_left_stack_hight_percent,
total_right_stack_hight_percent, total_stack_innder_percent,
total_right_stack_hight_percent, total_stack_inner_percent,
total_master_inner_percent, master_num, stack_num);
if (m->isoverview) {

View File

@@ -705,17 +705,17 @@ void center_tile(Monitor *m) {
if (n - nmasters == 1) {
// 单个堆叠窗口
r = n - i;
if (c->stack_innder_per > 0.0f) {
if (c->stack_inner_per > 0.0f) {
h = (m->w.height - 2 * cur_gappov -
cur_gappiv * ie * (stack_num - 1)) *
c->stack_innder_per;
c->stack_inner_per;
c->master_mfact_per = mfact;
} else {
h = (m->w.height - ety - cur_gappov -
cur_gappiv * ie * (r - 1)) /
r;
c->stack_innder_per = h / (m->w.height - ety - cur_gappov -
cur_gappiv * ie * (r - 1));
c->stack_inner_per = h / (m->w.height - ety - cur_gappov -
cur_gappiv * ie * (r - 1));
c->master_mfact_per = mfact;
}
@@ -741,19 +741,19 @@ void center_tile(Monitor *m) {
if ((stack_index % 2) ^ (n % 2 == 0)) {
// 右侧堆叠窗口
if (c->stack_innder_per > 0.0f) {
h = slave_right_surplus_height * c->stack_innder_per /
if (c->stack_inner_per > 0.0f) {
h = slave_right_surplus_height * c->stack_inner_per /
slave_right_surplus_ratio;
slave_right_surplus_height =
slave_right_surplus_height - h;
slave_right_surplus_ratio =
slave_right_surplus_ratio - c->stack_innder_per;
slave_right_surplus_ratio - c->stack_inner_per;
c->master_mfact_per = mfact;
} else {
h = (m->w.height - ety - cur_gappov -
cur_gappiv * ie * (r - 1)) /
r;
c->stack_innder_per =
c->stack_inner_per =
h / (m->w.height - ety - cur_gappov -
cur_gappiv * ie * (r - 1));
c->master_mfact_per = mfact;
@@ -770,19 +770,19 @@ void center_tile(Monitor *m) {
ety += c->geom.height + cur_gappiv * ie;
} else {
// 左侧堆叠窗口
if (c->stack_innder_per > 0.0f) {
h = slave_left_surplus_height * c->stack_innder_per /
if (c->stack_inner_per > 0.0f) {
h = slave_left_surplus_height * c->stack_inner_per /
slave_left_surplus_ratio;
slave_left_surplus_height =
slave_left_surplus_height - h;
slave_left_surplus_ratio =
slave_left_surplus_ratio - c->stack_innder_per;
slave_left_surplus_ratio - c->stack_inner_per;
c->master_mfact_per = mfact;
} else {
h = (m->w.height - oty - cur_gappov -
cur_gappiv * ie * (r - 1)) /
r;
c->stack_innder_per =
c->stack_inner_per =
h / (m->w.height - oty - cur_gappov -
cur_gappiv * ie * (r - 1));
c->master_mfact_per = mfact;
@@ -884,22 +884,22 @@ void tile(Monitor *m) {
my += c->geom.height + cur_gappiv * ie;
} else {
r = n - i;
if (c->stack_innder_per > 0.0f) {
h = slave_surplus_height * c->stack_innder_per /
if (c->stack_inner_per > 0.0f) {
h = slave_surplus_height * c->stack_inner_per /
slave_surplus_ratio;
slave_surplus_height = slave_surplus_height - h;
slave_surplus_ratio = slave_surplus_ratio - c->stack_innder_per;
slave_surplus_ratio = slave_surplus_ratio - c->stack_inner_per;
c->master_mfact_per = mfact;
} else {
h = (m->w.height - ty - cur_gappov -
cur_gappiv * ie * (r - 1)) /
r;
c->stack_innder_per = h / (m->w.height - ty - cur_gappov -
cur_gappiv * ie * (r - 1));
c->stack_inner_per = h / (m->w.height - ty - cur_gappov -
cur_gappiv * ie * (r - 1));
c->master_mfact_per = mfact;
}
// wlr_log(WLR_ERROR, "stack_innder_per: %f", c->stack_innder_per);
// wlr_log(WLR_ERROR, "stack_inner_per: %f", c->stack_inner_per);
resize(c,
(struct wlr_box){.x = m->w.x + mw + cur_gappoh,
@@ -995,22 +995,22 @@ void right_tile(Monitor *m) {
my += c->geom.height + cur_gappiv * ie;
} else {
r = n - i;
if (c->stack_innder_per > 0.0f) {
h = slave_surplus_height * c->stack_innder_per /
if (c->stack_inner_per > 0.0f) {
h = slave_surplus_height * c->stack_inner_per /
slave_surplus_ratio;
slave_surplus_height = slave_surplus_height - h;
slave_surplus_ratio = slave_surplus_ratio - c->stack_innder_per;
slave_surplus_ratio = slave_surplus_ratio - c->stack_inner_per;
c->master_mfact_per = mfact;
} else {
h = (m->w.height - ty - cur_gappov -
cur_gappiv * ie * (r - 1)) /
r;
c->stack_innder_per = h / (m->w.height - ty - cur_gappov -
cur_gappiv * ie * (r - 1));
c->stack_inner_per = h / (m->w.height - ty - cur_gappov -
cur_gappiv * ie * (r - 1));
c->master_mfact_per = mfact;
}
// wlr_log(WLR_ERROR, "stack_innder_per: %f", c->stack_innder_per);
// wlr_log(WLR_ERROR, "stack_inner_per: %f", c->stack_inner_per);
resize(c,
(struct wlr_box){.x = m->w.x + cur_gappoh,
@@ -1047,3 +1047,14 @@ monocle(Monitor *m) {
if ((c = focustop(m)))
wlr_scene_node_raise_to_top(&c->scene->node);
}
void tgmix(Monitor *m) {
uint32_t n = m->visible_tiling_clients;
if (n <= 3) {
tile(m);
return;
} else {
grid(m);
return;
}
}

View File

@@ -12,6 +12,7 @@ static void vertical_grid(Monitor *m);
static void vertical_scroller(Monitor *m);
static void vertical_deck(Monitor *mon);
static void dual_scroller(Monitor *mon);
static void tgmix(Monitor *m);
/* layout(s) */
Layout overviewlayout = {"󰃇", overview, "overview"};
@@ -29,6 +30,7 @@ enum {
VERTICAL_DECK,
RIGHT_TILE,
DUAL_SCROLLER,
TGMIX,
};
Layout layouts[] = {
@@ -47,4 +49,5 @@ Layout layouts[] = {
{"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局
{"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局
{"DS", dual_scroller, "dual_scroller", DUAL_SCROLLER}, // 双行滚动布局
};
{"TG", tgmix, "tgmix", TGMIX}, // 混合布局
};

View File

@@ -78,17 +78,17 @@ void vertical_tile(Monitor *m) {
mx += c->geom.width + cur_gapih * ie;
} else {
r = n - i;
if (c->stack_innder_per > 0.0f) {
w = slave_surplus_width * c->stack_innder_per /
if (c->stack_inner_per > 0.0f) {
w = slave_surplus_width * c->stack_inner_per /
slave_surplus_ratio;
slave_surplus_width = slave_surplus_width - w;
slave_surplus_ratio = slave_surplus_ratio - c->stack_innder_per;
slave_surplus_ratio = slave_surplus_ratio - c->stack_inner_per;
c->master_mfact_per = mfact;
} else {
w = (m->w.width - tx - cur_gapih - cur_gapih * ie * (r - 1)) /
r;
c->stack_innder_per = w / (m->w.width - tx - cur_gapih -
cur_gapih * ie * (r - 1));
c->stack_inner_per = w / (m->w.width - tx - cur_gapih -
cur_gapih * ie * (r - 1));
c->master_mfact_per = mfact;
}

View File

@@ -165,7 +165,7 @@ enum {
}; /* EWMH atoms */
#endif
enum { UP, DOWN, LEFT, RIGHT, UNDIR }; /* smartmovewin */
enum { NONE, OPEN, MOVE, CLOSE, TAG, FOCUS };
enum { NONE, OPEN, MOVE, CLOSE, TAG, FOCUS, OPAFADEIN, OPAFADEOUT };
enum { UNFOLD, FOLD, INVALIDFOLD };
enum { PREV, NEXT };
enum { STATE_UNSPECIFIED = 0, STATE_ENABLED, STATE_DISABLED };
@@ -364,6 +364,7 @@ struct Client {
int isglobal;
int isnoborder;
int isnoshadow;
int isnoradius;
int isnoanimation;
int isopensilent;
int istagsilent;
@@ -394,8 +395,8 @@ struct Client {
float unfocused_opacity;
char oldmonname[128];
int noblur;
double master_mfact_per, master_inner_per, stack_innder_per;
double old_master_mfact_per, old_master_inner_per, old_stack_innder_per;
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;
int dual_scroller_row; // 0 = top row, 1 = bottom row, -1 = not set
@@ -509,7 +510,6 @@ struct Monitor {
uint32_t visible_clients;
uint32_t visible_tiling_clients;
uint32_t visible_scroll_tiling_clients;
bool has_visible_fullscreen_client;
struct wlr_scene_optimized_blur *blur;
char last_surface_ws_name[256];
struct wlr_ext_workspace_group_handle_v1 *ext_group;
@@ -852,6 +852,8 @@ 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;
static struct wl_event_source *hide_source;
static bool cursor_hidden = false;
@@ -1215,6 +1217,7 @@ static void apply_rule_properties(Client *c, const ConfigWinRule *r) {
APPLY_INT_PROP(c, r, isfullscreen);
APPLY_INT_PROP(c, r, isnoborder);
APPLY_INT_PROP(c, r, isnoshadow);
APPLY_INT_PROP(c, r, isnoradius);
APPLY_INT_PROP(c, r, isnoanimation);
APPLY_INT_PROP(c, r, isopensilent);
APPLY_INT_PROP(c, r, istagsilent);
@@ -1393,8 +1396,11 @@ void applyrules(Client *c) {
// if no geom rule hit and is normal winodw, use the center pos and record
// the hit size
if (!hit_rule_pos && (!client_is_x11(c) || !client_is_x11_popup(c))) {
if (!hit_rule_pos &&
(!client_is_x11(c) || (c->geom.x == 0 && c->geom.y == 0))) {
c->float_geom = c->geom = setclient_coordinate_center(c, c->geom, 0, 0);
} else {
c->float_geom = c->geom;
}
/*-----------------------apply rule action-------------------------*/
@@ -1712,10 +1718,11 @@ axisnotify(struct wl_listener *listener, void *data) {
* implemented checking the event's orientation and the delta of the event
*/
/* Notify the client with pointer focus of the axis event. */
wlr_seat_pointer_notify_axis(seat, // 滚轮事件发送给客户端也就是窗口
event->time_msec, event->orientation,
event->delta, event->delta_discrete,
event->source, event->relative_direction);
wlr_seat_pointer_notify_axis(
seat, // 滚轮事件发送给客户端也就是窗口
event->time_msec, event->orientation, event->delta * axis_scroll_factor,
roundf(event->delta_discrete * axis_scroll_factor), event->source,
event->relative_direction);
}
int ongesture(struct wlr_pointer_swipe_end_event *event) {
@@ -2001,16 +2008,27 @@ buttonpress(struct wl_listener *listener, void *data) {
}
void checkidleinhibitor(struct wlr_surface *exclude) {
int inhibited = 0, unused_lx, unused_ly;
int inhibited = 0;
Client *c = NULL;
struct wlr_surface *surface = NULL;
struct wlr_idle_inhibitor_v1 *inhibitor;
wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) {
struct wlr_surface *surface =
wlr_surface_get_root_surface(inhibitor->surface);
surface = wlr_surface_get_root_surface(inhibitor->surface);
if (exclude == surface) {
continue;
}
toplevel_from_wlr_surface(inhibitor->surface, &c, NULL);
if (idleinhibit_ignore_visible) {
inhibited = 1;
break;
}
struct wlr_scene_tree *tree = surface->data;
if (exclude != surface &&
(inhibit_regardless_of_visibility ||
(!tree ||
wlr_scene_node_coords(&tree->node, &unused_lx, &unused_ly)))) {
if (!tree || (tree->node.enabled && (!c || !c->animation.tagouting))) {
inhibited = 1;
break;
}
@@ -3436,13 +3454,13 @@ keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym,
keycode == k->keysymcode.keycode.keycode3))) &&
k->func) {
isbreak = k->func(&k->arg);
if (!k->ispassapply)
handled = 1;
else
handled = 0;
isbreak = k->func(&k->arg);
if (isbreak)
break;
}
@@ -3708,18 +3726,24 @@ void init_client_properties(Client *c) {
c->no_force_center = 0;
c->isnoborder = 0;
c->isnosizehint = 0;
c->isnoradius = 0;
c->isnoshadow = 0;
c->ignore_maximize = 1;
c->ignore_minimize = 1;
c->iscustomsize = 0;
c->master_mfact_per = 0.0f;
c->master_inner_per = 0.0f;
c->stack_innder_per = 0.0f;
c->stack_inner_per = 0.0f;
c->isterm = 0;
c->allow_csd = 0;
c->force_maximize = 0;
c->force_tearing = 0;
c->allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
c->scroller_proportion_single = 0.0f;
c->float_geom.width = 0;
c->float_geom.height = 0;
c->float_geom.x = 0;
c->float_geom.y = 0;
}
void // old fix to 0.5
@@ -4023,7 +4047,11 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
.y = grabc->geom.y,
.width = (int)round(cursor->x) - grabc->geom.x,
.height = (int)round(cursor->y) - grabc->geom.y};
resize(grabc, grabc->float_geom, 1);
if (last_apply_drap_time == 0 ||
time - last_apply_drap_time > drag_refresh_interval) {
resize(grabc, grabc->float_geom, 1);
last_apply_drap_time = time;
}
return;
} else {
resize_tile_client(grabc, true, 0, 0, time);
@@ -4319,7 +4347,7 @@ void exchange_two_client(Client *c1, Client *c2) {
uint32_t tmp_tags;
double master_inner_per = 0.0f;
double master_mfact_per = 0.0f;
double stack_innder_per = 0.0f;
double stack_inner_per = 0.0f;
if (c1 == NULL || c2 == NULL ||
(!exchange_cross_monitor && c1->mon != c2->mon)) {
@@ -4328,15 +4356,15 @@ void exchange_two_client(Client *c1, Client *c2) {
master_inner_per = c1->master_inner_per;
master_mfact_per = c1->master_mfact_per;
stack_innder_per = c1->stack_innder_per;
stack_inner_per = c1->stack_inner_per;
c1->master_inner_per = c2->master_inner_per;
c1->master_mfact_per = c2->master_mfact_per;
c1->stack_innder_per = c2->stack_innder_per;
c1->stack_inner_per = c2->stack_inner_per;
c2->master_inner_per = master_inner_per;
c2->master_mfact_per = master_mfact_per;
c2->stack_innder_per = stack_innder_per;
c2->stack_inner_per = stack_inner_per;
struct wl_list *tmp1_prev = c1->link.prev;
struct wl_list *tmp2_prev = c2->link.prev;
@@ -4507,7 +4535,7 @@ setfloating(Client *c, int floating) {
}
// 重新计算居中的坐标
if (!client_is_x11(c) || !client_is_x11_popup(c))
if (!client_is_x11(c) || (c->geom.x == 0 && c->geom.y == 0))
target_box = setclient_coordinate_center(c, target_box, 0, 0);
backup_box = c->geom;
hit = applyrulesgeom(c);