diff --git a/README.md b/README.md index 8e982b60..9780ac6e 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,8 @@ https://github.com/user-attachments/assets/014c893f-115c-4ae9-8342-f9ae3e9a0df0 - hwdata - seatd - pcre2 +- xorg-xwayland +- libxcb ## Arch Linux The package is in the Arch User Repository and is availble for manual download [here](https://aur.archlinux.org/packages/mangowc-git) or through a AUR helper like yay: @@ -80,7 +82,6 @@ yay -S mangowc-git ``` ## Gentoo Linux - The package is in the community-maintained repository called GURU. First, add GURU repository: @@ -98,6 +99,16 @@ Finally, install the package: emerge --ask --verbose gui-wm/mangowc ``` +## Fedora Linux +The package is in the third-party Terra repository. +First, add the [Terra Repository](https://terra.fyralabs.com/). + +Then, install the package: + +```bash +dnf install mangowc +``` + ## Other ```bash @@ -106,7 +117,7 @@ cd wlroots meson build -Dprefix=/usr sudo ninja -C build install -git clone https://github.com/wlrfx/scenefx.git +git clone -b 0.4.1 https://github.com/wlrfx/scenefx.git cd scenefx meson build -Dprefix=/usr sudo ninja -C build install @@ -170,7 +181,9 @@ git clone https://github.com/DreamMaoMao/mango-config.git ~/.config/mango ## Config Documentation -Refer to the [wiki](https://github.com/DreamMaoMao/mango/wiki/) +Refer to the repo wiki [wiki](https://github.com/DreamMaoMao/mango/wiki/) + +or the website docs [docs](https://mangowc.vercel.app/docs) # NixOS + Home-manager @@ -189,7 +202,10 @@ Here's an example of using the modules in a flake: inputs.nixpkgs.follows = "nixpkgs"; }; flake-parts.url = "github:hercules-ci/flake-parts"; - mango.url = "github:DreamMaoMao/mango"; + mango = { + url = "github:DreamMaoMao/mango"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = inputs@{ self, flake-parts, ... }: @@ -245,14 +261,6 @@ Here's an example of using the modules in a flake: } ``` - -# Sponsor - -My current device is a bit outdated and doesn't support certain features like HDR or VRR. If you'd like to support this project, here's how you can help. Thanks! - -![Screenshot_2025-10-13-20-06-49-26_ee1cec40dcf6eb3](https://github.com/user-attachments/assets/240a0727-9eb5-4212-a84c-10fa9f093147) - - # Packaging mango To package mango for other distributions, you can check the reference setup for: diff --git a/meson.build b/meson.build index 041a1fdf..460328ef 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('mango', ['c', 'cpp'], - version : '0.10.5', + version : '0.10.7', ) subdir('protocols') diff --git a/mmsg/mmsg.c b/mmsg/mmsg.c index 6f350ed0..2bbe870e 100644 --- a/mmsg/mmsg.c +++ b/mmsg/mmsg.c @@ -86,7 +86,7 @@ static void noop_description(void *data, struct wl_output *wl_output, const char *description) {} // 将 n 转换为 9 位二进制字符串,结果存入 buf(至少长度 10) -void bin_str_9bits(char *buf, unsigned int n) { +void bin_str_9bits(char *buf, uint32_t n) { for (int i = 8; i >= 0; i--) { *buf++ = ((n >> i) & 1) ? '1' : '0'; } @@ -268,7 +268,7 @@ static void dwl_ipc_output_kb_layout(void *data, static void dwl_ipc_output_scalefactor(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, - const unsigned int scalefactor) { + const uint32_t scalefactor) { if (!Aflag) return; char *output_name = data; diff --git a/nix/nixos-modules.nix b/nix/nixos-modules.nix index 5d0aa61e..33811022 100644 --- a/nix/nixos-modules.nix +++ b/nix/nixos-modules.nix @@ -26,6 +26,25 @@ in { xdg.portal = { enable = lib.mkDefault true; + config = { + mango = { + default = [ + "gtk" + ]; + # except those + "org.freedesktop.impl.portal.Secret" = ["gnome-keyring"]; + "org.freedesktop.impl.portal.ScreenCast" = ["wlr"]; + "org.freedesktop.impl.portal.ScreenShot" = ["wlr"]; + + # wlr does not have this interface + "org.freedesktop.impl.portal.Inhibit" = []; + }; + }; + extraPortals = with pkgs; [ + xdg-desktop-portal-wlr + xdg-desktop-portal-gtk + ]; + wlr.enable = lib.mkDefault true; configPackages = [cfg.package]; diff --git a/src/animation/client.h b/src/animation/client.h index 70da39e9..26c18451 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -1,4 +1,4 @@ -void client_actual_size(Client *c, unsigned int *width, unsigned int *height) { +void client_actual_size(Client *c, uint32_t *width, uint32_t *height) { *width = c->animation.current.width - c->bw; *height = c->animation.current.height - c->bw; @@ -183,8 +183,8 @@ void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int sx, int sy, if (buffer_data->should_scale) { - unsigned int surface_width = surface->current.width; - unsigned int surface_height = surface->current.height; + uint32_t surface_width = surface->current.width; + uint32_t surface_height = surface->current.height; surface_width = buffer_data->width_scale < 1 ? surface_width @@ -274,7 +274,7 @@ void client_draw_shadow(Client *c) { ? CORNER_LOCATION_NONE : CORNER_LOCATION_ALL; - unsigned int bwoffset = c->bw != 0 && hit_no_border ? c->bw : 0; + uint32_t bwoffset = c->bw != 0 && hit_no_border ? c->bw : 0; uint32_t width, height; client_actual_size(c, &width, &height); @@ -463,7 +463,7 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) { int offsetx = 0, offsety = 0, offsetw = 0, offseth = 0; struct ivec2 offset = {0, 0, 0, 0}; - if (!ISTILED(c) && !c->animation.tagining && !c->animation.tagouted && + if (!ISSCROLLTILED(c) && !c->animation.tagining && !c->animation.tagouted && !c->animation.tagouting) return offset; @@ -484,7 +484,7 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) { 需要主要border超出屏幕的时候不计算如偏差之内而是 要等窗口表面超出才开始计算偏差 */ - if (ISTILED(c) || c->animation.tagining || c->animation.tagouted || + if (ISSCROLLTILED(c) || c->animation.tagining || c->animation.tagouted || c->animation.tagouting) { if (left_out_offset > 0) { offsetx = GEZERO(left_out_offset - bw); @@ -512,7 +512,7 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) { offset.height = offseth; if ((clip_box->width + bw <= 0 || clip_box->height + bw <= 0) && - (ISTILED(c) || c->animation.tagouting || c->animation.tagining)) { + (ISSCROLLTILED(c) || c->animation.tagouting || c->animation.tagining)) { c->is_clip_to_hide = true; wlr_scene_node_set_enabled(&c->scene->node, false); } else if (c->is_clip_to_hide && VISIBLEON(c, c->mon)) { @@ -565,7 +565,7 @@ void client_apply_clip(Client *c, float factor) { } // 获取窗口动画实时位置矩形 - unsigned int width, height; + uint32_t width, height; client_actual_size(c, &width, &height); // 计算出除了边框的窗口实际剪切大小 @@ -650,17 +650,16 @@ 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); - unsigned int width = - c->animation.initial.width + - (c->current.width - c->animation.initial.width) * factor; - unsigned int height = + uint32_t width = c->animation.initial.width + + (c->current.width - c->animation.initial.width) * factor; + uint32_t height = c->animation.initial.height + (c->current.height - c->animation.initial.height) * factor; - unsigned int x = c->animation.initial.x + - (c->current.x - c->animation.initial.x) * factor; - unsigned int y = c->animation.initial.y + - (c->current.y - c->animation.initial.y) * 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; wlr_scene_node_set_position(&c->scene->node, x, y); @@ -716,17 +715,16 @@ void client_animation_next_tick(Client *c) { double sx = 0, sy = 0; struct wlr_surface *surface = NULL; - unsigned int width = - c->animation.initial.width + - (c->current.width - c->animation.initial.width) * factor; - unsigned int height = + uint32_t width = c->animation.initial.width + + (c->current.width - c->animation.initial.width) * factor; + uint32_t height = c->animation.initial.height + (c->current.height - c->animation.initial.height) * factor; - unsigned int x = c->animation.initial.x + - (c->current.x - c->animation.initial.x) * factor; - unsigned int y = c->animation.initial.y + - (c->current.y - c->animation.initial.y) * 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; wlr_scene_node_set_position(&c->scene->node, x, y); c->animation.current = (struct wlr_box){ @@ -1084,7 +1082,7 @@ void client_set_focused_opacity_animation(Client *c) { c->opacity_animation.running = true; } -void cleint_set_unfocused_opacity_animation(Client *c) { +void client_set_unfocused_opacity_animation(Client *c) { // Start border color animation to unfocused float *border_color = get_border_color(c); diff --git a/src/animation/common.h b/src/animation/common.h index 7079df86..8be49129 100644 --- a/src/animation/common.h +++ b/src/animation/common.h @@ -33,33 +33,33 @@ void init_baked_points(void) { baked_points_focus = calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_focus)); - for (unsigned int i = 0; i < BAKED_POINTS_COUNT; i++) { + for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) { baked_points_move[i] = calculate_animation_curve_at( (double)i / (BAKED_POINTS_COUNT - 1), MOVE); } - for (unsigned int i = 0; i < BAKED_POINTS_COUNT; i++) { + for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) { baked_points_open[i] = calculate_animation_curve_at( (double)i / (BAKED_POINTS_COUNT - 1), OPEN); } - for (unsigned int i = 0; i < BAKED_POINTS_COUNT; i++) { + for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) { baked_points_tag[i] = calculate_animation_curve_at( (double)i / (BAKED_POINTS_COUNT - 1), TAG); } - for (unsigned int i = 0; i < BAKED_POINTS_COUNT; i++) { + for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) { baked_points_close[i] = calculate_animation_curve_at( (double)i / (BAKED_POINTS_COUNT - 1), CLOSE); } - for (unsigned int i = 0; i < BAKED_POINTS_COUNT; i++) { + for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) { baked_points_focus[i] = calculate_animation_curve_at( (double)i / (BAKED_POINTS_COUNT - 1), FOCUS); } } double find_animation_curve_at(double t, int type) { - unsigned int down = 0; - unsigned int up = BAKED_POINTS_COUNT - 1; + uint32_t down = 0; + uint32_t up = BAKED_POINTS_COUNT - 1; - unsigned int middle = (up + down) / 2; + uint32_t middle = (up + down) / 2; struct dvec2 *baked_points; if (type == MOVE) { baked_points = baked_points_move; diff --git a/src/animation/layer.h b/src/animation/layer.h index 80caec56..104af95a 100644 --- a/src/animation/layer.h +++ b/src/animation/layer.h @@ -1,5 +1,4 @@ -void layer_actual_size(LayerSurface *l, unsigned int *width, - unsigned int *height) { +void layer_actual_size(LayerSurface *l, uint32_t *width, uint32_t *height) { struct wlr_box box; if (l->animation.running) { @@ -213,9 +212,8 @@ void layer_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int sx, struct wlr_surface *surface = scene_surface->surface; - unsigned int surface_width = - surface->current.width * buffer_data->width_scale; - unsigned int surface_height = + uint32_t surface_width = surface->current.width * buffer_data->width_scale; + uint32_t surface_height = surface->current.height * buffer_data->height_scale; if (surface_height > 0 && surface_width > 0) { @@ -245,17 +243,16 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) { int type = l->animation.action = l->animation.action; double factor = find_animation_curve_at(animation_passed, type); - unsigned int width = - l->animation.initial.width + - (l->current.width - l->animation.initial.width) * factor; - unsigned int height = + uint32_t width = l->animation.initial.width + + (l->current.width - l->animation.initial.width) * factor; + uint32_t height = l->animation.initial.height + (l->current.height - l->animation.initial.height) * factor; - unsigned int x = l->animation.initial.x + - (l->current.x - l->animation.initial.x) * factor; - unsigned int y = l->animation.initial.y + - (l->current.y - l->animation.initial.y) * factor; + uint32_t x = l->animation.initial.x + + (l->current.x - l->animation.initial.x) * factor; + uint32_t y = l->animation.initial.y + + (l->current.y - l->animation.initial.y) * factor; wlr_scene_node_set_position(&l->scene->node, x, y); @@ -310,17 +307,16 @@ void layer_animation_next_tick(LayerSurface *l) { int type = l->animation.action == NONE ? MOVE : l->animation.action; double factor = find_animation_curve_at(animation_passed, type); - unsigned int width = - l->animation.initial.width + - (l->current.width - l->animation.initial.width) * factor; - unsigned int height = + uint32_t width = l->animation.initial.width + + (l->current.width - l->animation.initial.width) * factor; + uint32_t height = l->animation.initial.height + (l->current.height - l->animation.initial.height) * factor; - unsigned int x = l->animation.initial.x + - (l->current.x - l->animation.initial.x) * factor; - unsigned int y = l->animation.initial.y + - (l->current.y - l->animation.initial.y) * factor; + uint32_t x = l->animation.initial.x + + (l->current.x - l->animation.initial.x) * factor; + 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), diff --git a/src/client/client.h b/src/client/client.h index 06f629de..10ecfdf7 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -526,16 +526,16 @@ static inline void client_set_size_bound(Client *c) { if (!size_hints) return; - if ((unsigned int)c->geom.width - 2 * c->bw < size_hints->min_width && + 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 ((unsigned int)c->geom.height - 2 * c->bw < size_hints->min_height && + 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 ((unsigned int)c->geom.width - 2 * c->bw > size_hints->max_width && + 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 ((unsigned int)c->geom.height - 2 * c->bw > size_hints->max_height && + 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; @@ -544,19 +544,19 @@ static inline void client_set_size_bound(Client *c) { toplevel = c->surface.xdg->toplevel; state = toplevel->current; - if ((unsigned int)c->geom.width - 2 * c->bw < state.min_width && + 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 ((unsigned int)c->geom.height - 2 * c->bw < state.min_height && + 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 ((unsigned int)c->geom.width - 2 * c->bw > state.max_width && + 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 ((unsigned int)c->geom.height - 2 * c->bw > state.max_height && + 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; } diff --git a/src/common/util.c b/src/common/util.c index 6eadbc67..79972054 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -82,14 +82,13 @@ void wl_list_append(struct wl_list *list, struct wl_list *object) { wl_list_insert(list->prev, object); } -unsigned int get_now_in_ms(void) { +uint32_t get_now_in_ms(void) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); return timespec_to_ms(&now); } -unsigned int timespec_to_ms(struct timespec *ts) { - return (unsigned int)ts->tv_sec * 1000 + - (unsigned int)ts->tv_nsec / 1000000; +uint32_t timespec_to_ms(struct timespec *ts) { + return (uint32_t)ts->tv_sec * 1000 + (uint32_t)ts->tv_nsec / 1000000; } diff --git a/src/common/util.h b/src/common/util.h index 3a0f6dae..2718eae8 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -6,5 +6,5 @@ void *ecalloc(size_t nmemb, size_t size); int fd_set_nonblock(int fd); int regex_match(const char *pattern_mb, const char *str_mb); void wl_list_append(struct wl_list *list, struct wl_list *object); -unsigned int get_now_in_ms(void); -unsigned int timespec_to_ms(struct timespec *ts); \ No newline at end of file +uint32_t get_now_in_ms(void); +uint32_t timespec_to_ms(struct timespec *ts); \ No newline at end of file diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 345fbc60..fe0ac889 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -52,7 +53,7 @@ typedef struct { typedef struct { const char *id; const char *title; - unsigned int tags; + uint32_t tags; int isfloating; int isfullscreen; float scroller_proportion; @@ -69,6 +70,7 @@ typedef struct { int isunglobal; int isglobal; int isoverlay; + int allow_shortcuts_inhibit; int ignore_maximize; int ignore_minimize; int isnosizehint; @@ -89,6 +91,7 @@ typedef struct { int noblur; float focused_opacity; float unfocused_opacity; + float scroller_proportion_single; uint32_t passmod; xkb_keysym_t keysym; KeyBinding globalkeybinding; @@ -122,29 +125,29 @@ KeyBinding default_key_bindings[] = {CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(9), CHVT(10), CHVT(11), CHVT(12)}; typedef struct { - unsigned int mod; - unsigned int button; + uint32_t mod; + uint32_t button; int (*func)(const Arg *); Arg arg; } MouseBinding; typedef struct { - unsigned int mod; - unsigned int dir; + uint32_t mod; + uint32_t dir; int (*func)(const Arg *); Arg arg; } AxisBinding; typedef struct { - unsigned int fold; + uint32_t fold; int (*func)(const Arg *); Arg arg; } SwitchBinding; typedef struct { - unsigned int mod; - unsigned int motion; - unsigned int fingers_count; + uint32_t mod; + uint32_t motion; + uint32_t fingers_count; int (*func)(const Arg *); Arg arg; } GestureBinding; @@ -208,7 +211,7 @@ typedef struct { int snap_distance; int enable_floating_snap; int drag_tile_to_tile; - unsigned int swipe_min_threshold; + uint32_t swipe_min_threshold; float focused_opacity; float unfocused_opacity; float *scroller_proportion_preset; @@ -217,21 +220,21 @@ typedef struct { char **circle_layout; int circle_layout_count; - unsigned int new_is_master; + uint32_t new_is_master; float default_mfact; - unsigned int default_nmaster; + uint32_t default_nmaster; int center_master_overspread; int center_when_single_stack; - unsigned int hotarea_size; - unsigned int enable_hotarea; - unsigned int ov_tab_mode; + uint32_t hotarea_size; + uint32_t enable_hotarea; + uint32_t ov_tab_mode; int overviewgappi; int overviewgappo; - unsigned int cursor_hide_timeout; + uint32_t cursor_hide_timeout; - unsigned int axis_bind_apply_timeout; - unsigned int focus_on_activate; + uint32_t axis_bind_apply_timeout; + uint32_t focus_on_activate; int inhibit_regardless_of_visibility; int sloppyfocus; int warpcursor; @@ -239,7 +242,7 @@ typedef struct { /* keyboard */ int repeat_rate; int repeat_delay; - unsigned int numlockon; + uint32_t numlockon; /* Trackpad */ int disable_trackpad; @@ -251,13 +254,13 @@ typedef struct { int disable_while_typing; int left_handed; int middle_button_emulation; - unsigned int accel_profile; + uint32_t accel_profile; double accel_speed; - unsigned int scroll_method; - unsigned int scroll_button; - unsigned int click_method; - unsigned int send_events_mode; - unsigned int button_map; + uint32_t scroll_method; + uint32_t scroll_button; + uint32_t click_method; + uint32_t send_events_mode; + uint32_t button_map; int blur; int blur_layer; @@ -267,18 +270,18 @@ typedef struct { int shadows; int shadow_only_floating; int layer_shadows; - unsigned int shadows_size; + uint32_t shadows_size; float shadows_blur; int shadows_position_x; int shadows_position_y; float shadowscolor[4]; int smartgaps; - unsigned int gappih; - unsigned int gappiv; - unsigned int gappoh; - unsigned int gappov; - unsigned int borderpx; + uint32_t gappih; + uint32_t gappiv; + uint32_t gappoh; + uint32_t gappov; + uint32_t borderpx; float scratchpad_width_ratio; float scratchpad_height_ratio; float rootcolor[4]; @@ -329,13 +332,15 @@ typedef struct { int exec_once_count; char *cursor_theme; - unsigned int cursor_size; + uint32_t cursor_size; int single_scratchpad; int xwayland_persistence; int syncobj_enable; int adaptive_sync; int allow_tearing; + int allow_shortcuts_inhibit; + int allow_lock_transparent; struct xkb_rule_names xkb_rules; @@ -515,61 +520,6 @@ long int parse_color(const char *hex_str) { return hex_num; } -xkb_keysym_t normalize_keysym(xkb_keysym_t sym) { - // 首先转换为小写(主要影响字母键) - sym = xkb_keysym_to_lower(sym); - - // 将数字小键盘键转换为普通数字键 - switch (sym) { - // 小键盘数字转换 - case XKB_KEY_KP_0: - return XKB_KEY_0; - case XKB_KEY_KP_1: - return XKB_KEY_1; - case XKB_KEY_KP_2: - return XKB_KEY_2; - case XKB_KEY_KP_3: - return XKB_KEY_3; - case XKB_KEY_KP_4: - return XKB_KEY_4; - case XKB_KEY_KP_5: - return XKB_KEY_5; - case XKB_KEY_KP_6: - return XKB_KEY_6; - case XKB_KEY_KP_7: - return XKB_KEY_7; - case XKB_KEY_KP_8: - return XKB_KEY_8; - case XKB_KEY_KP_9: - return XKB_KEY_9; - - // 将 Shift+数字 的符号转换回基础数字 - case XKB_KEY_exclam: - return XKB_KEY_1; // ! - case XKB_KEY_at: - return XKB_KEY_2; // @ - case XKB_KEY_numbersign: - return XKB_KEY_3; // # - case XKB_KEY_dollar: - return XKB_KEY_4; // $ - case XKB_KEY_percent: - return XKB_KEY_5; // % - case XKB_KEY_asciicircum: - return XKB_KEY_6; // ^ - case XKB_KEY_ampersand: - return XKB_KEY_7; // & - case XKB_KEY_asterisk: - return XKB_KEY_8; // * - case XKB_KEY_parenleft: - return XKB_KEY_9; // ( - case XKB_KEY_parenright: - return XKB_KEY_0; // ) - - default: - return sym; - } -} - // 辅助函数:检查字符串是否以指定的前缀开头(忽略大小写) static bool starts_with_ignore_case(const char *str, const char *prefix) { while (*prefix) { @@ -840,7 +790,7 @@ void convert_hex_to_rgba(float *color, unsigned long int hex) { color[3] = (hex & 0xFF) / 255.0f; } -unsigned int parse_num_type(char *str) { +uint32_t parse_num_type(char *str) { switch (str[0]) { case '-': return NUM_TYPE_MINUS; @@ -1043,7 +993,31 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, (*arg).i = atoi(arg_value2); } else if (strcmp(func_name, "view") == 0) { func = bind_to_view; - (*arg).ui = 1 << (atoi(arg_value) - 1); + + uint32_t mask = 0; + char *token; + char *arg_copy = strdup(arg_value); + + if (arg_copy != NULL) { + char *saveptr = NULL; + token = strtok_r(arg_copy, "|", &saveptr); + + while (token != NULL) { + int num = atoi(token); + if (num > 0 && num <= LENGTH(tags)) { + mask |= (1 << (num - 1)); + } + token = strtok_r(NULL, "|", &saveptr); + } + + free(arg_copy); + } + + if (mask) { + (*arg).ui = mask; + } else { + (*arg).ui = atoi(arg_value); + } (*arg).i = atoi(arg_value2); } else if (strcmp(func_name, "viewcrossmon") == 0) { func = viewcrossmon; @@ -1275,6 +1249,10 @@ void parse_option(Config *config, char *key, char *value) { config->adaptive_sync = atoi(value); } else if (strcmp(key, "allow_tearing") == 0) { config->allow_tearing = atoi(value); + } else if (strcmp(key, "allow_shortcuts_inhibit") == 0) { + config->allow_shortcuts_inhibit = atoi(value); + } else if (strcmp(key, "allow_lock_transparent") == 0) { + config->allow_lock_transparent = atoi(value); } else if (strcmp(key, "no_border_when_single") == 0) { config->no_border_when_single = atoi(value); } else if (strcmp(key, "no_radius_when_single") == 0) { @@ -1712,6 +1690,7 @@ void parse_option(Config *config, char *key, char *value) { rule->isunglobal = -1; rule->isglobal = -1; rule->isoverlay = -1; + rule->allow_shortcuts_inhibit = -1; rule->ignore_maximize = -1; rule->ignore_minimize = -1; rule->isnosizehint = -1; @@ -1733,6 +1712,7 @@ void parse_option(Config *config, char *key, char *value) { // float rule value, relay to a client property rule->focused_opacity = 0; rule->unfocused_opacity = 0; + rule->scroller_proportion_single = 0.0f; rule->scroller_proportion = 0; // special rule value,not directly set to client property @@ -1804,12 +1784,16 @@ void parse_option(Config *config, char *key, char *value) { rule->isunglobal = atoi(val); } else if (strcmp(key, "isglobal") == 0) { rule->isglobal = atoi(val); + } else if (strcmp(key, "scroller_proportion_single") == 0) { + rule->scroller_proportion_single = atof(val); } else if (strcmp(key, "unfocused_opacity") == 0) { rule->unfocused_opacity = atof(val); } else if (strcmp(key, "focused_opacity") == 0) { rule->focused_opacity = atof(val); } else if (strcmp(key, "isoverlay") == 0) { rule->isoverlay = atoi(val); + } else if (strcmp(key, "allow_shortcuts_inhibit") == 0) { + rule->allow_shortcuts_inhibit = atoi(val); } else if (strcmp(key, "ignore_maximize") == 0) { rule->ignore_maximize = atoi(val); } else if (strcmp(key, "ignore_minimize") == 0) { @@ -2322,35 +2306,55 @@ void parse_config_line(Config *config, const char *line) { void parse_config_file(Config *config, const char *file_path) { FILE *file; - // 检查路径是否以 ~/ 开头 - if (file_path[0] == '~' && (file_path[1] == '/' || file_path[1] == '\0')) { + char full_path[1024]; + + if (file_path[0] == '.' && file_path[1] == '/') { + // Relative path + + if (cli_config_path) { + char *config_path = strdup(cli_config_path); + char *config_dir = dirname(config_path); + snprintf(full_path, sizeof(full_path), "%s/%s", config_dir, + file_path + 1); + free(config_path); + } else { + const char *home = getenv("HOME"); + if (!home) { + fprintf(stderr, "Error: HOME environment variable not set.\n"); + return; + } + snprintf(full_path, sizeof(full_path), "%s/.config/mango/%s", home, + file_path + 1); + } + file = fopen(full_path, "r"); + + } else if (file_path[0] == '~' && + (file_path[1] == '/' || file_path[1] == '\0')) { + // Home directory + const char *home = getenv("HOME"); if (!home) { fprintf(stderr, "Error: HOME environment variable not set.\n"); return; } - - // 构建完整路径(家目录 + / + 原路径去掉 ~) - char full_path[1024]; snprintf(full_path, sizeof(full_path), "%s%s", home, file_path + 1); - file = fopen(full_path, "r"); - if (!file) { - perror("Error opening file"); - return; - } + } else { + // Absolute path file = fopen(file_path, "r"); - if (!file) { - perror("Error opening file"); - return; - } + } + + if (!file) { + perror("Error opening file"); + return; } char line[512]; while (fgets(line, sizeof(line), file)) { - if (line[0] == '#' || line[0] == '\n') + if (line[0] == '#' || line[0] == '\n') { continue; + } parse_config_line(config, line); } @@ -2700,6 +2704,8 @@ void override_config(void) { syncobj_enable = CLAMP_INT(config.syncobj_enable, 0, 1); adaptive_sync = CLAMP_INT(config.adaptive_sync, 0, 1); allow_tearing = CLAMP_INT(config.allow_tearing, 0, 2); + allow_shortcuts_inhibit = CLAMP_INT(config.allow_shortcuts_inhibit, 0, 1); + allow_lock_transparent = CLAMP_INT(config.allow_lock_transparent, 0, 1); axis_bind_apply_timeout = CLAMP_INT(config.axis_bind_apply_timeout, 0, 1000); focus_on_activate = CLAMP_INT(config.focus_on_activate, 0, 1); @@ -2877,6 +2883,8 @@ void set_value_default() { config.syncobj_enable = syncobj_enable; config.adaptive_sync = adaptive_sync; config.allow_tearing = allow_tearing; + config.allow_shortcuts_inhibit = allow_shortcuts_inhibit; + config.allow_lock_transparent = allow_lock_transparent; config.no_border_when_single = no_border_when_single; config.no_radius_when_single = no_radius_when_single; config.snap_distance = snap_distance; @@ -3035,11 +3043,9 @@ void parse_config(void) { create_config_keymap(); - // 获取 MANGOCONFIG 环境变量 - const char *mangoconfig = getenv("MANGOCONFIG"); - - // 如果 MANGOCONFIG 环境变量不存在或为空,则使用 HOME 环境变量 - if (!mangoconfig || mangoconfig[0] == '\0') { + if (cli_config_path) { + snprintf(filename, sizeof(filename), "%s", cli_config_path); + } else { // 获取当前用户家目录 const char *homedir = getenv("HOME"); if (!homedir) { @@ -3056,9 +3062,6 @@ void parse_config(void) { snprintf(filename, sizeof(filename), "%s/mango/config.conf", SYSCONFDIR); } - } else { - // 使用 MANGOCONFIG 环境变量作为配置文件夹路径 - snprintf(filename, sizeof(filename), "%s/config.conf", mangoconfig); } set_value_default(); @@ -3156,6 +3159,12 @@ void reapply_monitor_rules(void) { } } +void reapply_cursor_style(void) { + if (cursor_mgr) + wlr_xcursor_manager_destroy(cursor_mgr); + cursor_mgr = wlr_xcursor_manager_create(config.cursor_theme, cursor_size); +} + void reapply_border(void) { Client *c = NULL; @@ -3215,33 +3224,37 @@ void reapply_master(void) { } } +void parse_tagrule(Monitor *m) { + int i, jk; + ConfigTagRule tr; + + for (i = 0; i < config.tag_rules_count; i++) { + + tr = config.tag_rules[i]; + + if (config.tag_rules_count > 0 && + (!tr.monitor_name || + regex_match(tr.monitor_name, m->wlr_output->name))) { + + for (jk = 0; jk < LENGTH(layouts); jk++) { + if (tr.layout_name && + strcmp(layouts[jk].name, tr.layout_name) == 0) { + m->pertag->ltidxs[tr.id] = &layouts[jk]; + } + } + + m->pertag->no_hide[tr.id] = tr.no_hide; + } + } +} + void reapply_tagrule(void) { Monitor *m = NULL; - int i, jk; - char *rule_monitor_name = NULL; wl_list_for_each(m, &mons, link) { if (!m->wlr_output->enabled) { continue; } - - // apply tag rule - for (i = 1; i <= config.tag_rules_count; i++) { - rule_monitor_name = config.tag_rules[i - 1].monitor_name; - if (regex_match(rule_monitor_name, m->wlr_output->name) || - !rule_monitor_name) { - for (jk = 0; jk < LENGTH(layouts); jk++) { - if (config.tag_rules_count > 0 && - config.tag_rules[i - 1].layout_name && - strcmp(layouts[jk].name, - config.tag_rules[i - 1].layout_name) == 0) { - m->pertag->ltidxs[config.tag_rules[i - 1].id] = - &layouts[jk]; - m->pertag->no_hide[config.tag_rules[i - 1].id] = - config.tag_rules[i - 1].no_hide; - } - } - } - } + parse_tagrule(m); } } @@ -3253,6 +3266,7 @@ void reset_option(void) { set_env(); run_exec(); + reapply_cursor_style(); reapply_border(); reapply_keyboard(); reapply_pointer(); diff --git a/src/config/preset.h b/src/config/preset.h index be1c1b0a..ed743a83 100644 --- a/src/config/preset.h +++ b/src/config/preset.h @@ -33,27 +33,27 @@ 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}; // 动画曲线 /* appearance */ -unsigned int axis_bind_apply_timeout = 100; // 滚轮绑定动作的触发的时间间隔 -unsigned int focus_on_activate = 1; // 收到窗口激活请求是否自动跳转聚焦 -unsigned int new_is_master = 1; // 新窗口是否插在头部 -double default_mfact = 0.55f; // master 窗口比例 -unsigned int default_nmaster = 1; // 默认master数量 -int center_master_overspread = 0; // 中心master时是否铺满 -int center_when_single_stack = 1; // 单个stack时是否居中 +uint32_t axis_bind_apply_timeout = 100; // 滚轮绑定动作的触发的时间间隔 +uint32_t focus_on_activate = 1; // 收到窗口激活请求是否自动跳转聚焦 +uint32_t new_is_master = 1; // 新窗口是否插在头部 +double default_mfact = 0.55f; // master 窗口比例 +uint32_t default_nmaster = 1; // 默认master数量 +int center_master_overspread = 0; // 中心master时是否铺满 +int center_when_single_stack = 1; // 单个stack时是否居中 /* logging */ int log_level = WLR_ERROR; -unsigned int numlockon = 0; // 是否打开右边小键盘 -unsigned int capslock = 0; // 是否启用快捷键 +uint32_t numlockon = 0; // 是否打开右边小键盘 +uint32_t capslock = 0; // 是否启用快捷键 -unsigned int ov_tab_mode = 0; // alt tab切换模式 -unsigned int hotarea_size = 10; // 热区大小,10x10 -unsigned int enable_hotarea = 1; // 是否启用鼠标热区 -int smartgaps = 0; /* 1 means no outer gap when there is only one window */ -int sloppyfocus = 1; /* focus follows mouse */ -unsigned int gappih = 5; /* horiz inner gap between windows */ -unsigned int gappiv = 5; /* vert inner gap between windows */ -unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ -unsigned int gappov = 10; /* vert outer gap between windows and screen edge */ +uint32_t ov_tab_mode = 0; // alt tab切换模式 +uint32_t hotarea_size = 10; // 热区大小,10x10 +uint32_t enable_hotarea = 1; // 是否启用鼠标热区 +int smartgaps = 0; /* 1 means no outer gap when there is only one window */ +int sloppyfocus = 1; /* focus follows mouse */ +uint32_t gappih = 5; /* horiz inner gap between windows */ +uint32_t gappiv = 5; /* vert inner gap between windows */ +uint32_t gappoh = 10; /* horiz outer gap between windows and screen edge */ +uint32_t gappov = 10; /* vert outer gap between windows and screen edge */ float scratchpad_width_ratio = 0.8; float scratchpad_height_ratio = 0.9; @@ -73,15 +73,15 @@ int no_radius_when_single = 0; int snap_distance = 30; int enable_floating_snap = 0; int drag_tile_to_tile = 0; -unsigned int cursor_size = 24; -unsigned int cursor_hide_timeout = 0; +uint32_t cursor_size = 24; +uint32_t cursor_hide_timeout = 0; -unsigned int swipe_min_threshold = 1; +uint32_t swipe_min_threshold = 1; int inhibit_regardless_of_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ -unsigned int borderpx = 4; /* border pixel of windows */ +uint32_t borderpx = 4; /* border pixel of windows */ float rootcolor[] = COLOR(0x323232ff); float bordercolor[] = COLOR(0x444444ff); float focuscolor[] = COLOR(0xc66b25ff); @@ -103,8 +103,10 @@ int warpcursor = 1; /* Warp cursor to focused client */ 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; int allow_tearing = TEARING_DISABLED; +int allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE; /* keyboard */ @@ -164,7 +166,7 @@ LIBINPUT_CONFIG_SCROLL_EDGE LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN */ enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; -unsigned int scroll_button = 274; +uint32_t scroll_button = 274; /* You can choose between: LIBINPUT_CONFIG_CLICK_METHOD_NONE @@ -222,7 +224,7 @@ float blur_params_saturation = 1.2; int shadows = 0; int shadow_only_floating = 1; int layer_shadows = 0; -unsigned int shadows_size = 10; +uint32_t shadows_size = 10; double shadows_blur = 15; int shadows_position_x = 0; int shadows_position_y = 0; diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index b1b234bc..2be3b20c 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -1,6 +1,6 @@ int bind_to_view(const Arg *arg) { - unsigned int target = arg->ui; + uint32_t target = arg->ui; if (view_current_to_back && selmon->pertag->curtag && (target & TAGMASK) == (selmon->tagset[selmon->seltags])) { @@ -80,8 +80,12 @@ int defaultgaps(const Arg *arg) { int exchange_client(const Arg *arg) { Client *c = selmon->sel; - if (!c || c->isfloating || c->isfullscreen || c->ismaximizescreen) + if (!c || c->isfloating) return 0; + + if ((c->isfullscreen || c->ismaximizescreen) && !is_scroller_layout(c->mon)) + return 0; + exchange_two_client(c, direction_select(arg)); return 0; } @@ -126,10 +130,10 @@ int focuslast(const Arg *arg) { Client *c = NULL; Client *tc = NULL; bool begin = false; - unsigned int target = 0; + uint32_t target = 0; wl_list_for_each(c, &fstack, flink) { - if (c->iskilling || c->isminied || c->isunglobal || + if (c->iskilling || c->isminimized || c->isunglobal || !client_surface(c)->mapped || client_is_unmanaged(c) || client_is_x11_popup(c)) continue; @@ -167,7 +171,7 @@ int toggle_trackpad_enable(const Arg *arg) { } int focusmon(const Arg *arg) { - Client *c = NULL, *old_selmon_sel = NULL; + Client *c = NULL; Monitor *m = NULL; if (arg->i != UNDIR) { @@ -188,7 +192,6 @@ int focusmon(const Arg *arg) { if (!m || !m->wlr_output->enabled || m == selmon) return 0; - old_selmon_sel = selmon->sel; selmon = m; if (warpcursor) { warp_cursor_to_selmon(selmon); @@ -198,12 +201,10 @@ int focusmon(const Arg *arg) { selmon->sel = NULL; wlr_seat_pointer_notify_clear_focus(seat); wlr_seat_keyboard_notify_clear_focus(seat); + focusclient(NULL, 0); } else focusclient(c, 1); - if (old_selmon_sel) { - setborder_color(old_selmon_sel); - } return 0; } @@ -467,7 +468,7 @@ int restore_minimized(const Arg *arg) { if (selmon && selmon->sel && selmon->sel->is_in_scratchpad && selmon->sel->is_scratchpad_show) { - selmon->sel->isminied = 0; + selmon->sel->isminimized = 0; selmon->sel->is_scratchpad_show = 0; selmon->sel->is_in_scratchpad = 0; selmon->sel->isnamedscratchpad = 0; @@ -476,7 +477,7 @@ int restore_minimized(const Arg *arg) { } wl_list_for_each(c, &clients, link) { - if (c->isminied) { + if (c->isminimized && !c->isnamedscratchpad) { c->is_scratchpad_show = 0; c->is_in_scratchpad = 0; c->isnamedscratchpad = 0; @@ -497,7 +498,7 @@ int setlayout(const Arg *arg) { for (jk = 0; jk < LENGTH(layouts); jk++) { if (strcmp(layouts[jk].name, arg->v) == 0) { selmon->pertag->ltidxs[selmon->pertag->curtag] = &layouts[jk]; - + clear_fullscreen_and_maximized_state(selmon); arrange(selmon, false); printstatus(); return 0; @@ -527,7 +528,7 @@ int set_proportion(const Arg *arg) { return 0; if (selmon->sel) { - unsigned int max_client_width = + uint32_t max_client_width = selmon->w.width - 2 * scroller_structs - gappih; selmon->sel->scroller_proportion = arg->f; selmon->sel->geom.width = max_client_width * arg->f; @@ -712,14 +713,26 @@ int centerwin(const Arg *arg) { Client *c = NULL; c = selmon->sel; - if (!c || c->isfullscreen) + if (!c || c->isfullscreen || c->ismaximizescreen) return 0; - if (!c->isfloating) - setfloating(c, true); - c->float_geom = setclient_coordinate_center(c, c->geom, 0, 0); - c->iscustomsize = 1; - resize(c, c->float_geom, 1); + if (c->isfloating) { + c->float_geom = setclient_coordinate_center(c, c->geom, 0, 0); + c->iscustomsize = 1; + resize(c, c->float_geom, 1); + return 0; + } + + if (!is_scroller_layout(selmon)) + return 0; + + if (selmon->pertag->ltidxs[selmon->pertag->curtag]->id == SCROLLER) { + c->geom.x = selmon->w.x + (selmon->w.width - c->geom.width) / 2; + } else { + c->geom.y = selmon->w.y + (selmon->w.height - c->geom.height) / 2; + } + + arrange(selmon, false); return 0; } @@ -805,7 +818,7 @@ int spawn_on_empty(const Arg *arg) { return 0; } else { view(arg, true); - spawn(arg); + spawn_shell(arg); } return 0; } @@ -867,9 +880,9 @@ int switch_keyboard_layout(const Arg *arg) { xkb_layout_index_t next = (current + 1) % num_layouts; // 6. 应用新 keymap - unsigned int depressed = keyboard->modifiers.depressed; - unsigned int latched = keyboard->modifiers.latched; - unsigned int locked = keyboard->modifiers.locked; + uint32_t depressed = keyboard->modifiers.depressed; + uint32_t latched = keyboard->modifiers.latched; + uint32_t locked = keyboard->modifiers.locked; wlr_keyboard_set_keymap(keyboard, keyboard->keymap); wlr_keyboard_notify_modifiers(keyboard, depressed, latched, locked, next); @@ -904,7 +917,7 @@ int switch_layout(const Arg *arg) { int jk, ji; char *target_layout_name = NULL; - unsigned int len; + uint32_t len; if (config.circle_layout_count != 0) { for (jk = 0; jk < config.circle_layout_count; jk++) { @@ -935,7 +948,7 @@ int switch_layout(const Arg *arg) { break; } } - + clear_fullscreen_and_maximized_state(selmon); arrange(selmon, false); printstatus(); return 0; @@ -946,6 +959,7 @@ int switch_layout(const Arg *arg) { selmon->pertag->ltidxs[selmon->pertag->curtag]->name) == 0) { selmon->pertag->ltidxs[selmon->pertag->curtag] = jk == LENGTH(layouts) - 1 ? &layouts[0] : &layouts[jk + 1]; + clear_fullscreen_and_maximized_state(selmon); arrange(selmon, false); printstatus(); return 0; @@ -988,7 +1002,7 @@ int switch_proportion_preset(const Arg *arg) { target_proportion = config.scroller_proportion_preset[0]; } - unsigned int max_client_width = + uint32_t max_client_width = selmon->w.width - 2 * scroller_structs - gappih; selmon->sel->scroller_proportion = target_proportion; selmon->sel->geom.width = max_client_width * target_proportion; @@ -1005,7 +1019,7 @@ int tag(const Arg *arg) { } int tagmon(const Arg *arg) { - Monitor *m = NULL; + Monitor *m = NULL, *cm = NULL; Client *c = focustop(selmon); if (!c) @@ -1014,11 +1028,12 @@ int tagmon(const Arg *arg) { if (arg->i != UNDIR) { m = dirtomon(arg->i); } else if (arg->v) { - wl_list_for_each(m, &mons, link) { - if (!m->wlr_output->enabled) { + wl_list_for_each(cm, &mons, link) { + if (!cm->wlr_output->enabled) { continue; } - if (regex_match(arg->v, m->wlr_output->name)) { + if (regex_match(arg->v, cm->wlr_output->name)) { + m = cm; break; } } @@ -1029,8 +1044,8 @@ int tagmon(const Arg *arg) { if (!m || !m->wlr_output->enabled) return 0; - unsigned int newtags = arg->ui ? arg->ui : arg->i2 ? c->tags : 0; - unsigned int target; + uint32_t newtags = arg->ui ? arg->ui : arg->i2 ? c->tags : 0; + uint32_t target; if (c->mon == m) { view(&(Arg){.ui = newtags}, true); @@ -1121,7 +1136,7 @@ int toggle_named_scratchpad(const Arg *arg) { if (!target_client && arg->v3) { Arg arg_spawn = {.v = arg->v3}; - spawn(&arg_spawn); + spawn_shell(&arg_spawn); return 0; } @@ -1150,7 +1165,7 @@ int toggle_scratchpad(const Arg *arg) { continue; } - if (single_scratchpad && c->isnamedscratchpad && !c->isminied) { + if (single_scratchpad && c->isnamedscratchpad && !c->isminimized) { set_minimized(c); continue; } @@ -1270,7 +1285,7 @@ int toggleoverlay(const Arg *arg) { } int toggletag(const Arg *arg) { - unsigned int newtags; + uint32_t newtags; Client *sel = focustop(selmon); if (!sel) return 0; @@ -1293,8 +1308,8 @@ int toggletag(const Arg *arg) { } int toggleview(const Arg *arg) { - unsigned int newtagset; - unsigned int target; + uint32_t newtagset; + uint32_t target; target = arg->ui == 0 ? ~0 & TAGMASK : arg->ui; @@ -1311,7 +1326,7 @@ int toggleview(const Arg *arg) { } int viewtoleft(const Arg *arg) { - unsigned int target = selmon->tagset[selmon->seltags]; + uint32_t target = selmon->tagset[selmon->seltags]; if (selmon->isoverview || selmon->pertag->curtag == 0) { return 0; @@ -1334,7 +1349,7 @@ int viewtoright(const Arg *arg) { if (selmon->isoverview || selmon->pertag->curtag == 0) { return 0; } - unsigned int target = selmon->tagset[selmon->seltags]; + uint32_t target = selmon->tagset[selmon->seltags]; target <<= 1; if (!selmon || (target) == selmon->tagset[selmon->seltags]) @@ -1348,9 +1363,8 @@ int viewtoright(const Arg *arg) { } int viewtoleft_have_client(const Arg *arg) { - unsigned int n; - unsigned int current = - get_tags_first_tag_num(selmon->tagset[selmon->seltags]); + uint32_t n; + uint32_t current = get_tags_first_tag_num(selmon->tagset[selmon->seltags]); bool found = false; if (selmon->isoverview) { @@ -1373,9 +1387,8 @@ int viewtoleft_have_client(const Arg *arg) { } int viewtoright_have_client(const Arg *arg) { - unsigned int n; - unsigned int current = - get_tags_first_tag_num(selmon->tagset[selmon->seltags]); + uint32_t n; + uint32_t current = get_tags_first_tag_num(selmon->tagset[selmon->seltags]); bool found = false; if (selmon->isoverview) { @@ -1412,7 +1425,7 @@ int tagcrossmon(const Arg *arg) { } int comboview(const Arg *arg) { - unsigned int newtags = arg->ui & TAGMASK; + uint32_t newtags = arg->ui & TAGMASK; if (!newtags || !selmon) return 0; @@ -1475,7 +1488,7 @@ int minimized(const Arg *arg) { if (selmon && selmon->isoverview) return 0; - if (selmon->sel && !selmon->sel->isminied) { + if (selmon->sel && !selmon->sel->isminimized) { set_minimized(selmon->sel); } return 0; @@ -1490,14 +1503,14 @@ int toggleoverview(const Arg *arg) { } selmon->isoverview ^= 1; - unsigned int target; - unsigned int visible_client_number = 0; + uint32_t target; + uint32_t visible_client_number = 0; if (selmon->isoverview) { wl_list_for_each(c, &clients, link) if (c && c->mon == selmon && !client_is_unmanaged(c) && !client_is_x11_popup(c) && - !c->isminied && + !c->isminimized && !c->isunglobal) { visible_client_number++; } diff --git a/src/ext-protocol/dwl-ipc.h b/src/ext-protocol/dwl-ipc.h index 6b0c4c54..eda3f49f 100644 --- a/src/ext-protocol/dwl-ipc.h +++ b/src/ext-protocol/dwl-ipc.h @@ -1,12 +1,11 @@ #include "dwl-ipc-unstable-v2-protocol.h" static void dwl_ipc_manager_bind(struct wl_client *client, void *data, - unsigned int version, unsigned int id); + uint32_t version, uint32_t id); static void dwl_ipc_manager_destroy(struct wl_resource *resource); static void dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, - unsigned int id, - struct wl_resource *output); + uint32_t id, struct wl_resource *output); static void dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource); static void dwl_ipc_output_destroy(struct wl_resource *resource); @@ -14,15 +13,14 @@ static void dwl_ipc_output_printstatus(Monitor *monitor); static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output); static void dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, - unsigned int and_tags, - unsigned int xor_tags); + uint32_t and_tags, + uint32_t xor_tags); static void dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, - unsigned int index); + uint32_t index); static void dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, - unsigned int tagmask, - unsigned int toggle_tagset); + uint32_t tagmask, uint32_t toggle_tagset); static void dwl_ipc_output_quit(struct wl_client *client, struct wl_resource *resource); static void dwl_ipc_output_dispatch(struct wl_client *client, @@ -46,7 +44,7 @@ static struct zdwl_ipc_output_v2_interface dwl_output_implementation = { .set_client_tags = dwl_ipc_output_set_client_tags}; void dwl_ipc_manager_bind(struct wl_client *client, void *data, - unsigned int version, unsigned int id) { + uint32_t version, uint32_t id) { struct wl_resource *manager_resource = wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id); if (!manager_resource) { @@ -59,7 +57,7 @@ void dwl_ipc_manager_bind(struct wl_client *client, void *data, zdwl_ipc_manager_v2_send_tags(manager_resource, LENGTH(tags)); - for (unsigned int i = 0; i < LENGTH(layouts); i++) + for (uint32_t i = 0; i < LENGTH(layouts); i++) zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol); } @@ -68,7 +66,7 @@ void dwl_ipc_manager_destroy(struct wl_resource *resource) { } void dwl_ipc_manager_get_output(struct wl_client *client, - struct wl_resource *resource, unsigned int id, + struct wl_resource *resource, uint32_t id, struct wl_resource *output) { DwlIpcOutput *ipc_output; struct wlr_output *op = wlr_output_from_resource(output); @@ -101,12 +99,14 @@ static void dwl_ipc_output_destroy(struct wl_resource *resource) { free(ipc_output); } +// 修改IPC输出函数,接受掩码参数 void dwl_ipc_output_printstatus(Monitor *monitor) { DwlIpcOutput *ipc_output; wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link) dwl_ipc_output_printstatus_to(ipc_output); } +// 修改主IPC输出函数,根据掩码发送相应事件 void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) { Monitor *monitor = ipc_output->mon; Client *c = NULL, *focused = NULL; @@ -216,12 +216,11 @@ void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) { void dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, - unsigned int and_tags, - unsigned int xor_tags) { + uint32_t and_tags, uint32_t xor_tags) { DwlIpcOutput *ipc_output; Monitor *monitor = NULL; Client *selected_client = NULL; - unsigned int newtags = 0; + uint32_t newtags = 0; ipc_output = wl_resource_get_user_data(resource); if (!ipc_output) @@ -244,8 +243,7 @@ void dwl_ipc_output_set_client_tags(struct wl_client *client, } void dwl_ipc_output_set_layout(struct wl_client *client, - struct wl_resource *resource, - unsigned int index) { + struct wl_resource *resource, uint32_t index) { DwlIpcOutput *ipc_output; Monitor *monitor = NULL; @@ -258,16 +256,17 @@ void dwl_ipc_output_set_layout(struct wl_client *client, index = 0; monitor->pertag->ltidxs[monitor->pertag->curtag] = &layouts[index]; + clear_fullscreen_and_maximized_state(monitor); arrange(monitor, false); printstatus(); } void dwl_ipc_output_set_tags(struct wl_client *client, - struct wl_resource *resource, unsigned int tagmask, - unsigned int toggle_tagset) { + struct wl_resource *resource, uint32_t tagmask, + uint32_t toggle_tagset) { DwlIpcOutput *ipc_output; Monitor *monitor = NULL; - unsigned int newtags = tagmask & TAGMASK; + uint32_t newtags = tagmask & TAGMASK; ipc_output = wl_resource_get_user_data(resource); if (!ipc_output) diff --git a/src/ext-protocol/ext-workspace.h b/src/ext-protocol/ext-workspace.h index 930e6c98..d4e0e514 100644 --- a/src/ext-protocol/ext-workspace.h +++ b/src/ext-protocol/ext-workspace.h @@ -8,7 +8,7 @@ typedef struct Monitor Monitor; struct workspace { struct wl_list link; // Link in global workspaces list - unsigned int tag; // Numeric identifier (1-9, 0=overview) + uint32_t tag; // Numeric identifier (1-9, 0=overview) Monitor *m; // Associated monitor struct wlr_ext_workspace_handle_v1 *ext_workspace; // Protocol object /* Event listeners */ @@ -22,7 +22,7 @@ struct wlr_ext_workspace_manager_v1 *ext_manager; struct wl_list workspaces; void goto_workspace(struct workspace *target) { - unsigned int tag; + uint32_t tag; tag = 1 << (target->tag - 1); if (target->tag == 0) { toggleoverview(&(Arg){.i = -1}); @@ -33,7 +33,7 @@ void goto_workspace(struct workspace *target) { } void toggle_workspace(struct workspace *target) { - unsigned int tag; + uint32_t tag; tag = 1 << (target->tag - 1); if (target->tag == 0) { toggleview(&(Arg){.i = -1}); @@ -69,7 +69,7 @@ static void handle_ext_workspace_deactivate(struct wl_listener *listener, wlr_log(WLR_INFO, "ext deactivating workspace %d", workspace->tag); } -static const char *get_name_from_tag(unsigned int tag) { +static const char *get_name_from_tag(uint32_t tag) { static const char *names[] = {"overview", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; 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(unsigned int tag, Monitor *m) { +static void remove_workspace_by_tag(uint32_t tag, Monitor *m) { struct workspace *workspace, *tmp; wl_list_for_each_safe(workspace, tmp, &workspaces, link) { if (workspace->tag == tag && workspace->m == m) { @@ -127,7 +127,7 @@ static void add_workspace_by_tag(int tag, Monitor *m) { void dwl_ext_workspace_printstatus(Monitor *m) { struct workspace *w; - unsigned int tag_status = 0; + uint32_t tag_status = 0; wl_list_for_each(w, &workspaces, link) { if (w && w->m == m) { diff --git a/src/ext-protocol/foreign-toplevel.h b/src/ext-protocol/foreign-toplevel.h index adfcd21b..3b819485 100644 --- a/src/ext-protocol/foreign-toplevel.h +++ b/src/ext-protocol/foreign-toplevel.h @@ -4,17 +4,17 @@ static struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager; void handle_foreign_activate_request(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, foreign_activate_request); - unsigned int target; + uint32_t target; if (c && c->swallowing) return; - if (c && !c->isminied && c == selmon->sel) { + if (c && !c->isminimized && c == selmon->sel) { set_minimized(c); return; } - if (c->isminied) { + if (c->isminimized) { c->is_in_scratchpad = 0; c->isnamedscratchpad = 0; c->is_scratchpad_show = 0; diff --git a/src/fetch/client.h b/src/fetch/client.h index 6e675223..0bc84881 100644 --- a/src/fetch/client.h +++ b/src/fetch/client.h @@ -41,10 +41,21 @@ Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) { continue; } - if (!(appid = client_get_appid(c))) + if (c->swallowedby) { + appid = client_get_appid(c->swallowedby); + title = client_get_title(c->swallowedby); + } else { + appid = client_get_appid(c); + title = client_get_title(c); + } + + if (!appid) { appid = broken; - if (!(title = client_get_title(c))) + } + + if (!title) { title = broken; + } if (arg_id && strncmp(arg_id, "none", 4) == 0) arg_id = NULL; @@ -70,7 +81,7 @@ setclient_coordinate_center(Client *c, struct wlr_box geom, int offsetx, int len = 0; Monitor *m = c->mon ? c->mon : selmon; - unsigned int cbw = check_hit_no_border(c) ? c->bw : 0; + uint32_t cbw = check_hit_no_border(c) ? c->bw : 0; if (!c->no_force_center) { tempbox.x = m->w.x + (m->w.width - geom.width) / 2; @@ -128,8 +139,9 @@ Client *center_tiled_select(Monitor *m) { int dirx, diry; long int distance; wl_list_for_each(c, &clients, link) { - if (c && VISIBLEON(c, m) && ISTILED(c) && client_surface(c)->mapped && - !c->isfloating && !client_is_unmanaged(c)) { + if (c && VISIBLEON(c, m) && ISSCROLLTILED(c) && + client_surface(c)->mapped && !c->isfloating && + !client_is_unmanaged(c)) { dirx = c->geom.x + c->geom.width / 2 - (m->w.x + m->w.width / 2); diry = c->geom.y + c->geom.height / 2 - (m->w.y + m->w.height / 2); distance = dirx * dirx + diry * diry; @@ -142,7 +154,7 @@ Client *center_tiled_select(Monitor *m) { return target_c; } Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, - bool align) { + bool ignore_align) { Client *c = NULL; Client **tempClients = NULL; // 初始化为 NULL int last = -1; @@ -181,25 +193,29 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, int sel_x = tc->geom.x; int sel_y = tc->geom.y; long long int distance = LLONG_MAX; + long long int same_monitor_distance = LLONG_MAX; Client *tempFocusClients = NULL; + Client *tempSameMonitorFocusClients = NULL; switch (arg->i) { case UP: - for (int _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.y < sel_y && - tempClients[_i]->geom.x == sel_x && - tempClients[_i]->mon == tc->mon) { - int dis_x = tempClients[_i]->geom.x - sel_x; - int dis_y = tempClients[_i]->geom.y - sel_y; - long long int tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; + if (!ignore_align) { + for (int _i = 0; _i <= last; _i++) { + if (tempClients[_i]->geom.y < sel_y && + tempClients[_i]->geom.x == sel_x && + tempClients[_i]->mon == tc->mon) { + int dis_x = tempClients[_i]->geom.x - sel_x; + int dis_y = tempClients[_i]->geom.y - sel_y; + long long int tmp_distance = + dis_x * dis_x + dis_y * dis_y; // 计算距离 + if (tmp_distance < distance) { + distance = tmp_distance; + tempFocusClients = tempClients[_i]; + } } } } - if (!tempFocusClients && !align) { + if (!tempFocusClients) { for (int _i = 0; _i <= last; _i++) { if (tempClients[_i]->geom.y < sel_y) { int dis_x = tempClients[_i]->geom.x - sel_x; @@ -210,26 +226,33 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, distance = tmp_distance; tempFocusClients = tempClients[_i]; } + if (tempClients[_i]->mon == tc->mon && + tmp_distance < same_monitor_distance) { + same_monitor_distance = tmp_distance; + tempSameMonitorFocusClients = tempClients[_i]; + } } } } break; case DOWN: - for (int _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.y > sel_y && - tempClients[_i]->geom.x == sel_x && - tempClients[_i]->mon == tc->mon) { - int dis_x = tempClients[_i]->geom.x - sel_x; - int dis_y = tempClients[_i]->geom.y - sel_y; - long long int tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; + if (!ignore_align) { + for (int _i = 0; _i <= last; _i++) { + if (tempClients[_i]->geom.y > sel_y && + tempClients[_i]->geom.x == sel_x && + tempClients[_i]->mon == tc->mon) { + int dis_x = tempClients[_i]->geom.x - sel_x; + int dis_y = tempClients[_i]->geom.y - sel_y; + long long int tmp_distance = + dis_x * dis_x + dis_y * dis_y; // 计算距离 + if (tmp_distance < distance) { + distance = tmp_distance; + tempFocusClients = tempClients[_i]; + } } } } - if (!tempFocusClients && !align) { + if (!tempFocusClients) { for (int _i = 0; _i <= last; _i++) { if (tempClients[_i]->geom.y > sel_y) { int dis_x = tempClients[_i]->geom.x - sel_x; @@ -240,26 +263,33 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, distance = tmp_distance; tempFocusClients = tempClients[_i]; } + if (tempClients[_i]->mon == tc->mon && + tmp_distance < same_monitor_distance) { + same_monitor_distance = tmp_distance; + tempSameMonitorFocusClients = tempClients[_i]; + } } } } break; case LEFT: - for (int _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x < sel_x && - tempClients[_i]->geom.y == sel_y && - tempClients[_i]->mon == tc->mon) { - int dis_x = tempClients[_i]->geom.x - sel_x; - int dis_y = tempClients[_i]->geom.y - sel_y; - long long int tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; + if (!ignore_align) { + for (int _i = 0; _i <= last; _i++) { + if (tempClients[_i]->geom.x < sel_x && + tempClients[_i]->geom.y == sel_y && + tempClients[_i]->mon == tc->mon) { + int dis_x = tempClients[_i]->geom.x - sel_x; + int dis_y = tempClients[_i]->geom.y - sel_y; + long long int tmp_distance = + dis_x * dis_x + dis_y * dis_y; // 计算距离 + if (tmp_distance < distance) { + distance = tmp_distance; + tempFocusClients = tempClients[_i]; + } } } } - if (!tempFocusClients && !align) { + if (!tempFocusClients) { for (int _i = 0; _i <= last; _i++) { if (tempClients[_i]->geom.x < sel_x) { int dis_x = tempClients[_i]->geom.x - sel_x; @@ -270,28 +300,21 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, distance = tmp_distance; tempFocusClients = tempClients[_i]; } + if (tempClients[_i]->mon == tc->mon && + tmp_distance < same_monitor_distance) { + same_monitor_distance = tmp_distance; + tempSameMonitorFocusClients = tempClients[_i]; + } } } } break; case RIGHT: - for (int _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x > sel_x && - tempClients[_i]->geom.y == sel_y && - tempClients[_i]->mon == tc->mon) { - int dis_x = tempClients[_i]->geom.x - sel_x; - int dis_y = tempClients[_i]->geom.y - sel_y; - long long int tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - } - } - if (!tempFocusClients && !align) { + if (!ignore_align) { for (int _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x > sel_x) { + if (tempClients[_i]->geom.x > sel_x && + tempClients[_i]->geom.y == sel_y && + tempClients[_i]->mon == tc->mon) { int dis_x = tempClients[_i]->geom.x - sel_x; int dis_y = tempClients[_i]->geom.y - sel_y; long long int tmp_distance = @@ -303,11 +326,34 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, } } } + if (!tempFocusClients) { + for (int _i = 0; _i <= last; _i++) { + if (tempClients[_i]->geom.x > sel_x) { + int dis_x = tempClients[_i]->geom.x - sel_x; + int dis_y = tempClients[_i]->geom.y - sel_y; + long long int tmp_distance = + dis_x * dis_x + dis_y * dis_y; // 计算距离 + if (tmp_distance < distance) { + distance = tmp_distance; + tempFocusClients = tempClients[_i]; + } + if (tempClients[_i]->mon == tc->mon && + tmp_distance < same_monitor_distance) { + same_monitor_distance = tmp_distance; + tempSameMonitorFocusClients = tempClients[_i]; + } + } + } + } break; } free(tempClients); // 释放内存 - return tempFocusClients; + if (tempSameMonitorFocusClients) { + return tempSameMonitorFocusClients; + } else { + return tempFocusClients; + } } Client *direction_select(const Arg *arg) { @@ -317,12 +363,13 @@ Client *direction_select(const Arg *arg) { if (!tc) return NULL; - if (tc && (tc->isfullscreen || tc->ismaximizescreen)) { - // 不支持全屏窗口的焦点切换 + if (tc && (tc->isfullscreen || tc->ismaximizescreen) && + (!is_scroller_layout(selmon) || tc->isfloating)) { return NULL; } - return find_client_by_direction(tc, arg, true, false); + return find_client_by_direction( + tc, arg, true, is_scroller_layout(selmon) && !selmon->isoverview); } /* We probably should change the name of this, it sounds like @@ -374,7 +421,10 @@ Client *get_next_stack_client(Client *c, bool reverse) { } float *get_border_color(Client *c) { - if (c->isurgent) { + + if (c->mon != selmon) { + return bordercolor; + } else if (c->isurgent) { return urgentcolor; } else if (c->is_in_scratchpad && selmon && c == selmon->sel) { return scratchpadcolor; diff --git a/src/fetch/common.h b/src/fetch/common.h index 33d7272f..c96ee31b 100644 --- a/src/fetch/common.h +++ b/src/fetch/common.h @@ -1,5 +1,5 @@ pid_t getparentprocess(pid_t p) { - unsigned int v = 0; + uint32_t v = 0; FILE *f; char buf[256]; @@ -26,24 +26,6 @@ int isdescprocess(pid_t p, pid_t c) { return (int)c; } -char *get_autostart_path(char *autostart_path, unsigned int buf_size) { - const char *mangoconfig = getenv("MANGOCONFIG"); - - if (mangoconfig && mangoconfig[0] != '\0') { - snprintf(autostart_path, buf_size, "%s/autostart.sh", mangoconfig); - } else { - const char *homedir = getenv("HOME"); - if (!homedir) { - fprintf(stderr, "Error: HOME environment variable not set.\n"); - return NULL; - } - snprintf(autostart_path, buf_size, "%s/.config/mango/autostart.sh", - homedir); - } - - return autostart_path; -} - void get_layout_abbr(char *abbr, const char *full_name) { // 清空输出缓冲区 abbr[0] = '\0'; @@ -60,10 +42,10 @@ void get_layout_abbr(char *abbr, const char *full_name) { const char *open = strrchr(full_name, '('); const char *close = strrchr(full_name, ')'); if (open && close && close > open) { - unsigned int len = close - open - 1; + uint32_t len = close - open - 1; if (len > 0 && len <= 4) { // 提取并转换为小写 - for (unsigned int j = 0; j < len; j++) { + for (uint32_t j = 0; j < len; j++) { abbr[j] = tolower(open[j + 1]); } abbr[len] = '\0'; @@ -72,8 +54,8 @@ void get_layout_abbr(char *abbr, const char *full_name) { } // 3. 提取前2-3个字母并转换为小写 - unsigned int j = 0; - for (unsigned int i = 0; full_name[i] != '\0' && j < 3; i++) { + uint32_t j = 0; + for (uint32_t i = 0; full_name[i] != '\0' && j < 3; i++) { if (isalpha(full_name[i])) { abbr[j++] = tolower(full_name[i]); } @@ -115,6 +97,10 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, surface = wlr_scene_surface_try_from_buffer( wlr_scene_buffer_from_node(node)) ->surface; + else if (node->type == WLR_SCENE_NODE_RECT) { + surface = NULL; + break; + } /* start from the topmost layer, find a sureface that can be focused by pointer, diff --git a/src/fetch/monitor.h b/src/fetch/monitor.h index d55e9ab6..47a5b824 100644 --- a/src/fetch/monitor.h +++ b/src/fetch/monitor.h @@ -26,9 +26,9 @@ bool is_scroller_layout(Monitor *m) { return false; } -unsigned int get_tag_status(unsigned int tag, Monitor *m) { +uint32_t get_tag_status(uint32_t tag, Monitor *m) { Client *c = NULL; - unsigned int status = 0; + uint32_t status = 0; wl_list_for_each(c, &clients, link) { if (c->mon == m && c->tags & 1 << (tag - 1) & TAGMASK) { if (c->isurgent) { @@ -41,8 +41,8 @@ unsigned int get_tag_status(unsigned int tag, Monitor *m) { return status; } -unsigned int get_tags_first_tag_num(unsigned int source_tags) { - unsigned int i, tag; +uint32_t get_tags_first_tag_num(uint32_t source_tags) { + uint32_t i, tag; tag = 0; if (!source_tags) { @@ -63,8 +63,8 @@ unsigned int get_tags_first_tag_num(unsigned int source_tags) { } // 获取tags中最前面的tag的tagmask -unsigned int get_tags_first_tag(unsigned int source_tags) { - unsigned int i, tag; +uint32_t get_tags_first_tag(uint32_t source_tags) { + uint32_t i, tag; tag = 0; if (!source_tags) { diff --git a/src/layout/arrange.h b/src/layout/arrange.h index aafb79e0..7a1d6205 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -19,7 +19,7 @@ void set_size_per(Monitor *m, Client *c) { } void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx, - int offsety, unsigned int time, int type) { + int offsety, uint32_t time, int type) { Client *tc = NULL; float delta_x, delta_y; Client *next = NULL; @@ -213,7 +213,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx, } void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx, - int offsety, unsigned int time, int type) { + int offsety, uint32_t time, int type) { Client *tc = NULL; float delta_x, delta_y; Client *next = NULL; @@ -370,7 +370,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx, } void resize_tile_scroller(Client *grabc, bool isdrag, int offsetx, int offsety, - unsigned int time, bool isvertical) { + uint32_t time, bool isvertical) { float delta_x, delta_y; float new_scroller_proportion; @@ -474,7 +474,7 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int offsetx, int offsety, } void resize_tile_client(Client *grabc, bool isdrag, int offsetx, int offsety, - unsigned int time) { + uint32_t time) { if (!grabc || grabc->isfullscreen || grabc->ismaximizescreen) return; @@ -509,24 +509,22 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num, int stack_num) { Client *c = NULL; int i = 0; - unsigned int stack_index = 0; - unsigned int nmasters = m->pertag->nmasters[m->pertag->curtag]; + 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, &clients, link) { if (VISIBLEON(c, m) && ISTILED(c)) { - - if (total_master_inner_percent <= 0.0) - return; - if (i < m->pertag->nmasters[m->pertag->curtag]) { + 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->master_inner_per = c->master_inner_per / total_master_inner_percent; } else { c->ismaster = false; - c->master_inner_per = 1.0f / master_num; + c->master_inner_per = + master_num > 0 ? 1.0f / master_num : 1.0f; c->stack_innder_per = total_stack_hight_percent ? c->stack_innder_per / total_stack_hight_percent @@ -538,10 +536,7 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num, } else { wl_list_for_each(c, &clients, link) { if (VISIBLEON(c, m) && ISTILED(c)) { - - if (total_master_inner_percent <= 0.0) - return; - if (i < m->pertag->nmasters[m->pertag->curtag]) { + 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 = @@ -558,7 +553,8 @@ void reset_size_per_mon(Monitor *m, int tile_cilent_num, stack_index = i - nmasters; c->ismaster = false; - c->master_inner_per = 1.0f / master_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 = total_right_stack_hight_percent @@ -599,6 +595,7 @@ arrange(Monitor *m, bool want_animation) { return; 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) { @@ -619,6 +616,10 @@ arrange(Monitor *m, bool want_animation) { if (ISTILED(c)) { m->visible_tiling_clients++; } + + if (ISSCROLLTILED(c)) { + m->visible_scroll_tiling_clients++; + } } } @@ -632,7 +633,7 @@ arrange(Monitor *m, bool want_animation) { if (VISIBLEON(c, m)) { if (ISTILED(c)) { - if (i < m->pertag->nmasters[m->pertag->curtag]) { + if (i < nmasters) { master_num++; total_master_inner_percent += c->master_inner_per; } else { diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h index 178ae9e0..c036cfbe 100644 --- a/src/layout/horizontal.h +++ b/src/layout/horizontal.h @@ -1,9 +1,9 @@ // 网格布局窗口大小和位置计算 void grid(Monitor *m) { - unsigned int i, n; - unsigned int cx, cy, cw, ch; - unsigned int dx; - unsigned int cols, rows, overcols; + uint32_t i, n; + uint32_t cx, cy, cw, ch; + uint32_t dx; + uint32_t cols, rows, overcols; Client *c = NULL; n = 0; int target_gappo = enablegaps ? m->isoverview ? overviewgappo : gappoh : 0; @@ -23,10 +23,6 @@ void grid(Monitor *m) { if (c->mon != m) continue; - c->bw = m->visible_tiling_clients == 1 && no_border_when_single && - smartgaps - ? 0 - : borderpx; if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { cw = (m->w.width - 2 * target_gappo) * single_width_ratio; @@ -49,10 +45,6 @@ void grid(Monitor *m) { if (c->mon != m) continue; - c->bw = m->visible_tiling_clients == 1 && no_border_when_single && - smartgaps - ? 0 - : borderpx; if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { if (i == 0) { @@ -99,10 +91,7 @@ void grid(Monitor *m) { if (c->mon != m) continue; - c->bw = - m->visible_tiling_clients == 1 && no_border_when_single && smartgaps - ? 0 - : borderpx; + if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { cx = m->w.x + (i % cols) * (cw + target_gappi); @@ -121,15 +110,15 @@ void grid(Monitor *m) { } void deck(Monitor *m) { - unsigned int mw, my; + uint32_t mw, my; int i, n = 0; Client *c = NULL; Client *fc = NULL; float mfact; - unsigned int cur_gappih = enablegaps ? m->gappih : 0; - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; - unsigned int cur_gappov = enablegaps ? m->gappov : 0; + uint32_t cur_gappih = enablegaps ? m->gappih : 0; + uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; + uint32_t cur_gappov = enablegaps ? m->gappov : 0; cur_gappih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih; cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh; @@ -189,27 +178,62 @@ void deck(Monitor *m) { } } +void horizontal_scroll_adjust_fullandmax(Client *c, + struct wlr_box *target_geom) { + Monitor *m = c->mon; + uint32_t cur_gappih = enablegaps ? m->gappih : 0; + uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; + uint32_t cur_gappov = enablegaps ? m->gappov : 0; + + cur_gappih = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappih; + cur_gappoh = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappoh; + cur_gappov = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappov; + + if (c->isfullscreen) { + target_geom->height = m->m.height; + target_geom->width = m->m.width; + target_geom->y = m->m.y; + return; + } + + if (c->ismaximizescreen) { + target_geom->height = m->w.height - 2 * cur_gappov; + target_geom->width = m->w.width - 2 * cur_gappoh; + target_geom->y = m->w.y + cur_gappov; + return; + } + + target_geom->height = m->w.height - 2 * cur_gappov; + target_geom->y = m->w.y + (m->w.height - target_geom->height) / 2; +} + // 滚动布局 void scroller(Monitor *m) { - unsigned int i, n, j; + uint32_t i, n, j; + float single_proportion = 1.0; Client *c = NULL, *root_client = NULL; Client **tempClients = NULL; // 初始化为 NULL struct wlr_box target_geom; int focus_client_index = 0; bool need_scroller = false; - unsigned int cur_gappih = enablegaps ? m->gappih : 0; - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; - unsigned int cur_gappov = enablegaps ? m->gappov : 0; + uint32_t cur_gappih = enablegaps ? m->gappih : 0; + uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; + uint32_t cur_gappov = enablegaps ? m->gappov : 0; - cur_gappih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih; - cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh; - cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov; + cur_gappih = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappih; + cur_gappoh = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappoh; + cur_gappov = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappov; - unsigned int max_client_width = - m->w.width - 2 * scroller_structs - cur_gappih; + uint32_t max_client_width = m->w.width - 2 * scroller_structs - cur_gappih; - n = m->visible_tiling_clients; + n = m->visible_scroll_tiling_clients; if (n == 0) { return; // 没有需要处理的客户端,直接返回 @@ -225,17 +249,22 @@ void scroller(Monitor *m) { // 第二次遍历,填充 tempClients j = 0; wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, m) && ISTILED(c)) { + if (VISIBLEON(c, m) && ISSCROLLTILED(c)) { tempClients[j] = c; j++; } } - if (n == 1 && !scroller_ignore_proportion_single) { + if (n == 1 && !scroller_ignore_proportion_single && + !tempClients[0]->isfullscreen && !tempClients[0]->ismaximizescreen) { c = tempClients[0]; + + single_proportion = c->scroller_proportion_single > 0.0f + ? c->scroller_proportion_single + : scroller_default_proportion_single; + target_geom.height = m->w.height - 2 * cur_gappov; - target_geom.width = - (m->w.width - 2 * cur_gappoh) * scroller_default_proportion_single; + target_geom.width = (m->w.width - 2 * cur_gappoh) * single_proportion; target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; resize(c, target_geom, 0); @@ -243,11 +272,10 @@ void scroller(Monitor *m) { return; } - if (m->sel && !client_is_unmanaged(m->sel) && !m->sel->isfloating && - !m->sel->ismaximizescreen && !m->sel->isfullscreen) { + if (m->sel && !client_is_unmanaged(m->sel) && ISSCROLLTILED(m->sel)) { root_client = m->sel; - } else if (m->prevsel && ISTILED(m->prevsel) && VISIBLEON(m->prevsel, m) && - !client_is_unmanaged(m->prevsel)) { + } else if (m->prevsel && ISSCROLLTILED(m->prevsel) && + VISIBLEON(m->prevsel, m) && !client_is_unmanaged(m->prevsel)) { root_client = m->prevsel; } else { root_client = center_tiled_select(m); @@ -261,8 +289,7 @@ void scroller(Monitor *m) { for (i = 0; i < n; i++) { c = tempClients[i]; if (root_client == c) { - if (!c->is_pending_open_animation && - c->geom.x >= m->w.x + scroller_structs && + if (c->geom.x >= m->w.x + scroller_structs && c->geom.x + c->geom.width <= m->w.x + m->w.width - scroller_structs) { need_scroller = false; @@ -284,11 +311,18 @@ void scroller(Monitor *m) { target_geom.height = m->w.height - 2 * cur_gappov; target_geom.width = max_client_width * c->scroller_proportion; target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; - - if (need_scroller) { + horizontal_scroll_adjust_fullandmax(tempClients[focus_client_index], + &target_geom); + if (tempClients[focus_client_index]->isfullscreen) { + target_geom.x = m->m.x; + resize(tempClients[focus_client_index], target_geom, 0); + } else if (tempClients[focus_client_index]->ismaximizescreen) { + target_geom.x = m->w.x + cur_gappoh; + resize(tempClients[focus_client_index], target_geom, 0); + } else if (need_scroller) { if (scroller_focus_center || ((!m->prevsel || - (ISTILED(m->prevsel) && + (ISSCROLLTILED(m->prevsel) && (m->prevsel->scroller_proportion * max_client_width) + (root_client->scroller_proportion * max_client_width) > m->w.width - 2 * scroller_structs - cur_gappih)) && @@ -311,14 +345,17 @@ void scroller(Monitor *m) { for (i = 1; i <= focus_client_index; i++) { c = tempClients[focus_client_index - i]; target_geom.width = max_client_width * c->scroller_proportion; + horizontal_scroll_adjust_fullandmax(c, &target_geom); target_geom.x = tempClients[focus_client_index - i + 1]->geom.x - cur_gappih - target_geom.width; + resize(c, target_geom, 0); } for (i = 1; i < n - focus_client_index; i++) { c = tempClients[focus_client_index + i]; target_geom.width = max_client_width * c->scroller_proportion; + horizontal_scroll_adjust_fullandmax(c, &target_geom); target_geom.x = tempClients[focus_client_index + i - 1]->geom.x + cur_gappih + tempClients[focus_client_index + i - 1]->geom.width; @@ -329,7 +366,7 @@ void scroller(Monitor *m) { } void center_tile(Monitor *m) { - unsigned int i, n = 0, h, r, ie = enablegaps, mw, mx, my, oty, ety, tw; + uint32_t i, n = 0, h, r, ie = enablegaps, mw, mx, my, oty, ety, tw; Client *c = NULL; Client *fc = NULL; double mfact = 0; @@ -338,6 +375,8 @@ void center_tile(Monitor *m) { n = m->visible_tiling_clients; master_num = m->pertag->nmasters[m->pertag->curtag]; + master_num = n > master_num ? master_num : n; + stack_num = n - master_num; if (n == 0) @@ -350,10 +389,10 @@ void center_tile(Monitor *m) { } // 间隙参数处理 - unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; // 内部垂直间隙 - unsigned int cur_gappih = enablegaps ? m->gappih : 0; // 内部水平间隙 - unsigned int cur_gappov = enablegaps ? m->gappov : 0; // 外部垂直间隙 - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; // 外部水平间隙 + uint32_t cur_gappiv = enablegaps ? m->gappiv : 0; // 内部垂直间隙 + uint32_t cur_gappih = enablegaps ? m->gappih : 0; // 内部水平间隙 + uint32_t cur_gappov = enablegaps ? m->gappov : 0; // 外部垂直间隙 + uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; // 外部水平间隙 // 智能间隙处理 cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv; @@ -361,7 +400,7 @@ void center_tile(Monitor *m) { cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov; cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh; - unsigned int nmasters = m->pertag->nmasters[m->pertag->curtag]; + uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag]; mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per : m->pertag->mfacts[m->pertag->curtag]; @@ -374,6 +413,21 @@ void center_tile(Monitor *m) { // 判断是否需要主区域铺满 int should_overspread = center_master_overspread && (n <= nmasters); + uint32_t master_surplus_height = + (m->w.height - 2 * cur_gappov - + cur_gappiv * ie * (master_num - 1)); + float master_surplus_ratio = 1.0; + + uint32_t slave_left_surplus_height = + (m->w.height - 2 * cur_gappov - + cur_gappiv * ie * (stack_num / 2 - 1)); + float slave_left_surplus_ratio = 1.0; + + uint32_t slave_right_surplus_height = + (m->w.height - 2 * cur_gappov - + cur_gappiv * ie * ((stack_num + 1) / 2 - 1)); + float slave_right_surplus_ratio = 1.0; + if (n > nmasters || !should_overspread) { // 计算主区域宽度(居中模式) mw = nmasters ? (m->w.width - 2 * cur_gappoh - cur_gappih * ie) * mfact @@ -418,9 +472,9 @@ void center_tile(Monitor *m) { // 主区域窗口 r = MIN(n, nmasters) - i; if (c->master_inner_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (master_num - 1)) * - c->master_inner_per; + h = master_surplus_height * c->master_inner_per / master_surplus_ratio; + master_surplus_height = master_surplus_height - h; + master_surplus_ratio = master_surplus_ratio - c->master_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - my - cur_gappov - @@ -440,7 +494,7 @@ void center_tile(Monitor *m) { my += c->geom.height + cur_gappiv * ie; } else { // 堆叠区域窗口 - unsigned int stack_index = i - nmasters; + uint32_t stack_index = i - nmasters; if (n - nmasters == 1) { // 单个堆叠窗口 @@ -482,9 +536,9 @@ void center_tile(Monitor *m) { if ((stack_index % 2) ^ (n % 2 == 0)) { // 右侧堆叠窗口 if (c->stack_innder_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * ((stack_num + 1) / 2 - 1)) * - c->stack_innder_per; + h = slave_right_surplus_height * c->stack_innder_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; c->master_mfact_per = mfact; } else { h = (m->w.height - ety - cur_gappov - @@ -508,9 +562,9 @@ void center_tile(Monitor *m) { } else { // 左侧堆叠窗口 if (c->stack_innder_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (stack_num / 2 - 1)) * - c->stack_innder_per; + h = slave_left_surplus_height * c->stack_innder_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; c->master_mfact_per = mfact; } else { h = (m->w.height - oty - cur_gappov - @@ -538,7 +592,7 @@ void center_tile(Monitor *m) { } void tile(Monitor *m) { - unsigned int i, n = 0, h, r, ie = enablegaps, mw, my, ty; + uint32_t i, n = 0, h, r, ie = enablegaps, mw, my, ty; Client *c = NULL; Client *fc = NULL; double mfact = 0; @@ -547,15 +601,16 @@ void tile(Monitor *m) { n = m->visible_tiling_clients; master_num = m->pertag->nmasters[m->pertag->curtag]; + master_num = n > master_num ? master_num : n; stack_num = n - master_num; if (n == 0) return; - unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; - unsigned int cur_gappih = enablegaps ? m->gappih : 0; - unsigned int cur_gappov = enablegaps ? m->gappov : 0; - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; + uint32_t cur_gappiv = enablegaps ? m->gappiv : 0; + uint32_t cur_gappih = enablegaps ? m->gappih : 0; + uint32_t cur_gappov = enablegaps ? m->gappov : 0; + uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv; cur_gappih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih; @@ -579,15 +634,26 @@ void tile(Monitor *m) { mw = m->w.width - 2 * cur_gappoh + cur_gappih * ie; i = 0; my = ty = cur_gappov; + + uint32_t master_surplus_height = + (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1)); + float master_surplus_ratio = 1.0; + + uint32_t slave_surplus_height = + (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1)); + float slave_surplus_ratio = 1.0; + wl_list_for_each(c, &clients, link) { if (!VISIBLEON(c, m) || !ISTILED(c)) continue; if (i < m->pertag->nmasters[m->pertag->curtag]) { r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i; if (c->master_inner_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (master_num - 1)) * - c->master_inner_per; + h = master_surplus_height * c->master_inner_per / + master_surplus_ratio; + master_surplus_height = master_surplus_height - h; + master_surplus_ratio = + master_surplus_ratio - c->master_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - my - cur_gappov - @@ -607,9 +673,10 @@ void tile(Monitor *m) { } else { r = n - i; if (c->stack_innder_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (stack_num - 1)) * - c->stack_innder_per; + h = slave_surplus_height * c->stack_innder_per / + slave_surplus_ratio; + slave_surplus_height = slave_surplus_height - h; + slave_surplus_ratio = slave_surplus_ratio - c->stack_innder_per; c->master_mfact_per = mfact; } else { h = (m->w.height - ty - cur_gappov - @@ -635,7 +702,7 @@ void tile(Monitor *m) { } void right_tile(Monitor *m) { - unsigned int i, n = 0, h, r, ie = enablegaps, mw, my, ty; + uint32_t i, n = 0, h, r, ie = enablegaps, mw, my, ty; Client *c = NULL; Client *fc = NULL; double mfact = 0; @@ -644,15 +711,16 @@ void right_tile(Monitor *m) { n = m->visible_tiling_clients; master_num = m->pertag->nmasters[m->pertag->curtag]; + master_num = n > master_num ? master_num : n; stack_num = n - master_num; if (n == 0) return; - unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; - unsigned int cur_gappih = enablegaps ? m->gappih : 0; - unsigned int cur_gappov = enablegaps ? m->gappov : 0; - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; + uint32_t cur_gappiv = enablegaps ? m->gappiv : 0; + uint32_t cur_gappih = enablegaps ? m->gappih : 0; + uint32_t cur_gappov = enablegaps ? m->gappov : 0; + uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv; cur_gappih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih; @@ -676,15 +744,26 @@ void right_tile(Monitor *m) { mw = m->w.width - 2 * cur_gappoh + cur_gappih * ie; i = 0; my = ty = cur_gappov; + + uint32_t master_surplus_height = + (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1)); + float master_surplus_ratio = 1.0; + + uint32_t slave_surplus_height = + (m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1)); + float slave_surplus_ratio = 1.0; + wl_list_for_each(c, &clients, link) { if (!VISIBLEON(c, m) || !ISTILED(c)) continue; if (i < m->pertag->nmasters[m->pertag->curtag]) { r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i; if (c->master_inner_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (master_num - 1)) * - c->master_inner_per; + h = master_surplus_height * c->master_inner_per / + master_surplus_ratio; + master_surplus_height = master_surplus_height - h; + master_surplus_ratio = + master_surplus_ratio - c->master_inner_per; c->master_mfact_per = mfact; } else { h = (m->w.height - my - cur_gappov - @@ -705,9 +784,10 @@ void right_tile(Monitor *m) { } else { r = n - i; if (c->stack_innder_per > 0.0f) { - h = (m->w.height - 2 * cur_gappov - - cur_gappiv * ie * (stack_num - 1)) * - c->stack_innder_per; + h = slave_surplus_height * c->stack_innder_per / + slave_surplus_ratio; + slave_surplus_height = slave_surplus_height - h; + slave_surplus_ratio = slave_surplus_ratio - c->stack_innder_per; c->master_mfact_per = mfact; } else { h = (m->w.height - ty - cur_gappov - @@ -737,8 +817,8 @@ monocle(Monitor *m) { Client *c = NULL; struct wlr_box geom; - unsigned int cur_gappov = enablegaps ? m->gappov : 0; - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; + uint32_t cur_gappov = enablegaps ? m->gappov : 0; + uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh; cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov; diff --git a/src/layout/vertical.h b/src/layout/vertical.h index 6ae21a6c..3893a4ca 100644 --- a/src/layout/vertical.h +++ b/src/layout/vertical.h @@ -1,5 +1,5 @@ void vertical_tile(Monitor *m) { - unsigned int i, n = 0, w, r, ie = enablegaps, mh, mx, tx; + uint32_t i, n = 0, w, r, ie = enablegaps, mh, mx, tx; Client *c = NULL; Client *fc = NULL; double mfact = 0; @@ -8,15 +8,16 @@ void vertical_tile(Monitor *m) { n = m->visible_tiling_clients; master_num = m->pertag->nmasters[m->pertag->curtag]; + master_num = n > master_num ? master_num : n; stack_num = n - master_num; if (n == 0) return; - unsigned int cur_gapih = enablegaps ? m->gappih : 0; - unsigned int cur_gapiv = enablegaps ? m->gappiv : 0; - unsigned int cur_gapoh = enablegaps ? m->gappoh : 0; - unsigned int cur_gapov = enablegaps ? m->gappov : 0; + uint32_t cur_gapih = enablegaps ? m->gappih : 0; + uint32_t cur_gapiv = enablegaps ? m->gappiv : 0; + uint32_t cur_gapoh = enablegaps ? m->gappoh : 0; + uint32_t cur_gapov = enablegaps ? m->gappov : 0; cur_gapih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapih; cur_gapiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapiv; @@ -40,15 +41,26 @@ void vertical_tile(Monitor *m) { i = 0; mx = tx = cur_gapih; + + uint32_t master_surplus_width = + (m->w.width - 2 * cur_gapih - cur_gapih * ie * (master_num - 1)); + float master_surplus_ratio = 1.0; + + uint32_t slave_surplus_width = + (m->w.width - 2 * cur_gapih - cur_gapih * ie * (stack_num - 1)); + float slave_surplus_ratio = 1.0; + wl_list_for_each(c, &clients, link) { if (!VISIBLEON(c, m) || !ISTILED(c)) continue; if (i < m->pertag->nmasters[m->pertag->curtag]) { r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i; if (c->master_inner_per > 0.0f) { - w = (m->w.width - 2 * cur_gapih - - cur_gapih * ie * (master_num - 1)) * - c->master_inner_per; + w = master_surplus_width * c->master_inner_per / + master_surplus_ratio; + master_surplus_width = master_surplus_width - w; + master_surplus_ratio = + master_surplus_ratio - c->master_inner_per; c->master_mfact_per = mfact; } else { w = (m->w.width - mx - cur_gapih - cur_gapih * ie * (r - 1)) / @@ -67,9 +79,10 @@ void vertical_tile(Monitor *m) { } else { r = n - i; if (c->stack_innder_per > 0.0f) { - w = (m->w.width - 2 * cur_gapih - - cur_gapih * ie * (stack_num - 1)) * - c->stack_innder_per; + w = slave_surplus_width * c->stack_innder_per / + slave_surplus_ratio; + slave_surplus_width = slave_surplus_width - w; + slave_surplus_ratio = slave_surplus_ratio - c->stack_innder_per; c->master_mfact_per = mfact; } else { w = (m->w.width - tx - cur_gapih - cur_gapih * ie * (r - 1)) / @@ -92,15 +105,15 @@ void vertical_tile(Monitor *m) { } void vertical_deck(Monitor *m) { - unsigned int mh, mx; + uint32_t mh, mx; int i, n = 0; Client *c = NULL; Client *fc = NULL; float mfact; - unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; - unsigned int cur_gappov = enablegaps ? m->gappov : 0; + uint32_t cur_gappiv = enablegaps ? m->gappiv : 0; + uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; + uint32_t cur_gappov = enablegaps ? m->gappov : 0; cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv; cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh; @@ -155,25 +168,62 @@ void vertical_deck(Monitor *m) { } } +void vertical_scroll_adjust_fullandmax(Client *c, struct wlr_box *target_geom) { + Monitor *m = c->mon; + uint32_t cur_gappiv = enablegaps ? m->gappiv : 0; + uint32_t cur_gappov = enablegaps ? m->gappov : 0; + uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; + + cur_gappiv = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappiv; + cur_gappov = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappov; + cur_gappoh = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappoh; + + if (c->isfullscreen) { + target_geom->width = m->m.width; + target_geom->height = m->m.height; + target_geom->x = m->m.x; + return; + } + + if (c->ismaximizescreen) { + target_geom->width = m->w.width - 2 * cur_gappoh; + target_geom->height = m->w.height - 2 * cur_gappov; + target_geom->x = m->w.x + cur_gappoh; + return; + } + + target_geom->width = m->w.width - 2 * cur_gappoh; + target_geom->x = m->w.x + (m->w.width - target_geom->width) / 2; +} + +// 竖屏滚动布局 void vertical_scroller(Monitor *m) { - unsigned int i, n, j; + uint32_t i, n, j; + float single_proportion = 1.0; + Client *c = NULL, *root_client = NULL; Client **tempClients = NULL; struct wlr_box target_geom; int focus_client_index = 0; bool need_scroller = false; - unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; - unsigned int cur_gappov = enablegaps ? m->gappov : 0; - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; + uint32_t cur_gappiv = enablegaps ? m->gappiv : 0; + uint32_t cur_gappov = enablegaps ? m->gappov : 0; + uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; - cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv; - cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov; - cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh; + cur_gappiv = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappiv; + cur_gappov = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappov; + cur_gappoh = + smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappoh; - unsigned int max_client_height = + uint32_t max_client_height = m->w.height - 2 * scroller_structs - cur_gappiv; - n = m->visible_tiling_clients; + n = m->visible_scroll_tiling_clients; if (n == 0) { return; @@ -186,29 +236,33 @@ void vertical_scroller(Monitor *m) { j = 0; wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, m) && ISTILED(c)) { + if (VISIBLEON(c, m) && ISSCROLLTILED(c)) { tempClients[j] = c; j++; } } - if (n == 1 && !scroller_ignore_proportion_single) { + if (n == 1 && !scroller_ignore_proportion_single && + !tempClients[0]->isfullscreen && !tempClients[0]->ismaximizescreen) { c = tempClients[0]; + + single_proportion = c->scroller_proportion_single > 0.0f + ? c->scroller_proportion_single + : scroller_default_proportion_single; + target_geom.width = m->w.width - 2 * cur_gappoh; - target_geom.height = - (m->w.height - 2 * cur_gappov) * scroller_default_proportion_single; - target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; + target_geom.height = (m->w.height - 2 * cur_gappov) * single_proportion; target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; + target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; resize(c, target_geom, 0); free(tempClients); return; } - if (m->sel && !client_is_unmanaged(m->sel) && !m->sel->isfloating && - !m->sel->ismaximizescreen && !m->sel->isfullscreen) { + if (m->sel && !client_is_unmanaged(m->sel) && ISSCROLLTILED(m->sel)) { root_client = m->sel; - } else if (m->prevsel && ISTILED(m->prevsel) && VISIBLEON(m->prevsel, m) && - !client_is_unmanaged(m->prevsel)) { + } else if (m->prevsel && ISSCROLLTILED(m->prevsel) && + VISIBLEON(m->prevsel, m) && !client_is_unmanaged(m->prevsel)) { root_client = m->prevsel; } else { root_client = center_tiled_select(m); @@ -222,8 +276,7 @@ void vertical_scroller(Monitor *m) { for (i = 0; i < n; i++) { c = tempClients[i]; if (root_client == c) { - if (!c->is_pending_open_animation && - c->geom.y >= m->w.y + scroller_structs && + if (c->geom.y >= m->w.y + scroller_structs && c->geom.y + c->geom.height <= m->w.y + m->w.height - scroller_structs) { need_scroller = false; @@ -245,11 +298,19 @@ void vertical_scroller(Monitor *m) { target_geom.width = m->w.width - 2 * cur_gappoh; target_geom.height = max_client_height * c->scroller_proportion; target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; + vertical_scroll_adjust_fullandmax(tempClients[focus_client_index], + &target_geom); - if (need_scroller) { + if (tempClients[focus_client_index]->isfullscreen) { + target_geom.y = m->m.y; + resize(tempClients[focus_client_index], target_geom, 0); + } else if (tempClients[focus_client_index]->ismaximizescreen) { + target_geom.y = m->w.y + cur_gappov; + resize(tempClients[focus_client_index], target_geom, 0); + } else if (need_scroller) { if (scroller_focus_center || ((!m->prevsel || - (ISTILED(m->prevsel) && + (ISSCROLLTILED(m->prevsel) && (m->prevsel->scroller_proportion * max_client_height) + (root_client->scroller_proportion * max_client_height) > m->w.height - 2 * scroller_structs - cur_gappiv)) && @@ -272,14 +333,17 @@ void vertical_scroller(Monitor *m) { for (i = 1; i <= focus_client_index; i++) { c = tempClients[focus_client_index - i]; target_geom.height = max_client_height * c->scroller_proportion; + vertical_scroll_adjust_fullandmax(c, &target_geom); target_geom.y = tempClients[focus_client_index - i + 1]->geom.y - cur_gappiv - target_geom.height; + resize(c, target_geom, 0); } for (i = 1; i < n - focus_client_index; i++) { c = tempClients[focus_client_index + i]; target_geom.height = max_client_height * c->scroller_proportion; + vertical_scroll_adjust_fullandmax(c, &target_geom); target_geom.y = tempClients[focus_client_index + i - 1]->geom.y + cur_gappiv + tempClients[focus_client_index + i - 1]->geom.height; @@ -290,10 +354,10 @@ void vertical_scroller(Monitor *m) { } void vertical_grid(Monitor *m) { - unsigned int i, n; - unsigned int cx, cy, cw, ch; - unsigned int dy; - unsigned int rows, cols, overrows; + uint32_t i, n; + uint32_t cx, cy, cw, ch; + uint32_t dy; + uint32_t rows, cols, overrows; Client *c = NULL; int target_gappo = enablegaps ? m->isoverview ? overviewgappo : gappov : 0; int target_gappi = enablegaps ? m->isoverview ? overviewgappi : gappiv : 0; @@ -312,10 +376,6 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; - c->bw = m->visible_tiling_clients == 1 && no_border_when_single && - smartgaps - ? 0 - : borderpx; if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { ch = (m->w.height - 2 * target_gappo) * single_height_ratio; @@ -339,10 +399,6 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; - c->bw = m->visible_tiling_clients == 1 && no_border_when_single && - smartgaps - ? 0 - : borderpx; if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { if (i == 0) { @@ -385,10 +441,6 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; - c->bw = - m->visible_tiling_clients == 1 && no_border_when_single && smartgaps - ? 0 - : borderpx; if (VISIBLEON(c, m) && !c->isunglobal && ((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) { cx = m->w.x + (i / rows) * (cw + target_gappi); diff --git a/src/mango.c b/src/mango.c index 960b5cb5..a142cb6b 100644 --- a/src/mango.c +++ b/src/mango.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -101,8 +102,11 @@ 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 ISTILED(A) \ - (A && !(A)->isfloating && !(A)->isminied && !(A)->iskilling && \ + (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]) @@ -172,6 +176,33 @@ enum tearing_mode { 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; @@ -192,13 +223,13 @@ typedef struct { char *v; char *v2; char *v3; - unsigned int ui; - unsigned int ui2; + uint32_t ui; + uint32_t ui2; } Arg; typedef struct { - unsigned int mod; - unsigned int button; + uint32_t mod; + uint32_t button; int (*func)(const Arg *); const Arg arg; } Button; // 鼠标按键 @@ -209,8 +240,8 @@ typedef struct { } KeyMode; typedef struct { - unsigned int mod; - unsigned int dir; + uint32_t mod; + uint32_t dir; int (*func)(const Arg *); const Arg arg; } Axis; @@ -238,8 +269,8 @@ struct dwl_animation { bool tagouting; bool begin_fade_in; bool tag_from_rule; - unsigned int time_started; - unsigned int duration; + uint32_t time_started; + uint32_t duration; struct wlr_box initial; struct wlr_box current; int action; @@ -250,8 +281,8 @@ struct dwl_opacity_animation { float current_opacity; float target_opacity; float initial_opacity; - unsigned int time_started; - unsigned int duration; + uint32_t time_started; + uint32_t duration; float current_border_color[4]; float target_border_color[4]; float initial_border_color[4]; @@ -268,7 +299,7 @@ typedef struct { struct Client { /* Must keep these three elements in this order */ - unsigned int type; /* XDGShell or X11* */ + 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 */ @@ -301,13 +332,13 @@ struct Client { struct wl_listener set_hints; struct wl_listener set_geometry; #endif - unsigned int bw; - unsigned int tags, oldtags, mini_restore_tag; + uint32_t bw; + uint32_t tags, oldtags, mini_restore_tag; bool dirty; - unsigned int configure_serial; + uint32_t configure_serial; struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel; int isfloating, isurgent, isfullscreen, isfakefullscreen, - need_float_size_reduce, isminied, isoverlay, isnosizehint, + need_float_size_reduce, isminimized, isoverlay, isnosizehint, ignore_maximize, ignore_minimize; int ismaximizescreen; int overview_backup_bw; @@ -370,6 +401,9 @@ struct Client { bool isleftstack; int tearing_hint; int force_tearing; + int allow_shortcuts_inhibit; + float scroller_proportion_single; + bool isfocusing; }; typedef struct { @@ -379,7 +413,7 @@ typedef struct { } DwlIpcOutput; typedef struct { - unsigned int mod; + uint32_t mod; xkb_keysym_t keysym; int (*func)(const Arg *); const Arg arg; @@ -390,8 +424,8 @@ typedef struct { int nsyms; const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */ - unsigned int mods; /* invalid if nsyms == 0 */ - unsigned int keycode; + uint32_t mods; /* invalid if nsyms == 0 */ + uint32_t keycode; struct wl_event_source *key_repeat_source; struct wl_listener modifiers; @@ -399,9 +433,15 @@ typedef struct { 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 */ - unsigned int type; /* LayerShell */ + uint32_t type; /* LayerShell */ struct wlr_box geom, current, pending, animainit_geom; Monitor *mon; struct wlr_scene_tree *scene; @@ -433,7 +473,7 @@ typedef struct { const char *symbol; void (*arrange)(Monitor *); const char *name; - unsigned int id; + uint32_t id; } Layout; struct Monitor { @@ -450,8 +490,8 @@ struct Monitor { struct wlr_box w; /* window area, layout-relative */ struct wl_list layers[4]; /* LayerSurface::link */ const Layout *lt; - unsigned int seltags; - unsigned int tagset[2]; + uint32_t seltags; + uint32_t tagset[2]; double mfact; int nmaster; @@ -465,8 +505,9 @@ struct Monitor { int isoverview; int is_in_hotarea; int asleep; - unsigned int visible_clients; - unsigned int visible_tiling_clients; + 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]; @@ -498,7 +539,7 @@ arrange(Monitor *m, static void arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive); static void arrangelayers(Monitor *m); -static char *get_autostart_path(char *, unsigned int); // 自启动命令执行 +static void handle_print_status(struct wl_listener *listener, void *data); static void axisnotify(struct wl_listener *listener, void *data); // 滚轮事件处理 static void buttonpress(struct wl_listener *listener, @@ -563,21 +604,20 @@ static void gpureset(struct wl_listener *listener, void *data); static int keyrepeat(void *data); static void inputdevice(struct wl_listener *listener, void *data); -static int keybinding(unsigned int state, bool locked, unsigned int mods, - xkb_keysym_t sym, unsigned int keycode); +static int keybinding(uint32_t state, bool locked, uint32_t mods, + xkb_keysym_t sym, uint32_t keycode); static void keypress(struct wl_listener *listener, void *data); static void keypressmod(struct wl_listener *listener, void *data); static bool keypressglobal(struct wlr_surface *last_surface, struct wlr_keyboard *keyboard, - struct wlr_keyboard_key_event *event, - unsigned int mods, xkb_keysym_t keysym, - unsigned int keycode); + struct wlr_keyboard_key_event *event, uint32_t mods, + xkb_keysym_t keysym, uint32_t keycode); static void locksession(struct wl_listener *listener, void *data); static void mapnotify(struct wl_listener *listener, void *data); static void maximizenotify(struct wl_listener *listener, void *data); static void minimizenotify(struct wl_listener *listener, void *data); static void motionabsolute(struct wl_listener *listener, void *data); -static void motionnotify(unsigned int time, struct wlr_input_device *device, +static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, double sy, double sx_unaccel, double sy_unaccel); static void motionrelative(struct wl_listener *listener, void *data); @@ -591,7 +631,7 @@ static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); static void outputmgrtest(struct wl_listener *listener, void *data); static void pointerfocus(Client *c, struct wlr_surface *surface, double sx, - double sy, unsigned int time); + double sy, uint32_t time); static void printstatus(void); static void quitsignal(int signo); static void powermgrsetmode(struct wl_listener *listener, void *data); @@ -609,7 +649,7 @@ static void setmaximizescreen(Client *c, int maximizescreen); static void reset_maximizescreen_size(Client *c); static void setgaps(int oh, int ov, int ih, int iv); -static void setmon(Client *c, Monitor *m, unsigned int newtags, bool focus); +static void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus); static void setpsel(struct wl_listener *listener, void *data); static void setsel(struct wl_listener *listener, void *data); static void setup(void); @@ -624,7 +664,9 @@ static void urgent(struct wl_listener *listener, void *data); static void view(const Arg *arg, bool want_animation); static void handlesig(int signo); - +static void +handle_keyboard_shortcuts_inhibit_new_inhibitor(struct wl_listener *listener, + void *data); static void virtualkeyboard(struct wl_listener *listener, void *data); static void virtualpointer(struct wl_listener *listener, void *data); static void warp_cursor(const Client *c); @@ -638,7 +680,7 @@ static Client *termforwin(Client *w); static void swallow(Client *c, Client *w); static void warp_cursor_to_selmon(Monitor *m); -unsigned int want_restore_fullscreen(Client *target_client); +uint32_t want_restore_fullscreen(Client *target_client); static void overview_restore(Client *c, const Arg *arg); static void overview_backup(Client *c); static int applyrulesgeom(Client *c); @@ -651,7 +693,7 @@ static void tag_client(const Arg *arg, Client *target_client); static struct wlr_box setclient_coordinate_center(Client *c, struct wlr_box geom, int offsetx, int offsety); -static unsigned int get_tags_first_tag(unsigned int tags); +static uint32_t get_tags_first_tag(uint32_t tags); static struct wlr_output_mode * get_nearest_output_mode(struct wlr_output *output, int width, int height, @@ -682,11 +724,11 @@ static bool check_hit_no_border(Client *c); static void reset_keyboard_layout(void); static void client_update_oldmonname_record(Client *c, Monitor *m); static void pending_kill_client(Client *c); -static unsigned int get_tags_first_tag_num(unsigned int source_tags); +static uint32_t get_tags_first_tag_num(uint32_t source_tags); static void set_layer_open_animaiton(LayerSurface *l, struct wlr_box geo); static void init_fadeout_layers(LayerSurface *l); -static void layer_actual_size(LayerSurface *l, unsigned int *width, - unsigned int *height); +static void layer_actual_size(LayerSurface *l, uint32_t *width, + uint32_t *height); static void get_layer_target_geometry(LayerSurface *l, struct wlr_box *target_box); static void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int sx, @@ -708,17 +750,18 @@ static Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title); static bool switch_scratchpad_client_state(Client *c); static bool check_trackpad_disabled(struct wlr_pointer *pointer); -static unsigned int get_tag_status(unsigned int tag, Monitor *m); +static uint32_t get_tag_status(uint32_t tag, Monitor *m); static void enable_adaptive_sync(Monitor *m, struct wlr_output_state *state); static Client *get_next_stack_client(Client *c, bool reverse); static void set_float_malposition(Client *tc); static void set_size_per(Monitor *m, Client *c); static void resize_tile_client(Client *grabc, bool isdrag, int offsetx, - int offsety, unsigned int time); + int offsety, uint32_t time); static void refresh_monitors_workspaces_status(Monitor *m); static void init_client_properties(Client *c); static float *get_border_color(Client *c); static void request_fresh_all_monitors(void); +static void clear_fullscreen_and_maximized_state(Monitor *m); #include "data/static_keymap.h" #include "dispatch/bind_declare.h" @@ -728,7 +771,7 @@ static void request_fresh_all_monitors(void); static const char broken[] = "broken"; static pid_t child_pid = -1; static int locked; -static unsigned int locked_mods = 0; +static uint32_t locked_mods = 0; static void *exclusive_focus; static struct wl_display *dpy; static struct wl_event_loop *event_loop; @@ -752,10 +795,13 @@ static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; +static struct wlr_keyboard_shortcuts_inhibit_manager_v1 + *keyboard_shortcuts_inhibit; static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; static struct wlr_output_power_manager_v1 *power_mgr; static struct wlr_pointer_gestures_v1 *pointer_gestures; static struct wlr_drm_lease_v1_manager *drm_lease_manager; +struct mango_print_status_manager *print_status_manager; static struct wlr_cursor *cursor; static struct wlr_xcursor_manager *cursor_mgr; @@ -775,7 +821,8 @@ static struct wlr_pointer_constraint_v1 *active_constraint; static struct wlr_seat *seat; static KeyboardGroup *kb_group; static struct wl_list inputdevices; -static unsigned int cursor_mode; +static struct wl_list keyboard_shortcut_inhibitors; +static uint32_t cursor_mode; static Client *grabc; static int grabcx, grabcy; /* client-relative */ static int drag_begin_cursorx, drag_begin_cursory; /* client-relative */ @@ -792,7 +839,7 @@ static int axis_apply_time = 0; static int axis_apply_dir = 0; static int scroller_focus_lock = 0; -static unsigned int swipe_fingers = 0; +static uint32_t swipe_fingers = 0; static double swipe_dx = 0; static double swipe_dy = 0; @@ -807,6 +854,7 @@ struct dvec2 *baked_points_focus; static struct wl_event_source *hide_source; static bool cursor_hidden = false; static bool tag_combo = false; +static const char *cli_config_path = NULL; static KeyMode keymode = { .mode = {'d', 'e', 'f', 'a', 'u', 'l', 't', '\0'}, .isdefault = true, @@ -822,7 +870,7 @@ static struct { #include "config/preset.h" struct Pertag { - unsigned int curtag, prevtag; /* current and previous tag */ + uint32_t curtag, prevtag; /* current and previous tag */ int 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 */ @@ -830,6 +878,10 @@ struct Pertag { *ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */ }; +static struct wl_signal mango_print_status; + +static struct wl_listener print_status_listener = {.notify = + handle_print_status}; static struct wl_listener cursor_axis = {.notify = axisnotify}; static struct wl_listener cursor_button = {.notify = buttonpress}; static struct wl_listener cursor_frame = {.notify = cursorframe}; @@ -861,6 +913,8 @@ static struct wl_listener request_start_drag = {.notify = requeststartdrag}; static struct wl_listener start_drag = {.notify = startdrag}; static struct wl_listener new_session_lock = {.notify = locksession}; static struct wl_listener drm_lease_request = {.notify = requestdrmlease}; +static struct wl_listener keyboard_shortcuts_inhibit_new_inhibitor = { + .notify = handle_keyboard_shortcuts_inhibit_new_inhibitor}; #ifdef XWAYLAND static void activatex11(struct wl_listener *listener, void *data); @@ -911,8 +965,26 @@ void applybounds(Client *c, struct wlr_box *bbox) { c->geom.y = bbox->y; } +void clear_fullscreen_and_maximized_state(Monitor *m) { + Client *fc = NULL; + wl_list_for_each(fc, &clients, link) { + if (fc && VISIBLEON(fc, m) && ISFULLSCREEN(fc)) { + clear_fullscreen_flag(fc); + } + } +} + /*清除全屏标志,还原全屏时清0的border*/ void clear_fullscreen_flag(Client *c) { + + if ((c->mon->pertag->ltidxs[get_tags_first_tag_num(c->tags)]->id == + SCROLLER || + c->mon->pertag->ltidxs[get_tags_first_tag_num(c->tags)]->id == + VERTICAL_SCROLLER) && + !c->isfloating) { + return; + } + if (c->isfullscreen) { setfullscreen(c, false); } @@ -967,7 +1039,7 @@ void swallow(Client *c, Client *w) { c->isurgent = w->isurgent; c->isfullscreen = w->isfullscreen; c->ismaximizescreen = w->ismaximizescreen; - c->isminied = w->isminied; + c->isminimized = w->isminimized; c->is_in_scratchpad = w->is_in_scratchpad; c->is_scratchpad_show = w->is_scratchpad_show; c->tags = w->tags; @@ -987,7 +1059,7 @@ void swallow(Client *c, Client *w) { if (!c->foreign_toplevel && c->mon) add_foreign_toplevel(c); - if (c->isminied && c->foreign_toplevel) { + if (c->isminimized && c->foreign_toplevel) { wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, false); wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, true); @@ -1152,8 +1224,10 @@ static void apply_rule_properties(Client *c, const ConfigWinRule *r) { APPLY_INT_PROP(c, r, isnosizehint); APPLY_INT_PROP(c, r, isunglobal); APPLY_INT_PROP(c, r, noblur); + APPLY_INT_PROP(c, r, allow_shortcuts_inhibit); APPLY_FLOAT_PROP(c, r, scroller_proportion); + APPLY_FLOAT_PROP(c, r, scroller_proportion_single); APPLY_FLOAT_PROP(c, r, focused_opacity); APPLY_FLOAT_PROP(c, r, unfocused_opacity); @@ -1245,7 +1319,7 @@ void set_float_malposition(Client *tc) { void applyrules(Client *c) { /* rule matching */ const char *appid, *title; - unsigned int i, newtags = 0; + uint32_t i, newtags = 0; const ConfigWinRule *r; Monitor *m = NULL; Client *fc = NULL; @@ -1332,7 +1406,7 @@ void applyrules(Client *c) { if (!c->noswallow && !c->isfloating && !client_is_float_type(c) && !c->surface.xdg->initial_commit) { Client *p = termforwin(c); - if (p) { + if (p && !p->isminimized) { c->swallowedby = p; p->swallowing = c; wl_list_remove(&c->link); @@ -1347,7 +1421,8 @@ void applyrules(Client *c) { int fullscreen_state_backup = c->isfullscreen || client_wants_fullscreen(c); setmon(c, mon, newtags, - !c->isopensilent && !client_should_ignore_focus(c) && + !c->isopensilent && + !(client_is_x11_popup(c) && client_should_ignore_focus(c)) && (!c->istagsilent || !newtags || newtags & mon->tagset[mon->seltags])); @@ -1419,9 +1494,9 @@ void apply_window_snap(Client *c) { int snap_up_mon = 0, snap_down_mon = 0, snap_left_mon = 0, snap_right_mon = 0; - unsigned int cbw = !render_border || c->fake_no_border ? borderpx : 0; - unsigned int tcbw; - unsigned int cx, cy, cw, ch, tcx, tcy, tcw, tch; + uint32_t cbw = !render_border || c->fake_no_border ? borderpx : 0; + uint32_t tcbw; + uint32_t cx, cy, cw, ch, tcx, tcy, tcw, tch; cx = c->geom.x + cbw; cy = c->geom.y + cbw; cw = c->geom.width - 2 * cbw; @@ -1512,12 +1587,19 @@ void apply_window_snap(Client *c) { resize(c, c->geom, 0); } +void focuslayer(LayerSurface *l) { + focusclient(NULL, 0); + dwl_im_relay_set_focus(dwl_input_method_relay, l->layer_surface->surface); + client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat)); +} + void reset_exclusive_layer(Monitor *m) { LayerSurface *l = NULL; int i; - unsigned int layers_above_shell[] = { + uint32_t layers_above_shell[] = { ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, ZWLR_LAYER_SHELL_V1_LAYER_TOP, + ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, }; if (!m) @@ -1525,18 +1607,24 @@ void reset_exclusive_layer(Monitor *m) { for (i = 0; i < (int)LENGTH(layers_above_shell); i++) { wl_list_for_each_reverse(l, &m->layers[layers_above_shell[i]], link) { + if (l == exclusive_focus && + l->layer_surface->current.keyboard_interactive != + ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) + exclusive_focus = NULL; + if (l->layer_surface->current.keyboard_interactive == + ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE && + l->layer_surface->surface == + seat->keyboard_state.focused_surface) + focusclient(focustop(selmon), 1); + if (locked || l->layer_surface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE || !l->mapped || l == exclusive_focus) continue; /* Deactivate the focused client. */ - focusclient(NULL, 0); exclusive_focus = l; - dwl_im_relay_set_focus(dwl_input_method_relay, - l->layer_surface->surface); - client_notify_enter(l->layer_surface->surface, - wlr_seat_get_keyboard(seat)); + focuslayer(l); return; } } @@ -1573,10 +1661,10 @@ axisnotify(struct wl_listener *listener, void *data) { * for example when you move the scroll wheel. */ struct wlr_pointer_axis_event *event = data; struct wlr_keyboard *keyboard, *hard_keyboard; - unsigned int mods, hard_mods; + uint32_t mods, hard_mods; AxisBinding *a; int ji; - unsigned int adir; + uint32_t adir; // IDLE_NOTIFY_ACTIVITY; handlecursoractivity(); wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); @@ -1630,11 +1718,11 @@ axisnotify(struct wl_listener *listener, void *data) { int ongesture(struct wlr_pointer_swipe_end_event *event) { struct wlr_keyboard *keyboard, *hard_keyboard; - unsigned int mods, hard_mods; + uint32_t mods, hard_mods; const GestureBinding *g; - unsigned int motion; - unsigned int adx = (int)round(fabs(swipe_dx)); - unsigned int ady = (int)round(fabs(swipe_dy)); + uint32_t motion; + uint32_t adx = (int)round(fabs(swipe_dx)); + uint32_t ady = (int)round(fabs(swipe_dy)); int handled = 0; int ji; @@ -1799,7 +1887,7 @@ void // 鼠标按键事件 buttonpress(struct wl_listener *listener, void *data) { struct wlr_pointer_button_event *event = data; struct wlr_keyboard *hard_keyboard, *keyboard; - unsigned int hard_mods, mods; + uint32_t hard_mods, mods; Client *c = NULL; LayerSurface *l = NULL; struct wlr_surface *surface; @@ -1837,11 +1925,7 @@ buttonpress(struct wl_listener *listener, void *data) { if (l && !exclusive_focus && l->layer_surface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) { - focusclient(NULL, 0); - dwl_im_relay_set_focus(dwl_input_method_relay, - l->layer_surface->surface); - client_notify_enter(l->layer_surface->surface, - wlr_seat_get_keyboard(seat)); + focuslayer(l); } } @@ -1950,6 +2034,7 @@ void setcursorshape(struct wl_listener *listener, void *data) { } void cleanuplisteners(void) { + wl_list_remove(&print_status_listener.link); wl_list_remove(&cursor_axis.link); wl_list_remove(&cursor_button.link); wl_list_remove(&cursor_frame.link); @@ -1979,6 +2064,7 @@ void cleanuplisteners(void) { wl_list_remove(&start_drag.link); wl_list_remove(&new_session_lock.link); wl_list_remove(&tearing_new_object.link); + wl_list_remove(&keyboard_shortcuts_inhibit_new_inhibitor.link); if (drm_lease_manager) { wl_list_remove(&drm_lease_request.link); } @@ -2019,7 +2105,7 @@ void cleanup(void) { void cleanupmon(struct wl_listener *listener, void *data) { Monitor *m = wl_container_of(listener, m, destroy); LayerSurface *l = NULL, *tmp = NULL; - unsigned int i; + uint32_t i; /* m->layers[i] are intentionally not unlinked */ for (i = 0; i < LENGTH(m->layers); i++) { @@ -2172,6 +2258,13 @@ void maplayersurfacenotify(struct wl_listener *listener, void *data) { } // 刷新布局,让窗口能感应到exclude_zone变化以及设置独占表面 arrangelayers(l->mon); + + // 按需交互layer需要像正常窗口一样抢占非独占layer的焦点 + if (!exclusive_focus && + l->layer_surface->current.keyboard_interactive == + ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) { + focuslayer(l); + } } void commitlayersurfacenotify(struct wl_listener *listener, void *data) { @@ -2435,14 +2528,14 @@ KeyboardGroup *createkeyboardgroup(void) { xkb_mod_index_t mod_index = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM); if (mod_index != XKB_MOD_INVALID) - locked_mods |= (unsigned int)1 << mod_index; + locked_mods |= (uint32_t)1 << mod_index; } if (capslock) { xkb_mod_index_t mod_index = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); if (mod_index != XKB_MOD_INVALID) - locked_mods |= (unsigned int)1 << mod_index; + locked_mods |= (uint32_t)1 << mod_index; } if (locked_mods) @@ -2566,7 +2659,7 @@ void createmon(struct wl_listener *listener, void *data) { * monitor) becomes available. */ struct wlr_output *wlr_output = data; const ConfigMonitorRule *r; - unsigned int i; + uint32_t i; int ji, jk; struct wlr_output_state state; Monitor *m = NULL; @@ -2683,18 +2776,7 @@ void createmon(struct wl_listener *listener, void *data) { } // apply tag rule - for (i = 1; i <= config.tag_rules_count; i++) { - for (jk = 0; jk < LENGTH(layouts); jk++) { - if (config.tag_rules_count > 0 && - config.tag_rules[i - 1].layout_name && - strcmp(layouts[jk].name, config.tag_rules[i - 1].layout_name) == - 0) { - m->pertag->ltidxs[config.tag_rules[i - 1].id] = &layouts[jk]; - m->pertag->no_hide[config.tag_rules[i - 1].id] = - config.tag_rules[i - 1].no_hide; - } - } - } + parse_tagrule(m); /* The xdg-protocol specifies: * @@ -2994,7 +3076,9 @@ void destroylock(SessionLock *lock, int unlock) { if ((locked = !unlock)) goto destroy; - wlr_scene_node_set_enabled(&locked_bg->node, false); + if (locked_bg->node.enabled) { + wlr_scene_node_set_enabled(&locked_bg->node, false); + } focusclient(focustop(selmon), 0); motionnotify(0, NULL, 0, 0, 0, 0); @@ -3092,6 +3176,10 @@ void destroykeyboardgroup(struct wl_listener *listener, void *data) { } void focusclient(Client *c, int lift) { + + Client *last_focus_client = NULL; + Monitor *um = NULL; + struct wlr_surface *old_keyboard_focus_surface = seat->keyboard_state.focused_surface; @@ -3126,12 +3214,16 @@ void focusclient(Client *c, int lift) { if (c && !c->iskilling && !client_is_unmanaged(c) && c->mon) { + last_focus_client = selmon->sel; selmon = c->mon; selmon->prevsel = selmon->sel; selmon->sel = c; + c->isfocusing = true; - if (selmon->prevsel && !selmon->prevsel->iskilling) { - cleint_set_unfocused_opacity_animation(selmon->prevsel); + if (last_focus_client && !last_focus_client->iskilling && + last_focus_client != c) { + last_focus_client->isfocusing = false; + client_set_unfocused_opacity_animation(last_focus_client); } client_set_focused_opacity_animation(c); @@ -3141,7 +3233,6 @@ void focusclient(Client *c, int lift) { if (c && selmon->prevsel && (selmon->prevsel->tags & selmon->tagset[selmon->seltags]) && (c->tags & selmon->tagset[selmon->seltags]) && !c->isfloating && - !c->isfullscreen && !c->ismaximizescreen && is_scroller_layout(selmon)) { arrange(selmon, false); } @@ -3154,6 +3245,15 @@ void focusclient(Client *c, int lift) { c->isurgent = 0; } + // update other monitor focus disappear + wl_list_for_each(um, &mons, link) { + if (um->wlr_output->enabled && um != selmon && um->sel && + !um->sel->iskilling && um->sel->isfocusing) { + um->sel->isfocusing = false; + client_set_unfocused_opacity_animation(um->sel); + } + } + if (c && !c->iskilling && c->foreign_toplevel) wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true); @@ -3232,7 +3332,7 @@ void inputdevice(struct wl_listener *listener, void *data) { /* This event is raised by the backend when a new input device becomes * available. */ struct wlr_input_device *device = data; - unsigned int caps; + uint32_t caps; switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD: @@ -3277,9 +3377,20 @@ int keyrepeat(void *data) { return 0; } +bool is_keyboard_shortcut_inhibitor(struct wlr_surface *surface) { + KeyboardShortcutsInhibitor *kbsinhibitor; + + wl_list_for_each(kbsinhibitor, &keyboard_shortcut_inhibitors, link) { + if (kbsinhibitor->inhibitor->surface == surface) { + return true; + } + } + return false; +} + int // 17 -keybinding(unsigned int state, bool locked, unsigned int mods, xkb_keysym_t sym, - unsigned int keycode) { +keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym, + uint32_t keycode) { /* * Here we handle compositor keybindings. This is when the compositor is * processing keys, rather than passing them on to the client for its @@ -3295,6 +3406,10 @@ keybinding(unsigned int state, bool locked, unsigned int mods, xkb_keysym_t sym, keycode == 62 || keycode == 108 || keycode == 105 || keycode == 134) return false; + if (is_keyboard_shortcut_inhibitor(seat->keyboard_state.focused_surface)) { + return false; + } + for (ji = 0; ji < config.key_bindings_count; ji++) { if (config.key_bindings_count < 1) break; @@ -3319,8 +3434,8 @@ keybinding(unsigned int state, bool locked, unsigned int mods, xkb_keysym_t sym, (strcmp(keymode.mode, k->mode) == 0)) && CLEANMASK(mods) == CLEANMASK(k->mod) && ((k->keysymcode.type == KEY_TYPE_SYM && - normalize_keysym(sym) == - normalize_keysym(k->keysymcode.keysym)) || + xkb_keysym_to_lower(sym) == + xkb_keysym_to_lower(k->keysymcode.keysym)) || (k->keysymcode.type == KEY_TYPE_CODE && (keycode == k->keysymcode.keycode.keycode1 || keycode == k->keysymcode.keycode.keycode2 || @@ -3339,10 +3454,10 @@ keybinding(unsigned int state, bool locked, unsigned int mods, xkb_keysym_t sym, bool keypressglobal(struct wlr_surface *last_surface, struct wlr_keyboard *keyboard, - struct wlr_keyboard_key_event *event, unsigned int mods, - xkb_keysym_t keysym, unsigned int keycode) { + struct wlr_keyboard_key_event *event, uint32_t mods, + xkb_keysym_t keysym, uint32_t keycode) { Client *c = NULL, *lastc = focustop(selmon); - unsigned int keycodes[32] = {0}; + uint32_t keycodes[32] = {0}; int reset = false; const char *appid = NULL; const char *title = NULL; @@ -3418,19 +3533,19 @@ void keypress(struct wl_listener *listener, void *data) { #endif /* Translate libinput keycode -> xkbcommon */ - unsigned int keycode = event->keycode + 8; + uint32_t keycode = event->keycode + 8; /* Get a list of keysyms based on the keymap for this keyboard */ const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms(group->wlr_group->keyboard.xkb_state, keycode, &syms); int handled = 0; - unsigned int mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard); + uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard); wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); // ov tab mode detect moe key release - if (ov_tab_mode && !locked && + if (ov_tab_mode && !locked && group == kb_group && event->state == WL_KEYBOARD_KEY_STATE_RELEASED && (keycode == 133 || keycode == 37 || keycode == 64 || keycode == 50 || keycode == 134 || keycode == 105 || keycode == 108 || keycode == 62) && @@ -3513,7 +3628,9 @@ void pending_kill_client(Client *c) { void locksession(struct wl_listener *listener, void *data) { struct wlr_session_lock_v1 *session_lock = data; SessionLock *lock; - wlr_scene_node_set_enabled(&locked_bg->node, true); + if (!allow_lock_transparent) { + wlr_scene_node_set_enabled(&locked_bg->node, true); + } if (cur_lock) { wlr_session_lock_v1_destroy(session_lock); return; @@ -3562,13 +3679,14 @@ static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, } void init_client_properties(Client *c) { + c->isfocusing = false; c->ismaximizescreen = 0; c->isfullscreen = 0; c->need_float_size_reduce = 0; c->iskilling = 0; c->istagswitching = 0; c->isglobal = 0; - c->isminied = 0; + c->isminimized = 0; c->isoverlay = 0; c->isunglobal = 0; c->is_in_scratchpad = 0; @@ -3602,6 +3720,8 @@ void init_client_properties(Client *c) { 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; } void // old fix to 0.5 @@ -3680,9 +3800,9 @@ mapnotify(struct wl_listener *listener, void *data) { // tile at the top wl_list_insert(&clients, &c->link); // 新窗口是master,头部入栈 else if (selmon && is_scroller_layout(selmon) && - selmon->visible_tiling_clients > 0) { + selmon->visible_scroll_tiling_clients > 0) { - if (selmon->sel && ISTILED(selmon->sel) && + if (selmon->sel && ISSCROLLTILED(selmon->sel) && VISIBLEON(selmon->sel, selmon)) { at_client = selmon->sel; } else { @@ -3739,7 +3859,7 @@ void maximizenotify(struct wl_listener *listener, void *data) { void unminimize(Client *c) { if (c && c->is_in_scratchpad && c->is_scratchpad_show) { - c->isminied = 0; + c->isminimized = 0; c->is_scratchpad_show = 0; c->is_in_scratchpad = 0; c->isnamedscratchpad = 0; @@ -3747,7 +3867,7 @@ void unminimize(Client *c) { return; } - if (c && c->isminied) { + if (c && c->isminimized) { show_hide_client(c); c->is_scratchpad_show = 0; c->is_in_scratchpad = 0; @@ -3767,7 +3887,7 @@ void set_minimized(Client *c) { c->oldtags = c->mon->tagset[c->mon->seltags]; c->mini_restore_tag = c->tags; c->tags = 0; - c->isminied = 1; + c->isminimized = 1; c->is_in_scratchpad = 1; c->is_scratchpad_show = 0; focusclient(focustop(selmon), 1); @@ -3782,15 +3902,15 @@ void minimizenotify(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, minimize); - if (!c || !c->mon || c->iskilling || c->isminied) + if (!c || !c->mon || c->iskilling || c->isminimized) return; if (client_request_minimize(c, data) && !c->ignore_minimize) { - if (!c->isminied) + if (!c->isminimized) set_minimized(c); client_set_minimized(c, true); } else { - if (c->isminied) + if (c->isminimized) unminimize(c); client_set_minimized(c, false); } @@ -3821,7 +3941,7 @@ void motionabsolute(struct wl_listener *listener, void *data) { motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); } -void motionnotify(unsigned int time, struct wlr_input_device *device, double dx, +void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, double dx_unaccel, double dy_unaccel) { double sx = 0, sy = 0, sx_confined, sy_confined; Client *c = NULL, *w = NULL; @@ -3916,35 +4036,18 @@ void motionnotify(unsigned int time, struct wlr_input_device *device, double dx, if (!surface && !seat->drag && !cursor_hidden) wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); - if (c && c->mon && !c->animation.running && - (!(c->geom.x + c->geom.width > c->mon->m.x + c->mon->m.width || - c->geom.x < c->mon->m.x || - c->geom.y + c->geom.height > c->mon->m.y + c->mon->m.height || - c->geom.y < c->mon->m.y) || - !ISTILED(c))) { + if (c && c->mon && !c->animation.running && (INSIDEMON(c) || !ISTILED(c))) { scroller_focus_lock = 0; } should_lock = false; - if (!scroller_focus_lock || - !(c && c->mon && - (c->geom.x + c->geom.width > c->mon->m.x + c->mon->m.width || - c->geom.x < c->mon->m.x || - c->geom.y + c->geom.height > c->mon->m.y + c->mon->m.height || - c->geom.y < c->mon->m.y))) { - if (c && c->mon && is_scroller_layout(c->mon) && - (c->geom.x + c->geom.width > c->mon->m.x + c->mon->m.width || - c->geom.x < c->mon->m.x || - c->geom.y + c->geom.height > c->mon->m.y + c->mon->m.height || - c->geom.y < c->mon->m.y)) { + if (!scroller_focus_lock || !(c && c->mon && !INSIDEMON(c))) { + if (c && c->mon && is_scroller_layout(c->mon) && !INSIDEMON(c)) { should_lock = true; } if (!(!edge_scroller_pointer_focus && c && c->mon && - is_scroller_layout(c->mon) && - (c->geom.x < c->mon->m.x || c->geom.y < c->mon->m.y || - c->geom.x + c->geom.width > c->mon->m.x + c->mon->m.width || - c->geom.y + c->geom.height > c->mon->m.y + c->mon->m.height))) + is_scroller_layout(c->mon) && !INSIDEMON(c))) pointerfocus(c, surface, sx, sy, time); if (should_lock && c && c->mon && ISTILED(c) && c == c->mon->sel) { @@ -4046,7 +4149,7 @@ void outputmgrtest(struct wl_listener *listener, void *data) { } void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, - unsigned int time) { + uint32_t time) { struct timespec now; if (surface != seat->pointer_state.focused_surface && sloppyfocus && time && @@ -4071,20 +4174,8 @@ void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, wlr_seat_pointer_notify_motion(seat, time, sx, sy); } -void // 17 -printstatus(void) { - Monitor *m = NULL; - wl_list_for_each(m, &mons, link) { - if (!m->wlr_output->enabled) { - continue; - } - // Update workspace active states - dwl_ext_workspace_printstatus(m); - - // Update IPC output status - dwl_ipc_output_printstatus(m); - } -} +// 修改printstatus函数,接受掩码参数 +void printstatus(void) { wl_signal_emit(&mango_print_status, NULL); } void powermgrsetmode(struct wl_listener *listener, void *data) { struct wlr_output_power_v1_set_mode_event *event = data; @@ -4225,7 +4316,7 @@ void setborder_color(Client *c) { void exchange_two_client(Client *c1, Client *c2) { Monitor *tmp_mon = NULL; - unsigned int tmp_tags; + uint32_t tmp_tags; double master_inner_per = 0.0f; double master_mfact_per = 0.0f; double stack_innder_per = 0.0f; @@ -4303,7 +4394,6 @@ run(char *startup_cmd) { set_env(); - char autostart_temp_path[1024]; /* Add a Unix socket to the Wayland display. */ const char *socket = wl_display_add_socket_auto(dpy); if (!socket) @@ -4317,9 +4407,7 @@ run(char *startup_cmd) { /* Now that the socket exists and the backend is started, run the * startup command */ - if (!startup_cmd) - startup_cmd = get_autostart_path(autostart_temp_path, - sizeof(autostart_temp_path)); + if (startup_cmd) { int piperw[2]; if (pipe(piperw) < 0) @@ -4495,6 +4583,9 @@ void setmaximizescreen(Client *c, int maximizescreen) { if (!c || !c->mon || !client_surface(c)->mapped || c->iskilling) return; + if (c->mon->isoverview) + return; + c->ismaximizescreen = maximizescreen; if (maximizescreen) { @@ -4504,17 +4595,14 @@ void setmaximizescreen(Client *c, int maximizescreen) { if (c->isfloating) c->float_geom = c->geom; - if (selmon->isoverview) { - Arg arg = {0}; - toggleoverview(&arg); - } maximizescreen_box.x = c->mon->w.x + gappoh; maximizescreen_box.y = c->mon->w.y + gappov; maximizescreen_box.width = c->mon->w.width - 2 * gappoh; maximizescreen_box.height = c->mon->w.height - 2 * gappov; wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层 - resize(c, maximizescreen_box, 0); + if (!is_scroller_layout(c->mon) || c->isfloating) + resize(c, maximizescreen_box, 0); c->ismaximizescreen = 1; } else { c->bw = c->isnoborder ? 0 : borderpx; @@ -4523,9 +4611,8 @@ void setmaximizescreen(Client *c, int maximizescreen) { setfloating(c, 1); } - wlr_scene_node_reparent(&c->scene->node, layers[maximizescreen ? LyrTile - : c->isfloating ? LyrTop - : LyrTile]); + wlr_scene_node_reparent(&c->scene->node, + layers[c->isfloating ? LyrTop : LyrTile]); if (!c->ismaximizescreen) { set_size_per(c->mon, c); } @@ -4551,11 +4638,15 @@ void setfakefullscreen(Client *c, int fakefullscreen) { void setfullscreen(Client *c, int fullscreen) // 用自定义全屏代理自带全屏 { - c->isfullscreen = fullscreen; if (!c || !c->mon || !client_surface(c)->mapped || c->iskilling) return; + if (c->mon->isoverview) + return; + + c->isfullscreen = fullscreen; + client_set_fullscreen(c, fullscreen); if (fullscreen) { @@ -4564,14 +4655,11 @@ void setfullscreen(Client *c, int fullscreen) // 用自定义全屏代理自带 if (c->isfloating) c->float_geom = c->geom; - if (selmon->isoverview) { - Arg arg = {0}; - toggleoverview(&arg); - } c->bw = 0; wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层 - resize(c, c->mon->m, 1); + if (!is_scroller_layout(c->mon) || c->isfloating) + resize(c, c->mon->m, 1); c->isfullscreen = 1; } else { c->bw = c->isnoborder ? 0 : borderpx; @@ -4662,9 +4750,9 @@ void reset_keyboard_layout(void) { } // Apply the new keymap - unsigned int depressed = keyboard->modifiers.depressed; - unsigned int latched = keyboard->modifiers.latched; - unsigned int locked = keyboard->modifiers.locked; + uint32_t depressed = keyboard->modifiers.depressed; + uint32_t latched = keyboard->modifiers.latched; + uint32_t locked = keyboard->modifiers.locked; wlr_keyboard_set_keymap(keyboard, new_keymap); @@ -4699,7 +4787,7 @@ cleanup_context: xkb_context_unref(context); } -void setmon(Client *c, Monitor *m, unsigned int newtags, bool focus) { +void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) { Monitor *oldmon = c->mon; if (oldmon == m) @@ -4769,15 +4857,18 @@ void setsel(struct wl_listener *listener, void *data) { } void show_hide_client(Client *c) { + uint32_t target = 1; + + set_size_per(c->mon, c); + target = get_tags_first_tag(c->oldtags); - unsigned int target = get_tags_first_tag(c->oldtags); if (!c->is_in_scratchpad) { tag_client(&(Arg){.ui = target}, c); } else { c->tags = c->oldtags; arrange(c->mon, false); } - c->isminied = 0; + c->isminimized = 0; wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, false); focusclient(c, 1); wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true); @@ -4804,6 +4895,20 @@ void create_output(struct wlr_backend *backend, void *data) { #endif } +// 修改信号处理函数,接收掩码参数 +void handle_print_status(struct wl_listener *listener, void *data) { + + Monitor *m = NULL; + wl_list_for_each(m, &mons, link) { + if (!m->wlr_output->enabled) { + continue; + } + dwl_ext_workspace_printstatus(m); + + dwl_ipc_output_printstatus(m); + } +} + void setup(void) { setenv("XCURSOR_SIZE", "24", 1); @@ -4899,6 +5004,10 @@ void setup(void) { wlr_alpha_modifier_v1_create(dpy); wlr_ext_data_control_manager_v1_create(dpy, 1); + // 在 setup 函数中 + wl_signal_init(&mango_print_status); + wl_signal_add(&mango_print_status, &print_status_listener); + /* Initializes the interface used to implement urgency hints */ activation = wlr_xdg_activation_v1_create(dpy); wl_signal_add(&activation->events.request_activate, &request_activate); @@ -5017,6 +5126,7 @@ void setup(void) { * to let us know when new input devices are available on the backend. */ wl_list_init(&inputdevices); + wl_list_init(&keyboard_shortcut_inhibitors); wl_signal_add(&backend->events.new_input, &new_input_device); virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); wl_signal_add(&virtual_keyboard_mgr->events.new_virtual_keyboard, @@ -5046,6 +5156,10 @@ void setup(void) { kb_group = createkeyboardgroup(); wl_list_init(&kb_group->destroy.link); + keyboard_shortcuts_inhibit = wlr_keyboard_shortcuts_inhibit_v1_create(dpy); + wl_signal_add(&keyboard_shortcuts_inhibit->events.new_inhibitor, + &keyboard_shortcuts_inhibit_new_inhibitor); + output_mgr = wlr_output_manager_v1_create(dpy); wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); wl_signal_add(&output_mgr->events.test, &output_mgr_test); @@ -5134,11 +5248,15 @@ void tag_client(const Arg *arg, Client *target_client) { void overview(Monitor *m) { grid(m); } // 目标窗口有其他窗口和它同个tag就返回0 -unsigned int want_restore_fullscreen(Client *target_client) { +uint32_t want_restore_fullscreen(Client *target_client) { Client *c = NULL; wl_list_for_each(c, &clients, link) { if (c && c != target_client && c->tags == target_client->tags && - c == selmon->sel) { + c == selmon->sel && + c->mon->pertag->ltidxs[get_tags_first_tag_num(c->tags)]->id != + SCROLLER && + c->mon->pertag->ltidxs[get_tags_first_tag_num(c->tags)]->id != + VERTICAL_SCROLLER) { return 0; } } @@ -5257,7 +5375,7 @@ void unmapnotify(struct wl_listener *listener, void *data) { Monitor *m = NULL; c->iskilling = 1; - if (animations && !c->is_clip_to_hide && !c->isminied && + if (animations && !c->is_clip_to_hide && !c->isminimized && (!c->mon || VISIBLEON(c, c->mon))) init_fadeout_client(c); @@ -5506,7 +5624,7 @@ urgent(struct wl_listener *listener, void *data) { void view_in_mon(const Arg *arg, bool want_animation, Monitor *m, bool changefocus) { - unsigned int i, tmptag; + uint32_t i, tmptag; if (!m || (arg->ui != (~0 & TAGMASK) && m->isoverview)) { return; @@ -5517,9 +5635,9 @@ void view_in_mon(const Arg *arg, bool want_animation, Monitor *m, } if (arg->ui == UINT32_MAX) { - m->pertag->prevtag = m->tagset[m->seltags]; + m->pertag->prevtag = get_tags_first_tag_num(m->tagset[m->seltags]); m->seltags ^= 1; /* toggle sel tagset */ - m->pertag->curtag = m->tagset[m->seltags]; + m->pertag->curtag = get_tags_first_tag_num(m->tagset[m->seltags]); goto toggleseltags; } @@ -5573,6 +5691,49 @@ void view(const Arg *arg, bool want_animation) { } } +static void +handle_keyboard_shortcuts_inhibitor_destroy(struct wl_listener *listener, + void *data) { + KeyboardShortcutsInhibitor *inhibitor = + wl_container_of(listener, inhibitor, destroy); + + wlr_log(WLR_DEBUG, "Removing keyboard shortcuts inhibitor"); + + wl_list_remove(&inhibitor->link); + wl_list_remove(&inhibitor->destroy.link); + free(inhibitor); +} + +void handle_keyboard_shortcuts_inhibit_new_inhibitor( + struct wl_listener *listener, void *data) { + + struct wlr_keyboard_shortcuts_inhibitor_v1 *inhibitor = data; + + if (allow_shortcuts_inhibit == SHORTCUTS_INHIBIT_DISABLE) { + return; + } + + // per-view, seat-agnostic config via criteria + Client *c = get_client_from_surface(inhibitor->surface); + if (c && !c->allow_shortcuts_inhibit) { + return; + } + + wlr_log(WLR_DEBUG, "Adding keyboard shortcuts inhibitor"); + + KeyboardShortcutsInhibitor *kbsinhibitor = + calloc(1, sizeof(KeyboardShortcutsInhibitor)); + + kbsinhibitor->inhibitor = inhibitor; + + kbsinhibitor->destroy.notify = handle_keyboard_shortcuts_inhibitor_destroy; + wl_signal_add(&inhibitor->events.destroy, &kbsinhibitor->destroy); + + wl_list_insert(&keyboard_shortcut_inhibitors, &kbsinhibitor->link); + + wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor); +} + void virtualkeyboard(struct wl_listener *listener, void *data) { struct wlr_virtual_keyboard_v1 *kb = data; /* virtual keyboards shouldn't share keyboard group */ @@ -5625,8 +5786,8 @@ void activatex11(struct wl_listener *listener, void *data) { if (c && c->swallowing) return; - if (c->isminied) { - c->isminied = 0; + if (c->isminimized) { + c->isminimized = 0; c->tags = c->mini_restore_tag; c->is_scratchpad_show = 0; c->is_in_scratchpad = 0; @@ -5760,13 +5921,15 @@ int main(int argc, char *argv[]) { char *startup_cmd = NULL; int c; - while ((c = getopt(argc, argv, "s:hdv")) != -1) { + while ((c = getopt(argc, argv, "s:c:hdv")) != -1) { if (c == 's') startup_cmd = optarg; else if (c == 'd') log_level = WLR_DEBUG; else if (c == 'v') die("mango " VERSION); + else if (c == 'c') + cli_config_path = optarg; else goto usage; } @@ -5784,5 +5947,5 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; usage: - die("Usage: %s [-v] [-d] [-s startup command]", argv[0]); + die("Usage: %s [-v] [-d] [-c config file] [-s startup command]", argv[0]); }