Compare commits

...

87 commits
0.11.0 ... main

Author SHA1 Message Date
DreamMaoMao
722f9f6876
Merge pull request #683 from realcharmer/packaging
Include packaging status in README
2026-02-20 09:09:16 +08:00
Emil Miler
f0259c6285 Include packaging status in README 2026-02-19 15:02:03 +01:00
DreamMaoMao
2f12f46919 opt: use base surface of client when xytonode in rect node 2026-02-19 19:07:44 +08:00
DreamMaoMao
68075c0044 feat: support index arg in switch_keyboard_layout 2026-02-19 11:23:08 +08:00
DreamMaoMao
23d7b11e27 fix: only apply scroller overspread to head and tail client 2026-02-19 11:17:36 +08:00
DreamMaoMao
6924ca8512 feat: add global option prefer_scroller_overspread 2026-02-19 00:00:58 +08:00
DreamMaoMao
259fdb3a87 bump versiont to 0.12.3 2026-02-18 13:26:24 +08:00
DreamMaoMao
c3dcee2c8e opt: remove useless code 2026-02-17 08:33:45 +08:00
DreamMaoMao
15729db193
Merge pull request #668 from Yappaholic/main
docs: add guix installation instructions
2026-02-16 13:16:56 +08:00
DreamMaoMao
fa88ebace0 project: version not use latest tag 2026-02-16 11:56:51 +08:00
DreamMaoMao
112fb5c007 opt: optimize code struct 2026-02-16 10:06:16 +08:00
DreamMaoMao
1158fb2e3c opt: don't skip frame when grab client 2026-02-16 07:46:42 +08:00
Yappaholic
26a616e3d5 docs: add guix installation instructions 2026-02-15 16:50:07 +03:00
DreamMaoMao
933638d1b8
Merge pull request #666 from squassina/main
fix warning about meson
2026-02-15 19:14:27 +08:00
Ricardo Squassina Lee
f75efa1312
Fix wayland protocol directory variable retrieval 2026-02-15 07:08:35 -03:00
DreamMaoMao
62ab00a7a3 update readme 2026-02-15 16:43:02 +08:00
DreamMaoMao
7ccbeae8b8 fix: if the progress not the child of main, not assume it is stop 2026-02-15 14:08:53 +08:00
DreamMaoMao
49cb5a9d7e feat: support frame skip for x11 app resize 2026-02-15 12:50:42 +08:00
DreamMaoMao
0696fe964d opt: optimize frame skip logic 2026-02-15 10:31:23 +08:00
DreamMaoMao
842b45b584 feat: add skip timer to avoid rermanently block render 2026-02-15 09:02:36 +08:00
DreamMaoMao
02067e3b1e fix: some client property missing init 2026-02-15 08:07:00 +08:00
DreamMaoMao
fdd54afb7e fix: some app frame skip fail when disable animaitons 2026-02-15 08:00:44 +08:00
DreamMaoMao
91110efe0e
Merge pull request #645 from jampe/feature-config-isfakefullscreen
support isfakefullscreen as windowrule property
2026-02-14 08:46:23 +08:00
DreamMaoMao
89413aacf5 fix: fix center tile size per reset 2026-02-14 08:35:30 +08:00
DreamMaoMao
0fe87e6286 fix: fix multi master focus record error 2026-02-13 20:23:03 +08:00
DreamMaoMao
c05eec7f53 feat: support restore stack from non-tile state 2026-02-13 20:02:23 +08:00
DreamMaoMao
8a924494c6 opt: the tagset is current tagset when open window in ov mode 2026-02-13 18:16:06 +08:00
DreamMaoMao
711498490b opt: not back to ov tag when view prev tag 2026-02-13 18:11:18 +08:00
DreamMaoMao
f251615524 opt: flush the blur background cache when unmap a background layer 2026-02-13 11:07:11 +08:00
DreamMaoMao
5ae8975b11 bump version to 0.12.2 2026-02-13 10:44:17 +08:00
DreamMaoMao
313adefd10 opt: better x11 coordinate adjust 2026-02-12 18:55:03 +08:00
DreamMaoMao
17acdae69c opt: make x11 floating window coordinate auto ajust the monitor change 2026-02-12 18:12:01 +08:00
DreamMaoMao
bc52b95c1e opt: make x11 unmanaged window coordinate auto ajust the monitor change 2026-02-12 18:10:02 +08:00
DreamMaoMao
53ee82a726 feat: make force_tiled_state as a option 2026-02-12 11:19:39 +08:00
DreamMaoMao
8484093e32 fix: crash when pointerfocus to a null scene client 2026-02-11 20:44:44 +08:00
DreamMaoMao
b5a157038c opt: tell the synckeymap timer not need to call anymore 2026-02-11 08:31:22 +08:00
DreamMaoMao
783cb86c56 feat: support match monitor make model serial 2026-02-10 10:31:31 +08:00
DreamMaoMao
c7f90cbc69 bump version to 0.12.1 2026-02-09 18:08:28 +08:00
DreamMaoMao
b05bc1ce65 opt: add btn_left and btn_right bind check in config check 2026-02-09 11:50:54 +08:00
DreamMaoMao
6b79a432a4 opt: allow none mode in some mouse button 2026-02-09 11:18:14 +08:00
Daniel Jampen
454145f6e0
support isfakefullscreen as windowrule property 2026-02-08 17:56:26 +01:00
DreamMaoMao
6970315822
Update README.md 2026-02-08 18:17:55 +08:00
DreamMaoMao
e8bf6380fb opt: turn keymap sync into XWAYLAND macro 2026-02-08 12:44:56 +08:00
DreamMaoMao
4820b7a8ab feat: allow single mod keybind 2026-02-08 12:15:44 +08:00
DreamMaoMao
faf2e1e9da opt: sync keymap to xwayland after xwayland ready 2026-02-08 12:13:04 +08:00
DreamMaoMao
acf8363714
Merge pull request #642 from iynaix/source-optional
feat: add a source-optional keyword
2026-02-08 11:27:22 +08:00
DreamMaoMao
241afb4b97 fix: warpcursor not apply in some case 2026-02-08 11:18:38 +08:00
Lin Xianyi
5de87db8ca feat: add a source-optional keyword 2026-02-08 11:15:16 +08:00
DreamMaoMao
9b92f139c0 fix: correct dmabuf version 2026-02-07 21:46:18 +08:00
DreamMaoMao
e658f5c90d opt: fix format 2026-02-07 19:57:07 +08:00
Yujonpradhananga
3db2ac58b4 opt: fix spelling mistake 2026-02-07 17:45:11 +08:00
DreamMaoMao
f8dfeedff1 fix: headless backend cant use keybarod and pointer 2026-02-07 17:32:38 +08:00
DreamMaoMao
2ca2ab739d
Merge pull request #640 from iynaix/mmsg-help
fix: improve help message for mmsg
2026-02-07 17:30:20 +08:00
DreamMaoMao
9e5bccb457
Merge pull request #639 from iynaix/config-exit-code
fix: -p exits with failure if there are parse failures
2026-02-07 17:30:06 +08:00
Lin Xianyi
2734d91e6a fix: improve help message for mmsg 2026-02-07 13:31:30 +08:00
Lin Xianyi
818652d20f fix: -p exits with failure if there are parse failures 2026-02-07 12:12:13 +08:00
DreamMaoMao
4586319bef
Merge pull request #637 from talned/main
Add DesktopNames entry to mango.desktop
2026-02-06 16:14:17 +08:00
Talmed
080dfaa3ae
Add DesktopNames entry to mango.desktop 2026-02-06 19:04:16 +11:00
DreamMaoMao
00a7e579c9 fix: miss reset root color when reload config 2026-02-06 07:43:09 +08:00
DreamMaoMao
8e898417a7 opt: key name case insensitive in keybind 2026-02-05 11:06:52 +08:00
DreamMaoMao
65fcd58949 opt: optimize file detect message 2026-02-04 21:50:44 +08:00
DreamMaoMao
2bda8e3bf1 opt: avoid double reset foreign toplevel handle 2026-02-04 21:42:05 +08:00
DreamMaoMao
a4faf2c494 opt: avoid stack inner per change when switch tty 2026-02-04 21:29:37 +08:00
DreamMaoMao
b0f839468c opt: don't change stack inner per when swallow 2026-02-04 17:42:13 +08:00
DreamMaoMao
8ba259fbb7 opt: avoid opacity flickering in focus animation when open new window 2026-02-04 09:45:26 +08:00
DreamMaoMao
16e361e1ca
Merge pull request #630 from axQuadratic/tagmon_fix
Fix uninitialised argument fields when calling `mmsg -d`
2026-02-04 09:05:01 +08:00
quadratic
336f873d83 fix: uninitialised argument fields when calling mmsg -d 2026-02-03 21:11:41 +01:00
DreamMaoMao
50b67ac539 fix: miss init arg value 2026-02-03 10:15:42 +08:00
DreamMaoMao
0546a2d4c4 opt: allow use comma symbol in spawn shell value 2026-02-03 10:06:26 +08:00
DreamMaoMao
eb0607501d opt: change drag resize request limit to 120hz for floating window 2026-02-02 14:54:09 +08:00
DreamMaoMao
bcee63fa76 feat: add config check in mango cli 2026-02-02 14:54:09 +08:00
DreamMaoMao
5172444e08 bump version to 0.12.0 2026-02-01 15:33:05 +08:00
DreamMaoMao
ca09aa69db opt: not hide null buffer layer if is not mapped 2026-01-30 08:47:12 +08:00
DreamMaoMao
aa5241fb7b fix: allow layer surface attach null buffer 2026-01-29 22:31:41 +08:00
DreamMaoMao
672706c71f fix: not apply vrr disalbe when enable it at the beginning 2026-01-29 11:58:28 +08:00
DreamMaoMao
d9f679a8e3 fix: tagcrossmon not apply in current monitor 2026-01-29 09:49:25 +08:00
DreamMaoMao
4591b69e4d fix: accel_profile can't set to 0 2026-01-29 09:34:58 +08:00
DreamMaoMao
e535aea28b fix: avoid redundant frame requests 2026-01-28 14:50:27 +08:00
DreamMaoMao
30692f6da0 feat: add option hotarea_corner 2026-01-28 09:39:27 +08:00
DreamMaoMao
2e6e23633e break change: remove useless option adaptive_sync 2026-01-28 09:39:27 +08:00
DreamMaoMao
6624d80522 break change: new monitorrule format 2026-01-28 09:39:27 +08:00
DreamMaoMao
05010a1114 fix: crash when some qt app commit a null surface 2026-01-26 18:35:08 +08:00
DreamMaoMao
00de523039 fix: border apply error for smartgap 2026-01-24 23:05:13 +08:00
DreamMaoMao
f1cca251b8 fix: bordercorlor not update when it is in open animaiton 2026-01-24 22:58:47 +08:00
DreamMaoMao
0652f99e6e opt: change preset config prefer 2026-01-24 22:58:47 +08:00
DreamMaoMao
334bc076a0 opt: optimize smartgap 2026-01-24 22:58:47 +08:00
DreamMaoMao
49921eadfa feat: add drag_corner drag_warp_cursor 2026-01-21 13:54:55 +08:00
18 changed files with 1549 additions and 530 deletions

View file

@ -23,19 +23,9 @@ This project's development is based on [dwl](https://codeberg.org/dwl/dwl/).
- Ipc support(get/send message from/to compositor by external program) - Ipc support(get/send message from/to compositor by external program)
- Hycov-like overview - Hycov-like overview
- Window effects from scenefx (blur, shadow, corner radius, opacity) - Window effects from scenefx (blur, shadow, corner radius, opacity)
- Zero flickering - every frame is perfect.
Master-Stack Layout https://github.com/user-attachments/assets/bb83004a-0563-4b48-ad89-6461a9b78b1f
https://github.com/user-attachments/assets/a9d4776e-b50b-48fb-94ce-651d8a749b8a
Scroller Layout
https://github.com/user-attachments/assets/c9bf9415-fad1-4400-bcdc-3ad2d76de85a
Layer animation
https://github.com/user-attachments/assets/014c893f-115c-4ae9-8342-f9ae3e9a0df0
# Our discord # Our discord
[mangowc](https://discord.gg/CPjbDxesh5) [mangowc](https://discord.gg/CPjbDxesh5)
@ -54,6 +44,8 @@ https://github.com/user-attachments/assets/014c893f-115c-4ae9-8342-f9ae3e9a0df0
# Installation # Installation
[![Packaging status](https://repology.org/badge/vertical-allrepos/mangowc.svg)](https://repology.org/project/mangowc/versions)
## Dependencies ## Dependencies
- glibc - glibc
@ -75,7 +67,7 @@ https://github.com/user-attachments/assets/014c893f-115c-4ae9-8342-f9ae3e9a0df0
- libxcb - libxcb
## Arch Linux ## 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: The package is in the Arch User Repository and is available for manual download [here](https://aur.archlinux.org/packages/mangowc-git) or through a AUR helper like yay:
```bash ```bash
yay -S mangowc-git yay -S mangowc-git
@ -109,6 +101,34 @@ Then, install the package:
dnf install mangowc dnf install mangowc
``` ```
## GuixSD
The package definition is described in the source repository.
First, add `mangowc` channel to `channels.scm` file:
```scheme
;; In $HOME/.config/guix/channels.scm
(cons (channel
(name 'mangowc)
(url "https://github.com/DreamMaoMao/mangowc.git"))
... ;; Your other channels
%default-channels)
```
Then, run `guix pull` and after update you can either run
`guix install mangowc` or add it to your configuration via:
```scheme
(use-modules (mangowc)) ;; Add mangowc module
;; Add mangowc to packages list
(packages (cons
mangowc
... ;; Other packages you specified
%base-packages))
```
And then rebuild your system.
## Other ## Other
```bash ```bash

View file

@ -240,12 +240,11 @@ bind=CTRL+ALT,Left,resizewin,-50,+0
bind=CTRL+ALT,Right,resizewin,+50,+0 bind=CTRL+ALT,Right,resizewin,+50,+0
# Mouse Button Bindings # Mouse Button Bindings
# NONE mode key only work in ov mode # btn_left and btn_right can't bind none mod key
mousebind=SUPER,btn_left,moveresize,curmove mousebind=SUPER,btn_left,moveresize,curmove
mousebind=NONE,btn_middle,togglemaximizescreen,0 mousebind=NONE,btn_middle,togglemaximizescreen,0
mousebind=SUPER,btn_right,moveresize,curresize mousebind=SUPER,btn_right,moveresize,curresize
mousebind=NONE,btn_left,toggleoverview,1
mousebind=NONE,btn_right,killclient,0
# Axis Bindings # Axis Bindings
axisbind=SUPER,UP,viewtoleft_have_client axisbind=SUPER,UP,viewtoleft_have_client

View file

@ -1,6 +1,7 @@
[Desktop Entry] [Desktop Entry]
Encoding=UTF-8 Encoding=UTF-8
Name=Mango Name=Mango
DesktopNames=mango;wlroots
Comment=mango WM Comment=mango WM
Exec=mango Exec=mango
Icon=mango Icon=mango

View file

@ -1,5 +1,5 @@
project('mango', ['c', 'cpp'], project('mango', ['c', 'cpp'],
version : '0.11.0', version : '0.12.3',
) )
subdir('protocols') subdir('protocols')
@ -56,7 +56,7 @@ endif
if is_git_repo if is_git_repo
# 如果是 Git 目录,获取 Commit Hash 和最新的 tag # 如果是 Git 目录,获取 Commit Hash 和最新的 tag
commit_hash = run_command(git, 'rev-parse', '--short', 'HEAD', check : false).stdout().strip() commit_hash = run_command(git, 'rev-parse', '--short', 'HEAD', check : false).stdout().strip()
latest_tag = run_command(git, 'describe', '--tags', '--abbrev=0', check : false).stdout().strip() latest_tag = meson.project_version()
version_with_hash = '@0@(@1@)'.format(latest_tag, commit_hash) version_with_hash = '@0@(@1@)'.format(latest_tag, commit_hash)
else else
# 如果不是 Git 目录,使用项目版本号和 "release" 字符串 # 如果不是 Git 目录,使用项目版本号和 "release" 字符串

View file

@ -500,12 +500,48 @@ static const struct wl_registry_listener registry_listener = {
static void usage(void) { static void usage(void) {
fprintf(stderr, fprintf(stderr,
"usage:" "mmsg - MangoWC IPC\n"
"\t%s [-OTLq]\n" "\n"
"\t%s [-o <output>] -s [-t <tags>] [-l <layout>] [-c <tags>] [-d " "SYNOPSIS:\n"
"\tmmsg [-OTLq]\n"
"\tmmsg [-o <output>] -s [-t <tags>] [-l <layout>] [-c <tags>] [-d "
"<cmd>,<arg1>,<arg2>,<arg3>,<arg4>,<arg5>]\n" "<cmd>,<arg1>,<arg2>,<arg3>,<arg4>,<arg5>]\n"
"\t%s [-o <output>] (-g | -w) [-OotlcvmfxekbA]\n", "\tmmsg [-o <output>] (-g | -w) [-OotlcvmfxekbA]\n"
argv0, argv0, argv0); "\n"
"OPERATION MODES:\n"
"\t-g Get values (tags, layout, focused client)\n"
"\t-s Set values (switch tags, layouts)\n"
"\t-w Watch mode (stream events)\n"
"\n"
"GENERAL OPTIONS:\n"
"\t-O Get all output (monitor) information\n"
"\t-T Get number of tags\n"
"\t-L Get all available layouts\n"
"\t-q Quit MangoWC\n"
"\t-o <output> Select output (monitor)\n"
"\n"
"GET OPTIONS (used with -g or -w):\n"
"\t-O Get output name\n"
"\t-o Get output (monitor) focus information\n"
"\t-t Get selected tags\n"
"\t-l Get current layout\n"
"\t-c Get title and appid of focused clients\n"
"\t-v Get visibility of statusbar\n"
"\t-m Get fullscreen status\n"
"\t-f Get floating status\n"
"\t-x Get focused client geometry\n"
"\t-e Get name of last focused layer\n"
"\t-k Get current keyboard layout\n"
"\t-b Get current keybind mode\n"
"\t-A Get scale factor of monitor\n"
"\n"
"SET OPTIONS (used with -s):\n"
"\t-o <output> Select output (monitor)\n"
"\t-t <tags> Set selected tags (can be used with [+-^.] "
"modifiers)\n"
"\t-l <layout> Set current layout\n"
"\t-c <tags> Get title and appid of focused client\n"
"\t-d <cmd>,<args...> Dispatch internal command (max 5 args)\n");
exit(2); exit(2);
} }

View file

@ -1,6 +1,6 @@
wayland_scanner = find_program('wayland-scanner') wayland_scanner = find_program('wayland-scanner')
wayland_protos_dep = dependency('wayland-protocols') wayland_protos_dep = dependency('wayland-protocols')
wl_protocol_dir = wayland_protos_dep.get_pkgconfig_variable('pkgdatadir') wl_protocol_dir = wayland_protos_dep.get_variable(pkgconfig:'pkgdatadir')
wayland_scanner_code = generator( wayland_scanner_code = generator(
wayland_scanner, wayland_scanner,
output: '@BASENAME@-protocol.c', output: '@BASENAME@-protocol.c',

View file

@ -47,7 +47,7 @@ bool is_horizontal_right_stack_layout(Monitor *m) {
return false; return false;
} }
int32_t is_special_animaiton_rule(Client *c) { int32_t is_special_animation_rule(Client *c) {
if (is_scroller_layout(c->mon) && !c->isfloating) { if (is_scroller_layout(c->mon) && !c->isfloating) {
return DOWN; return DOWN;
@ -70,7 +70,7 @@ int32_t is_special_animaiton_rule(Client *c) {
} }
} }
void set_client_open_animaiton(Client *c, struct wlr_box geo) { void set_client_open_animation(Client *c, struct wlr_box geo) {
int32_t slide_direction; int32_t slide_direction;
int32_t horizontal, horizontal_value; int32_t horizontal, horizontal_value;
int32_t vertical, vertical_value; int32_t vertical, vertical_value;
@ -96,7 +96,7 @@ void set_client_open_animaiton(Client *c, struct wlr_box geo) {
geo.y + (geo.height - c->animainit_geom.height) / 2; geo.y + (geo.height - c->animainit_geom.height) / 2;
return; return;
} else { } else {
special_direction = is_special_animaiton_rule(c); special_direction = is_special_animation_rule(c);
center_x = c->geom.x + c->geom.width / 2; center_x = c->geom.x + c->geom.width / 2;
center_y = c->geom.y + c->geom.height / 2; center_y = c->geom.y + c->geom.height / 2;
if (special_direction == UNDIR) { if (special_direction == UNDIR) {
@ -363,7 +363,6 @@ void apply_border(Client *c) {
current_corner_location = set_client_corner_location(c); current_corner_location = set_client_corner_location(c);
} }
// Handle no-border cases
if (hit_no_border && smartgaps) { if (hit_no_border && smartgaps) {
c->bw = 0; c->bw = 0;
c->fake_no_border = true; c->fake_no_border = true;
@ -773,71 +772,71 @@ void init_fadeout_client(Client *c) {
return; return;
} }
Client *fadeout_cient = ecalloc(1, sizeof(*fadeout_cient)); Client *fadeout_client = ecalloc(1, sizeof(*fadeout_client));
wlr_scene_node_set_enabled(&c->scene->node, true); wlr_scene_node_set_enabled(&c->scene->node, true);
client_set_border_color(c, bordercolor); client_set_border_color(c, bordercolor);
fadeout_cient->scene = fadeout_client->scene =
wlr_scene_tree_snapshot(&c->scene->node, layers[LyrFadeOut]); wlr_scene_tree_snapshot(&c->scene->node, layers[LyrFadeOut]);
wlr_scene_node_set_enabled(&c->scene->node, false); wlr_scene_node_set_enabled(&c->scene->node, false);
if (!fadeout_cient->scene) { if (!fadeout_client->scene) {
free(fadeout_cient); free(fadeout_client);
return; return;
} }
fadeout_cient->animation.duration = animation_duration_close; fadeout_client->animation.duration = animation_duration_close;
fadeout_cient->geom = fadeout_cient->current = fadeout_client->geom = fadeout_client->current =
fadeout_cient->animainit_geom = fadeout_cient->animation.initial = fadeout_client->animainit_geom = fadeout_client->animation.initial =
c->animation.current; c->animation.current;
fadeout_cient->mon = c->mon; fadeout_client->mon = c->mon;
fadeout_cient->animation_type_close = c->animation_type_close; fadeout_client->animation_type_close = c->animation_type_close;
fadeout_cient->animation.action = CLOSE; fadeout_client->animation.action = CLOSE;
fadeout_cient->bw = c->bw; fadeout_client->bw = c->bw;
fadeout_cient->nofadeout = c->nofadeout; fadeout_client->nofadeout = c->nofadeout;
// 这里snap节点的坐标设置是使用的相对坐标所以不能加上原来坐标 // 这里snap节点的坐标设置是使用的相对坐标所以不能加上原来坐标
// 这跟普通node有区别 // 这跟普通node有区别
fadeout_cient->animation.initial.x = 0; fadeout_client->animation.initial.x = 0;
fadeout_cient->animation.initial.y = 0; fadeout_client->animation.initial.y = 0;
if ((!c->animation_type_close && if ((!c->animation_type_close &&
strcmp(animation_type_close, "fade") == 0) || strcmp(animation_type_close, "fade") == 0) ||
(c->animation_type_close && (c->animation_type_close &&
strcmp(c->animation_type_close, "fade") == 0)) { strcmp(c->animation_type_close, "fade") == 0)) {
fadeout_cient->current.x = 0; fadeout_client->current.x = 0;
fadeout_cient->current.y = 0; fadeout_client->current.y = 0;
fadeout_cient->current.width = 0; fadeout_client->current.width = 0;
fadeout_cient->current.height = 0; fadeout_client->current.height = 0;
} else if ((c->animation_type_close && } else if ((c->animation_type_close &&
strcmp(c->animation_type_close, "slide") == 0) || strcmp(c->animation_type_close, "slide") == 0) ||
(!c->animation_type_close && (!c->animation_type_close &&
strcmp(animation_type_close, "slide") == 0)) { strcmp(animation_type_close, "slide") == 0)) {
fadeout_cient->current.y = fadeout_client->current.y =
c->geom.y + c->geom.height / 2 > c->mon->m.y + c->mon->m.height / 2 c->geom.y + c->geom.height / 2 > c->mon->m.y + c->mon->m.height / 2
? c->mon->m.height - ? c->mon->m.height -
(c->animation.current.y - c->mon->m.y) // down out (c->animation.current.y - c->mon->m.y) // down out
: c->mon->m.y - c->geom.height; // up out : c->mon->m.y - c->geom.height; // up out
fadeout_cient->current.x = 0; // x无偏差垂直划出 fadeout_client->current.x = 0; // x无偏差垂直划出
} else { } else {
fadeout_cient->current.y = fadeout_client->current.y =
(fadeout_cient->geom.height - (fadeout_client->geom.height -
fadeout_cient->geom.height * zoom_end_ratio) / fadeout_client->geom.height * zoom_end_ratio) /
2; 2;
fadeout_cient->current.x = fadeout_client->current.x =
(fadeout_cient->geom.width - (fadeout_client->geom.width -
fadeout_cient->geom.width * zoom_end_ratio) / fadeout_client->geom.width * zoom_end_ratio) /
2; 2;
fadeout_cient->current.width = fadeout_client->current.width =
fadeout_cient->geom.width * zoom_end_ratio; fadeout_client->geom.width * zoom_end_ratio;
fadeout_cient->current.height = fadeout_client->current.height =
fadeout_cient->geom.height * zoom_end_ratio; fadeout_client->geom.height * zoom_end_ratio;
} }
fadeout_cient->animation.time_started = get_now_in_ms(); fadeout_client->animation.time_started = get_now_in_ms();
wlr_scene_node_set_enabled(&fadeout_cient->scene->node, true); wlr_scene_node_set_enabled(&fadeout_client->scene->node, true);
wl_list_insert(&fadeout_clients, &fadeout_cient->fadeout_link); wl_list_insert(&fadeout_clients, &fadeout_client->fadeout_link);
// 请求刷新屏幕 // 请求刷新屏幕
request_fresh_all_monitors(); request_fresh_all_monitors();
@ -972,7 +971,7 @@ void resize(Client *c, struct wlr_box geo, int32_t interact) {
c->animainit_geom.height = c->animation.current.height; c->animainit_geom.height = c->animation.current.height;
c->animainit_geom.width = c->animation.current.width; c->animainit_geom.width = c->animation.current.width;
} else if (c->is_pending_open_animation) { } else if (c->is_pending_open_animation) {
set_client_open_animaiton(c, c->geom); set_client_open_animation(c, c->geom);
} else { } else {
c->animainit_geom = c->animation.current; c->animainit_geom = c->animation.current;
} }
@ -981,6 +980,12 @@ void resize(Client *c, struct wlr_box geo, int32_t interact) {
c->bw = 0; c->bw = 0;
} }
bool hit_no_border = check_hit_no_border(c);
if (hit_no_border && smartgaps) {
c->bw = 0;
c->fake_no_border = true;
}
// c->geom 是真实的窗口大小和位置,跟过度的动画无关,用于计算布局 // c->geom 是真实的窗口大小和位置,跟过度的动画无关,用于计算布局
c->configure_serial = client_set_size(c, c->geom.width - 2 * c->bw, c->configure_serial = client_set_size(c, c->geom.width - 2 * c->bw,
c->geom.height - 2 * c->bw); c->geom.height - 2 * c->bw);
@ -1049,20 +1054,11 @@ void client_set_focused_opacity_animation(Client *c) {
sizeof(c->opacity_animation.target_border_color)); sizeof(c->opacity_animation.target_border_color));
c->opacity_animation.target_opacity = c->focused_opacity; c->opacity_animation.target_opacity = c->focused_opacity;
c->opacity_animation.time_started = get_now_in_ms(); c->opacity_animation.time_started = get_now_in_ms();
if (c->opacity_animation.running) { memcpy(c->opacity_animation.initial_border_color,
memcpy(c->opacity_animation.initial_border_color, c->opacity_animation.current_border_color,
c->opacity_animation.current_border_color, sizeof(c->opacity_animation.initial_border_color));
sizeof(c->opacity_animation.initial_border_color)); c->opacity_animation.initial_opacity = c->opacity_animation.current_opacity;
c->opacity_animation.initial_opacity =
c->opacity_animation.current_opacity;
} else {
memcpy(c->opacity_animation.initial_border_color, border_color,
sizeof(c->opacity_animation.initial_border_color));
memcpy(c->opacity_animation.current_border_color, border_color,
sizeof(c->opacity_animation.current_border_color));
c->opacity_animation.initial_opacity = c->unfocused_opacity;
c->opacity_animation.current_opacity = c->unfocused_opacity;
}
c->opacity_animation.running = true; c->opacity_animation.running = true;
} }
@ -1082,20 +1078,10 @@ void client_set_unfocused_opacity_animation(Client *c) {
c->opacity_animation.target_opacity = c->unfocused_opacity; c->opacity_animation.target_opacity = c->unfocused_opacity;
c->opacity_animation.time_started = get_now_in_ms(); c->opacity_animation.time_started = get_now_in_ms();
if (c->opacity_animation.running) { memcpy(c->opacity_animation.initial_border_color,
memcpy(c->opacity_animation.initial_border_color, c->opacity_animation.current_border_color,
c->opacity_animation.current_border_color, sizeof(c->opacity_animation.initial_border_color));
sizeof(c->opacity_animation.initial_border_color)); c->opacity_animation.initial_opacity = c->opacity_animation.current_opacity;
c->opacity_animation.initial_opacity =
c->opacity_animation.current_opacity;
} else {
memcpy(c->opacity_animation.initial_border_color, border_color,
sizeof(c->opacity_animation.initial_border_color));
memcpy(c->opacity_animation.current_border_color, border_color,
sizeof(c->opacity_animation.current_border_color));
c->opacity_animation.initial_opacity = c->focused_opacity;
c->opacity_animation.current_opacity = c->focused_opacity;
}
c->opacity_animation.running = true; c->opacity_animation.running = true;
} }
@ -1130,7 +1116,12 @@ bool client_apply_focus_opacity(Client *c) {
if (target_opacity > opacity) { if (target_opacity > opacity) {
target_opacity = opacity; target_opacity = opacity;
} }
memcpy(c->opacity_animation.current_border_color,
c->opacity_animation.target_border_color,
sizeof(c->opacity_animation.current_border_color));
c->opacity_animation.current_opacity = target_opacity;
client_set_opacity(c, target_opacity); client_set_opacity(c, target_opacity);
client_set_border_color(c, c->opacity_animation.target_border_color);
} else if (animations && c->opacity_animation.running) { } else if (animations && c->opacity_animation.running) {
struct timespec now; struct timespec now;
@ -1161,7 +1152,7 @@ bool client_apply_focus_opacity(Client *c) {
eased_progress; eased_progress;
} }
client_set_border_color(c, c->opacity_animation.current_border_color); client_set_border_color(c, c->opacity_animation.current_border_color);
if (linear_progress == 1.0f) { if (linear_progress >= 1.0f) {
c->opacity_animation.running = false; c->opacity_animation.running = false;
} else { } else {
return true; return true;

View file

@ -254,10 +254,13 @@ static inline int32_t client_is_stopped(Client *c) {
wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL); wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);
if (waitid(P_PID, pid, &in, WNOHANG | WCONTINUED | WSTOPPED | WNOWAIT) < if (waitid(P_PID, pid, &in, WNOHANG | WCONTINUED | WSTOPPED | WNOWAIT) <
0) { 0) {
/* This process is not our child process, while is very unluckely that /* This process is not our child process. We cannot determine its
* it is stopped, in order to do not skip frames assume that it is. */ * stopped state; assume it is not stopped to avoid blocking frame skip.
*/
if (errno == ECHILD) if (errno == ECHILD)
return 1; return 0; // if not our child, assume not stopped
/* Other errors, also assume not stopped. */
return 0;
} else if (in.si_pid) { } else if (in.si_pid) {
if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED) if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED)
return 1; return 1;
@ -319,9 +322,24 @@ static inline uint32_t client_set_size(Client *c, uint32_t width,
uint32_t height) { uint32_t height) {
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c)) {
struct wlr_surface_state *state =
&c->surface.xwayland->surface->current;
if ((int32_t)c->geom.width - 2 * (int32_t)c->bw ==
(int32_t)state->width &&
(int32_t)c->geom.height - 2 * (int32_t)c->bw ==
(int32_t)state->height &&
(int32_t)c->surface.xwayland->x ==
(int32_t)c->geom.x + (int32_t)c->bw &&
(int32_t)c->surface.xwayland->y ==
(int32_t)c->geom.y + (int32_t)c->bw) {
return 0;
}
wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x + c->bw, wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x + c->bw,
c->geom.y + c->bw, width, height); c->geom.y + c->bw, width, height);
return 0; return 1;
} }
#endif #endif
if ((int32_t)width == c->surface.xdg->toplevel->current.width && if ((int32_t)width == c->surface.xdg->toplevel->current.width &&
@ -547,4 +565,4 @@ static inline void client_set_size_bound(Client *c) {
state.max_height > 0) { state.max_height > 0) {
c->geom.height = state.max_height + 2 * c->bw; c->geom.height = state.max_height + 2 * c->bw;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -47,8 +47,9 @@ int32_t log_level = WLR_ERROR;
uint32_t numlockon = 0; // 是否打开右边小键盘 uint32_t numlockon = 0; // 是否打开右边小键盘
uint32_t capslock = 0; // 是否启用快捷键 uint32_t capslock = 0; // 是否启用快捷键
uint32_t ov_tab_mode = 0; // alt tab切换模式 uint32_t ov_tab_mode = 0; // alt tab切换模式
uint32_t hotarea_size = 10; // 热区大小,10x10 uint32_t hotarea_size = 10; // 热区大小,10x10
uint32_t hotarea_corner = BOTTOM_LEFT;
uint32_t enable_hotarea = 1; // 是否启用鼠标热区 uint32_t enable_hotarea = 1; // 是否启用鼠标热区
int32_t smartgaps = 0; /* 1 means no outer gap when there is only one window */ int32_t smartgaps = 0; /* 1 means no outer gap when there is only one window */
int32_t sloppyfocus = 1; /* focus follows mouse */ int32_t sloppyfocus = 1; /* focus follows mouse */
@ -62,9 +63,10 @@ float scratchpad_height_ratio = 0.9;
int32_t scroller_structs = 20; int32_t scroller_structs = 20;
float scroller_default_proportion = 0.9; float scroller_default_proportion = 0.9;
float scroller_default_proportion_single = 1.0; float scroller_default_proportion_single = 1.0;
int32_t scroller_ignore_proportion_single = 0; int32_t scroller_ignore_proportion_single = 1;
int32_t scroller_focus_center = 0; int32_t scroller_focus_center = 0;
int32_t scroller_prefer_center = 0; int32_t scroller_prefer_center = 0;
int32_t scroller_prefer_overspread = 1;
int32_t focus_cross_monitor = 0; int32_t focus_cross_monitor = 0;
int32_t focus_cross_tag = 0; int32_t focus_cross_tag = 0;
int32_t exchange_cross_monitor = 0; int32_t exchange_cross_monitor = 0;
@ -101,12 +103,14 @@ int32_t overviewgappo = 30; /* overview时 窗口与窗口 缝隙大小 */
* behavior */ * behavior */
float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
int32_t warpcursor = 1; /* Warp cursor to focused client */ int32_t warpcursor = 1;
int32_t drag_corner = 3;
int32_t drag_warp_cursor = 1;
int32_t xwayland_persistence = 1; /* xwayland persistence */ int32_t xwayland_persistence = 1; /* xwayland persistence */
int32_t syncobj_enable = 0; int32_t syncobj_enable = 0;
int32_t adaptive_sync = 0;
int32_t allow_lock_transparent = 0; int32_t allow_lock_transparent = 0;
double drag_refresh_interval = 16.0; double drag_tile_refresh_interval = 16.0;
double drag_floating_refresh_interval = 8.0;
int32_t allow_tearing = TEARING_DISABLED; int32_t allow_tearing = TEARING_DISABLED;
int32_t allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE; int32_t allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
@ -233,4 +237,3 @@ double shadows_blur = 15;
int32_t shadows_position_x = 0; int32_t shadows_position_x = 0;
int32_t shadows_position_y = 0; int32_t shadows_position_y = 0;
float shadowscolor[] = COLOR(0x000000ff); float shadowscolor[] = COLOR(0x000000ff);
;

View file

@ -338,6 +338,9 @@ int32_t killclient(const Arg *arg) {
} }
int32_t moveresize(const Arg *arg) { int32_t moveresize(const Arg *arg) {
const char *cursors[] = {"nw-resize", "ne-resize", "sw-resize",
"se-resize"};
if (cursor_mode != CurNormal && cursor_mode != CurPressed) if (cursor_mode != CurNormal && cursor_mode != CurPressed)
return 0; return 0;
xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
@ -363,10 +366,29 @@ int32_t moveresize(const Arg *arg) {
/* Doesn't work for X11 output - the next absolute motion event /* Doesn't work for X11 output - the next absolute motion event
* returns the cursor to where it started */ * returns the cursor to where it started */
if (grabc->isfloating) { if (grabc->isfloating) {
wlr_cursor_warp_closest(cursor, NULL, rzcorner = drag_corner;
grabc->geom.x + grabc->geom.width, grabcx = (int)round(cursor->x);
grabc->geom.y + grabc->geom.height); grabcy = (int)round(cursor->y);
wlr_cursor_set_xcursor(cursor, cursor_mgr, "bottom_right_corner"); if (rzcorner == 4)
/* identify the closest corner index */
rzcorner = (grabcx - grabc->geom.x <
grabc->geom.x + grabc->geom.width - grabcx
? 0
: 1) +
(grabcy - grabc->geom.y <
grabc->geom.y + grabc->geom.height - grabcy
? 0
: 2);
if (drag_warp_cursor) {
grabcx = rzcorner & 1 ? grabc->geom.x + grabc->geom.width
: grabc->geom.x;
grabcy = rzcorner & 2 ? grabc->geom.y + grabc->geom.height
: grabc->geom.y;
wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy);
}
wlr_cursor_set_xcursor(cursor, cursor_mgr, cursors[rzcorner]);
} else { } else {
wlr_cursor_set_xcursor(cursor, cursor_mgr, "grab"); wlr_cursor_set_xcursor(cursor, cursor_mgr, "grab");
} }
@ -878,16 +900,20 @@ int32_t switch_keyboard_layout(const Arg *arg) {
wlr_log(WLR_INFO, "Only one layout available"); wlr_log(WLR_INFO, "Only one layout available");
return 0; return 0;
} }
xkb_layout_index_t next = (current + 1) % num_layouts;
xkb_layout_index_t next = 0;
if (arg->i > 0 && arg->i <= num_layouts) {
next = arg->i - 1;
} else {
next = (current + 1) % num_layouts;
}
// 6. 应用新 keymap // 6. 应用新 keymap
uint32_t depressed = keyboard->modifiers.depressed; uint32_t depressed = keyboard->modifiers.depressed;
uint32_t latched = keyboard->modifiers.latched; uint32_t latched = keyboard->modifiers.latched;
uint32_t locked = keyboard->modifiers.locked; uint32_t locked = keyboard->modifiers.locked;
wlr_keyboard_set_keymap(keyboard, keyboard->keymap);
wlr_keyboard_notify_modifiers(keyboard, depressed, latched, locked, next); wlr_keyboard_notify_modifiers(keyboard, depressed, latched, locked, next);
keyboard->modifiers.group = 0;
// 7. 更新 seat // 7. 更新 seat
wlr_seat_set_keyboard(seat, keyboard); wlr_seat_set_keyboard(seat, keyboard);
@ -901,10 +927,7 @@ int32_t switch_keyboard_layout(const Arg *arg) {
struct wlr_keyboard *tkb = (struct wlr_keyboard *)id->device_data; struct wlr_keyboard *tkb = (struct wlr_keyboard *)id->device_data;
wlr_keyboard_set_keymap(tkb, keyboard->keymap);
wlr_keyboard_notify_modifiers(tkb, depressed, latched, locked, next); wlr_keyboard_notify_modifiers(tkb, depressed, latched, locked, next);
tkb->modifiers.group = 0;
// 7. 更新 seat // 7. 更新 seat
wlr_seat_set_keyboard(seat, tkb); wlr_seat_set_keyboard(seat, tkb);
wlr_seat_keyboard_notify_modifiers(seat, &tkb->modifiers); wlr_seat_keyboard_notify_modifiers(seat, &tkb->modifiers);
@ -1200,13 +1223,15 @@ int32_t togglefloating(const Arg *arg) {
if (!sel) if (!sel)
return 0; return 0;
bool isfloating = sel->isfloating;
if ((sel->isfullscreen || sel->ismaximizescreen)) { if ((sel->isfullscreen || sel->ismaximizescreen)) {
sel->isfloating = 1; isfloating = 1;
} else { } else {
sel->isfloating = !sel->isfloating; isfloating = !sel->isfloating;
} }
setfloating(sel, sel->isfloating); setfloating(sel, isfloating);
return 0; return 0;
} }
@ -1422,9 +1447,14 @@ int32_t viewcrossmon(const Arg *arg) {
} }
int32_t tagcrossmon(const Arg *arg) { int32_t tagcrossmon(const Arg *arg) {
if (!selmon->sel) if (!selmon || !selmon->sel)
return 0; return 0;
if (regex_match(selmon->wlr_output->name, arg->v)) {
tag_client(arg, selmon->sel);
return 0;
}
tagmon(&(Arg){.ui = arg->ui, .i = UNDIR, .v = arg->v}); tagmon(&(Arg){.ui = arg->ui, .i = UNDIR, .v = arg->v});
return 0; return 0;
} }
@ -1499,6 +1529,16 @@ int32_t minimized(const Arg *arg) {
return 0; return 0;
} }
void fix_mon_tagset_from_overview(Monitor *m) {
if (m->tagset[m->seltags] == (m->ovbk_prev_tagset & TAGMASK)) {
m->tagset[m->seltags ^ 1] = m->ovbk_current_tagset;
m->pertag->prevtag = get_tags_first_tag_num(m->ovbk_current_tagset);
} else {
m->tagset[m->seltags ^ 1] = m->ovbk_prev_tagset;
m->pertag->prevtag = get_tags_first_tag_num(m->ovbk_prev_tagset);
}
}
int32_t toggleoverview(const Arg *arg) { int32_t toggleoverview(const Arg *arg) {
Client *c = NULL; Client *c = NULL;
@ -1520,6 +1560,8 @@ int32_t toggleoverview(const Arg *arg) {
visible_client_number++; visible_client_number++;
} }
if (visible_client_number > 0) { if (visible_client_number > 0) {
selmon->ovbk_current_tagset = selmon->tagset[selmon->seltags];
selmon->ovbk_prev_tagset = selmon->tagset[selmon->seltags ^ 1];
target = ~0 & TAGMASK; target = ~0 & TAGMASK;
} else { } else {
selmon->isoverview ^= 1; selmon->isoverview ^= 1;
@ -1530,6 +1572,7 @@ int32_t toggleoverview(const Arg *arg) {
} else if (!selmon->isoverview && !selmon->sel) { } else if (!selmon->isoverview && !selmon->sel) {
target = (1 << (selmon->pertag->prevtag - 1)); target = (1 << (selmon->pertag->prevtag - 1));
view(&(Arg){.ui = target}, false); view(&(Arg){.ui = target}, false);
fix_mon_tagset_from_overview(selmon);
refresh_monitors_workspaces_status(selmon); refresh_monitors_workspaces_status(selmon);
return 0; return 0;
} }
@ -1552,7 +1595,7 @@ int32_t toggleoverview(const Arg *arg) {
} }
view(&(Arg){.ui = target}, false); view(&(Arg){.ui = target}, false);
fix_mon_tagset_from_overview(selmon);
refresh_monitors_workspaces_status(selmon); refresh_monitors_workspaces_status(selmon);
return 0; return 0;
} }

View file

@ -12,7 +12,9 @@ bool check_hit_no_border(Client *c) {
} }
} }
if (no_border_when_single && c && c->mon && c->mon->visible_clients == 1) { if (no_border_when_single && c && c->mon &&
((ISSCROLLTILED(c) && c->mon->visible_scroll_tiling_clients == 1) ||
c->mon->visible_clients == 1)) {
hit_no_border = true; hit_no_border = true;
} }
return hit_no_border; return hit_no_border;
@ -572,23 +574,29 @@ bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc) {
if (id == TILE || id == VERTICAL_TILE || id == DECK || if (id == TILE || id == VERTICAL_TILE || id == DECK ||
id == VERTICAL_DECK || id == RIGHT_TILE) { id == VERTICAL_DECK || id == RIGHT_TILE) {
if (fc && !fc->ismaster) if (tc->ismaster ^ sc->ismaster)
return false; return false;
else if (!sc->ismaster) if (fc && !(fc->ismaster ^ sc->ismaster))
return false;
else
return true; return true;
} }
if (id == TGMIX) { if (id == TGMIX) {
if (fc && !fc->ismaster) if (tc->ismaster ^ sc->ismaster)
return false;
if (fc && !(fc->ismaster ^ sc->ismaster))
return false; return false;
if (!sc->ismaster && sc->mon->visible_tiling_clients <= 3) if (!sc->ismaster && sc->mon->visible_tiling_clients <= 3)
return true; return true;
} }
if (id == CENTER_TILE) { if (id == CENTER_TILE) {
if (fc && !fc->ismaster) if (tc->ismaster ^ sc->ismaster)
return false; return false;
if (!sc->ismaster && sc->geom.x == tc->geom.x) if (fc && !(fc->ismaster ^ sc->ismaster))
return false;
if (sc->geom.x == tc->geom.x)
return true; return true;
else else
return false; return false;

View file

@ -100,10 +100,6 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
surface = wlr_scene_surface_try_from_buffer( surface = wlr_scene_surface_try_from_buffer(
wlr_scene_buffer_from_node(node)) wlr_scene_buffer_from_node(node))
->surface; ->surface;
else if (node->type == WLR_SCENE_NODE_RECT) {
surface = NULL;
break;
}
/* start from the topmost layer, /* start from the topmost layer,
find a sureface that can be focused by pointer, find a sureface that can be focused by pointer,
@ -119,6 +115,13 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
l = pnode->data; l = pnode->data;
} }
} }
if (node->type == WLR_SCENE_NODE_RECT) {
if (c) {
surface = client_surface(c);
}
break;
}
} }
if (psurface) if (psurface)

View file

@ -1,3 +1,45 @@
void restore_size_per(Monitor *m, Client *c) {
Client *fc = NULL;
double total_master_inner_per = 0;
double total_stack_inner_per = 0;
if (!m || !c)
return;
const Layout *current_layout = m->pertag->ltidxs[m->pertag->curtag];
if (current_layout->id == SCROLLER ||
current_layout->id == VERTICAL_SCROLLER || current_layout->id == GRID ||
current_layout->id == VERTICAL_GRID || current_layout->id == DECK ||
current_layout->id == VERTICAL_DECK || current_layout->id == MONOCLE) {
return;
}
if (current_layout->id == CENTER_TILE || c->ismaster) {
wl_list_for_each(fc, &clients, link) {
if (VISIBLEON(fc, m) && ISTILED(fc) && !c->ismaster) {
set_size_per(m, fc);
}
}
return;
}
wl_list_for_each(fc, &clients, link) {
if (VISIBLEON(fc, m) && ISTILED(fc) && fc != c) {
if (fc->ismaster) {
total_master_inner_per += fc->master_inner_per;
} else {
total_stack_inner_per += fc->stack_inner_per;
}
}
}
if (!c->ismaster && total_stack_inner_per) {
c->stack_inner_per = total_stack_inner_per * c->stack_inner_per /
(1 - c->stack_inner_per);
}
}
void set_size_per(Monitor *m, Client *c) { void set_size_per(Monitor *m, Client *c) {
Client *fc = NULL; Client *fc = NULL;
bool found = false; bool found = false;
@ -5,8 +47,13 @@ void set_size_per(Monitor *m, Client *c) {
if (!m || !c) if (!m || !c)
return; return;
const Layout *current_layout = m->pertag->ltidxs[m->pertag->curtag];
wl_list_for_each(fc, &clients, link) { wl_list_for_each(fc, &clients, link) {
if (VISIBLEON(fc, m) && ISTILED(fc) && fc != c) { if (VISIBLEON(fc, m) && ISTILED(fc) && fc != c) {
if (current_layout->id == CENTER_TILE &&
!(fc->isleftstack ^ c->isleftstack))
continue;
c->master_mfact_per = fc->master_mfact_per; c->master_mfact_per = fc->master_mfact_per;
c->master_inner_per = fc->master_inner_per; c->master_inner_per = fc->master_inner_per;
c->stack_inner_per = fc->stack_inner_per; c->stack_inner_per = fc->stack_inner_per;
@ -210,7 +257,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
} }
if (last_apply_drap_time == 0 || if (last_apply_drap_time == 0 ||
time - last_apply_drap_time > drag_refresh_interval) { time - last_apply_drap_time > drag_tile_refresh_interval) {
arrange(grabc->mon, false, false); arrange(grabc->mon, false, false);
last_apply_drap_time = time; last_apply_drap_time = time;
} }
@ -367,7 +414,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
} }
if (last_apply_drap_time == 0 || if (last_apply_drap_time == 0 ||
time - last_apply_drap_time > drag_refresh_interval) { time - last_apply_drap_time > drag_tile_refresh_interval) {
arrange(grabc->mon, false, false); arrange(grabc->mon, false, false);
last_apply_drap_time = time; last_apply_drap_time = time;
} }
@ -548,7 +595,7 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
} }
if (last_apply_drap_time == 0 || if (last_apply_drap_time == 0 ||
time - last_apply_drap_time > drag_refresh_interval) { time - last_apply_drap_time > drag_tile_refresh_interval) {
arrange(grabc->mon, false, false); arrange(grabc->mon, false, false);
last_apply_drap_time = time; last_apply_drap_time = time;
} }

View file

@ -117,6 +117,7 @@ void deck(Monitor *m) {
Client *c = NULL; Client *c = NULL;
Client *fc = NULL; Client *fc = NULL;
float mfact; float mfact;
uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
int32_t cur_gappih = enablegaps ? m->gappih : 0; int32_t cur_gappih = enablegaps ? m->gappih : 0;
int32_t cur_gappoh = enablegaps ? m->gappoh : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
@ -142,8 +143,8 @@ void deck(Monitor *m) {
: m->pertag->mfacts[m->pertag->curtag]; : m->pertag->mfacts[m->pertag->curtag];
// Calculate master width including outer gaps // Calculate master width including outer gaps
if (n > m->nmaster) if (n > nmasters)
mw = m->nmaster ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0; mw = nmasters ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0;
else else
mw = m->w.width - 2 * cur_gappoh; mw = m->w.width - 2 * cur_gappoh;
@ -151,7 +152,7 @@ void deck(Monitor *m) {
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, m) || !ISTILED(c)) if (!VISIBLEON(c, m) || !ISTILED(c))
continue; continue;
if (i < m->nmaster) { if (i < nmasters) {
c->master_mfact_per = mfact; c->master_mfact_per = mfact;
// Master area clients // Master area clients
resize( resize(
@ -160,7 +161,7 @@ void deck(Monitor *m) {
.y = m->w.y + cur_gappov + my, .y = m->w.y + cur_gappov + my,
.width = mw, .width = mw,
.height = (m->w.height - 2 * cur_gappov - my) / .height = (m->w.height - 2 * cur_gappov - my) /
(MIN(n, m->nmaster) - i)}, (MIN(n, nmasters) - i)},
0); 0);
my += c->geom.height; my += c->geom.height;
} else { } else {
@ -282,6 +283,7 @@ void scroller(Monitor *m) {
struct wlr_box target_geom; struct wlr_box target_geom;
int32_t focus_client_index = 0; int32_t focus_client_index = 0;
bool need_scroller = false; bool need_scroller = false;
bool over_overspread_to_left = false;
int32_t cur_gappih = enablegaps ? m->gappih : 0; int32_t cur_gappih = enablegaps ? m->gappih : 0;
int32_t cur_gappoh = enablegaps ? m->gappoh : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
int32_t cur_gappov = enablegaps ? m->gappov : 0; int32_t cur_gappov = enablegaps ? m->gappov : 0;
@ -370,6 +372,46 @@ void scroller(Monitor *m) {
} }
} }
bool need_apply_overspread =
scroller_prefer_overspread && m->visible_scroll_tiling_clients > 1 &&
(focus_client_index == 0 || focus_client_index == n - 1) &&
tempClients[focus_client_index]->scroller_proportion < 1.0f;
if (need_apply_overspread) {
if (focus_client_index == 0) {
over_overspread_to_left = true;
} else {
over_overspread_to_left = false;
}
if (over_overspread_to_left &&
(!INSIDEMON(tempClients[1]) ||
(tempClients[1]->scroller_proportion +
tempClients[focus_client_index]->scroller_proportion >=
1.0f))) {
need_scroller = true;
} else if (!over_overspread_to_left &&
(!INSIDEMON(tempClients[focus_client_index - 1]) ||
(tempClients[focus_client_index - 1]->scroller_proportion +
tempClients[focus_client_index]->scroller_proportion >=
1.0f))) {
need_scroller = true;
} else {
need_apply_overspread = false;
}
}
bool need_apply_center =
scroller_focus_center || m->visible_scroll_tiling_clients == 1 ||
(scroller_prefer_center && !need_apply_overspread &&
(!m->prevsel ||
(ISSCROLLTILED(m->prevsel) &&
(m->prevsel->scroller_proportion * max_client_width) +
(tempClients[focus_client_index]->scroller_proportion *
max_client_width) >
m->w.width - 2 * scroller_structs - cur_gappih)));
if (n == 1 && scroller_ignore_proportion_single) { if (n == 1 && scroller_ignore_proportion_single) {
need_scroller = true; need_scroller = true;
} }
@ -393,18 +435,26 @@ void scroller(Monitor *m) {
tempClients[focus_client_index], &target_geom); tempClients[focus_client_index], &target_geom);
arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv); arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv);
} else if (need_scroller) { } else if (need_scroller) {
if (scroller_focus_center || if (need_apply_center) {
((!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)) &&
scroller_prefer_center)) {
target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2;
} else if (need_apply_overspread) {
if (over_overspread_to_left) {
target_geom.x = m->w.x + scroller_structs;
} else {
target_geom.x =
m->w.x +
(m->w.width -
tempClients[focus_client_index]->scroller_proportion *
max_client_width -
scroller_structs);
}
} else { } else {
target_geom.x = root_client->geom.x > m->w.x + (m->w.width) / 2 target_geom.x = tempClients[focus_client_index]->geom.x >
m->w.x + (m->w.width) / 2
? m->w.x + (m->w.width - ? m->w.x + (m->w.width -
root_client->scroller_proportion * tempClients[focus_client_index]
->scroller_proportion *
max_client_width - max_client_width -
scroller_structs) scroller_structs)
: m->w.x + scroller_structs; : m->w.x + scroller_structs;

View file

@ -17,8 +17,8 @@ static void tgmix(Monitor *m);
Layout overviewlayout = {"󰃇", overview, "overview"}; Layout overviewlayout = {"󰃇", overview, "overview"};
enum { enum {
SCROLLER,
TILE, TILE,
SCROLLER,
GRID, GRID,
MONOCLE, MONOCLE,
DECK, DECK,
@ -34,8 +34,8 @@ enum {
Layout layouts[] = { Layout layouts[] = {
// 最少两个,不能删除少于两个 // 最少两个,不能删除少于两个
/* symbol arrange function name */ /* symbol arrange function name */
{"S", scroller, "scroller", SCROLLER}, // 滚动布局
{"T", tile, "tile", TILE}, // 平铺布局 {"T", tile, "tile", TILE}, // 平铺布局
{"S", scroller, "scroller", SCROLLER}, // 滚动布局
{"G", grid, "grid", GRID}, // 格子布局 {"G", grid, "grid", GRID}, // 格子布局
{"M", monocle, "monocle", MONOCLE}, // 单屏布局 {"M", monocle, "monocle", MONOCLE}, // 单屏布局
{"K", deck, "deck", DECK}, // 卡片布局 {"K", deck, "deck", DECK}, // 卡片布局

View file

@ -110,6 +110,7 @@ void vertical_deck(Monitor *m) {
Client *c = NULL; Client *c = NULL;
Client *fc = NULL; Client *fc = NULL;
float mfact; float mfact;
uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
int32_t cur_gappiv = enablegaps ? m->gappiv : 0; int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
int32_t cur_gappoh = enablegaps ? m->gappoh : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
@ -134,8 +135,8 @@ void vertical_deck(Monitor *m) {
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
: m->pertag->mfacts[m->pertag->curtag]; : m->pertag->mfacts[m->pertag->curtag];
if (n > m->nmaster) if (n > nmasters)
mh = m->nmaster ? round((m->w.height - 2 * cur_gappov) * mfact) : 0; mh = nmasters ? round((m->w.height - 2 * cur_gappov) * mfact) : 0;
else else
mh = m->w.height - 2 * cur_gappov; mh = m->w.height - 2 * cur_gappov;
@ -143,13 +144,13 @@ void vertical_deck(Monitor *m) {
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, m) || !ISTILED(c)) if (!VISIBLEON(c, m) || !ISTILED(c))
continue; continue;
if (i < m->nmaster) { if (i < nmasters) {
resize( resize(
c, c,
(struct wlr_box){.x = m->w.x + cur_gappoh + mx, (struct wlr_box){.x = m->w.x + cur_gappoh + mx,
.y = m->w.y + cur_gappov, .y = m->w.y + cur_gappov,
.width = (m->w.width - 2 * cur_gappoh - mx) / .width = (m->w.width - 2 * cur_gappoh - mx) /
(MIN(n, m->nmaster) - i), (MIN(n, nmasters) - i),
.height = mh}, .height = mh},
0); 0);
mx += c->geom.width; mx += c->geom.width;
@ -269,6 +270,7 @@ void vertical_scroller(Monitor *m) {
struct wlr_box target_geom; struct wlr_box target_geom;
int32_t focus_client_index = 0; int32_t focus_client_index = 0;
bool need_scroller = false; bool need_scroller = false;
bool over_overspread_to_up = false;
int32_t cur_gappiv = enablegaps ? m->gappiv : 0; int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
int32_t cur_gappov = enablegaps ? m->gappov : 0; int32_t cur_gappov = enablegaps ? m->gappov : 0;
int32_t cur_gappoh = enablegaps ? m->gappoh : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
@ -354,6 +356,46 @@ void vertical_scroller(Monitor *m) {
} }
} }
bool need_apply_overspread =
scroller_prefer_overspread && m->visible_scroll_tiling_clients > 1 &&
(focus_client_index == 0 || focus_client_index == n - 1) &&
tempClients[focus_client_index]->scroller_proportion < 1.0f;
if (need_apply_overspread) {
if (focus_client_index == 0) {
over_overspread_to_up = true;
} else {
over_overspread_to_up = false;
}
if (over_overspread_to_up &&
(!INSIDEMON(tempClients[1]) ||
(tempClients[1]->scroller_proportion +
tempClients[focus_client_index]->scroller_proportion >=
1.0f))) {
need_scroller = true;
} else if (!over_overspread_to_up &&
(!INSIDEMON(tempClients[focus_client_index - 1]) ||
(tempClients[focus_client_index - 1]->scroller_proportion +
tempClients[focus_client_index]->scroller_proportion >=
1.0f))) {
need_scroller = true;
} else {
need_apply_overspread = false;
}
}
bool need_apply_center =
scroller_focus_center || m->visible_scroll_tiling_clients == 1 ||
(scroller_prefer_center && !need_apply_overspread &&
(!m->prevsel ||
(ISSCROLLTILED(m->prevsel) &&
(m->prevsel->scroller_proportion * max_client_height) +
(tempClients[focus_client_index]->scroller_proportion *
max_client_height) >
m->w.height - 2 * scroller_structs - cur_gappiv)));
if (n == 1 && scroller_ignore_proportion_single) { if (n == 1 && scroller_ignore_proportion_single) {
need_scroller = true; need_scroller = true;
} }
@ -380,18 +422,24 @@ void vertical_scroller(Monitor *m) {
arrange_stack_vertical(tempClients[focus_client_index], target_geom, arrange_stack_vertical(tempClients[focus_client_index], target_geom,
cur_gappih); cur_gappih);
} else if (need_scroller) { } else if (need_scroller) {
if (scroller_focus_center || if (need_apply_center) {
((!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)) &&
scroller_prefer_center)) {
target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2;
} else if (need_apply_overspread) {
if (over_overspread_to_up) {
target_geom.y = m->w.y + scroller_structs;
} else {
target_geom.y =
m->w.y +
(m->w.height -
tempClients[focus_client_index]->scroller_proportion *
max_client_height -
scroller_structs);
}
} else { } else {
target_geom.y = root_client->geom.y > m->w.y + (m->w.height) / 2 target_geom.y = root_client->geom.y > m->w.y + (m->w.height) / 2
? m->w.y + (m->w.height - ? m->w.y + (m->w.height -
root_client->scroller_proportion * tempClients[focus_client_index]
->scroller_proportion *
max_client_height - max_client_height -
scroller_structs) scroller_structs)
: m->w.y + scroller_structs; : m->w.y + scroller_structs;

File diff suppressed because it is too large Load diff