mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2025-10-29 05:40:21 -04:00
Merge remote-tracking branch 'origin/main' into tablet-test
This commit is contained in:
commit
4e8af666e8
17 changed files with 540 additions and 314 deletions
17
README.md
17
README.md
|
|
@ -18,14 +18,14 @@ This project's development is based on [dwl](https://codeberg.org/dwl/dwl/).
|
|||
- Excellent input method support (text input v2/v3)
|
||||
- Flexible window layouts with easy switching (scroller, master, monocle, spiral, etc.)
|
||||
- Rich window states (swallow, minimize, maximize, unglobal, global, fakefullscreen, overlay, etc.)
|
||||
- Simple yet powerful external configuration
|
||||
- Simple yet powerful external configuration(support shortcuts hot-reload)
|
||||
- Sway-like scratchpad and named scratchpad
|
||||
- Ipc support(get/send message from/to compositor by external program)
|
||||
- Hycov-like overview
|
||||
- Window effects from scenefx (blur, shadow, corner radius, opacity)
|
||||
|
||||
3. **Some disadvantages**
|
||||
- Since it uses the fully automatic layout like dwm style, it does not allow you to manually adjust the window size when the window is in tiled state. It only allows you to change the layout parameters to adjust the window ratio.
|
||||
- Since it uses the fully automatic layout like dwm style, it does not allow you to manually adjust the window size when the window is in tiled state. It only allows you to use dispatch like `setmfact` or `increase_proportion` bind to adjust the tiled window ratio.
|
||||
|
||||
|
||||
Master-Stack Layout
|
||||
|
|
@ -107,13 +107,10 @@ Finally, install the package:
|
|||
emerge --ask --verbose gui-wm/mangowc
|
||||
```
|
||||
|
||||
Patching wlroots is done by getting the patch with git from [the repository](https://github.com/DreamMaoMao/wlroots.git)
|
||||
and then copying it to `/etc/portage/patches/gui-libs/wlroots/`.
|
||||
|
||||
## Other
|
||||
|
||||
```bash
|
||||
git clone -b 0.19.0 https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||
git clone -b 0.19.1 https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||
cd wlroots
|
||||
meson build -Dprefix=/usr
|
||||
sudo ninja -C build install
|
||||
|
|
@ -245,13 +242,11 @@ Here's an example of using the modules in a flake:
|
|||
|
||||
To package mango for other distributions, you can check the reference setup for:
|
||||
|
||||
- [nix](https://github.com/DreamMaoMao/mango/blob/main/nix/default.nix)
|
||||
- [arch](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=mango-git).
|
||||
- [nix](https://github.com/DreamMaoMao/mangowc/blob/main/nix/default.nix)
|
||||
- [arch](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=mangowc-git).
|
||||
- [gentoo](https://data.gpo.zugaina.org/guru/gui-wm/mangowc)
|
||||
|
||||
Currently building mango requires a patched version of `wlroots-0.19`. If possible, the patch can be extracted from the [latest commit](https://github.com/DreamMaoMao/wlroots.git)
|
||||
and applied on `prepare` step. If it is not possible, you will need to create a separate `wlroots` package and make it a build dependency.
|
||||
You might also need to package `scenefx` for your distribution, check availability [here](https://github.com/wlrfx/scenefx.git).
|
||||
You might need to package `scenefx` for your distribution, check availability [here](https://github.com/wlrfx/scenefx.git).
|
||||
|
||||
If you encounter build errors when packaging `mango`, feel free to create an issue and ask a question, but
|
||||
Read The Friendly Manual on packaging software in your distribution first.
|
||||
|
|
|
|||
66
config.conf
66
config.conf
|
|
@ -28,7 +28,7 @@ unfocused_opacity=1.0
|
|||
# Animation Configuration(support type:zoom,slide)
|
||||
# tag_animation_direction: 0-horizontal,1-vertical
|
||||
animations=1
|
||||
layer_animations=0
|
||||
layer_animations=1
|
||||
animation_type_open=slide
|
||||
animation_type_close=slide
|
||||
animation_fade_in=1
|
||||
|
|
@ -183,35 +183,35 @@ bind=ALT,x,switch_proportion_preset,
|
|||
bind=SUPER,n,switch_layout
|
||||
|
||||
# tag switch
|
||||
bind=SUPER,Left,viewtoleft,
|
||||
bind=CTRL,Left,viewtoleft_have_client,
|
||||
bind=SUPER,Right,viewtoright,
|
||||
bind=CTRL,Right,viewtoright_have_client,
|
||||
bind=CTRL+SUPER,Left,tagtoleft,
|
||||
bind=CTRL+SUPER,Right,tagtoright,
|
||||
bind=SUPER,Left,viewtoleft,0
|
||||
bind=CTRL,Left,viewtoleft_have_client,0
|
||||
bind=SUPER,Right,viewtoright,0
|
||||
bind=CTRL,Right,viewtoright_have_client,0
|
||||
bind=CTRL+SUPER,Left,tagtoleft,0
|
||||
bind=CTRL+SUPER,Right,tagtoright,0
|
||||
|
||||
bind=Ctrl,1,view,1
|
||||
bind=Ctrl,2,view,2
|
||||
bind=Ctrl,3,view,3
|
||||
bind=Ctrl,4,view,4
|
||||
bind=Ctrl,5,view,5
|
||||
bind=Ctrl,6,view,6
|
||||
bind=Ctrl,7,view,7
|
||||
bind=Ctrl,8,view,8
|
||||
bind=Ctrl,9,view,9
|
||||
bind=Ctrl,1,view,1,0
|
||||
bind=Ctrl,2,view,2,0
|
||||
bind=Ctrl,3,view,3,0
|
||||
bind=Ctrl,4,view,4,0
|
||||
bind=Ctrl,5,view,5,0
|
||||
bind=Ctrl,6,view,6,0
|
||||
bind=Ctrl,7,view,7,0
|
||||
bind=Ctrl,8,view,8,0
|
||||
bind=Ctrl,9,view,9,0
|
||||
|
||||
# tag: move client to the tag and focus it
|
||||
# tagsilent: move client to the tag and not focus it
|
||||
# bind=Alt,1,tagsilent,1
|
||||
bind=Alt,1,tag,1
|
||||
bind=Alt,2,tag,2
|
||||
bind=Alt,3,tag,3
|
||||
bind=Alt,4,tag,4
|
||||
bind=Alt,5,tag,5
|
||||
bind=Alt,6,tag,6
|
||||
bind=Alt,7,tag,7
|
||||
bind=Alt,8,tag,8
|
||||
bind=Alt,9,tag,9
|
||||
bind=Alt,1,tag,1,0
|
||||
bind=Alt,2,tag,2,0
|
||||
bind=Alt,3,tag,3,0
|
||||
bind=Alt,4,tag,4,0
|
||||
bind=Alt,5,tag,5,0
|
||||
bind=Alt,6,tag,6,0
|
||||
bind=Alt,7,tag,7,0
|
||||
bind=Alt,8,tag,8,0
|
||||
bind=Alt,9,tag,9,0
|
||||
|
||||
# monitor switch
|
||||
bind=alt+shift,Left,focusmon,left
|
||||
|
|
@ -224,6 +224,17 @@ bind=ALT+SHIFT,X,incgaps,1
|
|||
bind=ALT+SHIFT,Z,incgaps,-1
|
||||
bind=ALT+SHIFT,R,togglegaps
|
||||
|
||||
# adjust tile window size
|
||||
# change master fact for tile,spiral,deck,dwindle
|
||||
bind=ALT+SUPER,h,setmfact,-0.05
|
||||
bind=ALT+SUPER,l,setmfact,+0.05
|
||||
# change sub master fact for dwindle,spiral
|
||||
bind=ALT+SUPER,k,setsmfact,-0.05
|
||||
bind=ALT+SUPER,j,setsmfact,+0.05
|
||||
# change scroller proportion
|
||||
bind=ctrl+super,j,increase_proportion,0.1
|
||||
bind=ctrl+super,k,increase_proportion,-0.1
|
||||
|
||||
# movewin
|
||||
bind=CTRL+SHIFT,Up,movewin,+0,-50
|
||||
bind=CTRL+SHIFT,Down,movewin,+0,+50
|
||||
|
|
@ -247,3 +258,8 @@ mousebind=NONE,btn_right,killclient,0
|
|||
# Axis Bindings
|
||||
axisbind=SUPER,UP,viewtoleft_have_client
|
||||
axisbind=SUPER,DOWN,viewtoright_have_client
|
||||
|
||||
|
||||
# layer rule
|
||||
layerrule=animation_type_open:zoom,layer_name:rofi
|
||||
layerrule=animation_type_close:zoom,layer_name:rofi
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
project('mango', ['c', 'cpp'],
|
||||
version : '0.8.6',
|
||||
version : '0.8.9',
|
||||
)
|
||||
|
||||
subdir('protocols')
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
lib,
|
||||
fetchFromGitHub,
|
||||
libX11,
|
||||
libinput,
|
||||
libxcb,
|
||||
|
|
@ -23,17 +22,6 @@
|
|||
libGL,
|
||||
}: let
|
||||
pname = "mango";
|
||||
# Use patched wlroots from github.com/DreamMaoMao/wlroots
|
||||
wlroots-git = wlroots_0_19.overrideAttrs (
|
||||
final: prev: {
|
||||
src = fetchFromGitHub {
|
||||
owner = "DreamMaoMao";
|
||||
repo = "wlroots";
|
||||
rev = "afbb5b7c2b14152730b57aa11119b1b16a299d5b";
|
||||
sha256 = "sha256-pVU+CuiqvduMTpsnDHX/+EWY2qxHX2lXKiVzdGtcnYY=";
|
||||
};
|
||||
}
|
||||
);
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
inherit pname;
|
||||
|
|
@ -60,7 +48,7 @@ in
|
|||
pixman
|
||||
wayland
|
||||
wayland-protocols
|
||||
wlroots-git
|
||||
wlroots_0_19
|
||||
scenefx
|
||||
libGL
|
||||
]
|
||||
|
|
@ -83,4 +71,4 @@ in
|
|||
maintainers = [];
|
||||
platforms = lib.platforms.unix;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -30,13 +30,6 @@ enum corner_location set_client_corner_location(Client *c) {
|
|||
|
||||
bool is_horizontal_stack_layout(Monitor *m) {
|
||||
|
||||
if (!m->pertag->curtag &&
|
||||
(strcmp(m->pertag->ltidxs[m->pertag->prevtag]->name, "tile") == 0 ||
|
||||
strcmp(m->pertag->ltidxs[m->pertag->prevtag]->name, "spiral") == 0 ||
|
||||
strcmp(m->pertag->ltidxs[m->pertag->prevtag]->name, "dwindle") == 0 ||
|
||||
strcmp(m->pertag->ltidxs[m->pertag->prevtag]->name, "deck") == 0))
|
||||
return true;
|
||||
|
||||
if (m->pertag->curtag &&
|
||||
(strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "tile") == 0 ||
|
||||
strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "spiral") == 0 ||
|
||||
|
|
@ -899,6 +892,11 @@ void client_set_pending_state(Client *c) {
|
|||
c->animation.duration = 0;
|
||||
}
|
||||
|
||||
if (c->istagswitching) {
|
||||
c->animation.duration = 0;
|
||||
c->istagswitching = 0;
|
||||
}
|
||||
|
||||
// 开始动画
|
||||
client_commit(c);
|
||||
c->dirty = true;
|
||||
|
|
@ -1014,6 +1012,10 @@ void resize(Client *c, struct wlr_box geo, int interact) {
|
|||
c->animainit_geom = c->geom;
|
||||
}
|
||||
|
||||
if (c->scratchpad_switching_mon) {
|
||||
c->animainit_geom = c->geom;
|
||||
}
|
||||
|
||||
// 开始应用动画设置
|
||||
client_set_pending_state(c);
|
||||
|
||||
|
|
|
|||
85
src/animation/tag.h
Normal file
85
src/animation/tag.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
void set_tagin_animation(Monitor *m, Client *c) {
|
||||
if (c->animation.running) {
|
||||
c->animainit_geom.x = c->animation.current.x;
|
||||
c->animainit_geom.y = c->animation.current.y;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m->pertag->curtag > m->pertag->prevtag) {
|
||||
|
||||
c->animainit_geom.x = tag_animation_direction == VERTICAL
|
||||
? c->animation.current.x
|
||||
: c->mon->m.x + c->mon->m.width;
|
||||
c->animainit_geom.y = tag_animation_direction == VERTICAL
|
||||
? c->mon->m.y + c->mon->m.height
|
||||
: c->animation.current.y;
|
||||
|
||||
} else {
|
||||
|
||||
c->animainit_geom.x = tag_animation_direction == VERTICAL
|
||||
? c->animation.current.x
|
||||
: m->m.x - c->geom.width;
|
||||
c->animainit_geom.y = tag_animation_direction == VERTICAL
|
||||
? m->m.y - c->geom.height
|
||||
: c->animation.current.y;
|
||||
}
|
||||
}
|
||||
|
||||
void set_arrange_visible(Monitor *m, Client *c, bool want_animation) {
|
||||
|
||||
if (!c->is_clip_to_hide || !ISTILED(c) || !is_scroller_layout(c->mon)) {
|
||||
c->is_clip_to_hide = false;
|
||||
wlr_scene_node_set_enabled(&c->scene->node, true);
|
||||
wlr_scene_node_set_enabled(&c->scene_surface->node, true);
|
||||
}
|
||||
client_set_suspended(c, false);
|
||||
|
||||
if (!c->animation.tag_from_rule && want_animation &&
|
||||
m->pertag->prevtag != 0 && m->pertag->curtag != 0 && animations) {
|
||||
c->animation.tagining = true;
|
||||
set_tagin_animation(m, c);
|
||||
} else {
|
||||
c->animainit_geom.x = c->animation.current.x;
|
||||
c->animainit_geom.y = c->animation.current.y;
|
||||
}
|
||||
|
||||
c->animation.tag_from_rule = false;
|
||||
c->animation.tagouting = false;
|
||||
c->animation.tagouted = false;
|
||||
resize(c, c->geom, 0);
|
||||
}
|
||||
|
||||
void set_tagout_animation(Monitor *m, Client *c) {
|
||||
if (m->pertag->curtag > m->pertag->prevtag) {
|
||||
c->pending = c->geom;
|
||||
c->pending.x = tag_animation_direction == VERTICAL
|
||||
? c->animation.current.x
|
||||
: c->mon->m.x - c->geom.width;
|
||||
c->pending.y = tag_animation_direction == VERTICAL
|
||||
? c->mon->m.y - c->geom.height
|
||||
: c->animation.current.y;
|
||||
|
||||
resize(c, c->geom, 0);
|
||||
} else {
|
||||
c->pending = c->geom;
|
||||
c->pending.x = tag_animation_direction == VERTICAL
|
||||
? c->animation.current.x
|
||||
: c->mon->m.x + c->mon->m.width;
|
||||
c->pending.y = tag_animation_direction == VERTICAL
|
||||
? c->mon->m.y + c->mon->m.height
|
||||
: c->animation.current.y;
|
||||
resize(c, c->geom, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void set_arrange_hidden(Monitor *m, Client *c, bool want_animation) {
|
||||
if ((c->tags & (1 << (m->pertag->prevtag - 1))) &&
|
||||
m->pertag->prevtag != 0 && m->pertag->curtag != 0 && animations) {
|
||||
c->animation.tagouting = true;
|
||||
c->animation.tagining = false;
|
||||
set_tagout_animation(m, c);
|
||||
} else {
|
||||
wlr_scene_node_set_enabled(&c->scene->node, false);
|
||||
client_set_suspended(c, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -132,6 +132,7 @@ typedef struct {
|
|||
char *layout_name; // 布局名称
|
||||
char *monitor_name;
|
||||
int no_render_border;
|
||||
int no_hide;
|
||||
} ConfigTagRule;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -173,7 +174,10 @@ typedef struct {
|
|||
int scroller_prefer_center;
|
||||
int edge_scroller_pointer_focus;
|
||||
int focus_cross_monitor;
|
||||
int exchange_cross_monitor;
|
||||
int scratchpad_cross_monitor;
|
||||
int focus_cross_tag;
|
||||
int view_current_to_back;
|
||||
int no_border_when_single;
|
||||
int no_radius_when_single;
|
||||
int snap_distance;
|
||||
|
|
@ -301,6 +305,7 @@ typedef struct {
|
|||
int single_scratchpad;
|
||||
int xwayland_persistence;
|
||||
int syncobj_enable;
|
||||
int adaptive_sync;
|
||||
|
||||
struct xkb_rule_names xkb_rules;
|
||||
} Config;
|
||||
|
|
@ -724,15 +729,19 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
|||
func = switch_proportion_preset;
|
||||
} else if (strcmp(func_name, "viewtoleft") == 0) {
|
||||
func = viewtoleft;
|
||||
(*arg).i = atoi(arg_value);
|
||||
} else if (strcmp(func_name, "viewtoright") == 0) {
|
||||
func = viewtoright;
|
||||
(*arg).i = atoi(arg_value);
|
||||
} else if (strcmp(func_name, "tagsilent") == 0) {
|
||||
func = tagsilent;
|
||||
(*arg).ui = 1 << (atoi(arg_value) - 1);
|
||||
} else if (strcmp(func_name, "tagtoleft") == 0) {
|
||||
func = tagtoleft;
|
||||
(*arg).i = atoi(arg_value);
|
||||
} else if (strcmp(func_name, "tagtoright") == 0) {
|
||||
func = tagtoright;
|
||||
(*arg).i = atoi(arg_value);
|
||||
} else if (strcmp(func_name, "killclient") == 0) {
|
||||
func = killclient;
|
||||
} else if (strcmp(func_name, "centerwin") == 0) {
|
||||
|
|
@ -808,22 +817,29 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
|||
func = togglemaxmizescreen;
|
||||
} else if (strcmp(func_name, "viewtoleft_have_client") == 0) {
|
||||
func = viewtoleft_have_client;
|
||||
(*arg).i = atoi(arg_value);
|
||||
} else if (strcmp(func_name, "viewtoright_have_client") == 0) {
|
||||
func = viewtoright_have_client;
|
||||
(*arg).i = atoi(arg_value);
|
||||
} else if (strcmp(func_name, "reload_config") == 0) {
|
||||
func = reload_config;
|
||||
} else if (strcmp(func_name, "tag") == 0) {
|
||||
func = tag;
|
||||
(*arg).ui = 1 << (atoi(arg_value) - 1);
|
||||
(*arg).i = atoi(arg_value2);
|
||||
} else if (strcmp(func_name, "view") == 0) {
|
||||
func = bind_to_view;
|
||||
(*arg).ui = 1 << (atoi(arg_value) - 1);
|
||||
(*arg).i = atoi(arg_value2);
|
||||
} else if (strcmp(func_name, "toggletag") == 0) {
|
||||
func = toggletag;
|
||||
(*arg).ui = 1 << (atoi(arg_value) - 1);
|
||||
} else if (strcmp(func_name, "toggleview") == 0) {
|
||||
func = toggleview;
|
||||
(*arg).ui = 1 << (atoi(arg_value) - 1);
|
||||
} else if (strcmp(func_name, "comboview") == 0) {
|
||||
func = comboview;
|
||||
(*arg).ui = 1 << (atoi(arg_value) - 1);
|
||||
} else if (strcmp(func_name, "smartmovewin") == 0) {
|
||||
func = smartmovewin;
|
||||
(*arg).i = parse_direction(arg_value);
|
||||
|
|
@ -967,10 +983,14 @@ void parse_config_line(Config *config, const char *line) {
|
|||
config->edge_scroller_pointer_focus = atoi(value);
|
||||
} else if (strcmp(key, "focus_cross_monitor") == 0) {
|
||||
config->focus_cross_monitor = atoi(value);
|
||||
} else if (strcmp(key, "exchange_cross_monitor") == 0) {
|
||||
config->exchange_cross_monitor = atoi(value);
|
||||
} else if (strcmp(key, "scratchpad_cross_monitor") == 0) {
|
||||
config->scratchpad_cross_monitor = atoi(value);
|
||||
} else if (strcmp(key, "focus_cross_tag") == 0) {
|
||||
config->focus_cross_tag = atoi(value);
|
||||
} else if (strcmp(key, "focus_cross_tag") == 0) {
|
||||
config->focus_cross_tag = atoi(value);
|
||||
} else if (strcmp(key, "view_current_to_back") == 0) {
|
||||
config->view_current_to_back = atoi(value);
|
||||
} else if (strcmp(key, "blur") == 0) {
|
||||
config->blur = atoi(value);
|
||||
} else if (strcmp(key, "blur_layer") == 0) {
|
||||
|
|
@ -1011,6 +1031,8 @@ void parse_config_line(Config *config, const char *line) {
|
|||
config->xwayland_persistence = atoi(value);
|
||||
} else if (strcmp(key, "syncobj_enable") == 0) {
|
||||
config->syncobj_enable = atoi(value);
|
||||
} else if (strcmp(key, "adaptive_sync") == 0) {
|
||||
config->adaptive_sync = 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) {
|
||||
|
|
@ -1359,13 +1381,15 @@ void parse_config_line(Config *config, const char *line) {
|
|||
trim_whitespace(val);
|
||||
|
||||
if (strcmp(key, "id") == 0) {
|
||||
rule->id = CLAMP_INT(atoi(val), 1, LENGTH(tags));
|
||||
rule->id = CLAMP_INT(atoi(val), 0, LENGTH(tags));
|
||||
} else if (strcmp(key, "layout_name") == 0) {
|
||||
rule->layout_name = strdup(val);
|
||||
} else if (strcmp(key, "monitor_name") == 0) {
|
||||
rule->monitor_name = strdup(val);
|
||||
} else if (strcmp(key, "no_render_border") == 0) {
|
||||
rule->no_render_border = CLAMP_INT(atoi(val), 0, 1);
|
||||
} else if (strcmp(key, "no_hide") == 0) {
|
||||
rule->no_hide = CLAMP_INT(atoi(val), 0, 1);
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, ",");
|
||||
|
|
@ -1695,9 +1719,9 @@ void parse_config_line(Config *config, const char *line) {
|
|||
memset(binding, 0, sizeof(KeyBinding));
|
||||
|
||||
char mod_str[256], keysym_str[256], func_name[256],
|
||||
arg_value[256] = "none", arg_value2[256] = "none",
|
||||
arg_value3[256] = "none", arg_value4[256] = "none",
|
||||
arg_value5[256] = "none";
|
||||
arg_value[256] = "0\0", arg_value2[256] = "0\0",
|
||||
arg_value3[256] = "0\0", arg_value4[256] = "0\0",
|
||||
arg_value5[256] = "0\0";
|
||||
if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]",
|
||||
mod_str, keysym_str, func_name, arg_value, arg_value2,
|
||||
arg_value3, arg_value4, arg_value5) < 3) {
|
||||
|
|
@ -1754,9 +1778,9 @@ void parse_config_line(Config *config, const char *line) {
|
|||
memset(binding, 0, sizeof(MouseBinding));
|
||||
|
||||
char mod_str[256], button_str[256], func_name[256],
|
||||
arg_value[256] = "none", arg_value2[256] = "none",
|
||||
arg_value3[256] = "none", arg_value4[256] = "none",
|
||||
arg_value5[256] = "none";
|
||||
arg_value[256] = "0\0", arg_value2[256] = "0\0",
|
||||
arg_value3[256] = "0\0", arg_value4[256] = "0\0",
|
||||
arg_value5[256] = "0\0";
|
||||
if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]",
|
||||
mod_str, button_str, func_name, arg_value, arg_value2,
|
||||
arg_value3, arg_value4, arg_value5) < 3) {
|
||||
|
|
@ -1813,9 +1837,9 @@ void parse_config_line(Config *config, const char *line) {
|
|||
memset(binding, 0, sizeof(AxisBinding));
|
||||
|
||||
char mod_str[256], dir_str[256], func_name[256],
|
||||
arg_value[256] = "none", arg_value2[256] = "none",
|
||||
arg_value3[256] = "none", arg_value4[256] = "none",
|
||||
arg_value5[256] = "none";
|
||||
arg_value[256] = "0\0", arg_value2[256] = "0\0",
|
||||
arg_value3[256] = "0\0", arg_value4[256] = "0\0",
|
||||
arg_value5[256] = "0\0";
|
||||
if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]",
|
||||
mod_str, dir_str, func_name, arg_value, arg_value2,
|
||||
arg_value3, arg_value4, arg_value5) < 3) {
|
||||
|
|
@ -1875,9 +1899,9 @@ void parse_config_line(Config *config, const char *line) {
|
|||
memset(binding, 0, sizeof(SwitchBinding));
|
||||
|
||||
char fold_str[256], func_name[256],
|
||||
arg_value[256] = "none", arg_value2[256] = "none",
|
||||
arg_value3[256] = "none", arg_value4[256] = "none",
|
||||
arg_value5[256] = "none";
|
||||
arg_value[256] = "0\0", arg_value2[256] = "0\0",
|
||||
arg_value3[256] = "0\0", arg_value4[256] = "0\0",
|
||||
arg_value5[256] = "0\0";
|
||||
if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]",
|
||||
fold_str, func_name, arg_value, arg_value2, arg_value3,
|
||||
arg_value4, arg_value5) < 3) {
|
||||
|
|
@ -1931,9 +1955,9 @@ void parse_config_line(Config *config, const char *line) {
|
|||
memset(binding, 0, sizeof(GestureBinding));
|
||||
|
||||
char mod_str[256], motion_str[256], fingers_count_str[256],
|
||||
func_name[256], arg_value[256] = "none", arg_value2[256] = "none",
|
||||
arg_value3[256] = "none", arg_value4[256] = "none",
|
||||
arg_value5[256] = "none";
|
||||
func_name[256], arg_value[256] = "0\0", arg_value2[256] = "0\0",
|
||||
arg_value3[256] = "0\0", arg_value4[256] = "0\0",
|
||||
arg_value5[256] = "0\0";
|
||||
if (sscanf(value,
|
||||
"%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]",
|
||||
mod_str, motion_str, fingers_count_str, func_name, arg_value,
|
||||
|
|
@ -2338,6 +2362,7 @@ void override_config(void) {
|
|||
// 杂项设置
|
||||
xwayland_persistence = CLAMP_INT(config.xwayland_persistence, 0, 1);
|
||||
syncobj_enable = CLAMP_INT(config.syncobj_enable, 0, 1);
|
||||
adaptive_sync = CLAMP_INT(config.adaptive_sync, 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);
|
||||
|
|
@ -2346,7 +2371,10 @@ void override_config(void) {
|
|||
sloppyfocus = CLAMP_INT(config.sloppyfocus, 0, 1);
|
||||
warpcursor = CLAMP_INT(config.warpcursor, 0, 1);
|
||||
focus_cross_monitor = CLAMP_INT(config.focus_cross_monitor, 0, 1);
|
||||
exchange_cross_monitor = CLAMP_INT(config.exchange_cross_monitor, 0, 1);
|
||||
scratchpad_cross_monitor = CLAMP_INT(config.scratchpad_cross_monitor, 0, 1);
|
||||
focus_cross_tag = CLAMP_INT(config.focus_cross_tag, 0, 1);
|
||||
view_current_to_back = CLAMP_INT(config.view_current_to_back, 0, 1);
|
||||
enable_floating_snap = CLAMP_INT(config.enable_floating_snap, 0, 1);
|
||||
snap_distance = CLAMP_INT(config.snap_distance, 0, 99999);
|
||||
cursor_size = CLAMP_INT(config.cursor_size, 4, 512);
|
||||
|
|
@ -2494,10 +2522,14 @@ void set_value_default() {
|
|||
config.scroller_prefer_center = scroller_prefer_center;
|
||||
config.edge_scroller_pointer_focus = edge_scroller_pointer_focus;
|
||||
config.focus_cross_monitor = focus_cross_monitor;
|
||||
config.exchange_cross_monitor = exchange_cross_monitor;
|
||||
config.scratchpad_cross_monitor = scratchpad_cross_monitor;
|
||||
config.focus_cross_tag = focus_cross_tag;
|
||||
config.view_current_to_back = view_current_to_back;
|
||||
config.single_scratchpad = single_scratchpad;
|
||||
config.xwayland_persistence = xwayland_persistence;
|
||||
config.syncobj_enable = syncobj_enable;
|
||||
config.adaptive_sync = adaptive_sync;
|
||||
config.no_border_when_single = no_border_when_single;
|
||||
config.no_radius_when_single = no_radius_when_single;
|
||||
config.snap_distance = snap_distance;
|
||||
|
|
@ -2734,11 +2766,11 @@ void reapply_monitor_rules(void) {
|
|||
}
|
||||
|
||||
if (mr->width > 0 && mr->height > 0 && mr->refresh > 0) {
|
||||
internal_mode = get_output_mode(m->wlr_output, mr->width,
|
||||
mr->height, mr->refresh);
|
||||
internal_mode = get_nearest_output_mode(
|
||||
m->wlr_output, mr->width, mr->height, mr->refresh);
|
||||
if (internal_mode) {
|
||||
wlr_output_state_set_mode(&state, internal_mode);
|
||||
} else {
|
||||
} else if (wlr_output_is_headless(m->wlr_output)) {
|
||||
wlr_output_state_set_custom_mode(
|
||||
&state, mr->width, mr->height,
|
||||
(int)roundf(mr->refresh * 1000));
|
||||
|
|
@ -2752,6 +2784,10 @@ void reapply_monitor_rules(void) {
|
|||
}
|
||||
}
|
||||
|
||||
if (adaptive_sync) {
|
||||
enable_adaptive_sync(m, &state);
|
||||
}
|
||||
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
wlr_output_state_finish(&state);
|
||||
updatemons(NULL, NULL);
|
||||
|
|
@ -2836,6 +2872,8 @@ void reapply_tagrule(void) {
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ int scroller_focus_center = 0;
|
|||
int scroller_prefer_center = 0;
|
||||
int focus_cross_monitor = 0;
|
||||
int focus_cross_tag = 0;
|
||||
int exchange_cross_monitor = 0;
|
||||
int scratchpad_cross_monitor = 0;
|
||||
int view_current_to_back = 1;
|
||||
int no_border_when_single = 0;
|
||||
int no_radius_when_single = 0;
|
||||
int snap_distance = 30;
|
||||
|
|
@ -95,6 +98,7 @@ float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
|
|||
int warpcursor = 1; /* Warp cursor to focused client */
|
||||
int xwayland_persistence = 1; /* xwayland persistence */
|
||||
int syncobj_enable = 0;
|
||||
int adaptive_sync = 0;
|
||||
|
||||
/* keyboard */
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ void bind_to_view(const Arg *arg);
|
|||
void toggletag(const Arg *arg);
|
||||
void toggleview(const Arg *arg);
|
||||
void tag(const Arg *arg);
|
||||
void comboview(const Arg *arg);
|
||||
void incgaps(const Arg *arg);
|
||||
void incigaps(const Arg *arg);
|
||||
void incihgaps(const Arg *arg);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ void bind_to_view(const Arg *arg) {
|
|||
|
||||
unsigned int target = arg->ui;
|
||||
|
||||
if (selmon->pertag->curtag &&
|
||||
if (view_current_to_back && selmon->pertag->curtag &&
|
||||
(target & TAGMASK) == (selmon->tagset[selmon->seltags])) {
|
||||
if (selmon->pertag->prevtag)
|
||||
target = 1 << (selmon->pertag->prevtag - 1);
|
||||
|
|
@ -11,16 +11,16 @@ void bind_to_view(const Arg *arg) {
|
|||
}
|
||||
|
||||
if ((int)target == INT_MIN && selmon->pertag->curtag == 0) {
|
||||
if (selmon->pertag->prevtag)
|
||||
if (view_current_to_back && selmon->pertag->prevtag)
|
||||
target = 1 << (selmon->pertag->prevtag - 1);
|
||||
else
|
||||
target = 0;
|
||||
}
|
||||
|
||||
if (target == 0 || (int)target == INT_MIN) {
|
||||
view(&(Arg){.ui = ~0 & TAGMASK}, false);
|
||||
view(&(Arg){.ui = ~0 & TAGMASK, .i = arg->i}, false);
|
||||
} else {
|
||||
view(&(Arg){.ui = target}, true);
|
||||
view(&(Arg){.ui = target, .i = arg->i}, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -86,6 +86,8 @@ void focusdir(const Arg *arg) {
|
|||
viewtoleft_have_client(NULL);
|
||||
if (arg->i == RIGHT || arg->i == DOWN)
|
||||
viewtoright_have_client(NULL);
|
||||
} else if (config.focus_cross_monitor) {
|
||||
focusmon(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -129,7 +131,7 @@ void toggle_trackpad_enable(const Arg *arg) {
|
|||
}
|
||||
|
||||
void focusmon(const Arg *arg) {
|
||||
Client *c;
|
||||
Client *c, *old_selmon_sel;
|
||||
Monitor *m = NULL;
|
||||
|
||||
if (arg->i != UNDIR) {
|
||||
|
|
@ -150,6 +152,7 @@ void focusmon(const Arg *arg) {
|
|||
if (!m || !m->wlr_output->enabled)
|
||||
return;
|
||||
|
||||
old_selmon_sel = selmon->sel;
|
||||
selmon = m;
|
||||
warp_cursor_to_selmon(selmon);
|
||||
c = focustop(selmon);
|
||||
|
|
@ -159,6 +162,10 @@ void focusmon(const Arg *arg) {
|
|||
wlr_seat_keyboard_notify_clear_focus(seat);
|
||||
} else
|
||||
focusclient(c, 1);
|
||||
|
||||
if (old_selmon_sel) {
|
||||
setborder_color(old_selmon_sel);
|
||||
}
|
||||
}
|
||||
|
||||
void // 17
|
||||
|
|
@ -392,6 +399,10 @@ void resizewin(const Arg *arg) {
|
|||
|
||||
void restore_minimized(const Arg *arg) {
|
||||
Client *c;
|
||||
|
||||
if (selmon && selmon->isoverview)
|
||||
return;
|
||||
|
||||
if (selmon && selmon->sel && selmon->sel->is_in_scratchpad &&
|
||||
selmon->sel->is_scratchpad_show) {
|
||||
selmon->sel->isminied = 0;
|
||||
|
|
@ -410,6 +421,8 @@ void restore_minimized(const Arg *arg) {
|
|||
c->isnamedscratchpad = 0;
|
||||
setborder_color(c);
|
||||
arrange(c->mon, false);
|
||||
focusclient(c, 0);
|
||||
warp_cursor(c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -418,6 +431,7 @@ void restore_minimized(const Arg *arg) {
|
|||
void // 17
|
||||
setlayout(const Arg *arg) {
|
||||
int jk;
|
||||
|
||||
for (jk = 0; jk < LENGTH(layouts); jk++) {
|
||||
if (strcmp(layouts[jk].name, arg->v) == 0) {
|
||||
selmon->pertag->ltidxs[selmon->pertag->curtag] = &layouts[jk];
|
||||
|
|
@ -846,6 +860,7 @@ void switch_layout(const Arg *arg) {
|
|||
len = MAX(strlen(layouts[ji].name), strlen(target_layout_name));
|
||||
if (strncmp(layouts[ji].name, target_layout_name, len) == 0) {
|
||||
selmon->pertag->ltidxs[selmon->pertag->curtag] = &layouts[ji];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -990,7 +1005,7 @@ void tagtoleft(const Arg *arg) {
|
|||
if (selmon->sel != NULL &&
|
||||
__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 &&
|
||||
selmon->tagset[selmon->seltags] > 1) {
|
||||
tag(&(Arg){.ui = selmon->tagset[selmon->seltags] >> 1});
|
||||
tag(&(Arg){.ui = selmon->tagset[selmon->seltags] >> 1, .i = arg->i});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -998,7 +1013,7 @@ void tagtoright(const Arg *arg) {
|
|||
if (selmon->sel != NULL &&
|
||||
__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 &&
|
||||
selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) {
|
||||
tag(&(Arg){.ui = selmon->tagset[selmon->seltags] << 1});
|
||||
tag(&(Arg){.ui = selmon->tagset[selmon->seltags] << 1, .i = arg->i});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1027,8 +1042,12 @@ void toggle_scratchpad(const Arg *arg) {
|
|||
Client *c;
|
||||
bool hit = false;
|
||||
Client *tmp = NULL;
|
||||
|
||||
if (selmon && selmon->isoverview)
|
||||
return;
|
||||
|
||||
wl_list_for_each_safe(c, tmp, &clients, link) {
|
||||
if (c->mon != selmon) {
|
||||
if (!scratchpad_cross_monitor && c->mon != selmon) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1055,6 +1074,9 @@ void togglefakefullscreen(const Arg *arg) {
|
|||
void togglefloating(const Arg *arg) {
|
||||
Client *sel = focustop(selmon);
|
||||
|
||||
if (selmon && selmon->isoverview)
|
||||
return;
|
||||
|
||||
if (!sel)
|
||||
return;
|
||||
|
||||
|
|
@ -1192,7 +1214,7 @@ void viewtoleft(const Arg *arg) {
|
|||
if (!selmon || (target) == selmon->tagset[selmon->seltags])
|
||||
return;
|
||||
|
||||
view(&(Arg){.ui = target & TAGMASK}, true);
|
||||
view(&(Arg){.ui = target & TAGMASK, .i = arg->i}, true);
|
||||
}
|
||||
void viewtoright(const Arg *arg) {
|
||||
if (selmon->isoverview || selmon->pertag->curtag == 0) {
|
||||
|
|
@ -1207,7 +1229,7 @@ void viewtoright(const Arg *arg) {
|
|||
return;
|
||||
}
|
||||
|
||||
view(&(Arg){.ui = target & TAGMASK}, true);
|
||||
view(&(Arg){.ui = target & TAGMASK, .i = arg->i}, true);
|
||||
}
|
||||
|
||||
void viewtoleft_have_client(const Arg *arg) {
|
||||
|
|
@ -1231,7 +1253,7 @@ void viewtoleft_have_client(const Arg *arg) {
|
|||
}
|
||||
|
||||
if (found)
|
||||
view(&(Arg){.ui = (1 << (n - 1)) & TAGMASK}, true);
|
||||
view(&(Arg){.ui = (1 << (n - 1)) & TAGMASK, .i = arg->i}, true);
|
||||
}
|
||||
|
||||
void viewtoright_have_client(const Arg *arg) {
|
||||
|
|
@ -1255,7 +1277,25 @@ void viewtoright_have_client(const Arg *arg) {
|
|||
}
|
||||
|
||||
if (found)
|
||||
view(&(Arg){.ui = (1 << (n - 1)) & TAGMASK}, true);
|
||||
view(&(Arg){.ui = (1 << (n - 1)) & TAGMASK, .i = arg->i}, true);
|
||||
}
|
||||
|
||||
void comboview(const Arg *arg) {
|
||||
unsigned int newtags = arg->ui & TAGMASK;
|
||||
unsigned int target_tag = selmon->tagset[selmon->seltags];
|
||||
|
||||
if (!newtags || !selmon)
|
||||
return;
|
||||
|
||||
if (tag_combo)
|
||||
target_tag |= newtags;
|
||||
else {
|
||||
tag_combo = true;
|
||||
target_tag = newtags;
|
||||
}
|
||||
|
||||
view(&(Arg){.ui = target_tag}, false);
|
||||
printstatus();
|
||||
}
|
||||
|
||||
void zoom(const Arg *arg) {
|
||||
|
|
|
|||
|
|
@ -140,12 +140,10 @@ void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) {
|
|||
title = focused ? client_get_title(focused) : "";
|
||||
appid = focused ? client_get_appid(focused) : "";
|
||||
|
||||
if (monitor->pertag->curtag) {
|
||||
symbol = monitor->pertag->ltidxs[monitor->pertag->curtag]->symbol;
|
||||
} else if (monitor->isoverview) {
|
||||
if (monitor->isoverview) {
|
||||
symbol = overviewlayout.symbol;
|
||||
} else {
|
||||
symbol = monitor->pertag->ltidxs[monitor->pertag->prevtag]->symbol;
|
||||
symbol = monitor->pertag->ltidxs[monitor->pertag->curtag]->symbol;
|
||||
}
|
||||
|
||||
keyboard = &kb_group->wlr_group->keyboard;
|
||||
|
|
@ -264,7 +262,7 @@ void dwl_ipc_output_set_tags(struct wl_client *client,
|
|||
return;
|
||||
monitor = ipc_output->mon;
|
||||
|
||||
view_in_mon(&(Arg){.ui = newtags}, true, monitor);
|
||||
view_in_mon(&(Arg){.ui = newtags}, true, monitor, true);
|
||||
}
|
||||
|
||||
void dwl_ipc_output_quit(struct wl_client *client,
|
||||
|
|
|
|||
|
|
@ -102,7 +102,9 @@ void dwl_ext_workspace_printstatus(Monitor *m) {
|
|||
wlr_ext_workspace_handle_v1_set_hidden(w->ext_workspace, false);
|
||||
} else {
|
||||
wlr_ext_workspace_handle_v1_set_urgent(w->ext_workspace, false);
|
||||
wlr_ext_workspace_handle_v1_set_hidden(w->ext_workspace, true);
|
||||
if (!w->m->pertag->no_hide[w->tag])
|
||||
wlr_ext_workspace_handle_v1_set_hidden(w->ext_workspace,
|
||||
true);
|
||||
}
|
||||
|
||||
if ((m->tagset[m->seltags] & (1 << (w->tag - 1)) & TAGMASK) ||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) {
|
|||
const char *appid, *title;
|
||||
Client *c = NULL;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != selmon) {
|
||||
if (!scratchpad_cross_monitor && c->mon != selmon) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -121,14 +121,14 @@ static bool is_window_rule_matches(const ConfigWinRule *r, const char *appid,
|
|||
regex_match(r->title, title));
|
||||
}
|
||||
|
||||
Client *center_select(Monitor *m) {
|
||||
Client *center_tiled_select(Monitor *m) {
|
||||
Client *c = NULL;
|
||||
Client *target_c = NULL;
|
||||
long int mini_distance = -1;
|
||||
int dirx, diry;
|
||||
long int distance;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c && VISIBLEON(c, m) && client_surface(c)->mapped &&
|
||||
if (c && VISIBLEON(c, m) && ISTILED(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);
|
||||
|
|
|
|||
|
|
@ -17,20 +17,13 @@ Monitor *dirtomon(enum wlr_direction dir) {
|
|||
|
||||
bool is_scroller_layout(Monitor *m) {
|
||||
|
||||
if (!m->pertag->curtag &&
|
||||
strcmp(m->pertag->ltidxs[m->pertag->prevtag]->name, "scroller") == 0)
|
||||
return true;
|
||||
|
||||
if (!m->pertag->curtag &&
|
||||
strcmp(m->pertag->ltidxs[m->pertag->prevtag]->name,
|
||||
"vertical_scroller") == 0)
|
||||
return true;
|
||||
|
||||
if (strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "scroller") == 0)
|
||||
return true;
|
||||
|
||||
if (strcmp(m->pertag->ltidxs[m->pertag->curtag]->name,
|
||||
"vertical_scroller") == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,10 @@ void grid(Monitor *m) {
|
|||
|
||||
if (n == 1) {
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
|
||||
c->bw = m->visible_tiling_clients == 1 && no_border_when_single &&
|
||||
smartgaps
|
||||
? 0
|
||||
|
|
@ -164,6 +168,9 @@ void grid(Monitor *m) {
|
|||
ch = (m->w.height - 2 * overviewgappo) * 0.65;
|
||||
i = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
|
||||
c->bw = m->visible_tiling_clients == 1 && no_border_when_single &&
|
||||
smartgaps
|
||||
? 0
|
||||
|
|
@ -212,6 +219,9 @@ void grid(Monitor *m) {
|
|||
// 调整每个客户端的位置和大小
|
||||
i = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
c->bw =
|
||||
m->visible_tiling_clients == 1 && no_border_when_single && smartgaps
|
||||
? 0
|
||||
|
|
@ -347,10 +357,11 @@ void scroller(Monitor *m) {
|
|||
if (m->sel && !client_is_unmanaged(m->sel) && !m->sel->isfloating &&
|
||||
!m->sel->ismaxmizescreen && !m->sel->isfullscreen) {
|
||||
root_client = m->sel;
|
||||
} else if (m->prevtilesel && !client_is_unmanaged(m->prevtilesel)) {
|
||||
root_client = m->prevtilesel;
|
||||
} else if (m->prevsel && ISTILED(m->prevsel) && VISIBLEON(m->prevsel, m) &&
|
||||
!client_is_unmanaged(m->prevsel)) {
|
||||
root_client = m->prevsel;
|
||||
} else {
|
||||
root_client = center_select(m);
|
||||
root_client = center_tiled_select(m);
|
||||
}
|
||||
|
||||
if (!root_client) {
|
||||
|
|
@ -380,10 +391,11 @@ void scroller(Monitor *m) {
|
|||
|
||||
if (need_scroller) {
|
||||
if (scroller_focus_center ||
|
||||
((!m->prevtilesel ||
|
||||
(m->prevtilesel->scroller_proportion * max_client_width) +
|
||||
(root_client->scroller_proportion * max_client_width) >
|
||||
m->w.width - 2 * scroller_structs - cur_gappih) &&
|
||||
((!m->prevsel ||
|
||||
(ISTILED(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;
|
||||
} else {
|
||||
|
|
@ -439,10 +451,10 @@ void 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;
|
||||
|
||||
if (n > selmon->pertag->nmasters[selmon->pertag->curtag])
|
||||
mw = selmon->pertag->nmasters[selmon->pertag->curtag]
|
||||
if (n > m->pertag->nmasters[m->pertag->curtag])
|
||||
mw = m->pertag->nmasters[m->pertag->curtag]
|
||||
? (m->w.width + cur_gappih * ie) *
|
||||
selmon->pertag->mfacts[selmon->pertag->curtag]
|
||||
m->pertag->mfacts[m->pertag->curtag]
|
||||
: 0;
|
||||
else
|
||||
mw = m->w.width - 2 * cur_gappoh + cur_gappih * ie;
|
||||
|
|
@ -451,8 +463,8 @@ void tile(Monitor *m) {
|
|||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || !ISTILED(c))
|
||||
continue;
|
||||
if (i < selmon->pertag->nmasters[selmon->pertag->curtag]) {
|
||||
r = MIN(n, selmon->pertag->nmasters[selmon->pertag->curtag]) - i;
|
||||
if (i < m->pertag->nmasters[m->pertag->curtag]) {
|
||||
r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i;
|
||||
h = (m->w.height - my - cur_gappov - cur_gappiv * ie * (r - 1)) / r;
|
||||
resize(c,
|
||||
(struct wlr_box){.x = m->w.x + cur_gappoh,
|
||||
|
|
|
|||
|
|
@ -138,6 +138,10 @@ void vertical_grid(Monitor *m) {
|
|||
|
||||
if (n == 1) {
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
|
||||
c->bw = m->visible_tiling_clients == 1 && no_border_when_single &&
|
||||
smartgaps
|
||||
? 0
|
||||
|
|
@ -162,6 +166,10 @@ void vertical_grid(Monitor *m) {
|
|||
cw = (m->w.width - 2 * overviewgappo) * 0.65;
|
||||
i = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
|
||||
c->bw = m->visible_tiling_clients == 1 && no_border_when_single &&
|
||||
smartgaps
|
||||
? 0
|
||||
|
|
@ -207,6 +215,9 @@ void vertical_grid(Monitor *m) {
|
|||
|
||||
i = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != m)
|
||||
continue;
|
||||
|
||||
c->bw =
|
||||
m->visible_tiling_clients == 1 && no_border_when_single && smartgaps
|
||||
? 0
|
||||
|
|
@ -333,10 +344,11 @@ void vertical_scroller(Monitor *m) {
|
|||
if (m->sel && !client_is_unmanaged(m->sel) && !m->sel->isfloating &&
|
||||
!m->sel->ismaxmizescreen && !m->sel->isfullscreen) {
|
||||
root_client = m->sel;
|
||||
} else if (m->prevtilesel && !client_is_unmanaged(m->prevtilesel)) {
|
||||
root_client = m->prevtilesel;
|
||||
} else if (m->prevsel && ISTILED(m->prevsel) && VISIBLEON(m->prevsel, m) &&
|
||||
!client_is_unmanaged(m->prevsel)) {
|
||||
root_client = m->prevsel;
|
||||
} else {
|
||||
root_client = center_select(m);
|
||||
root_client = center_tiled_select(m);
|
||||
}
|
||||
|
||||
if (!root_client) {
|
||||
|
|
@ -366,10 +378,11 @@ void vertical_scroller(Monitor *m) {
|
|||
|
||||
if (need_scroller) {
|
||||
if (scroller_focus_center ||
|
||||
((!m->prevtilesel ||
|
||||
(m->prevtilesel->scroller_proportion * max_client_height) +
|
||||
(root_client->scroller_proportion * max_client_height) >
|
||||
m->w.height - 2 * scroller_structs - cur_gappiv) &&
|
||||
((!m->prevsel ||
|
||||
(ISTILED(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;
|
||||
} else {
|
||||
|
|
@ -425,10 +438,10 @@ void vertical_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;
|
||||
|
||||
if (n > selmon->pertag->nmasters[selmon->pertag->curtag])
|
||||
mh = selmon->pertag->nmasters[selmon->pertag->curtag]
|
||||
if (n > m->pertag->nmasters[m->pertag->curtag])
|
||||
mh = m->pertag->nmasters[m->pertag->curtag]
|
||||
? (m->w.height + cur_gappiv * ie) *
|
||||
selmon->pertag->mfacts[selmon->pertag->curtag]
|
||||
m->pertag->mfacts[m->pertag->curtag]
|
||||
: 0;
|
||||
else
|
||||
mh = m->w.height - 2 * cur_gappoh + cur_gappiv * ie;
|
||||
|
|
@ -437,8 +450,8 @@ void vertical_tile(Monitor *m) {
|
|||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || !ISTILED(c))
|
||||
continue;
|
||||
if (i < selmon->pertag->nmasters[selmon->pertag->curtag]) {
|
||||
r = MIN(n, selmon->pertag->nmasters[selmon->pertag->curtag]) - i;
|
||||
if (i < m->pertag->nmasters[m->pertag->curtag]) {
|
||||
r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i;
|
||||
w = (m->w.width - mx - cur_gappov - cur_gappiv * ie * (r - 1)) / r;
|
||||
resize(c,
|
||||
(struct wlr_box){.x = m->w.x + mx,
|
||||
|
|
|
|||
401
src/mango.c
401
src/mango.c
|
|
@ -314,6 +314,7 @@ struct Client {
|
|||
int isopensilent;
|
||||
int istagsilent;
|
||||
int iskilling;
|
||||
int istagswitching;
|
||||
int isnamedscratchpad;
|
||||
bool is_pending_open_animation;
|
||||
bool is_restoring_from_ov;
|
||||
|
|
@ -325,6 +326,7 @@ struct Client {
|
|||
Client *swallowing, *swallowedby;
|
||||
bool is_clip_to_hide;
|
||||
bool drag_to_tile;
|
||||
bool scratchpad_switching_mon;
|
||||
bool fake_no_border;
|
||||
int nofadein;
|
||||
int nofadeout;
|
||||
|
|
@ -436,7 +438,7 @@ struct Monitor {
|
|||
int gappoh; /* horizontal outer gaps */
|
||||
int gappov; /* vertical outer gaps */
|
||||
Pertag *pertag;
|
||||
Client *sel, *prevtilesel;
|
||||
Client *sel, *prevsel;
|
||||
int isoverview;
|
||||
int is_in_hotarea;
|
||||
int gamma_lut_changed;
|
||||
|
|
@ -644,9 +646,9 @@ static struct wlr_box setclient_coordinate_center(Client *c,
|
|||
int offsetx, int offsety);
|
||||
static unsigned int get_tags_first_tag(unsigned int tags);
|
||||
|
||||
static struct wlr_output_mode *get_output_mode(struct wlr_output *output,
|
||||
int width, int height,
|
||||
float refresh);
|
||||
static struct wlr_output_mode *
|
||||
get_nearest_output_mode(struct wlr_output *output, int width, int height,
|
||||
float refresh);
|
||||
|
||||
static void client_commit(Client *c);
|
||||
static void layer_commit(LayerSurface *l);
|
||||
|
|
@ -657,7 +659,8 @@ static void scene_buffer_apply_opacity(struct wlr_scene_buffer *buffer, int sx,
|
|||
int sy, void *data);
|
||||
|
||||
static Client *direction_select(const Arg *arg);
|
||||
static void view_in_mon(const Arg *arg, bool want_animation, Monitor *m);
|
||||
static void view_in_mon(const Arg *arg, bool want_animation, Monitor *m,
|
||||
bool changefocus);
|
||||
|
||||
static void buffer_set_effect(Client *c, BufferData buffer_data);
|
||||
static void snap_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
||||
|
|
@ -665,7 +668,7 @@ static void snap_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
|||
static void client_set_pending_state(Client *c);
|
||||
static void layer_set_pending_state(LayerSurface *l);
|
||||
static void set_rect_size(struct wlr_scene_rect *rect, int width, int height);
|
||||
static Client *center_select(Monitor *m);
|
||||
static Client *center_tiled_select(Monitor *m);
|
||||
static void handlecursoractivity(void);
|
||||
static int hidecursor(void *data);
|
||||
static bool check_hit_no_border(Client *c);
|
||||
|
|
@ -691,13 +694,15 @@ static struct wlr_scene_tree *
|
|||
wlr_scene_tree_snapshot(struct wlr_scene_node *node,
|
||||
struct wlr_scene_tree *parent);
|
||||
static bool is_scroller_layout(Monitor *m);
|
||||
void create_output(struct wlr_backend *backend, void *data);
|
||||
static void create_output(struct wlr_backend *backend, void *data);
|
||||
static const char *get_layout_abbr(const char *full_name);
|
||||
void apply_named_scratchpad(Client *target_client);
|
||||
Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title);
|
||||
bool switch_scratchpad_client_state(Client *c);
|
||||
bool check_trackpad_disabled(struct wlr_pointer *pointer);
|
||||
unsigned int get_tag_status(unsigned int tag, Monitor *m);
|
||||
static void apply_named_scratchpad(Client *target_client);
|
||||
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 void enable_adaptive_sync(Monitor *m, struct wlr_output_state *state);
|
||||
|
||||
#include "data/static_keymap.h"
|
||||
#include "dispatch/bind_declare.h"
|
||||
|
|
@ -782,6 +787,8 @@ struct dvec2 *baked_points_close;
|
|||
|
||||
static struct wl_event_source *hide_source;
|
||||
static bool cursor_hidden = false;
|
||||
static bool tag_combo = false;
|
||||
|
||||
static struct {
|
||||
enum wp_cursor_shape_device_v1_shape shape;
|
||||
struct wlr_surface *surface;
|
||||
|
|
@ -797,6 +804,7 @@ struct Pertag {
|
|||
int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
|
||||
float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
|
||||
float smfacts[LENGTH(tags) + 1]; /* smfacts per tag */
|
||||
bool no_hide[LENGTH(tags) + 1]; /* no_hide per tag */
|
||||
const Layout
|
||||
*ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */
|
||||
};
|
||||
|
|
@ -849,6 +857,7 @@ static struct wlr_xwayland *xwayland;
|
|||
#include "animation/client.h"
|
||||
#include "animation/common.h"
|
||||
#include "animation/layer.h"
|
||||
#include "animation/tag.h"
|
||||
#include "config/parse_config.h"
|
||||
#include "dispatch/bind_define.h"
|
||||
#include "ext-protocol/all.h"
|
||||
|
|
@ -891,6 +900,10 @@ void clear_fullscreen_flag(Client *c) {
|
|||
}
|
||||
|
||||
void minimized(const Arg *arg) {
|
||||
|
||||
if (selmon && selmon->isoverview)
|
||||
return;
|
||||
|
||||
if (selmon->sel && !selmon->sel->isminied) {
|
||||
set_minimized(selmon->sel);
|
||||
}
|
||||
|
|
@ -920,7 +933,7 @@ void show_scratchpad(Client *c) {
|
|||
resize(c, c->geom, 0);
|
||||
}
|
||||
|
||||
c->oldtags = selmon->tagset[selmon->seltags];
|
||||
c->oldtags = c->mon->tagset[c->mon->seltags];
|
||||
wl_list_remove(&c->link); // 从原来位置移除
|
||||
wl_list_insert(clients.prev->next, &c->link); // 插入开头
|
||||
show_hide_client(c);
|
||||
|
|
@ -969,6 +982,38 @@ void swallow(Client *c, Client *w) {
|
|||
}
|
||||
|
||||
bool switch_scratchpad_client_state(Client *c) {
|
||||
|
||||
if (scratchpad_cross_monitor && selmon && c->mon != selmon &&
|
||||
c->is_in_scratchpad) {
|
||||
// 保存原始monitor用于尺寸计算
|
||||
Monitor *oldmon = c->mon;
|
||||
c->scratchpad_switching_mon = true;
|
||||
c->mon = selmon;
|
||||
reset_foreign_tolevel(c);
|
||||
client_update_oldmonname_record(c, selmon);
|
||||
|
||||
// 根据新monitor调整窗口尺寸
|
||||
c->float_geom.width =
|
||||
(int)(c->float_geom.width * c->mon->w.width / oldmon->w.width);
|
||||
c->float_geom.height =
|
||||
(int)(c->float_geom.height * c->mon->w.height / oldmon->w.height);
|
||||
|
||||
c->float_geom = setclient_coordinate_center(c, c->float_geom, 0, 0);
|
||||
|
||||
// 只有显示状态的scratchpad才需要聚焦和返回true
|
||||
if (c->is_scratchpad_show) {
|
||||
c->tags = get_tags_first_tag(selmon->tagset[selmon->seltags]);
|
||||
resize(c, c->float_geom, 0);
|
||||
arrange(selmon, false);
|
||||
focusclient(c, true);
|
||||
c->scratchpad_switching_mon = false;
|
||||
return true;
|
||||
} else {
|
||||
resize(c, c->float_geom, 0);
|
||||
c->scratchpad_switching_mon = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->is_in_scratchpad && c->is_scratchpad_show &&
|
||||
(selmon->tagset[selmon->seltags] & c->tags) == 0) {
|
||||
unsigned int target =
|
||||
|
|
@ -990,9 +1035,11 @@ bool switch_scratchpad_client_state(Client *c) {
|
|||
void apply_named_scratchpad(Client *target_client) {
|
||||
Client *c = NULL;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != selmon) {
|
||||
|
||||
if (!scratchpad_cross_monitor && c->mon != selmon) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (single_scratchpad && c->is_in_scratchpad && c->is_scratchpad_show &&
|
||||
c != target_client) {
|
||||
set_minimized(c);
|
||||
|
|
@ -1237,7 +1284,7 @@ void applyrules(Client *c) {
|
|||
!(c->mon == selmon && c->tags & c->mon->tagset[c->mon->seltags]) &&
|
||||
!c->isopensilent && !c->istagsilent) {
|
||||
c->animation.tag_from_rule = true;
|
||||
view_in_mon(&(Arg){.ui = c->tags}, true, c->mon);
|
||||
view_in_mon(&(Arg){.ui = c->tags}, true, c->mon, true);
|
||||
}
|
||||
|
||||
setfullscreen(c, fullscreen_state_backup);
|
||||
|
|
@ -1248,7 +1295,8 @@ void applyrules(Client *c) {
|
|||
*/
|
||||
wl_list_for_each(fc, &clients,
|
||||
link) if (fc && fc != c && c->tags & fc->tags &&
|
||||
ISFULLSCREEN(fc) && !c->isfloating) {
|
||||
VISIBLEON(fc, c->mon) && ISFULLSCREEN(fc) &&
|
||||
!c->isfloating) {
|
||||
clear_fullscreen_flag(fc);
|
||||
arrange(c->mon, false);
|
||||
}
|
||||
|
|
@ -1265,92 +1313,6 @@ void applyrules(Client *c) {
|
|||
}
|
||||
}
|
||||
|
||||
void set_tagin_animation(Monitor *m, Client *c) {
|
||||
if (c->animation.running) {
|
||||
c->animainit_geom.x = c->animation.current.x;
|
||||
c->animainit_geom.y = c->animation.current.y;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m->pertag->curtag > m->pertag->prevtag) {
|
||||
|
||||
c->animainit_geom.x = tag_animation_direction == VERTICAL
|
||||
? c->animation.current.x
|
||||
: c->mon->m.x + c->mon->m.width;
|
||||
c->animainit_geom.y = tag_animation_direction == VERTICAL
|
||||
? c->mon->m.y + c->mon->m.height
|
||||
: c->animation.current.y;
|
||||
|
||||
} else {
|
||||
|
||||
c->animainit_geom.x = tag_animation_direction == VERTICAL
|
||||
? c->animation.current.x
|
||||
: m->m.x - c->geom.width;
|
||||
c->animainit_geom.y = tag_animation_direction == VERTICAL
|
||||
? m->m.y - c->geom.height
|
||||
: c->animation.current.y;
|
||||
}
|
||||
}
|
||||
|
||||
void set_arrange_visible(Monitor *m, Client *c, bool want_animation) {
|
||||
|
||||
if (!c->is_clip_to_hide || !ISTILED(c) || !is_scroller_layout(c->mon)) {
|
||||
c->is_clip_to_hide = false;
|
||||
wlr_scene_node_set_enabled(&c->scene->node, true);
|
||||
wlr_scene_node_set_enabled(&c->scene_surface->node, true);
|
||||
}
|
||||
client_set_suspended(c, false);
|
||||
|
||||
if (!c->animation.tag_from_rule && want_animation &&
|
||||
m->pertag->prevtag != 0 && m->pertag->curtag != 0 && animations) {
|
||||
c->animation.tagining = true;
|
||||
set_tagin_animation(m, c);
|
||||
} else {
|
||||
c->animainit_geom.x = c->animation.current.x;
|
||||
c->animainit_geom.y = c->animation.current.y;
|
||||
}
|
||||
|
||||
c->animation.tag_from_rule = false;
|
||||
c->animation.tagouting = false;
|
||||
c->animation.tagouted = false;
|
||||
resize(c, c->geom, 0);
|
||||
}
|
||||
|
||||
void set_tagout_animation(Monitor *m, Client *c) {
|
||||
if (m->pertag->curtag > m->pertag->prevtag) {
|
||||
c->pending = c->geom;
|
||||
c->pending.x = tag_animation_direction == VERTICAL
|
||||
? c->animation.current.x
|
||||
: c->mon->m.x - c->geom.width;
|
||||
c->pending.y = tag_animation_direction == VERTICAL
|
||||
? c->mon->m.y - c->geom.height
|
||||
: c->animation.current.y;
|
||||
|
||||
resize(c, c->geom, 0);
|
||||
} else {
|
||||
c->pending = c->geom;
|
||||
c->pending.x = tag_animation_direction == VERTICAL
|
||||
? c->animation.current.x
|
||||
: c->mon->m.x + c->mon->m.width;
|
||||
c->pending.y = tag_animation_direction == VERTICAL
|
||||
? c->mon->m.y + c->mon->m.height
|
||||
: c->animation.current.y;
|
||||
resize(c, c->geom, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void set_arrange_hidden(Monitor *m, Client *c, bool want_animation) {
|
||||
if ((c->tags & (1 << (m->pertag->prevtag - 1))) &&
|
||||
m->pertag->prevtag != 0 && m->pertag->curtag != 0 && animations) {
|
||||
c->animation.tagouting = true;
|
||||
c->animation.tagining = false;
|
||||
set_tagout_animation(m, c);
|
||||
} else {
|
||||
wlr_scene_node_set_enabled(&c->scene->node, false);
|
||||
client_set_suspended(c, true);
|
||||
}
|
||||
}
|
||||
|
||||
void // 17
|
||||
arrange(Monitor *m, bool want_animation) {
|
||||
Client *c;
|
||||
|
|
@ -1369,7 +1331,7 @@ arrange(Monitor *m, bool want_animation) {
|
|||
|
||||
if (c->mon == m && (c->isglobal || c->isunglobal)) {
|
||||
c->tags = m->tagset[m->seltags];
|
||||
if (selmon->sel == NULL)
|
||||
if (c->mon->sel == NULL)
|
||||
focusclient(c, 0);
|
||||
}
|
||||
|
||||
|
|
@ -1394,12 +1356,8 @@ arrange(Monitor *m, bool want_animation) {
|
|||
|
||||
if (m->isoverview) {
|
||||
overviewlayout.arrange(m);
|
||||
} else if (m && m->pertag->curtag &&
|
||||
m->pertag->ltidxs[m->pertag->curtag]->arrange) {
|
||||
} else {
|
||||
m->pertag->ltidxs[m->pertag->curtag]->arrange(m);
|
||||
} else if (m && m->pertag->prevtag &&
|
||||
m->pertag->ltidxs[m->pertag->prevtag]->arrange) {
|
||||
m->pertag->ltidxs[m->pertag->prevtag]->arrange(m);
|
||||
}
|
||||
|
||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
|
|
@ -1902,7 +1860,7 @@ buttonpress(struct wl_listener *listener, void *data) {
|
|||
client_update_oldmonname_record(grabc, selmon);
|
||||
setmon(grabc, selmon, 0, true);
|
||||
reset_foreign_tolevel(grabc);
|
||||
selmon->prevtilesel = ISTILED(selmon->sel) ? selmon->sel : NULL;
|
||||
selmon->prevsel = ISTILED(selmon->sel) ? selmon->sel : NULL;
|
||||
selmon->sel = grabc;
|
||||
tmpc = grabc;
|
||||
grabc = NULL;
|
||||
|
|
@ -2510,17 +2468,37 @@ void createlocksurface(struct wl_listener *listener, void *data) {
|
|||
client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat));
|
||||
}
|
||||
|
||||
struct wlr_output_mode *get_output_mode(struct wlr_output *output, int width,
|
||||
int height, float refresh) {
|
||||
struct wlr_output_mode *mode;
|
||||
struct wlr_output_mode *get_nearest_output_mode(struct wlr_output *output,
|
||||
int width, int height,
|
||||
float refresh) {
|
||||
struct wlr_output_mode *mode, *nearest_mode = NULL;
|
||||
float min_diff = 99999.0f;
|
||||
|
||||
wl_list_for_each(mode, &output->modes, link) {
|
||||
if (mode->width == width && mode->height == height &&
|
||||
(int)round(mode->refresh / 1000) == (int)round(refresh)) {
|
||||
return mode;
|
||||
if (mode->width == width && mode->height == height) {
|
||||
float mode_refresh = mode->refresh / 1000.0f;
|
||||
float diff = fabsf(mode_refresh - refresh);
|
||||
|
||||
if (diff < min_diff) {
|
||||
min_diff = diff;
|
||||
nearest_mode = mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nearest_mode;
|
||||
}
|
||||
|
||||
void enable_adaptive_sync(Monitor *m, struct wlr_output_state *state) {
|
||||
wlr_output_state_set_adaptive_sync_enabled(state, true);
|
||||
if (!wlr_output_test_state(m->wlr_output, state)) {
|
||||
wlr_output_state_set_adaptive_sync_enabled(state, false);
|
||||
wlr_log(WLR_DEBUG, "failed to enable adaptive sync for output %s",
|
||||
m->wlr_output->name);
|
||||
} else {
|
||||
wlr_log(WLR_INFO, "adaptive sync enabled for output %s",
|
||||
m->wlr_output->name);
|
||||
}
|
||||
}
|
||||
|
||||
void createmon(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -2585,12 +2563,13 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
rr = r->rr;
|
||||
|
||||
if (r->width > 0 && r->height > 0 && r->refresh > 0) {
|
||||
custom_monitor_mode = true;
|
||||
internal_mode = get_output_mode(m->wlr_output, r->width,
|
||||
r->height, r->refresh);
|
||||
internal_mode = get_nearest_output_mode(m->wlr_output, r->width,
|
||||
r->height, r->refresh);
|
||||
if (internal_mode) {
|
||||
custom_monitor_mode = true;
|
||||
wlr_output_state_set_mode(&state, internal_mode);
|
||||
} else {
|
||||
} else if (wlr_output_is_headless(m->wlr_output)) {
|
||||
custom_monitor_mode = true;
|
||||
wlr_output_state_set_custom_mode(
|
||||
&state, r->width, r->height,
|
||||
(int)roundf(r->refresh * 1000));
|
||||
|
|
@ -2610,6 +2589,10 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
wlr_output_state_set_mode(&state,
|
||||
wlr_output_preferred_mode(wlr_output));
|
||||
|
||||
if (adaptive_sync) {
|
||||
enable_adaptive_sync(m, &state);
|
||||
}
|
||||
|
||||
/* Set up event listeners */
|
||||
LISTEN(&wlr_output->events.frame, &m->frame, rendermon);
|
||||
LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon);
|
||||
|
|
@ -2639,6 +2622,8 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2783,22 +2768,24 @@ void configure_pointer(struct libinput_device *device) {
|
|||
}
|
||||
|
||||
void createpointer(struct wlr_pointer *pointer) {
|
||||
struct libinput_device *device =
|
||||
wlr_libinput_get_device_handle(&pointer->base);
|
||||
|
||||
if (device && wlr_input_device_is_libinput(&pointer->base)) {
|
||||
struct libinput_device *device = NULL;
|
||||
|
||||
if (wlr_input_device_is_libinput(&pointer->base) &&
|
||||
(device = wlr_libinput_get_device_handle(&pointer->base))) {
|
||||
|
||||
configure_pointer(device);
|
||||
|
||||
InputDevice *input_dev = calloc(1, sizeof(InputDevice));
|
||||
input_dev->wlr_device = &pointer->base;
|
||||
input_dev->libinput_device = device;
|
||||
|
||||
input_dev->destroy_listener.notify = destroyinputdevice;
|
||||
wl_signal_add(&pointer->base.events.destroy,
|
||||
&input_dev->destroy_listener);
|
||||
|
||||
wl_list_insert(&inputdevices, &input_dev->link);
|
||||
}
|
||||
|
||||
InputDevice *input_dev = calloc(1, sizeof(InputDevice));
|
||||
input_dev->wlr_device = &pointer->base;
|
||||
input_dev->libinput_device = device;
|
||||
|
||||
input_dev->destroy_listener.notify = destroyinputdevice;
|
||||
wl_signal_add(&pointer->base.events.destroy, &input_dev->destroy_listener);
|
||||
|
||||
wl_list_insert(&inputdevices, &input_dev->link);
|
||||
|
||||
wlr_cursor_attach_input_device(cursor, &pointer->base);
|
||||
}
|
||||
|
||||
|
|
@ -2823,32 +2810,36 @@ void switch_toggle(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
void createswitch(struct wlr_switch *switch_device) {
|
||||
struct libinput_device *device =
|
||||
wlr_libinput_get_device_handle(&switch_device->base);
|
||||
|
||||
InputDevice *input_dev = calloc(1, sizeof(InputDevice));
|
||||
input_dev->wlr_device = &switch_device->base;
|
||||
input_dev->libinput_device = device;
|
||||
input_dev->device_data = NULL; // 初始化为 NULL
|
||||
struct libinput_device *device = NULL;
|
||||
|
||||
input_dev->destroy_listener.notify = destroyinputdevice;
|
||||
wl_signal_add(&switch_device->base.events.destroy,
|
||||
&input_dev->destroy_listener);
|
||||
if (wlr_input_device_is_libinput(&switch_device->base) &&
|
||||
(device = wlr_libinput_get_device_handle(&switch_device->base))) {
|
||||
|
||||
// 创建 Switch 特定数据
|
||||
Switch *sw = calloc(1, sizeof(Switch));
|
||||
sw->wlr_switch = switch_device;
|
||||
sw->toggle.notify = switch_toggle;
|
||||
sw->input_dev = input_dev;
|
||||
InputDevice *input_dev = calloc(1, sizeof(InputDevice));
|
||||
input_dev->wlr_device = &switch_device->base;
|
||||
input_dev->libinput_device = device;
|
||||
input_dev->device_data = NULL; // 初始化为 NULL
|
||||
|
||||
// 将 Switch 指针保存到 input_device 中
|
||||
input_dev->device_data = sw;
|
||||
input_dev->destroy_listener.notify = destroyinputdevice;
|
||||
wl_signal_add(&switch_device->base.events.destroy,
|
||||
&input_dev->destroy_listener);
|
||||
|
||||
// 添加 toggle 监听器
|
||||
wl_signal_add(&switch_device->events.toggle, &sw->toggle);
|
||||
// 创建 Switch 特定数据
|
||||
Switch *sw = calloc(1, sizeof(Switch));
|
||||
sw->wlr_switch = switch_device;
|
||||
sw->toggle.notify = switch_toggle;
|
||||
sw->input_dev = input_dev;
|
||||
|
||||
// 添加到全局列表
|
||||
wl_list_insert(&inputdevices, &input_dev->link);
|
||||
// 将 Switch 指针保存到 input_device 中
|
||||
input_dev->device_data = sw;
|
||||
|
||||
// 添加 toggle 监听器
|
||||
wl_signal_add(&switch_device->events.toggle, &sw->toggle);
|
||||
|
||||
// 添加到全局列表
|
||||
wl_list_insert(&inputdevices, &input_dev->link);
|
||||
}
|
||||
}
|
||||
|
||||
void createpointerconstraint(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -3066,12 +3057,15 @@ void focusclient(Client *c, int lift) {
|
|||
if (c && !c->iskilling && !client_is_unmanaged(c) && c->mon) {
|
||||
|
||||
selmon = c->mon;
|
||||
selmon->prevtilesel = ISTILED(selmon->sel) ? selmon->sel : NULL;
|
||||
selmon->prevsel = selmon->sel;
|
||||
selmon->sel = c;
|
||||
|
||||
// decide whether need to re-arrange
|
||||
|
||||
if (c && ISTILED(c) && VISIBLEON(c, selmon) && !INSIDEMON(c) &&
|
||||
if (c && selmon->prevsel &&
|
||||
(selmon->prevsel->tags & selmon->tagset[selmon->seltags]) &&
|
||||
(c->tags & selmon->tagset[selmon->seltags]) && !c->isfloating &&
|
||||
!c->isfullscreen && !c->ismaxmizescreen &&
|
||||
is_scroller_layout(selmon)) {
|
||||
arrange(selmon, false);
|
||||
}
|
||||
|
|
@ -3343,6 +3337,8 @@ void keypress(struct wl_listener *listener, void *data) {
|
|||
if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
for (i = 0; i < nsyms; i++)
|
||||
handled = keybinding(mods, syms[i], keycode) || handled;
|
||||
} else if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||
tag_combo = false;
|
||||
}
|
||||
|
||||
if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) {
|
||||
|
|
@ -3445,7 +3441,7 @@ static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx,
|
|||
|
||||
if (blur && c && !c->noblur) {
|
||||
wlr_scene_buffer_set_backdrop_blur(buffer, true);
|
||||
wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, true);
|
||||
wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, false);
|
||||
if (blur_optimized) {
|
||||
wlr_scene_buffer_set_backdrop_blur_optimized(buffer, true);
|
||||
} else {
|
||||
|
|
@ -3461,6 +3457,7 @@ void init_client_properties(Client *c) {
|
|||
c->isfullscreen = 0;
|
||||
c->need_float_size_reduce = 0;
|
||||
c->iskilling = 0;
|
||||
c->istagswitching = 0;
|
||||
c->isglobal = 0;
|
||||
c->isminied = 0;
|
||||
c->isoverlay = 0;
|
||||
|
|
@ -3476,6 +3473,7 @@ void init_client_properties(Client *c) {
|
|||
c->scroller_proportion = scroller_default_proportion;
|
||||
c->is_pending_open_animation = true;
|
||||
c->drag_to_tile = false;
|
||||
c->scratchpad_switching_mon = false;
|
||||
c->fake_no_border = false;
|
||||
c->focused_opacity = focused_opacity;
|
||||
c->unfocused_opacity = unfocused_opacity;
|
||||
|
|
@ -3568,13 +3566,17 @@ mapnotify(struct wl_listener *listener, void *data) {
|
|||
VISIBLEON(selmon->sel, selmon)) {
|
||||
at_client = selmon->sel;
|
||||
} else {
|
||||
at_client = center_select(selmon);
|
||||
at_client = center_tiled_select(selmon);
|
||||
}
|
||||
|
||||
at_client->link.next->prev = &c->link;
|
||||
c->link.prev = &at_client->link;
|
||||
c->link.next = at_client->link.next;
|
||||
at_client->link.next = &c->link;
|
||||
if (at_client) {
|
||||
at_client->link.next->prev = &c->link;
|
||||
c->link.prev = &at_client->link;
|
||||
c->link.next = at_client->link.next;
|
||||
at_client->link.next = &c->link;
|
||||
} else {
|
||||
wl_list_insert(clients.prev, &c->link); // 尾部入栈
|
||||
}
|
||||
} else
|
||||
wl_list_insert(clients.prev, &c->link); // 尾部入栈
|
||||
wl_list_insert(&fstack, &c->flink);
|
||||
|
|
@ -4112,7 +4114,12 @@ void setborder_color(Client *c) {
|
|||
}
|
||||
|
||||
void exchange_two_client(Client *c1, Client *c2) {
|
||||
if (c1 == NULL || c2 == NULL || c1->mon != c2->mon) {
|
||||
|
||||
Monitor *tmp_mon;
|
||||
unsigned int tmp_tags;
|
||||
|
||||
if (c1 == NULL || c2 == NULL ||
|
||||
(!exchange_cross_monitor && c1->mon != c2->mon)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -4153,8 +4160,18 @@ void exchange_two_client(Client *c1, Client *c2) {
|
|||
tmp2_next->prev = &c1->link;
|
||||
}
|
||||
|
||||
arrange(c1->mon, false);
|
||||
focusclient(c1, 0);
|
||||
if (exchange_cross_monitor) {
|
||||
tmp_mon = c2->mon;
|
||||
tmp_tags = c2->tags;
|
||||
setmon(c2, c1->mon, c1->tags, false);
|
||||
setmon(c1, tmp_mon, tmp_tags, false);
|
||||
arrange(c1->mon, false);
|
||||
arrange(c2->mon, false);
|
||||
focusclient(c1, 0);
|
||||
} else {
|
||||
arrange(c1->mon, false);
|
||||
focusclient(c1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void // 17
|
||||
|
|
@ -4310,9 +4327,9 @@ setfloating(Client *c, int floating) {
|
|||
c->is_in_scratchpad = 0;
|
||||
c->isnamedscratchpad = 0;
|
||||
// 让当前tag中的全屏窗口退出全屏参与平铺
|
||||
wl_list_for_each(fc, &clients, link) if (fc && fc != c &&
|
||||
c->tags & fc->tags &&
|
||||
ISFULLSCREEN(fc)) {
|
||||
wl_list_for_each(fc, &clients,
|
||||
link) if (fc && fc != c && VISIBLEON(fc, c->mon) &&
|
||||
c->tags & fc->tags && ISFULLSCREEN(fc)) {
|
||||
clear_fullscreen_flag(fc);
|
||||
}
|
||||
}
|
||||
|
|
@ -4533,8 +4550,8 @@ void setmon(Client *c, Monitor *m, unsigned int newtags, bool focus) {
|
|||
oldmon->sel = NULL;
|
||||
}
|
||||
|
||||
if (oldmon && oldmon->prevtilesel == c) {
|
||||
oldmon->prevtilesel = NULL;
|
||||
if (oldmon && oldmon->prevsel == c) {
|
||||
oldmon->prevsel = NULL;
|
||||
}
|
||||
|
||||
c->mon = m;
|
||||
|
|
@ -4554,7 +4571,12 @@ void setmon(Client *c, Monitor *m, unsigned int newtags, bool focus) {
|
|||
if (m && focus)
|
||||
focusclient(focustop(m), 1);
|
||||
|
||||
if (!c->foreign_toplevel && m) {
|
||||
if (m) {
|
||||
|
||||
if (c->foreign_toplevel) {
|
||||
remove_foreign_topleve(c);
|
||||
}
|
||||
|
||||
add_foreign_toplevel(c);
|
||||
if (m->sel && m->sel->foreign_toplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_activated(
|
||||
|
|
@ -4586,6 +4608,7 @@ void setsel(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
void show_hide_client(Client *c) {
|
||||
|
||||
unsigned int target = get_tags_first_tag(c->oldtags);
|
||||
tag_client(&(Arg){.ui = target}, c);
|
||||
// c->tags = c->oldtags;
|
||||
|
|
@ -4920,17 +4943,20 @@ void startdrag(struct wl_listener *listener, void *data) {
|
|||
void tag_client(const Arg *arg, Client *target_client) {
|
||||
Client *fc;
|
||||
if (target_client && arg->ui & TAGMASK) {
|
||||
|
||||
target_client->tags = arg->ui & TAGMASK;
|
||||
target_client->istagswitching = 1;
|
||||
|
||||
wl_list_for_each(fc, &clients, link) {
|
||||
if (fc && fc != target_client && target_client->tags & fc->tags &&
|
||||
ISFULLSCREEN(fc) && !target_client->isfloating) {
|
||||
clear_fullscreen_flag(fc);
|
||||
}
|
||||
}
|
||||
view(&(Arg){.ui = arg->ui}, false);
|
||||
view(&(Arg){.ui = arg->ui, .i = arg->i}, true);
|
||||
|
||||
} else {
|
||||
view(arg, false);
|
||||
view(arg, true);
|
||||
}
|
||||
|
||||
focusclient(target_client, 1);
|
||||
|
|
@ -5074,15 +5100,15 @@ void toggleoverview(const Arg *arg) {
|
|||
// overview到正常视图,还原之前退出的浮动和全屏窗口状态
|
||||
if (selmon->isoverview) {
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c && !client_is_unmanaged(c) &&
|
||||
if (c && c->mon == selmon && !client_is_unmanaged(c) &&
|
||||
!client_should_ignore_focus(c) && !c->isunglobal)
|
||||
overview_backup(c);
|
||||
}
|
||||
} else {
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c && !c->iskilling && !client_is_unmanaged(c) &&
|
||||
!c->isunglobal && !client_should_ignore_focus(c) &&
|
||||
client_surface(c)->mapped)
|
||||
if (c && c->mon == selmon && !c->iskilling &&
|
||||
!client_is_unmanaged(c) && !c->isunglobal &&
|
||||
!client_should_ignore_focus(c) && client_surface(c)->mapped)
|
||||
overview_restore(c, &(Arg){.ui = target});
|
||||
}
|
||||
}
|
||||
|
|
@ -5146,8 +5172,8 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
|||
if (c == m->sel) {
|
||||
m->sel = NULL;
|
||||
}
|
||||
if (c == m->prevtilesel) {
|
||||
m->prevtilesel = NULL;
|
||||
if (c == m->prevsel) {
|
||||
m->prevsel = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5377,7 +5403,8 @@ urgent(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
}
|
||||
|
||||
void view_in_mon(const Arg *arg, bool want_animation, Monitor *m) {
|
||||
void view_in_mon(const Arg *arg, bool want_animation, Monitor *m,
|
||||
bool changefocus) {
|
||||
unsigned int i, tmptag;
|
||||
|
||||
if (!m || (arg->ui != (~0 & TAGMASK) && m->isoverview)) {
|
||||
|
|
@ -5424,13 +5451,25 @@ void view_in_mon(const Arg *arg, bool want_animation, Monitor *m) {
|
|||
|
||||
toggleseltags:
|
||||
|
||||
focusclient(focustop(m), 1);
|
||||
if (changefocus)
|
||||
focusclient(focustop(m), 1);
|
||||
arrange(m, want_animation);
|
||||
printstatus();
|
||||
}
|
||||
|
||||
void view(const Arg *arg, bool want_animation) {
|
||||
view_in_mon(arg, want_animation, selmon);
|
||||
Monitor *m;
|
||||
if (arg->i) {
|
||||
view_in_mon(arg, want_animation, selmon, true);
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (!m->wlr_output->enabled || m == selmon)
|
||||
continue;
|
||||
// only arrange, not change monitor focus
|
||||
view_in_mon(arg, want_animation, m, false);
|
||||
}
|
||||
} else {
|
||||
view_in_mon(arg, want_animation, selmon, true);
|
||||
}
|
||||
}
|
||||
|
||||
void virtualkeyboard(struct wl_listener *listener, void *data) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue