mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-03-17 05:34:11 -04:00
Compare commits
No commits in common. "main" and "0.10.8" have entirely different histories.
67 changed files with 2718 additions and 7643 deletions
61
.github/scripts/sync-wiki.py
vendored
61
.github/scripts/sync-wiki.py
vendored
|
|
@ -1,61 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import json
|
|
||||||
import re
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
DOCS_DIR = Path("docs")
|
|
||||||
WIKI_DIR = Path("wiki-temp")
|
|
||||||
|
|
||||||
FRONTMATTER_RE = re.compile(r"\A---\s*\n.*?^---\s*\n", re.DOTALL | re.MULTILINE)
|
|
||||||
DOCS_LINK_RE = re.compile(r"\[([^\]]+)\]\(/docs/(?:[^/)]+/)*([^/)#]+)(#[^)]+)?\)")
|
|
||||||
|
|
||||||
|
|
||||||
def collect_all_files() -> list[tuple[Path, str]]:
|
|
||||||
files = []
|
|
||||||
|
|
||||||
def from_dir(directory: Path) -> list[Path]:
|
|
||||||
meta = directory / "meta.json"
|
|
||||||
if meta.exists():
|
|
||||||
data = json.loads(meta.read_text())
|
|
||||||
return [directory / f"{p}.md" for p in data.get("pages", []) if (directory / f"{p}.md").exists()]
|
|
||||||
return sorted(directory.glob("*.md"))
|
|
||||||
|
|
||||||
for src in from_dir(DOCS_DIR):
|
|
||||||
files.append((src, "Home" if src.stem == "index" else src.stem))
|
|
||||||
|
|
||||||
for subdir in sorted(DOCS_DIR.iterdir()):
|
|
||||||
if subdir.is_dir():
|
|
||||||
for src in from_dir(subdir):
|
|
||||||
files.append((src, src.stem))
|
|
||||||
|
|
||||||
return files
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
files = collect_all_files()
|
|
||||||
|
|
||||||
contents = {src: src.read_text() for src, _ in files}
|
|
||||||
|
|
||||||
for src, dest_name in files:
|
|
||||||
text = FRONTMATTER_RE.sub("", contents[src], count=1).lstrip("\n")
|
|
||||||
text = DOCS_LINK_RE.sub(lambda m: f"[{m.group(1)}]({m.group(2)}{m.group(3) or ''})", text)
|
|
||||||
(WIKI_DIR / f"{dest_name}.md").write_text(text)
|
|
||||||
|
|
||||||
lines: list[str] = []
|
|
||||||
current_section = None
|
|
||||||
for src, dest_name in files:
|
|
||||||
section = "General" if src.parent == DOCS_DIR else src.parent.name.replace("-", " ").title()
|
|
||||||
if section != current_section:
|
|
||||||
if current_section is not None:
|
|
||||||
lines.append("")
|
|
||||||
lines.append(f"## {section}\n")
|
|
||||||
current_section = section
|
|
||||||
if dest_name != "Home":
|
|
||||||
title = dest_name.replace("-", " ").replace("_", " ").title()
|
|
||||||
lines.append(f"- [[{dest_name}|{title}]]")
|
|
||||||
|
|
||||||
(WIKI_DIR / "_Sidebar.md").write_text("\n".join(lines))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
|
|
@ -16,7 +16,7 @@ jobs:
|
||||||
days-before-issue-stale: -1
|
days-before-issue-stale: -1
|
||||||
# 手动标记后,14 天后关闭
|
# 手动标记后,14 天后关闭
|
||||||
days-before-issue-close: 7
|
days-before-issue-close: 7
|
||||||
# 使用的标签
|
# 使用的标签(必须和你手动添加的标签一致)
|
||||||
stale-issue-label: "stale"
|
stale-issue-label: "stale"
|
||||||
# 自动关闭时自动加上的标签
|
# 自动关闭时自动加上的标签
|
||||||
close-issue-label: "automatic-closing"
|
close-issue-label: "automatic-closing"
|
||||||
|
|
|
||||||
44
.github/workflows/sync-website.yml
vendored
44
.github/workflows/sync-website.yml
vendored
|
|
@ -1,44 +0,0 @@
|
||||||
name: Sync website
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
paths:
|
|
||||||
- docs/**
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: sync-website
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
sync-website:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 1
|
|
||||||
token: ${{ github.token }}
|
|
||||||
|
|
||||||
- name: Checkout website
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
repository: mangowm/mangowm.github.io
|
|
||||||
path: website
|
|
||||||
token: ${{ secrets.WEBSITE_SYNC_TOKEN }}
|
|
||||||
fetch-depth: 1
|
|
||||||
|
|
||||||
- name: Sync docs
|
|
||||||
run: |
|
|
||||||
rm -rf website/apps/web/content/docs
|
|
||||||
cp -r docs website/apps/web/content/docs
|
|
||||||
|
|
||||||
- name: Commit and push
|
|
||||||
working-directory: website
|
|
||||||
run: |
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git add apps/web/content/docs
|
|
||||||
git diff --staged --quiet || git commit \
|
|
||||||
-m "docs: content update from mangowm/mango" \
|
|
||||||
-m "${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}"
|
|
||||||
git push
|
|
||||||
40
.github/workflows/sync-wiki.yml
vendored
40
.github/workflows/sync-wiki.yml
vendored
|
|
@ -1,40 +0,0 @@
|
||||||
name: Sync wiki
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
paths:
|
|
||||||
- docs/**
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: sync-wiki
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
sync-wiki:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Clone wiki
|
|
||||||
run: |
|
|
||||||
git clone --depth 1 \
|
|
||||||
https://x-access-token:${{ github.token }}@github.com/${{ github.repository }}.wiki.git \
|
|
||||||
wiki-temp
|
|
||||||
|
|
||||||
- name: Sync docs to wiki
|
|
||||||
run: |
|
|
||||||
find wiki-temp -not -path 'wiki-temp/.git*' -type f -delete
|
|
||||||
python3 .github/scripts/sync-wiki.py
|
|
||||||
|
|
||||||
- name: Commit and push
|
|
||||||
working-directory: wiki-temp
|
|
||||||
run: |
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git add -A
|
|
||||||
git diff --staged --quiet || git commit -m "sync from ${{ github.sha }}"
|
|
||||||
git push
|
|
||||||
99
README.md
99
README.md
|
|
@ -1,7 +1,7 @@
|
||||||
# Mango Wayland Compositor
|
# MangoWC
|
||||||
<div>
|
|
||||||
<img src="https://github.com/mangowm/mango/blob/main/assets/mango-transparency-256.png" alt="MangoWM Logo" width="120"/>
|
<img width="255" height="256" alt="mango-transparency-256" src="https://github.com/DreamMaoMao/mangowc/blob/main/assets/mango-transparency-256.png" />
|
||||||
</div>
|
|
||||||
|
|
||||||
This project's development is based on [dwl](https://codeberg.org/dwl/dwl/).
|
This project's development is based on [dwl](https://codeberg.org/dwl/dwl/).
|
||||||
|
|
||||||
|
|
@ -23,22 +23,25 @@ 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.
|
|
||||||
|
|
||||||
https://github.com/user-attachments/assets/bb83004a-0563-4b48-ad89-6461a9b78b1f
|
Master-Stack Layout
|
||||||
|
|
||||||
# Mango's Vision
|
https://github.com/user-attachments/assets/a9d4776e-b50b-48fb-94ce-651d8a749b8a
|
||||||
|
|
||||||
**Mango's primary goal is stability**: After months of testing and development—and aside from a few lingering GPU compatibility issues—it should now be stable enough. I don't plan on making many breaking changes.
|
Scroller Layout
|
||||||
|
|
||||||
**Mango's preference is practicality**: I tend to add features that genuinely help with daily workflows—things that make our work more convenient.
|
https://github.com/user-attachments/assets/c9bf9415-fad1-4400-bcdc-3ad2d76de85a
|
||||||
|
|
||||||
|
Layer animation
|
||||||
|
|
||||||
|
https://github.com/user-attachments/assets/014c893f-115c-4ae9-8342-f9ae3e9a0df0
|
||||||
|
|
||||||
**Mango won't cater to every user preference**: For niche feature requests, I'll take a wait-and-see approach. I'll only consider adding them if they get a significant number of upvotes.
|
|
||||||
|
|
||||||
# Our discord
|
# Our discord
|
||||||
[mangowm](https://discord.gg/CPjbDxesh5)
|
[mangowc](https://discord.gg/CPjbDxesh5)
|
||||||
|
|
||||||
# Supported layouts
|
# Supported layouts
|
||||||
|
|
||||||
- tile
|
- tile
|
||||||
- scroller
|
- scroller
|
||||||
- monocle
|
- monocle
|
||||||
|
|
@ -48,20 +51,21 @@ https://github.com/user-attachments/assets/bb83004a-0563-4b48-ad89-6461a9b78b1f
|
||||||
- vertical_tile
|
- vertical_tile
|
||||||
- vertical_grid
|
- vertical_grid
|
||||||
- vertical_scroller
|
- vertical_scroller
|
||||||
- tgmix
|
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
[](https://repology.org/project/mangowm/versions)
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
|
- glibc
|
||||||
- wayland
|
- wayland
|
||||||
- wayland-protocols
|
- wayland-protocols
|
||||||
- libinput
|
- libinput
|
||||||
- libdrm
|
- libdrm
|
||||||
- libxkbcommon
|
- libxkbcommon
|
||||||
- pixman
|
- pixman
|
||||||
|
- git
|
||||||
|
- meson
|
||||||
|
- ninja
|
||||||
- libdisplay-info
|
- libdisplay-info
|
||||||
- libliftoff
|
- libliftoff
|
||||||
- hwdata
|
- hwdata
|
||||||
|
|
@ -71,9 +75,9 @@ https://github.com/user-attachments/assets/bb83004a-0563-4b48-ad89-6461a9b78b1f
|
||||||
- libxcb
|
- libxcb
|
||||||
|
|
||||||
## Arch Linux
|
## Arch Linux
|
||||||
The package is in the Arch User Repository and is available for manual download [here](https://aur.archlinux.org/packages/mangowm-git) or through a AUR helper like yay:
|
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:
|
||||||
```bash
|
```bash
|
||||||
yay -S mangowm-git
|
yay -S mangowc-git
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -87,12 +91,12 @@ eselect repository enable guru
|
||||||
emerge --sync guru
|
emerge --sync guru
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, add `gui-libs/scenefx` and `gui-wm/mangowm` to the `package.accept_keywords`.
|
Then, add `gui-libs/scenefx` and `gui-wm/mangowc` to the `package.accept_keywords`.
|
||||||
|
|
||||||
Finally, install the package:
|
Finally, install the package:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
emerge --ask --verbose gui-wm/mangowm
|
emerge --ask --verbose gui-wm/mangowc
|
||||||
```
|
```
|
||||||
|
|
||||||
## Fedora Linux
|
## Fedora Linux
|
||||||
|
|
@ -102,38 +106,9 @@ First, add the [Terra Repository](https://terra.fyralabs.com/).
|
||||||
Then, install the package:
|
Then, install the package:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dnf install mangowm
|
dnf install mangowc
|
||||||
```
|
```
|
||||||
|
|
||||||
## Guix System
|
|
||||||
The package definition is described in the source repository.
|
|
||||||
First, add `mangowm` channel to `channels.scm` file:
|
|
||||||
|
|
||||||
```scheme
|
|
||||||
;; In $HOME/.config/guix/channels.scm
|
|
||||||
(cons (channel
|
|
||||||
(name 'mangowm)
|
|
||||||
(url "https://github.com/mangowm/mango.git")
|
|
||||||
(branch "main"))
|
|
||||||
... ;; Your other channels
|
|
||||||
%default-channels)
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, run `guix pull` and after update you can either run
|
|
||||||
`guix install mangowm` or add it to your configuration via:
|
|
||||||
|
|
||||||
```scheme
|
|
||||||
(use-modules (mangowm)) ;; Add mangowm module
|
|
||||||
|
|
||||||
;; Add mangowm to packages list
|
|
||||||
(packages (cons*
|
|
||||||
mangowm-git
|
|
||||||
... ;; Other packages you specified
|
|
||||||
%base-packages))
|
|
||||||
```
|
|
||||||
|
|
||||||
And then rebuild your system.
|
|
||||||
|
|
||||||
## Other
|
## Other
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -147,8 +122,8 @@ cd scenefx
|
||||||
meson build -Dprefix=/usr
|
meson build -Dprefix=/usr
|
||||||
sudo ninja -C build install
|
sudo ninja -C build install
|
||||||
|
|
||||||
git clone https://github.com/mangowm/mango.git
|
git clone https://github.com/DreamMaoMao/mangowc.git
|
||||||
cd mangowm
|
cd mangowc
|
||||||
meson build -Dprefix=/usr
|
meson build -Dprefix=/usr
|
||||||
sudo ninja -C build install
|
sudo ninja -C build install
|
||||||
```
|
```
|
||||||
|
|
@ -206,9 +181,9 @@ git clone https://github.com/DreamMaoMao/mango-config.git ~/.config/mango
|
||||||
|
|
||||||
## Config Documentation
|
## Config Documentation
|
||||||
|
|
||||||
Refer to the repo wiki [wiki](https://github.com/mangowm/mango/wiki/)
|
Refer to the repo wiki [wiki](https://github.com/DreamMaoMao/mango/wiki/)
|
||||||
|
|
||||||
or the website docs [docs](https://mangowm.github.io/)
|
or the website docs [docs](https://mangowc.vercel.app/docs)
|
||||||
|
|
||||||
# NixOS + Home-manager
|
# NixOS + Home-manager
|
||||||
|
|
||||||
|
|
@ -228,7 +203,7 @@ Here's an example of using the modules in a flake:
|
||||||
};
|
};
|
||||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||||
mango = {
|
mango = {
|
||||||
url = "github:mangowm/mango";
|
url = "github:DreamMaoMao/mango";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -290,9 +265,9 @@ Here's an example of using the modules in a flake:
|
||||||
|
|
||||||
To package mango for other distributions, you can check the reference setup for:
|
To package mango for other distributions, you can check the reference setup for:
|
||||||
|
|
||||||
- [nix](https://github.com/mangowm/mango/blob/main/nix/default.nix)
|
- [nix](https://github.com/DreamMaoMao/mangowc/blob/main/nix/default.nix)
|
||||||
- [arch](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=mangowm-git).
|
- [arch](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=mangowc-git).
|
||||||
- [gentoo](https://data.gpo.zugaina.org/guru/gui-wm/mangowm)
|
- [gentoo](https://data.gpo.zugaina.org/guru/gui-wm/mangowc)
|
||||||
|
|
||||||
You might 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).
|
||||||
|
|
||||||
|
|
@ -310,15 +285,3 @@ Read The Friendly Manual on packaging software in your distribution first.
|
||||||
- https://github.com/swaywm/sway - Sample of Wayland protocol
|
- https://github.com/swaywm/sway - Sample of Wayland protocol
|
||||||
|
|
||||||
- https://github.com/wlrfx/scenefx - Make it simple to add window effect.
|
- https://github.com/wlrfx/scenefx - Make it simple to add window effect.
|
||||||
|
|
||||||
|
|
||||||
# Sponsor
|
|
||||||
At present, I can only accept sponsorship through an encrypted connection.
|
|
||||||
If you find this project helpful to you, you can offer sponsorship in the following ways.
|
|
||||||
|
|
||||||
<img width="650" height="870" alt="image" src="https://github.com/user-attachments/assets/8c860317-90d2-4071-971d-f1a92b674469" />
|
|
||||||
|
|
||||||
|
|
||||||
Thanks to the following friends for their sponsorship of this project
|
|
||||||
|
|
||||||
[@tonybanters](https://github.com/tonybanters)
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
[preferred]
|
|
||||||
default=gtk
|
|
||||||
org.freedesktop.impl.portal.ScreenCast=wlr
|
|
||||||
org.freedesktop.impl.portal.Screenshot=wlr
|
|
||||||
org.freedesktop.impl.portal.Inhibit=none
|
|
||||||
|
|
@ -26,7 +26,7 @@ focused_opacity=1.0
|
||||||
unfocused_opacity=1.0
|
unfocused_opacity=1.0
|
||||||
|
|
||||||
# Animation Configuration(support type:zoom,slide)
|
# Animation Configuration(support type:zoom,slide)
|
||||||
# tag_animation_direction: 1-horizontal,0-vertical
|
# tag_animation_direction: 0-horizontal,1-vertical
|
||||||
animations=1
|
animations=1
|
||||||
layer_animations=1
|
layer_animations=1
|
||||||
animation_type_open=slide
|
animation_type_open=slide
|
||||||
|
|
@ -77,7 +77,7 @@ overviewgappo=30
|
||||||
no_border_when_single=0
|
no_border_when_single=0
|
||||||
axis_bind_apply_timeout=100
|
axis_bind_apply_timeout=100
|
||||||
focus_on_activate=1
|
focus_on_activate=1
|
||||||
idleinhibit_ignore_visible=0
|
inhibit_regardless_of_visibility=0
|
||||||
sloppyfocus=1
|
sloppyfocus=1
|
||||||
warpcursor=1
|
warpcursor=1
|
||||||
focus_cross_monitor=0
|
focus_cross_monitor=0
|
||||||
|
|
@ -240,11 +240,12 @@ 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
|
||||||
# btn_left and btn_right can't bind none mod key
|
# NONE mode key only work in ov mode
|
||||||
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
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
title: Bindings & Input
|
|
||||||
description: Keybindings, mouse gestures, and input devices.
|
|
||||||
icon: Keyboard
|
|
||||||
---
|
|
||||||
|
|
||||||
Configure how you interact with mangowm using flexible keybindings and input options.
|
|
||||||
|
|
||||||
<Cards>
|
|
||||||
|
|
||||||
<Card href="/docs/bindings/keys" title="Key Bindings" description="Keyboard shortcuts and modes" />
|
|
||||||
|
|
||||||
<Card href="/docs/bindings/mouse-gestures" title="Mouse Gestures" description="Touchpad and mouse gestures" />
|
|
||||||
|
|
||||||
</Cards>
|
|
||||||
|
|
@ -1,204 +0,0 @@
|
||||||
---
|
|
||||||
title: Key Bindings
|
|
||||||
description: Define keyboard shortcuts and modes.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Syntax
|
|
||||||
|
|
||||||
Key bindings follow this format:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
bind[flags]=MODIFIERS,KEY,COMMAND,PARAMETERS
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Modifiers**: `SUPER`, `CTRL`, `ALT`, `SHIFT`, `NONE` (combine with `+`, e.g. `SUPER+CTRL+ALT`).
|
|
||||||
- **Key**: Key name (from `xev` or `wev`) or keycode (e.g., `code:24` for `q`).
|
|
||||||
|
|
||||||
> **Info:** `bind` automatically converts keysym to keycode for comparison. This makes it compatible with all keyboard layouts, but the matching may not always be precise. If a key combination doesn't work on your keyboard layout, use a keycode instead (e.g., `code:24` instead of `q`).
|
|
||||||
|
|
||||||
### Flags
|
|
||||||
|
|
||||||
- `l`: Works even when screen is locked.
|
|
||||||
- `s`: Uses keysym instead of keycode to bind.
|
|
||||||
- `r`: Triggers on key release instead of press.
|
|
||||||
- `p`: Pass key event to client.
|
|
||||||
|
|
||||||
**Examples:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
bind=SUPER,Q,killclient
|
|
||||||
bindl=SUPER,L,spawn,swaylock
|
|
||||||
|
|
||||||
# Using keycode instead of key name
|
|
||||||
bind=ALT,code:24,killclient
|
|
||||||
|
|
||||||
# Combining keycodes for modifiers and keys
|
|
||||||
bind=code:64,code:24,killclient
|
|
||||||
bind=code:64+code:133,code:24,killclient
|
|
||||||
|
|
||||||
# Bind with no modifier
|
|
||||||
bind=NONE,XF86MonBrightnessUp,spawn,brightnessctl set +5%
|
|
||||||
|
|
||||||
# Bind a modifier key itself as the trigger key
|
|
||||||
bind=alt,shift_l,switch_keyboard_layout
|
|
||||||
```
|
|
||||||
|
|
||||||
## Key Modes (Submaps)
|
|
||||||
|
|
||||||
You can divide key bindings into named modes. Rules:
|
|
||||||
|
|
||||||
1. Set `keymode=<name>` before a group of `bind` lines — those binds only apply in that mode.
|
|
||||||
2. If no `keymode` is set before a bind, it belongs to the `default` mode.
|
|
||||||
3. The special `common` keymode applies its binds **across all modes**.
|
|
||||||
|
|
||||||
Use `setkeymode` to switch modes, and `mmsg -b` to query the current mode.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Binds in 'common' apply in every mode
|
|
||||||
keymode=common
|
|
||||||
bind=SUPER,r,reload_config
|
|
||||||
|
|
||||||
# Default mode bindings
|
|
||||||
keymode=default
|
|
||||||
bind=ALT,Return,spawn,foot
|
|
||||||
bind=SUPER,F,setkeymode,resize
|
|
||||||
|
|
||||||
# 'resize' mode bindings
|
|
||||||
keymode=resize
|
|
||||||
bind=NONE,Left,resizewin,-10,0
|
|
||||||
bind=NONE,Right,resizewin,+10,0
|
|
||||||
bind=NONE,Escape,setkeymode,default
|
|
||||||
```
|
|
||||||
|
|
||||||
### Single Modifier Key Binding
|
|
||||||
|
|
||||||
When binding a modifier key itself, use `NONE` for press and the modifier name for release:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Trigger on press of Super key
|
|
||||||
bind=none,Super_L,spawn,rofi -show run
|
|
||||||
|
|
||||||
# Trigger on release of Super key
|
|
||||||
bindr=Super,Super_L,spawn,rofi -show run
|
|
||||||
```
|
|
||||||
|
|
||||||
## Dispatchers List
|
|
||||||
|
|
||||||
### Window Management
|
|
||||||
|
|
||||||
| Command | Param | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `killclient` | - | Close the focused window. |
|
|
||||||
| `togglefloating` | - | Toggle floating state. |
|
|
||||||
| `togglefullscreen` | - | Toggle fullscreen. |
|
|
||||||
| `togglefakefullscreen` | - | Toggle "fake" fullscreen (remains constrained). |
|
|
||||||
| `togglemaximizescreen` | - | Maximize window (keep decoration/bar). |
|
|
||||||
| `toggleglobal` | - | Pin window to all tags. |
|
|
||||||
| `toggle_render_border` | - | Toggle border rendering. |
|
|
||||||
| `centerwin` | - | Center the floating window. |
|
|
||||||
| `minimized` | - | Minimize window to scratchpad. |
|
|
||||||
| `restore_minimized` | - | Restore window from scratchpad. |
|
|
||||||
| `toggle_scratchpad` | - | Toggle scratchpad. |
|
|
||||||
| `toggle_named_scratchpad` | `appid,title,cmd` | Toggle named scratchpad. Launches app if not running, otherwise shows/hides it. |
|
|
||||||
|
|
||||||
### Focus & Movement
|
|
||||||
|
|
||||||
| Command | Param | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `focusdir` | `left/right/up/down` | Focus window in direction. |
|
|
||||||
| `focusstack` | `next/prev` | Cycle focus within the stack. |
|
|
||||||
| `focuslast` | - | Focus the previously active window. |
|
|
||||||
| `exchange_client` | `left/right/up/down` | Swap window with neighbor in direction. |
|
|
||||||
| `exchange_stack_client` | `next/prev` | Exchange window position in stack. |
|
|
||||||
| `zoom` | - | Swap focused window with Master. |
|
|
||||||
|
|
||||||
### Tags & Monitors
|
|
||||||
|
|
||||||
| Command | Param | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `view` | `-1/0/1-9` or `mask [,synctag]` | View tag. `-1` = previous tagset, `0` = all tags, `1-9` = specific tag, mask e.g. `1\|3\|5`. Optional `synctag` (0/1) syncs the action to all monitors. |
|
|
||||||
| `viewtoleft` | `[synctag]` | View previous tag. Optional `synctag` (0/1) syncs to all monitors. |
|
|
||||||
| `viewtoright` | `[synctag]` | View next tag. Optional `synctag` (0/1) syncs to all monitors. |
|
|
||||||
| `viewtoleft_have_client` | `[synctag]` | View left tag and focus client if present. Optional `synctag` (0/1). |
|
|
||||||
| `viewtoright_have_client` | `[synctag]` | View right tag and focus client if present. Optional `synctag` (0/1). |
|
|
||||||
| `viewcrossmon` | `tag,monitor_spec` | View specified tag on specified monitor. |
|
|
||||||
| `tag` | `1-9 [,synctag]` | Move window to tag. Optional `synctag` (0/1) syncs to all monitors. |
|
|
||||||
| `tagsilent` | `1-9` | Move window to tag without focusing it. |
|
|
||||||
| `tagtoleft` | `[synctag]` | Move window to left tag. Optional `synctag` (0/1). |
|
|
||||||
| `tagtoright` | `[synctag]` | Move window to right tag. Optional `synctag` (0/1). |
|
|
||||||
| `tagcrossmon` | `tag,monitor_spec` | Move window to specified tag on specified monitor. |
|
|
||||||
| `toggletag` | `0-9` | Toggle tag on window (0 means all tags). |
|
|
||||||
| `toggleview` | `1-9` | Toggle tag view. |
|
|
||||||
| `comboview` | `1-9` | View multi tags pressed simultaneously. |
|
|
||||||
| `focusmon` | `left/right/up/down/monitor_spec` | Focus monitor by direction or [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
|
||||||
| `tagmon` | `left/right/up/down/monitor_spec,[keeptag]` | Move window to monitor by direction or [monitor spec](/docs/configuration/monitors#monitor-spec-format). `keeptag` is 0 or 1. |
|
|
||||||
|
|
||||||
### Layouts
|
|
||||||
|
|
||||||
| Command | Param | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `setlayout` | `name` | Switch to layout (e.g., `scroller`, `tile`). |
|
|
||||||
| `switch_layout` | - | Cycle through available layouts. |
|
|
||||||
| `incnmaster` | `+1/-1` | Increase/Decrease number of master windows. |
|
|
||||||
| `setmfact` | `+0.05` | Increase/Decrease master area size. |
|
|
||||||
| `set_proportion` | `float` | Set scroller window proportion (0.0–1.0). |
|
|
||||||
| `switch_proportion_preset` | - | Cycle proportion presets of scroller window. |
|
|
||||||
| `scroller_stack` | `left/right/up/down` | Move window inside/outside scroller stack by direction. |
|
|
||||||
| `incgaps` | `+/-value` | Adjust gap size. |
|
|
||||||
| `togglegaps` | - | Toggle gaps. |
|
|
||||||
|
|
||||||
### System
|
|
||||||
|
|
||||||
| Command | Param | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `spawn` | `cmd` | Execute a command. |
|
|
||||||
| `spawn_shell` | `cmd` | Execute shell command (supports pipes `\|`). |
|
|
||||||
| `spawn_on_empty` | `cmd,tagnumber` | Open command on empty tag. |
|
|
||||||
| `reload_config` | - | Hot-reload configuration. |
|
|
||||||
| `quit` | - | Exit mangowm. |
|
|
||||||
| `toggleoverview` | - | Toggle overview mode. |
|
|
||||||
| `create_virtual_output` | - | Create a headless monitor (for VNC/Sunshine). |
|
|
||||||
| `destroy_all_virtual_output` | - | Destroy all virtual monitors. |
|
|
||||||
| `toggleoverlay` | - | Toggle overlay state for the focused window. |
|
|
||||||
| `toggle_trackpad_enable` | - | Toggle trackpad enable. |
|
|
||||||
| `setkeymode` | `mode` | Set keymode. |
|
|
||||||
| `switch_keyboard_layout` | `[index]` | Switch keyboard layout. Optional index (0, 1, 2...) to switch to specific layout. |
|
|
||||||
| `setoption` | `key,value` | Set config option temporarily. |
|
|
||||||
| `disable_monitor` | `monitor_spec` | Shutdown monitor. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
|
||||||
| `enable_monitor` | `monitor_spec` | Power on monitor. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
|
||||||
| `toggle_monitor` | `monitor_spec` | Toggle monitor power. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
|
||||||
|
|
||||||
### Media Controls
|
|
||||||
|
|
||||||
> **Warning:** Some keyboards don't send standard media keys. Run `wev` and press your key to check the exact key name.
|
|
||||||
|
|
||||||
#### Brightness
|
|
||||||
|
|
||||||
Requires: `brightnessctl`
|
|
||||||
|
|
||||||
```ini
|
|
||||||
bind=NONE,XF86MonBrightnessUp,spawn,brightnessctl s +2%
|
|
||||||
bind=SHIFT,XF86MonBrightnessUp,spawn,brightnessctl s 100%
|
|
||||||
bind=NONE,XF86MonBrightnessDown,spawn,brightnessctl s 2%-
|
|
||||||
bind=SHIFT,XF86MonBrightnessDown,spawn,brightnessctl s 1%
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Volume
|
|
||||||
|
|
||||||
Requires: `wpctl` (WirePlumber)
|
|
||||||
|
|
||||||
```ini
|
|
||||||
bind=NONE,XF86AudioRaiseVolume,spawn,wpctl set-volume @DEFAULT_SINK@ 5%+
|
|
||||||
bind=NONE,XF86AudioLowerVolume,spawn,wpctl set-volume @DEFAULT_SINK@ 5%-
|
|
||||||
bind=NONE,XF86AudioMute,spawn,wpctl set-mute @DEFAULT_SINK@ toggle
|
|
||||||
bind=SHIFT,XF86AudioMute,spawn,wpctl set-mute @DEFAULT_SOURCE@ toggle
|
|
||||||
```
|
|
||||||
|
|
||||||
### Floating Window Movement
|
|
||||||
|
|
||||||
| Command | Param | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `smartmovewin` | `left/right/up/down` | Move floating window by snap distance. |
|
|
||||||
| `smartresizewin` | `left/right/up/down` | Resize floating window by snap distance. |
|
|
||||||
| `movewin` | `(x,y)` | Move floating window. |
|
|
||||||
| `resizewin` | `(width,height)` | Resize window. |
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"title": "Bindings & Input",
|
|
||||||
"pages": ["keys", "mouse-gestures"]
|
|
||||||
}
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
---
|
|
||||||
title: Mouse & Gestures
|
|
||||||
description: Configure mouse buttons, scrolling, gestures, and lid switches.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Mouse Bindings
|
|
||||||
|
|
||||||
Assign actions to mouse button presses with optional modifier keys.
|
|
||||||
|
|
||||||
### Syntax
|
|
||||||
|
|
||||||
```ini
|
|
||||||
mousebind=MODIFIERS,BUTTON,COMMAND,PARAMETERS
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Modifiers**: `SUPER`, `CTRL`, `ALT`, `SHIFT`, `NONE`. Combine with `+` (e.g., `SUPER+CTRL`)
|
|
||||||
- **Buttons**: `btn_left`, `btn_right`, `btn_middle`, `btn_side`, `btn_extra`, `btn_forward`, `btn_back`, `btn_task`
|
|
||||||
|
|
||||||
> **Warning:** When modifiers are set to `NONE`, only `btn_middle` works in normal mode. `btn_left` and `btn_right` only work in overview mode.
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Window manipulation
|
|
||||||
mousebind=SUPER,btn_left,moveresize,curmove
|
|
||||||
mousebind=SUPER,btn_right,moveresize,curresize
|
|
||||||
mousebind=SUPER+CTRL,btn_right,killclient
|
|
||||||
|
|
||||||
# Overview mode (requires NONE modifier)
|
|
||||||
mousebind=NONE,btn_left,toggleoverview,-1
|
|
||||||
mousebind=NONE,btn_right,killclient,0
|
|
||||||
mousebind=NONE,btn_middle,togglemaximizescreen,0
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Axis Bindings
|
|
||||||
|
|
||||||
Map scroll wheel movements to actions for workspace and window navigation.
|
|
||||||
|
|
||||||
### Syntax
|
|
||||||
|
|
||||||
```ini
|
|
||||||
axisbind=MODIFIERS,DIRECTION,COMMAND,PARAMETERS
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Direction**: `UP`, `DOWN`, `LEFT`, `RIGHT`
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```ini
|
|
||||||
axisbind=SUPER,UP,viewtoleft_have_client
|
|
||||||
axisbind=SUPER,DOWN,viewtoright_have_client
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Gesture Bindings
|
|
||||||
|
|
||||||
Enable touchpad swipe gestures for navigation and window management.
|
|
||||||
|
|
||||||
### Syntax
|
|
||||||
|
|
||||||
```ini
|
|
||||||
gesturebind=MODIFIERS,DIRECTION,FINGERS,COMMAND,PARAMETERS
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Direction**: `up`, `down`, `left`, `right`
|
|
||||||
- **Fingers**: `3` or `4`
|
|
||||||
|
|
||||||
> **Info:** Gestures require proper touchpad configuration. See [Input Devices](/docs/configuration/input) for touchpad settings like `tap_to_click` and `disable_while_typing`.
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# 3-finger: Window focus
|
|
||||||
gesturebind=none,left,3,focusdir,left
|
|
||||||
gesturebind=none,right,3,focusdir,right
|
|
||||||
gesturebind=none,up,3,focusdir,up
|
|
||||||
gesturebind=none,down,3,focusdir,down
|
|
||||||
|
|
||||||
# 4-finger: Workspace navigation
|
|
||||||
gesturebind=none,left,4,viewtoleft_have_client
|
|
||||||
gesturebind=none,right,4,viewtoright_have_client
|
|
||||||
gesturebind=none,up,4,toggleoverview
|
|
||||||
gesturebind=none,down,4,toggleoverview
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Switch Bindings
|
|
||||||
|
|
||||||
Trigger actions on hardware events like laptop lid open/close.
|
|
||||||
|
|
||||||
### Syntax
|
|
||||||
|
|
||||||
```ini
|
|
||||||
switchbind=FOLD_STATE,COMMAND,PARAMETERS
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Fold State**: `fold` (lid closed), `unfold` (lid opened)
|
|
||||||
|
|
||||||
> **Warning:** Disable system lid handling in `/etc/systemd/logind.conf`:
|
|
||||||
>
|
|
||||||
> ```ini
|
|
||||||
> HandleLidSwitch=ignore
|
|
||||||
> HandleLidSwitchExternalPower=ignore
|
|
||||||
> HandleLidSwitchDocked=ignore
|
|
||||||
> ```
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```ini
|
|
||||||
switchbind=fold,spawn,swaylock -f -c 000000
|
|
||||||
switchbind=unfold,spawn,wlr-dpms on
|
|
||||||
```
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
---
|
|
||||||
title: Basic Configuration
|
|
||||||
description: Learn how to configure mangowm files, environment variables, and autostart scripts.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuration File
|
|
||||||
|
|
||||||
mangowm uses a simple configuration file format. By default, it looks for a configuration file in `~/.config/mango/`.
|
|
||||||
|
|
||||||
1. **Locate Default Config**
|
|
||||||
|
|
||||||
A fallback configuration is provided at `/etc/mango/config.conf`. You can use this as a reference.
|
|
||||||
|
|
||||||
2. **Create User Config**
|
|
||||||
|
|
||||||
Copy the default config to your local config directory to start customizing.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p ~/.config/mango
|
|
||||||
cp /etc/mango/config.conf ~/.config/mango/config.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Launch with Custom Config (Optional)**
|
|
||||||
|
|
||||||
If you prefer to keep your config elsewhere, you can launch mango with the `-c` flag.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mango -c /path/to/your_config.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
### Sub-Configuration
|
|
||||||
|
|
||||||
To keep your configuration organized, you can split it into multiple files and include them using the `source` keyword.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Import keybindings from a separate file
|
|
||||||
source=~/.config/mango/bind.conf
|
|
||||||
|
|
||||||
# Relative paths work too
|
|
||||||
source=./theme.conf
|
|
||||||
|
|
||||||
# Optional: ignore if file doesn't exist (useful for shared configs)
|
|
||||||
source-optional=~/.config/mango/optional.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
### Validate Configuration
|
|
||||||
|
|
||||||
You can check your configuration for errors without starting mangowm:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mango -c /path/to/config.conf -p
|
|
||||||
```
|
|
||||||
|
|
||||||
Use with `source-optional` for shared configs across different setups.
|
|
||||||
|
|
||||||
## Environment Variables
|
|
||||||
|
|
||||||
You can define environment variables directly within your config file. These are set before the window manager fully initializes.
|
|
||||||
|
|
||||||
> **Warning:** Environment variables defined here will be **reset** every time you reload the configuration.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
env=QT_IM_MODULES,wayland;fcitx
|
|
||||||
env=XMODIFIERS,@im=fcitx
|
|
||||||
```
|
|
||||||
|
|
||||||
## Autostart
|
|
||||||
|
|
||||||
mangowm can automatically run commands or scripts upon startup. There are two modes for execution:
|
|
||||||
|
|
||||||
| Command | Behavior | Usage Case |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `exec-once` | Runs **only once** when mangowm starts. | Status bars, Wallpapers, Notification daemons |
|
|
||||||
| `exec` | Runs **every time** the config is reloaded. | Scripts that need to refresh settings |
|
|
||||||
|
|
||||||
### Example Setup
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Start the status bar once
|
|
||||||
exec-once=waybar
|
|
||||||
|
|
||||||
# Set wallpaper
|
|
||||||
exec-once=swaybg -i ~/.config/mango/wallpaper/room.png
|
|
||||||
|
|
||||||
# Reload a custom script on config change
|
|
||||||
exec=bash ~/.config/mango/reload-settings.sh
|
|
||||||
```
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
---
|
|
||||||
title: Configuration
|
|
||||||
description: Configure mangowm with config files, environment variables, and autostart.
|
|
||||||
icon: Settings
|
|
||||||
---
|
|
||||||
|
|
||||||
Configure mangowm through config files, environment variables, and autostart.
|
|
||||||
|
|
||||||
<Cards>
|
|
||||||
|
|
||||||
<Card href="/docs/configuration/basics" title="Basics" description="Config files, env vars, exec-once, exec" />
|
|
||||||
|
|
||||||
<Card href="/docs/configuration/monitors" title="Monitors" description="Monitor settings and resolution" />
|
|
||||||
|
|
||||||
<Card href="/docs/configuration/input" title="Input" description="Keyboard, mouse, and touchpad" />
|
|
||||||
|
|
||||||
<Card href="/docs/configuration/xdg-portals" title="XDG Portals" description="File pickers and notifications" />
|
|
||||||
|
|
||||||
<Card href="/docs/configuration/miscellaneous" title="Miscellaneous" description="Additional options" />
|
|
||||||
|
|
||||||
</Cards>
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
---
|
|
||||||
title: Input Devices
|
|
||||||
description: Configure keyboard layouts, mouse sensitivity, and touchpad gestures.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Device Configuration
|
|
||||||
|
|
||||||
mangowm provides granular control over different input devices.
|
|
||||||
|
|
||||||
### Keyboard Settings
|
|
||||||
|
|
||||||
Control key repeat rates and layout rules.
|
|
||||||
|
|
||||||
| Setting | Type | Default | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `repeat_rate` | `int` | `25` | How many times a key repeats per second. |
|
|
||||||
| `repeat_delay` | `int` | `600` | Delay (ms) before a held key starts repeating. |
|
|
||||||
| `numlockon` | `0` or `1` | `0` | Enable NumLock on startup. |
|
|
||||||
| `xkb_rules_rules` | `string` | - | XKB rules file (e.g., `evdev`, `base`). Usually auto-detected. |
|
|
||||||
| `xkb_rules_model` | `string` | - | Keyboard model (e.g., `pc104`, `macbook`). |
|
|
||||||
| `xkb_rules_layout` | `string` | - | Keyboard layout code (e.g., `us`, `de`, `us,de`). |
|
|
||||||
| `xkb_rules_variant` | `string` | - | Layout variant (e.g., `dvorak`, `colemak`, `intl`). |
|
|
||||||
| `xkb_rules_options` | `string` | - | XKB options (e.g., `caps:escape`, `ctrl:nocaps`). |
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
repeat_rate=40
|
|
||||||
repeat_delay=300
|
|
||||||
numlockon=1
|
|
||||||
xkb_rules_layout=us,de
|
|
||||||
xkb_rules_variant=dvorak
|
|
||||||
xkb_rules_options=caps:escape,ctrl:nocaps
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Trackpad Settings
|
|
||||||
|
|
||||||
Specific settings for laptop touchpads. Some settings may require a relogin to take effect.
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `disable_trackpad` | `0` | Set to `1` to disable the trackpad entirely. |
|
|
||||||
| `tap_to_click` | `1` | Tap to trigger a left click. |
|
|
||||||
| `tap_and_drag` | `1` | Tap and hold to drag items. |
|
|
||||||
| `trackpad_natural_scrolling` | `0` | Invert scrolling direction (natural scrolling). |
|
|
||||||
| `scroll_method` | `1` | `1` (Two-finger), `2` (Edge), `4` (Button). |
|
|
||||||
| `click_method` | `1` | `1` (Button areas), `2` (Clickfinger). |
|
|
||||||
| `drag_lock` | `1` | Lock dragging after tapping. |
|
|
||||||
| `disable_while_typing` | `1` | Disable trackpad while typing. |
|
|
||||||
| `left_handed` | `0` | Swap left/right buttons. |
|
|
||||||
| `middle_button_emulation` | `0` | Emulate middle button. |
|
|
||||||
| `swipe_min_threshold` | `1` | Minimum swipe threshold. |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Detailed descriptions:**
|
|
||||||
|
|
||||||
- `scroll_method` values:
|
|
||||||
- `0` — Never send scroll events (no scrolling).
|
|
||||||
- `1` — Two-finger scrolling: send scroll events when two fingers are logically down on the device.
|
|
||||||
- `2` — Edge scrolling: send scroll events when a finger moves along the bottom or right edge.
|
|
||||||
- `4` — Button scrolling: send scroll events when a button is held and the device moves along a scroll axis.
|
|
||||||
|
|
||||||
- `click_method` values:
|
|
||||||
- `0` — No software click emulation.
|
|
||||||
- `1` — Button areas: use software-defined areas on the touchpad to generate button events.
|
|
||||||
- `2` — Clickfinger: the number of fingers determines which button is pressed.
|
|
||||||
|
|
||||||
- `accel_profile` values:
|
|
||||||
- `0` — No acceleration.
|
|
||||||
- `1` — Flat: no dynamic acceleration. Pointer speed = original input speed × (1 + `accel_speed`).
|
|
||||||
- `2` — Adaptive: slow movement results in less acceleration, fast movement results in more.
|
|
||||||
|
|
||||||
- `button_map` values:
|
|
||||||
- `0` — 1/2/3 finger tap maps to left / right / middle.
|
|
||||||
- `1` — 1/2/3 finger tap maps to left / middle / right.
|
|
||||||
|
|
||||||
- `send_events_mode` values:
|
|
||||||
- `0` — Send events from this device normally.
|
|
||||||
- `1` — Do not send events from this device.
|
|
||||||
- `2` — Disable this device when an external pointer device is plugged in.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Mouse Settings
|
|
||||||
|
|
||||||
Configuration for external mice.
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `mouse_natural_scrolling` | `0` | Invert scrolling direction. |
|
|
||||||
| `accel_profile` | `2` | `0` (None), `1` (Flat), `2` (Adaptive). |
|
|
||||||
| `accel_speed` | `0.0` | Speed adjustment (-1.0 to 1.0). |
|
|
||||||
| `left_handed` | `0` | Swap left and right buttons. |
|
|
||||||
| `middle_button_emulation` | `0` | Emulate middle button. |
|
|
||||||
| `swipe_min_threshold` | `1` | Minimum swipe threshold. |
|
|
||||||
| `send_events_mode` | `0` | `0` (Enabled), `1` (Disabled), `2` (Disabled on external mouse). |
|
|
||||||
| `button_map` | `0` | `0` (Left/right/middle), `1` (Left/middle/right). |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Keyboard Layout Switching
|
|
||||||
|
|
||||||
To bind multiple layouts and toggle between them, define the layouts in `xkb_rules_layout` and use `xkb_rules_options` to set a toggle key combination. Then bind `switch_keyboard_layout` to trigger a switch.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Define two layouts: US QWERTY and US Dvorak
|
|
||||||
xkb_rules_layout=us,us
|
|
||||||
xkb_rules_variant=,dvorak
|
|
||||||
xkb_rules_options=grp:lalt_lshift_toggle
|
|
||||||
```
|
|
||||||
|
|
||||||
Or bind it manually to a key:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Bind Alt+Shift_L to cycle keyboard layout
|
|
||||||
bind=alt,shift_l,switch_keyboard_layout
|
|
||||||
```
|
|
||||||
|
|
||||||
Use `mmsg -g -k` to query the current keyboard layout at any time.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Input Method Editor (IME)
|
|
||||||
|
|
||||||
To use Fcitx5 or IBus, set these environment variables in your config file.
|
|
||||||
|
|
||||||
> **Info:** These settings require a restart of the window manager to take effect.
|
|
||||||
|
|
||||||
**For Fcitx5:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
env=GTK_IM_MODULE,fcitx
|
|
||||||
env=QT_IM_MODULE,fcitx
|
|
||||||
env=QT_IM_MODULES,wayland;fcitx
|
|
||||||
env=SDL_IM_MODULE,fcitx
|
|
||||||
env=XMODIFIERS,@im=fcitx
|
|
||||||
env=GLFW_IM_MODULE,ibus
|
|
||||||
```
|
|
||||||
|
|
||||||
**For IBus:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
env=GTK_IM_MODULE,ibus
|
|
||||||
env=QT_IM_MODULE,ibus
|
|
||||||
env=XMODIFIERS,@im=ibus
|
|
||||||
```
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"title": "Configuration",
|
|
||||||
"pages": ["basics", "monitors", "input", "xdg-portals", "miscellaneous"]
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
---
|
|
||||||
title: Miscellaneous
|
|
||||||
description: Advanced settings for XWayland, focus behavior, and system integration.
|
|
||||||
---
|
|
||||||
|
|
||||||
## System & Hardware
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `xwayland_persistence` | `1` | Keep XWayland running even when no X11 apps are open (reduces startup lag). |
|
|
||||||
| `syncobj_enable` | `0` | Enable `drm_syncobj` timeline support (helps with gaming stutter/lag). **Requires restart.** |
|
|
||||||
| `allow_lock_transparent` | `0` | Allow the lock screen to be transparent. |
|
|
||||||
| `allow_shortcuts_inhibit` | `1` | Allow shortcuts to be inhibited by clients. |
|
|
||||||
| `vrr` | - | Set via [monitor rule](/docs/configuration/monitors#monitor-rules). |
|
|
||||||
|
|
||||||
## Focus & Input
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `focus_on_activate` | `1` | Automatically focus windows when they request activation. |
|
|
||||||
| `sloppyfocus` | `1` | Focus follows the mouse cursor. |
|
|
||||||
| `warpcursor` | `1` | Warp the cursor to the center of the window when focus changes via keyboard. |
|
|
||||||
| `cursor_hide_timeout` | `0` | Hide the cursor after `N` seconds of inactivity (`0` to disable). |
|
|
||||||
| `drag_tile_to_tile` | `0` | Allow dragging a tiled window onto another to swap their positions. |
|
|
||||||
| `drag_corner` | `3` | Corner for drag-to-tile detection (0: none, 1–3: corners, 4: auto-detect). |
|
|
||||||
| `drag_warp_cursor` | `1` | Warp cursor when dragging windows to tile. |
|
|
||||||
| `axis_bind_apply_timeout` | `100` | Timeout (ms) for detecting consecutive scroll events for axis bindings. |
|
|
||||||
| `axis_scroll_factor` | `1.0` | Scroll factor for axis scroll speed (0.1–10.0). |
|
|
||||||
|
|
||||||
## Multi-Monitor & Tags
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `focus_cross_monitor` | `0` | Allow directional focus to cross monitor boundaries. |
|
|
||||||
| `exchange_cross_monitor` | `0` | Allow exchanging clients across monitor boundaries. |
|
|
||||||
| `focus_cross_tag` | `0` | Allow directional focus to cross into other tags. |
|
|
||||||
| `view_current_to_back` | `0` | Toggling the current tag switches back to the previously viewed tag. |
|
|
||||||
| `scratchpad_cross_monitor` | `0` | Share the scratchpad pool across all monitors. |
|
|
||||||
| `single_scratchpad` | `1` | Only allow one scratchpad (named or standard) to be visible at a time. |
|
|
||||||
| `circle_layout` | - | A comma-separated list of layouts `switch_layout` cycles through,the value sample:`tile,scroller`. |
|
|
||||||
|
|
||||||
## Window Behavior
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `enable_floating_snap` | `0` | Snap floating windows to edges or other windows. |
|
|
||||||
| `snap_distance` | `30` | Max distance (pixels) to trigger floating snap. |
|
|
||||||
| `no_border_when_single` | `0` | Remove window borders when only one window is visible on the tag. |
|
|
||||||
| `idleinhibit_ignore_visible` | `0` | Allow invisible clients (e.g., background audio players) to inhibit idle. |
|
|
||||||
| `drag_tile_refresh_interval` | `8.0` | Interval (1.0–16.0) to refresh tiled window resize during drag. Too small may cause application lag. |
|
|
||||||
| `drag_floating_refresh_interval` | `8.0` | Interval (1.0–16.0) to refresh floating window resize during drag. Too small may cause application lag. |
|
|
||||||
|
|
@ -1,276 +0,0 @@
|
||||||
---
|
|
||||||
title: Monitors
|
|
||||||
description: Manage display outputs, resolution, scaling, and tearing.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Monitor Rules
|
|
||||||
|
|
||||||
You can configure each display output individually using the `monitorrule` keyword.
|
|
||||||
|
|
||||||
**Syntax:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
monitorrule=name:Values,Parameter:Values,Parameter:Values
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Info:** If any of the matching fields (`name`, `make`, `model`, `serial`) are set, **all** of the set ones must match to be considered a match. Use `wlr-randr` to get your monitor's name, make, model, and serial.
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `name` | string | Any | Match by monitor name (supports regex) |
|
|
||||||
| `make` | string | Any | Match by monitor manufacturer |
|
|
||||||
| `model` | string | Any | Match by monitor model |
|
|
||||||
| `serial` | string | Any | Match by monitor serial number |
|
|
||||||
| `width` | integer | 0-9999 | Monitor width |
|
|
||||||
| `height` | integer | 0-9999 | Monitor height |
|
|
||||||
| `refresh` | float | 0.001-9999.0 | Monitor refresh rate |
|
|
||||||
| `x` | integer | 0-99999 | X position |
|
|
||||||
| `y` | integer | 0-99999 | Y position |
|
|
||||||
| `scale` | float | 0.01-100.0 | Monitor scale |
|
|
||||||
| `vrr` | integer | 0, 1 | Enable variable refresh rate |
|
|
||||||
| `rr` | integer | 0-7 | Monitor transform |
|
|
||||||
| `custom` | integer | 0, 1 | Enable custom mode (not supported on all displays — may cause black screen) |
|
|
||||||
|
|
||||||
### Transform Values
|
|
||||||
|
|
||||||
| Value | Rotation |
|
|
||||||
| :--- | :--- |
|
|
||||||
| `0` | No transform |
|
|
||||||
| `1` | 90° counter-clockwise |
|
|
||||||
| `2` | 180° counter-clockwise |
|
|
||||||
| `3` | 270° counter-clockwise |
|
|
||||||
| `4` | 180° vertical flip |
|
|
||||||
| `5` | Flip + 90° counter-clockwise |
|
|
||||||
| `6` | Flip + 180° counter-clockwise |
|
|
||||||
| `7` | Flip + 270° counter-clockwise |
|
|
||||||
|
|
||||||
> **Critical:** If you use XWayland applications, **never use negative coordinates** for your monitor positions. This is a known XWayland bug that causes click events to malfunction. Always arrange your monitors starting from `0,0` and extend into positive coordinates.
|
|
||||||
|
|
||||||
> **Note:** that "name" is a regular expression. If you want an exact match, you need to add `^` and `$` to the beginning and end of the expression, for example, `^eDP-1$` matches exactly the string `eDP-1`.
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Laptop display: 1080p, 60Hz, positioned at origin
|
|
||||||
monitorrule=name:^eDP-1$,width:1920,height:1080,refresh:60,x:0,y:10
|
|
||||||
|
|
||||||
# Match by make and model instead of name
|
|
||||||
monitorrule=make:Chimei Innolux Corporation,model:0x15F5,width:1920,height:1080,refresh:60,x:0,y:0
|
|
||||||
|
|
||||||
# Virtual monitor with pattern matching
|
|
||||||
monitorrule=name:HEADLESS-.*,width:1920,height:1080,refresh:60,x:1926,y:0,scale:1,rr:0,vrr:0
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Monitor Spec Format
|
|
||||||
|
|
||||||
Several commands (`focusmon`, `tagmon`, `disable_monitor`, `enable_monitor`, `toggle_monitor`, `viewcrossmon`, `tagcrossmon`) accept a **monitor_spec** string to identify a monitor.
|
|
||||||
|
|
||||||
**Format:**
|
|
||||||
|
|
||||||
```text
|
|
||||||
name:xxx&&make:xxx&&model:xxx&&serial:xxx
|
|
||||||
```
|
|
||||||
|
|
||||||
- Any field can be omitted and there is no order requirement.
|
|
||||||
- If all fields are omitted, the string is treated as the monitor name directly (e.g., `eDP-1`).
|
|
||||||
- Use `wlr-randr` to find your monitor's name, make, model, and serial.
|
|
||||||
|
|
||||||
**Examples:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# By name (shorthand)
|
|
||||||
mmsg -d toggle_monitor,eDP-1
|
|
||||||
|
|
||||||
# By make and model
|
|
||||||
mmsg -d toggle_monitor,make:Chimei Innolux Corporation&&model:0x15F5
|
|
||||||
|
|
||||||
# By serial
|
|
||||||
mmsg -d toggle_monitor,serial:12345678
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Tearing (Game Mode)
|
|
||||||
|
|
||||||
Tearing allows games to bypass the compositor's VSync for lower latency.
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `allow_tearing` | `0` | Global tearing control: `0` (Disable), `1` (Enable), `2` (Fullscreen only). |
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
**Enable Globally:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
allow_tearing=1
|
|
||||||
```
|
|
||||||
|
|
||||||
**Enable per Window:**
|
|
||||||
|
|
||||||
Use a window rule to force tearing for specific games.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
windowrule=force_tearing:1,title:vkcube
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tearing Behavior Matrix
|
|
||||||
|
|
||||||
| `force_tearing` \ `allow_tearing` | DISABLED (0) | ENABLED (1) | FULLSCREEN_ONLY (2) |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| **UNSPECIFIED** (0) | Not Allowed | Follows tearing_hint | Only fullscreen follows tearing_hint |
|
|
||||||
| **ENABLED** (1) | Not Allowed | Allowed | Only fullscreen allowed |
|
|
||||||
| **DISABLED** (2) | Not Allowed | Not Allowed | Not Allowed |
|
|
||||||
|
|
||||||
### Graphics Card Compatibility
|
|
||||||
|
|
||||||
> **Warning:** Some graphics cards require setting the `WLR_DRM_NO_ATOMIC` environment variable before mango starts to successfully enable tearing.
|
|
||||||
|
|
||||||
Add this to `/etc/environment` and reboot:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
WLR_DRM_NO_ATOMIC=1
|
|
||||||
```
|
|
||||||
|
|
||||||
Or run mango with the environment variable:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
WLR_DRM_NO_ATOMIC=1 mango
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## GPU Compatibility
|
|
||||||
|
|
||||||
If mango cannot display correctly or shows a black screen, try selecting a specific GPU:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Use a single GPU
|
|
||||||
WLR_DRM_DEVICES=/dev/dri/card1 mango
|
|
||||||
|
|
||||||
# Use multiple GPUs
|
|
||||||
WLR_DRM_DEVICES=/dev/dri/card0:/dev/dri/card1 mango
|
|
||||||
```
|
|
||||||
|
|
||||||
Some GPUs have compatibility issues with `syncobj_enable=1` — it may crash apps like `kitty` that use syncobj. Set `WLR_DRM_NO_ATOMIC=1` in `/etc/environment` and reboot to resolve this.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Power Management
|
|
||||||
|
|
||||||
You can control monitor power using the `mmsg` IPC tool.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Turn off
|
|
||||||
mmsg -d disable_monitor,eDP-1
|
|
||||||
|
|
||||||
# Turn on
|
|
||||||
mmsg -d enable_monitor,eDP-1
|
|
||||||
|
|
||||||
# Toggle
|
|
||||||
mmsg -d toggle_monitor,eDP-1
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also use `wlr-randr` for monitor management:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Turn off monitor
|
|
||||||
wlr-randr --output eDP-1 --off
|
|
||||||
|
|
||||||
# Turn on monitor
|
|
||||||
wlr-randr --output eDP-1 --on
|
|
||||||
|
|
||||||
# Show all monitors
|
|
||||||
wlr-randr
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Screen Scale
|
|
||||||
|
|
||||||
### Without Global Scale (Recommended)
|
|
||||||
|
|
||||||
- If you do not use XWayland apps, you can use monitor rules or `wlr-randr` to set a global monitor scale.
|
|
||||||
- If you are using XWayland apps, it is not recommended to set a global monitor scale.
|
|
||||||
|
|
||||||
You can set scale like this, for example with a 1.4 factor.
|
|
||||||
|
|
||||||
**Dependencies:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yay -S xorg-xrdb
|
|
||||||
yay -S xwayland-satellite
|
|
||||||
```
|
|
||||||
|
|
||||||
**In config file:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
env=QT_AUTO_SCREEN_SCALE_FACTOR,1
|
|
||||||
env=QT_WAYLAND_FORCE_DPI,140
|
|
||||||
```
|
|
||||||
|
|
||||||
**In autostart:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo "Xft.dpi: 140" | xrdb -merge
|
|
||||||
gsettings set org.gnome.desktop.interface text-scaling-factor 1.4
|
|
||||||
```
|
|
||||||
|
|
||||||
**Edit autostart for XWayland:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Start xwayland
|
|
||||||
/usr/sbin/xwayland-satellite :11 &
|
|
||||||
# Apply scale 1.4 for xwayland
|
|
||||||
sleep 0.5s && echo "Xft.dpi: 140" | xrdb -merge
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using xwayland-satellite to Prevent Blurry XWayland Apps
|
|
||||||
|
|
||||||
If you use fractional scaling, you can use `xwayland-satellite` to automatically scale XWayland apps to prevent blurriness, for example with a scale of 1.4.
|
|
||||||
|
|
||||||
**Dependencies:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yay -S xwayland-satellite
|
|
||||||
```
|
|
||||||
|
|
||||||
**In config file:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
env=DISPLAY,:2
|
|
||||||
exec-once=xwayland-satellite :2
|
|
||||||
monitorrule=name:eDP-1,width:1920,height:1080,refresh:60,x:0,y:0,scale:1.4,vrr:0,rr:0
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Warning:** Use a `DISPLAY` value other than `:1` to avoid conflicting with mangowm.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Virtual Monitors
|
|
||||||
|
|
||||||
You can create and manage virtual displays through IPC commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create virtual output
|
|
||||||
mmsg -d create_virtual_output
|
|
||||||
|
|
||||||
# Destroy all virtual outputs
|
|
||||||
mmsg -d destroy_all_virtual_output
|
|
||||||
```
|
|
||||||
|
|
||||||
You can configure virtual monitors using `wlr-randr`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Show all monitors
|
|
||||||
wlr-randr
|
|
||||||
|
|
||||||
# Configure virtual monitor
|
|
||||||
wlr-randr --output HEADLESS-1 --pos 1921,0 --scale 1 --custom-mode 1920x1080@60Hz
|
|
||||||
```
|
|
||||||
|
|
||||||
Virtual monitors can be used for screen sharing with tools like [Sunshine](https://github.com/LizardByte/Sunshine) and [Moonlight](https://github.com/moonlight-stream/moonlight-android), allowing other devices to act as extended monitors.
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
---
|
|
||||||
title: XDG Portals
|
|
||||||
description: Set up screen sharing, clipboard, keyring, and file pickers using XDG portals.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Portal Configuration
|
|
||||||
|
|
||||||
You can customize portal settings via the following paths:
|
|
||||||
|
|
||||||
- **User Configuration (Priority):** `~/.config/xdg-desktop-portal/mango-portals.conf`
|
|
||||||
- **System Fallback:** `/usr/share/xdg-desktop-portal/mango-portals.conf`
|
|
||||||
|
|
||||||
> **Warning:** If you previously added `dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=wlroots` to your config, remove it. Mango now handles this automatically.
|
|
||||||
|
|
||||||
## Screen Sharing
|
|
||||||
|
|
||||||
To enable screen sharing (OBS, Discord, WebRTC), you need `xdg-desktop-portal-wlr`.
|
|
||||||
|
|
||||||
1. **Install Dependencies**
|
|
||||||
|
|
||||||
`pipewire`, `pipewire-pulse`, `xdg-desktop-portal-wlr`
|
|
||||||
|
|
||||||
2. **Optional: Add to autostart**
|
|
||||||
|
|
||||||
In some situations the portal may not start automatically. You can add this to your autostart script to ensure it launches:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/usr/lib/xdg-desktop-portal-wlr &
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Restart your computer** to apply changes.
|
|
||||||
|
|
||||||
### Known Issues
|
|
||||||
|
|
||||||
- **Window screen sharing:** Some applications may have issues sharing individual windows. See [#184](https://github.com/mangowm/mango/pull/184) for workarounds.
|
|
||||||
|
|
||||||
- **Screen recording lag:** If you experience stuttering during screen recording, see [xdg-desktop-portal-wlr#351](https://github.com/emersion/xdg-desktop-portal-wlr/issues/351).
|
|
||||||
|
|
||||||
## Clipboard Manager
|
|
||||||
|
|
||||||
Use `cliphist` to manage clipboard history.
|
|
||||||
|
|
||||||
**Dependencies:** `wl-clipboard`, `cliphist`, `wl-clip-persist`
|
|
||||||
|
|
||||||
**Autostart Config:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Keep clipboard content after app closes
|
|
||||||
wl-clip-persist --clipboard regular --reconnect-tries 0 &
|
|
||||||
|
|
||||||
# Watch clipboard and store history
|
|
||||||
wl-paste --type text --watch cliphist store &
|
|
||||||
```
|
|
||||||
|
|
||||||
## GNOME Keyring
|
|
||||||
|
|
||||||
If you need to store passwords or secrets (e.g., for VS Code or Minecraft launchers), install `gnome-keyring`.
|
|
||||||
|
|
||||||
**Configuration:**
|
|
||||||
|
|
||||||
Add the following to `~/.config/xdg-desktop-portal/mango-portals.conf`:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[preferred]
|
|
||||||
default=gtk
|
|
||||||
org.freedesktop.impl.portal.ScreenCast=wlr
|
|
||||||
org.freedesktop.impl.portal.Screenshot=wlr
|
|
||||||
org.freedesktop.impl.portal.Secret=gnome-keyring
|
|
||||||
org.freedesktop.impl.portal.Inhibit=none
|
|
||||||
```
|
|
||||||
|
|
||||||
## File Picker (File Selector)
|
|
||||||
|
|
||||||
**Dependencies:** `xdg-desktop-portal`, `xdg-desktop-portal-gtk`
|
|
||||||
|
|
||||||
Reboot your computer once to apply.
|
|
||||||
101
docs/faq.md
101
docs/faq.md
|
|
@ -1,101 +0,0 @@
|
||||||
---
|
|
||||||
title: FAQ
|
|
||||||
description: Frequently asked questions and troubleshooting.
|
|
||||||
---
|
|
||||||
|
|
||||||
### How do I arrange tiled windows with my mouse?
|
|
||||||
|
|
||||||
You can enable the `drag_tile_to_tile` option in your config. This allows you to drag a tiled window onto another to swap them.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
drag_tile_to_tile=1
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Why is my background blurry or why does blur look wrong?
|
|
||||||
|
|
||||||
Blur applies to the transparent areas of windows. To disable it entirely, set `blur=0`.
|
|
||||||
|
|
||||||
If you are experiencing **performance issues with blur**, make sure `blur_optimized=1` (the default). This caches the wallpaper as the blur background, which is much cheaper on the GPU:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
blur_optimized=1
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Blur shows my wallpaper instead of the real background content
|
|
||||||
|
|
||||||
This is expected behavior when `blur_optimized=1` (the default). The optimizer caches the wallpaper to reduce GPU load — windows will blur against the wallpaper rather than the actual content stacked beneath them.
|
|
||||||
|
|
||||||
If you want blur to composite against the true background (i.e., show whatever is actually behind the window), set:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
blur_optimized=0
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Warning:** Disabling `blur_optimized` significantly increases GPU consumption and may cause rendering lag, especially on lower-end hardware.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### My games are lagging or stuttering
|
|
||||||
|
|
||||||
Try enabling **SyncObj** timeline support and **Adaptive Sync** (VRR) if your monitor supports it.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
syncobj_enable=1
|
|
||||||
adaptive_sync=1
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### My games have high input latency
|
|
||||||
|
|
||||||
You can enable **Tearing** (similar to VSync off).
|
|
||||||
|
|
||||||
First, enable it globally:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
allow_tearing=1
|
|
||||||
```
|
|
||||||
|
|
||||||
Then force it for your specific game:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
windowrule=force_tearing:1,title:Counter-Strike 2
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Warning:** Some graphics cards require setting `WLR_DRM_NO_ATOMIC=1` before mango starts for tearing to work. Add it to `/etc/environment` and reboot, or launch mango with `WLR_DRM_NO_ATOMIC=1 mango`. See [Monitors — Tearing](/docs/configuration/monitors#tearing-game-mode) for details.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### How do I use pipes `|` in spawn commands?
|
|
||||||
|
|
||||||
The standard `spawn` command does not support shell pipes directly. You must use `spawn_shell` instead.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
bind=SUPER,P,spawn_shell,echo "hello" | rofi -dmenu
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Certain key combinations do not work on my keyboard layout.
|
|
||||||
|
|
||||||
`bind` automatically converts keysym to keycode, which is compatible with most layouts but can sometimes be imprecise. If a key combination is not triggering, use the **keycode** directly instead of the key name.
|
|
||||||
|
|
||||||
Run `wev` and press the key to find its keycode, then use it in your bind:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Instead of:
|
|
||||||
bind=ALT,q,killclient
|
|
||||||
|
|
||||||
# Use the keycode (e.g., code:24 = q on most layouts):
|
|
||||||
bind=ALT,code:24,killclient
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also use `binds` (the `s` flag) to match by keysym instead of keycode:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
binds=ALT,q,killclient
|
|
||||||
```
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
---
|
|
||||||
title: Introduction
|
|
||||||
description: A lightweight and feature-rich Wayland compositor based on dwl.
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
**mango** is a Wayland compositor based on [dwl](https://codeberg.org/dwl/dwl/). It aims to be as lightweight as `dwl` and can be built completely within a few seconds, without compromising on functionality.
|
|
||||||
|
|
||||||
> **Philosophy:** **Lightweight & Fast**: mango is designed to be minimal yet functional. It compiles in seconds and offers a robust set of features out of the box.
|
|
||||||
|
|
||||||
## Feature Highlights
|
|
||||||
|
|
||||||
Beyond basic window management, mangowm provides a rich set of features designed for a modern Wayland experience.
|
|
||||||
|
|
||||||
- **[Animations](/docs/visuals/animations)** — Smooth, customizable animations for opening, moving, closing windows and tag switching.
|
|
||||||
- **[Layouts](/docs/window-management/layouts)** — Supports Scroller, Master-Stack, Monocle, Grid, Deck, and more, with per-tag layouts.
|
|
||||||
- **[Visual Effects](/docs/visuals/effects)** — Built-in blur, shadows, corner radius, and opacity effects powered by scenefx.
|
|
||||||
- **[IPC & Scripting](/docs/ipc)** — Control the compositor externally with robust IPC support for custom scripts and widgets.
|
|
||||||
|
|
||||||
## Additional Features
|
|
||||||
|
|
||||||
- **XWayland Support** — Excellent compatibility for legacy X11 applications.
|
|
||||||
- **Tag System** — Uses tags instead of workspaces, allowing separate window layouts for each tag.
|
|
||||||
- **Input Methods** — Great support for text input v2/v3 (Fcitx5, IBus).
|
|
||||||
- **Window States** — Rich states including swallow, minimize, maximize, fullscreen, and overlay.
|
|
||||||
- **Hot-Reload Config** — Simple external configuration that supports hot-reloading without restarting.
|
|
||||||
- **Scratchpads** — Support for both Sway-like and named scratchpads.
|
|
||||||
|
|
||||||
## Community
|
|
||||||
|
|
||||||
- **[Join the mangowm Discord](https://discord.gg/CPjbDxesh5)** — Chat with the community, get support, share your setup, and stay updated with the latest mangowm news.
|
|
||||||
- **[Join the GitHub Discussions](https://github.com/mangowm/mango/discussions)** — Ask questions, request features, report issues, or share ideas directly with contributors and other users.
|
|
||||||
|
|
||||||
## Acknowledgements
|
|
||||||
|
|
||||||
This project is built upon the hard work of several open-source projects:
|
|
||||||
|
|
||||||
- **[wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)** — Implementation of the Wayland protocol.
|
|
||||||
- **[mwc](https://github.com/nikoloc/mwc)** — Basal window animation reference.
|
|
||||||
- **[dwl](https://codeberg.org/dwl/dwl)** — Basal dwl features.
|
|
||||||
- **[sway](https://github.com/swaywm/sway)** — Sample implementation of the Wayland protocol.
|
|
||||||
- **[scenefx](https://github.com/wlrfx/scenefx)** — Library to simplify adding window effects.
|
|
||||||
|
|
@ -1,239 +0,0 @@
|
||||||
---
|
|
||||||
title: Installation
|
|
||||||
description: Install mangowm on AerynOS, Arch, Fedora, Gentoo, Guix System, NixOS, PikaOS, or build from source.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Package Installation
|
|
||||||
|
|
||||||
mangowm is available as a pre-built package on several distributions. Choose your distribution below.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### AerynOS
|
|
||||||
|
|
||||||
mangowm is available in the **AerynOS package repository**.
|
|
||||||
|
|
||||||
You can install it using the `moss` package manager:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo moss install mangowm
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Arch Linux
|
|
||||||
|
|
||||||
mangowm is available in the **Arch User Repository (AUR)**.
|
|
||||||
|
|
||||||
You can install it using an AUR helper like `yay` or `paru`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yay -S mangowm-git
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Tip:** This package pulls the latest git version, ensuring you have the newest features and fixes.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Fedora
|
|
||||||
|
|
||||||
The package is in the third-party **Terra repository**. First, add the Terra Repository.
|
|
||||||
|
|
||||||
> **Warning:** Both commands require root privileges. Use `sudo` if needed.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dnf install --nogpgcheck --repofrompath 'terra,https://repos.fyralabs.com/terra$releasever' terra-release
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, install the package:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dnf install mangowm
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Gentoo
|
|
||||||
|
|
||||||
The package is hosted in the community-maintained **GURU** repository.
|
|
||||||
|
|
||||||
1. **Add the GURU repository**
|
|
||||||
```bash
|
|
||||||
emerge --ask --verbose eselect-repository
|
|
||||||
eselect repository enable guru
|
|
||||||
emerge --sync guru
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Unmask packages**
|
|
||||||
Add the required packages to your `package.accept_keywords` file:
|
|
||||||
- `gui-libs/scenefx`
|
|
||||||
- `gui-wm/mangowm`
|
|
||||||
|
|
||||||
3. **Install mango**
|
|
||||||
```bash
|
|
||||||
emerge --ask --verbose gui-wm/mangowm
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Guix System
|
|
||||||
|
|
||||||
The package definition is described in the source repository.
|
|
||||||
|
|
||||||
1. **Add mango channel**
|
|
||||||
Add to `$HOME/.config/guix/channels.scm`:
|
|
||||||
```scheme
|
|
||||||
(cons (channel
|
|
||||||
(name 'mangowm)
|
|
||||||
(url "https://github.com/mangowm/mango.git")
|
|
||||||
(branch "main"))
|
|
||||||
%default-channels)
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Install**
|
|
||||||
After running `guix pull`, you can install mangowm:
|
|
||||||
```bash
|
|
||||||
guix install mangowm
|
|
||||||
```
|
|
||||||
|
|
||||||
Or add it to your system configuration using the mangowm module:
|
|
||||||
```scheme
|
|
||||||
(use-modules (mangowm))
|
|
||||||
|
|
||||||
(packages (cons*
|
|
||||||
mangowm-git
|
|
||||||
... ;; Other packages
|
|
||||||
%base-packages))
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Tip:** For more information, see the [Guix System documentation](https://guix.gnu.org/manual/devel/en/html_node/Channels.html).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### NixOS
|
|
||||||
|
|
||||||
The repository provides a Flake with a NixOS module.
|
|
||||||
|
|
||||||
1. **Add flake input**
|
|
||||||
```nix
|
|
||||||
# flake.nix
|
|
||||||
{
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
||||||
mangowm = {
|
|
||||||
url = "github:mangowm/mango";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
# other inputs ...
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Import the NixOS module**
|
|
||||||
|
|
||||||
**Option A — Import in `configuration.nix`:**
|
|
||||||
```nix
|
|
||||||
# configuration.nix (or any other file that you import)
|
|
||||||
{inputs, ...}: {
|
|
||||||
imports = [
|
|
||||||
inputs.mangowm.nixosModules.mango
|
|
||||||
# .. other imports ...
|
|
||||||
];
|
|
||||||
|
|
||||||
# ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Option B — Import directly in flake:**
|
|
||||||
```nix
|
|
||||||
# flake.nix
|
|
||||||
{
|
|
||||||
# ...
|
|
||||||
|
|
||||||
outputs = { self, nixpkgs, mangowm, ...}@inputs: let
|
|
||||||
inherit (nixpkgs) lib;
|
|
||||||
# ...
|
|
||||||
in {
|
|
||||||
nixosConfigurations.YourHostName = lib.nixosSystem {
|
|
||||||
modules = [
|
|
||||||
mangowm.nixosModules.mango # or inputs.mangowm.nixosModules.mango
|
|
||||||
# other imports ...
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Enable the module**
|
|
||||||
```nix
|
|
||||||
# configuration.nix (or any other file that you import)
|
|
||||||
{
|
|
||||||
programs.mango.enable = true;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Extra options**
|
|
||||||
- `programs.mango.package` — the mango package to use, allows usage of custom mango drvs
|
|
||||||
- `programs.mango.addLoginEntry` (default: `true`) — adds login entry to the display manager
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### PikaOS
|
|
||||||
|
|
||||||
mangowm is available in the **PikaOS package repository**.
|
|
||||||
|
|
||||||
You can install it using the `pikman` package manager:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pikman install mangowc
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Building from Source
|
|
||||||
|
|
||||||
If your distribution isn't listed above, or you want the latest unreleased changes, you can build mangowm from source.
|
|
||||||
|
|
||||||
> **Info:** Ensure the following dependencies are installed before proceeding:
|
|
||||||
> - `wayland`
|
|
||||||
> - `wayland-protocols`
|
|
||||||
> - `libinput`
|
|
||||||
> - `libdrm`
|
|
||||||
> - `libxkbcommon`
|
|
||||||
> - `pixman`
|
|
||||||
> - `libdisplay-info`
|
|
||||||
> - `libliftoff`
|
|
||||||
> - `hwdata`
|
|
||||||
> - `seatd`
|
|
||||||
> - `pcre2`
|
|
||||||
> - `xorg-xwayland`
|
|
||||||
> - `libxcb`
|
|
||||||
|
|
||||||
You will need to build `wlroots` and `scenefx` manually as well.
|
|
||||||
|
|
||||||
1. **Build wlroots**
|
|
||||||
Clone and install the specific version required (check README for latest version).
|
|
||||||
```bash
|
|
||||||
git clone -b 0.19.2 https://gitlab.freedesktop.org/wlroots/wlroots.git
|
|
||||||
cd wlroots
|
|
||||||
meson build -Dprefix=/usr
|
|
||||||
sudo ninja -C build install
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Build scenefx**
|
|
||||||
This library handles the visual effects.
|
|
||||||
```bash
|
|
||||||
git clone -b 0.4.1 https://github.com/wlrfx/scenefx.git
|
|
||||||
cd scenefx
|
|
||||||
meson build -Dprefix=/usr
|
|
||||||
sudo ninja -C build install
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Build mangowm**
|
|
||||||
Finally, compile the compositor itself.
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/mangowm/mango.git
|
|
||||||
cd mango
|
|
||||||
meson build -Dprefix=/usr
|
|
||||||
sudo ninja -C build install
|
|
||||||
```
|
|
||||||
154
docs/ipc.md
154
docs/ipc.md
|
|
@ -1,154 +0,0 @@
|
||||||
---
|
|
||||||
title: IPC
|
|
||||||
description: Control mangowm programmatically using mmsg.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
mangowm includes a powerful IPC (Inter-Process Communication) tool called `mmsg`. This allows you to query the window manager's state, watch for events, and execute commands from external scripts.
|
|
||||||
|
|
||||||
## Basic Usage
|
|
||||||
|
|
||||||
The general syntax for `mmsg` is:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mmsg [-OTLq]
|
|
||||||
mmsg [-o <output>] -s [-t <tags>] [-l <layout>] [-c <tags>] [-d <cmd>,<arg1>,<arg2>,<arg3>,<arg4>,<arg5>]
|
|
||||||
mmsg [-o <output>] (-g | -w) [-OotlcvmfxekbA]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Options
|
|
||||||
|
|
||||||
| Flag | Description |
|
|
||||||
| :--- | :--- |
|
|
||||||
| `-q` | Quit mangowm. |
|
|
||||||
| `-g` | **Get** values (tags, layout, focused client). |
|
|
||||||
| `-s` | **Set** values (switch tags, layouts). |
|
|
||||||
| `-w` | **Watch** mode (streams events). |
|
|
||||||
| `-O` | Get all output (monitor) information. |
|
|
||||||
| `-T` | Get number of tags. |
|
|
||||||
| `-L` | Get all available layouts. |
|
|
||||||
| `-o` | Select output (monitor). |
|
|
||||||
| `-t` | Get/set selected tags (set with `[+-^.]`). |
|
|
||||||
| `-l` | Get/set current layout. |
|
|
||||||
| `-c` | Get title and appid of focused client. |
|
|
||||||
| `-v` | Get visibility of statusbar. |
|
|
||||||
| `-m` | Get fullscreen status. |
|
|
||||||
| `-f` | Get floating status. |
|
|
||||||
| `-d` | **Dispatch** an internal command. |
|
|
||||||
| `-x` | Get focused client geometry. |
|
|
||||||
| `-e` | Get the name of the last focused layer. |
|
|
||||||
| `-k` | Get current keyboard layout. |
|
|
||||||
| `-b` | Get current keybind mode. |
|
|
||||||
| `-A` | Get scale factor of monitor. |
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### Tag Management
|
|
||||||
|
|
||||||
You can perform arithmetic on tags using the `-t` flag with `-s` (set).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Switch to Tag 1
|
|
||||||
mmsg -t 1
|
|
||||||
|
|
||||||
# Add Tag 2 to current view (Multiview)
|
|
||||||
mmsg -s -t 2+
|
|
||||||
|
|
||||||
# Remove Tag 2 from current view
|
|
||||||
mmsg -s -t 2-
|
|
||||||
|
|
||||||
# Toggle Tag 2
|
|
||||||
mmsg -s -t 2^
|
|
||||||
```
|
|
||||||
|
|
||||||
### Layouts
|
|
||||||
|
|
||||||
Switch layouts programmatically. Layout codes: `S` (Scroller), `T` (Tile), `G` (Grid), `M` (Monocle), `K` (Deck), `CT` (Center Tile), `RT` (Right Tile), `VS` (Vertical Scroller), `VT` (Vertical Tile), `VG` (Vertical Grid), `VK` (Vertical Deck), `TG` (TGMix).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Switch to Scroller
|
|
||||||
mmsg -l "S"
|
|
||||||
|
|
||||||
# Switch to Tile
|
|
||||||
mmsg -l "T"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dispatching Commands
|
|
||||||
|
|
||||||
Any command available in `config.conf` keybindings can be run via IPC.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Close the focused window
|
|
||||||
mmsg -d killclient
|
|
||||||
|
|
||||||
# Resize window by +10 width
|
|
||||||
mmsg -d resizewin,+10,0
|
|
||||||
|
|
||||||
# Toggle fullscreen
|
|
||||||
mmsg -d togglefullscreen
|
|
||||||
|
|
||||||
# Disable a monitor power
|
|
||||||
mmsg -d disable_monitor,eDP-1
|
|
||||||
```
|
|
||||||
|
|
||||||
### Monitoring & Status
|
|
||||||
|
|
||||||
Use `-g` or `-w` to build custom status bars or automation scripts.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Watch for all message changes
|
|
||||||
mmsg -w
|
|
||||||
|
|
||||||
# Get all messages without watch
|
|
||||||
mmsg -g
|
|
||||||
|
|
||||||
# Watch focused client appid and title
|
|
||||||
mmsg -w -c
|
|
||||||
|
|
||||||
# Get all available outputs
|
|
||||||
mmsg -O
|
|
||||||
|
|
||||||
# Get all tags message
|
|
||||||
mmsg -g -t
|
|
||||||
|
|
||||||
# Get current focused client message
|
|
||||||
mmsg -g -c
|
|
||||||
|
|
||||||
# Get current keyboard layout
|
|
||||||
mmsg -g -k
|
|
||||||
|
|
||||||
# Get current keybind mode
|
|
||||||
mmsg -g -b
|
|
||||||
|
|
||||||
# Get scale factor of current monitor
|
|
||||||
mmsg -g -A
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Tag Message Format
|
|
||||||
|
|
||||||
- State: 0 → none, 1 → active, 2 → urgent
|
|
||||||
|
|
||||||
Example output:
|
|
||||||
|
|
||||||
| Monitor | Tag Number | Tag State | Clients in Tag | Focused Client |
|
|
||||||
|---------|------------|-----------|----------------|----------------|
|
|
||||||
| eDP-1 | tag 2 | 0 | 1 | 0 |
|
|
||||||
|
|
||||||
| Monitor | occupied tags mask | active tags mask | urgent tags mask |
|
|
||||||
|---------|--------------------|------------------|------------------|
|
|
||||||
| eDP-1 | 14 | 6 | 0 |
|
|
||||||
|
|
||||||
## Virtual Monitors
|
|
||||||
|
|
||||||
You can create headless outputs for screen mirroring or remote desktop access (e.g., Sunshine/Moonlight).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create a virtual output
|
|
||||||
mmsg -d create_virtual_output
|
|
||||||
|
|
||||||
# Configure it (set resolution)
|
|
||||||
wlr-randr --output HEADLESS-1 --pos 1920,0 --mode 1920x1080@60Hz
|
|
||||||
|
|
||||||
# Destroy all virtual outputs
|
|
||||||
mmsg -d destroy_all_virtual_output
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"title": "mangowm",
|
|
||||||
"pages": [
|
|
||||||
"---Getting Started---",
|
|
||||||
"index",
|
|
||||||
"installation",
|
|
||||||
"quick-start",
|
|
||||||
"---Configuration---",
|
|
||||||
"configuration",
|
|
||||||
"visuals",
|
|
||||||
"window-management",
|
|
||||||
"bindings",
|
|
||||||
"---Reference---",
|
|
||||||
"ipc",
|
|
||||||
"faq"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
---
|
|
||||||
title: Quick Start
|
|
||||||
description: Basic configuration and first steps with mangowm.
|
|
||||||
---
|
|
||||||
|
|
||||||
Now that you have mangowm installed, let's get your environment set up.
|
|
||||||
|
|
||||||
## Initial Setup
|
|
||||||
|
|
||||||
1. **Create Configuration Directory**
|
|
||||||
|
|
||||||
mangowm looks for configuration files in `~/.config/mango/`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p ~/.config/mango
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Copy Default Config**
|
|
||||||
|
|
||||||
A default configuration file is provided at `/etc/mango/config.conf`. Copy it to your local directory to start customizing.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp /etc/mango/config.conf ~/.config/mango/config.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Launch mangowm**
|
|
||||||
|
|
||||||
You can now start the compositor from your TTY.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mango
|
|
||||||
```
|
|
||||||
|
|
||||||
Optional: To specify a custom config file path:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mango -c /path/to/your/config.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
## Essential Keybindings
|
|
||||||
|
|
||||||
mangowm uses the following keybinds by default:
|
|
||||||
|
|
||||||
| Key Combination | Action |
|
|
||||||
| :--- | :--- |
|
|
||||||
| `Alt` + `Return` | Open Terminal (defaults to `foot`) |
|
|
||||||
| `Alt` + `Space` | Open Launcher (defaults to `rofi`) |
|
|
||||||
| `Alt` + `Q` | Close (Kill) the active window |
|
|
||||||
| `Super` + `M` | Quit mangowm |
|
|
||||||
| `Super` + `F` | Toggle Fullscreen |
|
|
||||||
| `Alt` + `Arrow Keys` | Move focus (Left, Right, Up, Down) |
|
|
||||||
| `Ctrl` + `1-9` | Switch to Tag 1-9 |
|
|
||||||
| `Alt` + `1-9` | Move window to Tag 1-9 |
|
|
||||||
|
|
||||||
> **Warning:** Some default bindings rely on specific tools like `foot` (terminal) and `rofi` (launcher). Ensure you have them installed or update your `config.conf` to use your preferred alternatives.
|
|
||||||
|
|
||||||
## Recommended Tools
|
|
||||||
|
|
||||||
To get a fully functional desktop experience, we recommend installing the following components:
|
|
||||||
|
|
||||||
| Category | Recommended Tools |
|
|
||||||
| :--- | :--- |
|
|
||||||
| Application Launcher | rofi, bemenu, wmenu, fuzzel |
|
|
||||||
| Terminal Emulator | foot, wezterm, alacritty, kitty, ghostty |
|
|
||||||
| Status Bar | waybar, eww, quickshell, ags |
|
|
||||||
| Desktop Shell | Noctalia, DankMaterialShell |
|
|
||||||
| Wallpaper Setup | swww, swaybg |
|
|
||||||
| Notification Daemon | swaync, dunst, mako |
|
|
||||||
| Desktop Portal | xdg-desktop-portal, xdg-desktop-portal-wlr, xdg-desktop-portal-gtk |
|
|
||||||
| Clipboard | wl-clipboard, wl-clip-persist, cliphist |
|
|
||||||
| Gamma Control / Night Light | wlsunset, gammastep |
|
|
||||||
| Miscellaneous | xfce-polkit, wlogout |
|
|
||||||
|
|
||||||
## Example Configuration
|
|
||||||
|
|
||||||
Check out the [example configuration](https://github.com/DreamMaoMao/mango-config) by the creator of mangowm, including complete setups for mangowm, Waybar, Rofi, and more.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/DreamMaoMao/mango-config.git ~/.config/mango
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
Now that you are up and running, dive deeper into customizing mangowm:
|
|
||||||
|
|
||||||
- [Configure Monitors](/docs/configuration/monitors) — Set up resolution, scaling, and multi-monitor layouts.
|
|
||||||
- [Window Rules](/docs/window-management/rules#window-rules) — Define how specific applications should behave.
|
|
||||||
- [Appearance](/docs/visuals/theming) — Customize colors, borders, gaps, and effects.
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
---
|
|
||||||
title: Animations
|
|
||||||
description: Configure smooth transitions for windows and layers.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Enabling Animations
|
|
||||||
|
|
||||||
mangowm supports animations for both standard windows and layer shell surfaces (like bars and notifications).
|
|
||||||
|
|
||||||
```ini
|
|
||||||
animations=1
|
|
||||||
layer_animations=1
|
|
||||||
```
|
|
||||||
|
|
||||||
## Animation Types
|
|
||||||
|
|
||||||
You can define different animation styles for opening and closing windows and layer surfaces.
|
|
||||||
|
|
||||||
Available types: `slide`, `zoom`, `fade`, `none`.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
animation_type_open=zoom
|
|
||||||
animation_type_close=slide
|
|
||||||
layer_animation_type_open=slide
|
|
||||||
layer_animation_type_close=slide
|
|
||||||
```
|
|
||||||
|
|
||||||
## Fade Settings
|
|
||||||
|
|
||||||
Control the fade-in and fade-out effects for animations.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
animation_fade_in=1
|
|
||||||
animation_fade_out=1
|
|
||||||
fadein_begin_opacity=0.5
|
|
||||||
fadeout_begin_opacity=0.5
|
|
||||||
```
|
|
||||||
|
|
||||||
- `animation_fade_in` — Enable fade-in effect (0: disable, 1: enable)
|
|
||||||
- `animation_fade_out` — Enable fade-out effect (0: disable, 1: enable)
|
|
||||||
- `fadein_begin_opacity` — Starting opacity for fade-in animations (0.0–1.0)
|
|
||||||
- `fadeout_begin_opacity` — Starting opacity for fade-out animations (0.0–1.0)
|
|
||||||
|
|
||||||
## Zoom Settings
|
|
||||||
|
|
||||||
Adjust the zoom ratios for zoom animations.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
zoom_initial_ratio=0.3
|
|
||||||
zoom_end_ratio=0.8
|
|
||||||
```
|
|
||||||
|
|
||||||
- `zoom_initial_ratio` — Initial zoom ratio
|
|
||||||
- `zoom_end_ratio` — End zoom ratio
|
|
||||||
|
|
||||||
## Durations
|
|
||||||
|
|
||||||
Control the speed of animations (in milliseconds).
|
|
||||||
|
|
||||||
| Setting | Type | Default | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `animation_duration_move` | integer | `500` | Move animation duration (ms) |
|
|
||||||
| `animation_duration_open` | integer | `400` | Open animation duration (ms) |
|
|
||||||
| `animation_duration_tag` | integer | `300` | Tag animation duration (ms) |
|
|
||||||
| `animation_duration_close` | integer | `300` | Close animation duration (ms) |
|
|
||||||
| `animation_duration_focus` | integer | `0` | Focus change (opacity transition) animation duration (ms) |
|
|
||||||
|
|
||||||
```ini
|
|
||||||
animation_duration_move=500
|
|
||||||
animation_duration_open=400
|
|
||||||
animation_duration_tag=300
|
|
||||||
animation_duration_close=300
|
|
||||||
animation_duration_focus=0
|
|
||||||
```
|
|
||||||
|
|
||||||
## Custom Bezier Curves
|
|
||||||
|
|
||||||
Bezier curves determine the "feel" of an animation (e.g., linear vs. bouncy). The format is `x1,y1,x2,y2`.
|
|
||||||
|
|
||||||
You can visualize and generate curve values using online tools like [cssportal.com](https://www.cssportal.com/css-cubic-bezier-generator/) or [easings.net](https://easings.net).
|
|
||||||
|
|
||||||
| Setting | Type | Default | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `animation_curve_open` | string | `0.46,1.0,0.29,0.99` | Open animation bezier curve |
|
|
||||||
| `animation_curve_move` | string | `0.46,1.0,0.29,0.99` | Move animation bezier curve |
|
|
||||||
| `animation_curve_tag` | string | `0.46,1.0,0.29,0.99` | Tag animation bezier curve |
|
|
||||||
| `animation_curve_close` | string | `0.46,1.0,0.29,0.99` | Close animation bezier curve |
|
|
||||||
| `animation_curve_focus` | string | `0.46,1.0,0.29,0.99` | Focus change (opacity transition) animation bezier curve |
|
|
||||||
| `animation_curve_opafadein` | string | `0.46,1.0,0.29,0.99` | Open opacity animation bezier curve |
|
|
||||||
| `animation_curve_opafadeout` | string | `0.5,0.5,0.5,0.5` | Close opacity animation bezier curve |
|
|
||||||
|
|
||||||
```ini
|
|
||||||
animation_curve_open=0.46,1.0,0.29,0.99
|
|
||||||
animation_curve_move=0.46,1.0,0.29,0.99
|
|
||||||
animation_curve_tag=0.46,1.0,0.29,0.99
|
|
||||||
animation_curve_close=0.46,1.0,0.29,0.99
|
|
||||||
animation_curve_focus=0.46,1.0,0.29,0.99
|
|
||||||
animation_curve_opafadein=0.46,1.0,0.29,0.99
|
|
||||||
animation_curve_opafadeout=0.5,0.5,0.5,0.5
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tag Animation Direction
|
|
||||||
|
|
||||||
Control the direction of tag switch animations.
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `tag_animation_direction` | `1` | Tag animation direction (1: horizontal, 0: vertical) |
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
---
|
|
||||||
title: Window Effects
|
|
||||||
description: Add visual polish with blur, shadows, and opacity.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Blur
|
|
||||||
|
|
||||||
Blur creates a frosted glass effect for transparent windows.
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `blur` | `0` | Enable blur for windows. |
|
|
||||||
| `blur_layer` | `0` | Enable blur for layer surfaces (like bars/docks). |
|
|
||||||
| `blur_optimized` | `1` | Caches the wallpaper and blur background, significantly reducing GPU usage. Disabling it will significantly increase GPU consumption and may cause rendering lag. **Highly recommended.** |
|
|
||||||
| `blur_params_radius` | `5` | The strength (radius) of the blur. |
|
|
||||||
| `blur_params_num_passes` | `1` | Number of passes. Higher = smoother but more expensive. |
|
|
||||||
| `blur_params_noise` | `0.02` | Blur noise level. |
|
|
||||||
| `blur_params_brightness` | `0.9` | Blur brightness adjustment. |
|
|
||||||
| `blur_params_contrast` | `0.9` | Blur contrast adjustment. |
|
|
||||||
| `blur_params_saturation` | `1.2` | Blur saturation adjustment. |
|
|
||||||
|
|
||||||
> **Warning:** Blur has a relatively high impact on performance. If your hardware is limited, it is not recommended to enable it. If you experience lag with blur on, ensure `blur_optimized=1` — disabling it will significantly increase GPU consumption and may cause rendering lag. To disable blur entirely, set `blur=0`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Shadows
|
|
||||||
|
|
||||||
Drop shadows help distinguish floating windows from the background.
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `shadows` | `0` | Enable shadows. |
|
|
||||||
| `layer_shadows` | `0` | Enable shadows for layer surfaces. |
|
|
||||||
| `shadow_only_floating` | `1` | Only draw shadows for floating windows (saves performance). |
|
|
||||||
| `shadows_size` | `10` | Size of the shadow. |
|
|
||||||
| `shadows_blur` | `15` | Shadow blur amount. |
|
|
||||||
| `shadows_position_x` | `0` | Shadow X offset. |
|
|
||||||
| `shadows_position_y` | `0` | Shadow Y offset. |
|
|
||||||
| `shadowscolor` | `0x000000ff` | Color of the shadow. |
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Example shadows configuration
|
|
||||||
shadows=1
|
|
||||||
layer_shadows=1
|
|
||||||
shadow_only_floating=1
|
|
||||||
shadows_size=12
|
|
||||||
shadows_blur=15
|
|
||||||
shadows_position_x=0
|
|
||||||
shadows_position_y=0
|
|
||||||
shadowscolor=0x000000ff
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Opacity & Corner Radius
|
|
||||||
|
|
||||||
Control the transparency and roundness of your windows.
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `border_radius` | `0` | Window corner radius in pixels. |
|
|
||||||
| `border_radius_location_default` | `0` | Corner radius location: `0` (all), `1` (top-left), `2` (top-right), `3` (bottom-left), `4` (bottom-right), `5` (closest corner). |
|
|
||||||
| `no_radius_when_single` | `0` | Disable radius if only one window is visible. |
|
|
||||||
| `focused_opacity` | `1.0` | Opacity for the active window (0.0 - 1.0). |
|
|
||||||
| `unfocused_opacity` | `1.0` | Opacity for inactive windows (0.0 - 1.0). |
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Window corner radius in pixels
|
|
||||||
border_radius=0
|
|
||||||
|
|
||||||
# Corner radius location (0=all, 1=top-left, 2=top-right, 3=bottom-left, 4=bottom-right)
|
|
||||||
border_radius_location_default=0
|
|
||||||
|
|
||||||
# Disable radius if only one window is visible
|
|
||||||
no_radius_when_single=0
|
|
||||||
|
|
||||||
# Opacity for the active window (0.0 - 1.0)
|
|
||||||
focused_opacity=1.0
|
|
||||||
|
|
||||||
# Opacity for inactive windows
|
|
||||||
unfocused_opacity=1.0
|
|
||||||
```
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
---
|
|
||||||
title: Visuals
|
|
||||||
description: Customize borders, colors, effects, and animations.
|
|
||||||
icon: Palette
|
|
||||||
---
|
|
||||||
|
|
||||||
Customize the look of your desktop.
|
|
||||||
|
|
||||||
<Cards>
|
|
||||||
|
|
||||||
<Card href="/docs/visuals/theming" title="Theming" description="Borders, colors, and cursor" />
|
|
||||||
|
|
||||||
<Card href="/docs/visuals/status-bar" title="Status Bar" description="Built-in status bar" />
|
|
||||||
|
|
||||||
<Card href="/docs/visuals/effects" title="Effects" description="Blur, shadows, rounded corners" />
|
|
||||||
|
|
||||||
<Card href="/docs/visuals/animations" title="Animations" description="Window and tag animations" />
|
|
||||||
|
|
||||||
</Cards>
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"title": "Visuals",
|
|
||||||
"pages": ["theming", "status-bar", "effects", "animations"]
|
|
||||||
}
|
|
||||||
|
|
@ -1,141 +0,0 @@
|
||||||
---
|
|
||||||
title: Status Bar
|
|
||||||
description: Configure Waybar for mangowm.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Module Configuration
|
|
||||||
|
|
||||||
mangowm is compatible with Waybar's `ext/workspaces` module (Wayland standard) or the `dwl/tags` module. We recommend `ext/workspaces` for the best experience.
|
|
||||||
|
|
||||||
> **Tip:** You can also use the `dwl/tags` module, but `ext/workspaces` provides better integration with mangowm's features. The `ext/workspaces` module requires **Waybar > 0.14.0**.
|
|
||||||
|
|
||||||
### `config.jsonc`
|
|
||||||
|
|
||||||
Add the following to your Waybar configuration:
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"modules-left": [
|
|
||||||
"ext/workspaces",
|
|
||||||
"dwl/window"
|
|
||||||
],
|
|
||||||
"ext/workspaces": {
|
|
||||||
"format": "{icon}",
|
|
||||||
"ignore-hidden": true,
|
|
||||||
"on-click": "activate",
|
|
||||||
"on-click-right": "deactivate",
|
|
||||||
"sort-by-id": true
|
|
||||||
},
|
|
||||||
"dwl/window": {
|
|
||||||
"format": "[{layout}] {title}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Styling
|
|
||||||
|
|
||||||
You can style the tags using standard CSS in `style.css`.
|
|
||||||
|
|
||||||
### `style.css`
|
|
||||||
|
|
||||||
```css
|
|
||||||
#workspaces {
|
|
||||||
border-radius: 4px;
|
|
||||||
border-width: 2px;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: #c9b890;
|
|
||||||
margin-left: 4px;
|
|
||||||
padding-left: 10px;
|
|
||||||
padding-right: 6px;
|
|
||||||
background: rgba(40, 40, 40, 0.76);
|
|
||||||
}
|
|
||||||
|
|
||||||
#workspaces button {
|
|
||||||
border: none;
|
|
||||||
background: none;
|
|
||||||
box-shadow: inherit;
|
|
||||||
text-shadow: inherit;
|
|
||||||
color: #ddca9e;
|
|
||||||
padding: 1px;
|
|
||||||
padding-left: 1px;
|
|
||||||
padding-right: 1px;
|
|
||||||
margin-right: 2px;
|
|
||||||
margin-left: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#workspaces button.hidden {
|
|
||||||
color: #9e906f;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
#workspaces button.visible {
|
|
||||||
color: #ddca9e;
|
|
||||||
}
|
|
||||||
|
|
||||||
#workspaces button:hover {
|
|
||||||
color: #d79921;
|
|
||||||
}
|
|
||||||
|
|
||||||
#workspaces button.active {
|
|
||||||
background-color: #ddca9e;
|
|
||||||
color: #282828;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
padding-top: 1px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#workspaces button.urgent {
|
|
||||||
background-color: #ef5e5e;
|
|
||||||
color: #282828;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
padding-top: 1px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tags {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tags button {
|
|
||||||
background-color: #fff;
|
|
||||||
color: #a585cd;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tags button:not(.occupied):not(.focused) {
|
|
||||||
font-size: 0;
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 0;
|
|
||||||
margin: -17px;
|
|
||||||
padding: 0;
|
|
||||||
color: transparent;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tags button.occupied {
|
|
||||||
background-color: #fff;
|
|
||||||
color: #cdc885;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tags button.focused {
|
|
||||||
background-color: rgb(186, 142, 213);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tags button.urgent {
|
|
||||||
background: rgb(171, 101, 101);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#window {
|
|
||||||
background-color: rgb(237, 196, 147);
|
|
||||||
color: rgb(63, 37, 5);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Complete Configuration Example
|
|
||||||
|
|
||||||
> **Tip:** You can find a complete Waybar configuration for mangowm at [waybar-config](https://github.com/DreamMaoMao/waybar-config).
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
---
|
|
||||||
title: Theming
|
|
||||||
description: Customize the visual appearance of borders, colors, and the cursor.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Dimensions
|
|
||||||
|
|
||||||
Control the sizing of window borders and gaps.
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `borderpx` | `4` | Border width in pixels. |
|
|
||||||
| `gappih` | `5` | Horizontal inner gap (between windows). |
|
|
||||||
| `gappiv` | `5` | Vertical inner gap. |
|
|
||||||
| `gappoh` | `10` | Horizontal outer gap (between windows and screen edges). |
|
|
||||||
| `gappov` | `10` | Vertical outer gap. |
|
|
||||||
|
|
||||||
## Colors
|
|
||||||
|
|
||||||
Colors are defined in `0xRRGGBBAA` hex format.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Background color of the root window
|
|
||||||
rootcolor=0x323232ff
|
|
||||||
|
|
||||||
# Inactive window border
|
|
||||||
bordercolor=0x444444ff
|
|
||||||
|
|
||||||
# Active window border
|
|
||||||
focuscolor=0xc66b25ff
|
|
||||||
|
|
||||||
# Urgent window border (alerts)
|
|
||||||
urgentcolor=0xad401fff
|
|
||||||
```
|
|
||||||
|
|
||||||
### State-Specific Colors
|
|
||||||
|
|
||||||
You can also color-code windows based on their state:
|
|
||||||
|
|
||||||
| State | Config Key | Default Color |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| Maximized | `maximizescreencolor` | `0x89aa61ff` |
|
|
||||||
| Scratchpad | `scratchpadcolor` | `0x516c93ff` |
|
|
||||||
| Global | `globalcolor` | `0xb153a7ff` |
|
|
||||||
| Overlay | `overlaycolor` | `0x14a57cff` |
|
|
||||||
|
|
||||||
> **Tip:** For scratchpad window sizing, see [Scratchpad](/docs/window-management/scratchpad) configuration.
|
|
||||||
|
|
||||||
## Cursor Theme
|
|
||||||
|
|
||||||
Set the size and theme of your mouse cursor.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
cursor_size=24
|
|
||||||
cursor_theme=Adwaita
|
|
||||||
```
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
---
|
|
||||||
title: Window Management
|
|
||||||
description: Layouts, rules, and window behavior.
|
|
||||||
icon: LayoutGrid
|
|
||||||
---
|
|
||||||
|
|
||||||
Window management with layouts, rules, and scratchpad support.
|
|
||||||
|
|
||||||
<Cards>
|
|
||||||
|
|
||||||
<Card href="/docs/window-management/layouts" title="Layouts" description="Tile, scroller, monocle, grid, deck" />
|
|
||||||
|
|
||||||
<Card href="/docs/window-management/rules" title="Rules" description="Window rules and conditions" />
|
|
||||||
|
|
||||||
<Card href="/docs/window-management/overview" title="Overview" description="Window states and properties" />
|
|
||||||
|
|
||||||
<Card href="/docs/window-management/scratchpad" title="Scratchpad" description="Quick access to applications" />
|
|
||||||
|
|
||||||
</Cards>
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
---
|
|
||||||
title: Layouts
|
|
||||||
description: Configure and switch between different window layouts.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Supported Layouts
|
|
||||||
|
|
||||||
mangowm supports a variety of layouts that can be assigned per tag.
|
|
||||||
|
|
||||||
- `tile`
|
|
||||||
- `scroller`
|
|
||||||
- `monocle`
|
|
||||||
- `grid`
|
|
||||||
- `deck`
|
|
||||||
- `center_tile`
|
|
||||||
- `vertical_tile`
|
|
||||||
- `right_tile`
|
|
||||||
- `vertical_scroller`
|
|
||||||
- `vertical_grid`
|
|
||||||
- `vertical_deck`
|
|
||||||
- `tgmix`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Scroller Layout
|
|
||||||
|
|
||||||
The Scroller layout positions windows in a scrollable strip, similar to PaperWM.
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `scroller_structs` | `20` | Width reserved on sides when window ratio is 1. |
|
|
||||||
| `scroller_default_proportion` | `0.9` | Default width proportion for new windows. |
|
|
||||||
| `scroller_focus_center` | `0` | Always center the focused window (1 = enable). |
|
|
||||||
| `scroller_prefer_center` | `0` | Center focused window only if it was outside the view. |
|
|
||||||
| `scroller_prefer_overspread` | `1` | Allow windows to overspread when there's extra space. |
|
|
||||||
| `edge_scroller_pointer_focus` | `1` | Focus windows even if partially off-screen. |
|
|
||||||
| `scroller_proportion_preset` | `0.5,0.8,1.0` | Presets for cycling window widths. |
|
|
||||||
| `scroller_ignore_proportion_single` | `1` | Ignore proportion adjustments for single windows. |
|
|
||||||
| `scroller_default_proportion_single` | `1.0` | Default proportion for single windows in scroller. **Requires `scroller_ignore_proportion_single=0` to take effect.** |
|
|
||||||
|
|
||||||
> **Warning:** `scroller_prefer_overspread`, `scroller_focus_center`, and `scroller_prefer_center` interact with each other. Their priority order is:
|
|
||||||
>
|
|
||||||
> **scroller_prefer_overspread > scroller_focus_center > scroller_prefer_center**
|
|
||||||
>
|
|
||||||
> To ensure a lower-priority setting takes effect, you must set all higher-priority options to `0`.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Example scroller configuration
|
|
||||||
scroller_structs=20
|
|
||||||
scroller_default_proportion=0.9
|
|
||||||
scroller_focus_center=0
|
|
||||||
scroller_prefer_center=0
|
|
||||||
scroller_prefer_overspread=1
|
|
||||||
edge_scroller_pointer_focus=1
|
|
||||||
scroller_default_proportion_single=1.0
|
|
||||||
scroller_proportion_preset=0.5,0.8,1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Master-Stack Layouts
|
|
||||||
|
|
||||||
These settings apply to layouts like `tile` and `center_tile`.
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `new_is_master` | `1` | New windows become the master window. |
|
|
||||||
| `default_mfact` | `0.55` | The split ratio between master and stack areas. |
|
|
||||||
| `default_nmaster` | `1` | Number of allowed master windows. |
|
|
||||||
| `smartgaps` | `0` | Disable gaps when only one window is present. |
|
|
||||||
| `center_master_overspread` | `0` | (Center Tile) Master spreads across screen if no stack exists. |
|
|
||||||
| `center_when_single_stack` | `1` | (Center Tile) Center master when only one stack window exists. |
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Example master-stack configuration
|
|
||||||
new_is_master=1
|
|
||||||
smartgaps=0
|
|
||||||
default_mfact=0.55
|
|
||||||
default_nmaster=1
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Switching Layouts
|
|
||||||
|
|
||||||
You can switch layouts dynamically or set a default for specific tags using [Tag Rules](/docs/window-management/rules#tag-rules).
|
|
||||||
|
|
||||||
**Keybinding Examples:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Cycle through layouts
|
|
||||||
bind=SUPER,n,switch_layout
|
|
||||||
|
|
||||||
# Set specific layout
|
|
||||||
bind=SUPER,t,setlayout,tile
|
|
||||||
bind=SUPER,s,setlayout,scroller
|
|
||||||
```
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"title": "Window Management",
|
|
||||||
"pages": ["layouts", "rules", "overview", "scratchpad"]
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
---
|
|
||||||
title: Overview
|
|
||||||
description: Configure the overview mode for window navigation.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Overview Settings
|
|
||||||
|
|
||||||
| Setting | Type | Default | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `hotarea_size` | integer | `10` | Hot area size in pixels. |
|
|
||||||
| `enable_hotarea` | integer | `1` | Enable hot areas (0: disable, 1: enable). |
|
|
||||||
| `hotarea_corner` | integer | `2` | Hot area corner (0: top-left, 1: top-right, 2: bottom-left, 3: bottom-right). |
|
|
||||||
| `ov_tab_mode` | integer | `0` | Overview tab mode (0: disable, 1: enable). |
|
|
||||||
| `overviewgappi` | integer | `5` | Inner gap in overview mode. |
|
|
||||||
| `overviewgappo` | integer | `30` | Outer gap in overview mode. |
|
|
||||||
|
|
||||||
### Setting Descriptions
|
|
||||||
|
|
||||||
- `enable_hotarea` — Toggles overview when the cursor enters the configured corner.
|
|
||||||
- `hotarea_size` — Size of the hot area trigger zone in pixels.
|
|
||||||
- `hotarea_corner` — Corner that triggers the hot area (0: top-left, 1: top-right, 2: bottom-left, 3: bottom-right).
|
|
||||||
- `ov_tab_mode` — Circles focus through windows in overview; releasing the mod key exits overview.
|
|
||||||
|
|
||||||
### Mouse Interaction in Overview
|
|
||||||
|
|
||||||
When in overview mode:
|
|
||||||
|
|
||||||
- **Left mouse button** — Jump to (focus) a window.
|
|
||||||
- **Right mouse button** — Close a window.
|
|
||||||
|
|
@ -1,249 +0,0 @@
|
||||||
---
|
|
||||||
title: Rules
|
|
||||||
description: Define behavior for specific windows, tags, and layers.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Window Rules
|
|
||||||
|
|
||||||
Window rules allow you to set specific properties (floating, opacity, size, animations, etc.) for applications based on their `appid` or `title`. You can set all parameters in one line, and if you both set appid and title, the window will only follow the rules when appid and title both match.
|
|
||||||
|
|
||||||
**Format:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
windowrule=Parameter:Values,title:Values
|
|
||||||
windowrule=Parameter:Values,Parameter:Values,appid:Values,title:Values
|
|
||||||
```
|
|
||||||
|
|
||||||
### State & Behavior Parameters
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `appid` | string | Any | Match by application ID, supports regex |
|
|
||||||
| `title` | string | Any | Match by window title, supports regex |
|
|
||||||
| `isfloating` | integer | `0` / `1` | Force floating state |
|
|
||||||
| `isfullscreen` | integer | `0` / `1` | Force fullscreen state |
|
|
||||||
| `isfakefullscreen` | integer | `0` / `1` | Force fake-fullscreen state (window stays constrained) |
|
|
||||||
| `isglobal` | integer | `0` / `1` | Open as global window (sticky across tags) |
|
|
||||||
| `isoverlay` | integer | `0` / `1` | Make it always in top layer |
|
|
||||||
| `isopensilent` | integer | `0` / `1` | Open without focus |
|
|
||||||
| `istagsilent` | integer | `0` / `1` | Don't focus if client is not in current view tag |
|
|
||||||
| `force_maximize` | integer | `0` / `1` (default 1) | The state of client default to maximized |
|
|
||||||
| `ignore_maximize` | integer | `0` / `1` (default 1) | Don't handle maximize request from client |
|
|
||||||
| `ignore_minimize` | integer | `0` / `1` (default 1) | Don't handle minimize request from client |
|
|
||||||
| `force_tiled_state` | integer | `0` / `1` | Deceive the window into thinking it is tiling, so it better adheres to assigned dimensions |
|
|
||||||
| `noopenmaximized` | integer | `0` / `1` | Window does not open as maximized mode |
|
|
||||||
| `single_scratchpad` | integer | `0` / `1` (default 1) | Only show one out of named scratchpads or the normal scratchpad |
|
|
||||||
| `allow_shortcuts_inhibit` | integer | `0` / `1` (default 1) | Allow shortcuts to be inhibited by clients |
|
|
||||||
| `indleinhibit_when_focus` | integer | `0` / `1` (default 0) | Automatically keep idle inhibit active when this window is focused |
|
|
||||||
|
|
||||||
### Geometry & Position
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `width` | integer | 0-9999 | Window width when it becomes a floating window |
|
|
||||||
| `height` | integer | 0-9999 | Window height when it becomes a floating window |
|
|
||||||
| `offsetx` | integer | -999-999 | X offset from center (%), 100 is the edge of screen with outer gap |
|
|
||||||
| `offsety` | integer | -999-999 | Y offset from center (%), 100 is the edge of screen with outer gap |
|
|
||||||
| `monitor` | string | Any | Assign to monitor by [monitor spec](/docs/configuration/monitors#monitor-spec-format) (name, make, model, or serial) |
|
|
||||||
| `tags` | integer | 1-9 | Assign to specific tag |
|
|
||||||
| `no_force_center` | integer | `0` / `1` | Window does not force center |
|
|
||||||
| `isnosizehint` | integer | `0` / `1` | Don't use min size and max size for size hints |
|
|
||||||
|
|
||||||
### Visuals & Decoration
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `noblur` | integer | `0` / `1` | Window does not have blur effect |
|
|
||||||
| `isnoborder` | integer | `0` / `1` | Remove window border |
|
|
||||||
| `isnoshadow` | integer | `0` / `1` | Not apply shadow |
|
|
||||||
| `isnoradius` | integer | `0` / `1` | Not apply corner radius |
|
|
||||||
| `isnoanimation` | integer | `0` / `1` | Not apply animation |
|
|
||||||
| `focused_opacity` | integer | `0` / `1` | Window focused opacity |
|
|
||||||
| `unfocused_opacity` | integer | `0` / `1` | Window unfocused opacity |
|
|
||||||
| `allow_csd` | integer | `0` / `1` | Allow client side decoration |
|
|
||||||
|
|
||||||
> **Tip:** For detailed visual effects configuration, see the [Window Effects](/docs/visuals/effects) page for blur, shadows, and opacity settings.
|
|
||||||
|
|
||||||
### Layout & Scroller
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `scroller_proportion` | float | 0.1-1.0 | Set scroller proportion |
|
|
||||||
| `scroller_proportion_single` | float | 0.1-1.0 | Set scroller auto adjust proportion when it is single window |
|
|
||||||
|
|
||||||
> **Tip:** For comprehensive layout configuration, see the [Layouts](/docs/window-management/layouts) page for all layout options and detailed settings.
|
|
||||||
|
|
||||||
### Animation
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `animation_type_open` | string | zoom, slide, fade, none | Set open animation |
|
|
||||||
| `animation_type_close` | string | zoom, slide, fade, none | Set close animation |
|
|
||||||
| `nofadein` | integer | `0` / `1` | Window ignores fade-in animation |
|
|
||||||
| `nofadeout` | integer | `0` / `1` | Window ignores fade-out animation |
|
|
||||||
|
|
||||||
> **Tip:** For detailed animation configuration, see the [Animations](/docs/visuals/animations) page for available types and settings.
|
|
||||||
|
|
||||||
### Terminal & Swallowing
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `isterm` | integer | `0` / `1` | A new GUI window will replace the isterm window when it is opened |
|
|
||||||
| `noswallow` | integer | `0` / `1` | The window will not replace the isterm window |
|
|
||||||
|
|
||||||
### Global & Special Windows
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `globalkeybinding` | string | `[mod combination][-][key]` | Global keybinding (only works for Wayland apps) |
|
|
||||||
| `isunglobal` | integer | `0` / `1` | Open as unmanaged global window (for desktop pets or camera windows) |
|
|
||||||
| `isnamedscratchpad` | integer | `0` / `1` | 0: disable, 1: named scratchpad |
|
|
||||||
|
|
||||||
> **Tip:** For scratchpad usage, see the [Scratchpad](/docs/window-management/scratchpad) page for detailed configuration examples.
|
|
||||||
|
|
||||||
### Performance & Tearing
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `force_tearing` | integer | `0` / `1` | Set window to tearing state, refer to [Tearing](/docs/configuration/monitors#tearing-game-mode) |
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Set specific window size and position
|
|
||||||
windowrule=width:1000,height:900,appid:yesplaymusic,title:Demons
|
|
||||||
|
|
||||||
# Global keybindings for OBS Studio
|
|
||||||
windowrule=globalkeybinding:ctrl+alt-o,appid:com.obsproject.Studio
|
|
||||||
windowrule=globalkeybinding:ctrl+alt+n,appid:com.obsproject.Studio
|
|
||||||
windowrule=isopensilent:1,appid:com.obsproject.Studio
|
|
||||||
|
|
||||||
# Force tearing for games
|
|
||||||
windowrule=force_tearing:1,title:vkcube
|
|
||||||
windowrule=force_tearing:1,title:Counter-Strike 2
|
|
||||||
|
|
||||||
# Named scratchpad for file manager
|
|
||||||
windowrule=isnamedscratchpad:1,width:1280,height:800,appid:st-yazi
|
|
||||||
|
|
||||||
# Custom opacity for specific apps
|
|
||||||
windowrule=focused_opacity:0.8,appid:firefox
|
|
||||||
windowrule=unfocused_opacity:0.6,appid:foot
|
|
||||||
|
|
||||||
# Disable blur for selection tools
|
|
||||||
windowrule=noblur:1,appid:slurp
|
|
||||||
|
|
||||||
# Position windows relative to screen center
|
|
||||||
windowrule=offsetx:20,offsety:-30,width:800,height:600,appid:alacritty
|
|
||||||
|
|
||||||
# Send to specific tag and monitor
|
|
||||||
windowrule=tags:9,monitor:HDMI-A-1,appid:discord
|
|
||||||
|
|
||||||
# Terminal swallowing setup
|
|
||||||
windowrule=isterm:1,appid:st
|
|
||||||
windowrule=noswallow:1,appid:foot
|
|
||||||
|
|
||||||
# Disable client-side decorations
|
|
||||||
windowrule=allow_csd:1,appid:firefox
|
|
||||||
|
|
||||||
# Unmanaged global window (desktop pets, camera)
|
|
||||||
windowrule=isunglobal:1,appid:cheese
|
|
||||||
|
|
||||||
# Named scratchpad toggle
|
|
||||||
bind=alt,h,toggle_named_scratchpad,st-yazi,none,st -c st-yazi -e yazi
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Tag Rules
|
|
||||||
|
|
||||||
You can set all parameters in one line. If only `id` is set, the rule is followed when the id matches. If any of `monitor_name`, `monitor_make`, `monitor_model`, or `monitor_serial` are set, the rule is followed only if **all** of the set monitor fields match.
|
|
||||||
|
|
||||||
> **Warning:** Layouts set in tag rules have a higher priority than monitor rule layouts.
|
|
||||||
|
|
||||||
**Format:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
tagrule=id:Values,Parameter:Values,Parameter:Values
|
|
||||||
tagrule=id:Values,monitor_name:eDP-1,Parameter:Values,Parameter:Values
|
|
||||||
tagrule=id:Values,monitor_make:xxx,monitor_model:xxx,Parameter:Values
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Tip:** See [Layouts](/docs/window-management/layouts#supported-layouts) for detailed descriptions of each layout type.
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `id` | integer | 0-9 | Match by tag id, 0 means the ~0 tag |
|
|
||||||
| `monitor_name` | string | monitor name | Match by monitor name |
|
|
||||||
| `monitor_make` | string | monitor make | Match by monitor manufacturer |
|
|
||||||
| `monitor_model` | string | monitor model | Match by monitor model |
|
|
||||||
| `monitor_serial` | string | monitor serial | Match by monitor serial number |
|
|
||||||
| `layout_name` | string | layout name | Layout name to set |
|
|
||||||
| `no_render_border` | integer | `0` / `1` | Disable render border |
|
|
||||||
| `no_hide` | integer | `0` / `1` | Not hide even if the tag is empty |
|
|
||||||
| `nmaster` | integer | 0, 99 | Number of master windows |
|
|
||||||
| `mfact` | float | 0.1–0.9 | Master area factor |
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Set layout for specific tags
|
|
||||||
tagrule=id:1,layout_name:scroller
|
|
||||||
tagrule=id:2,layout_name:scroller
|
|
||||||
|
|
||||||
# Limit to specific monitor
|
|
||||||
tagrule=id:1,monitor_name:eDP-1,layout_name:scroller
|
|
||||||
tagrule=id:2,monitor_name:eDP-1,layout_name:scroller
|
|
||||||
|
|
||||||
# Persistent tags (1-4) with layout assignment
|
|
||||||
tagrule=id:1,no_hide:1,layout_name:scroller
|
|
||||||
tagrule=id:2,no_hide:1,layout_name:scroller
|
|
||||||
tagrule=id:3,monitor_name:eDP-1,no_hide:1,layout_name:scroller
|
|
||||||
tagrule=id:4,monitor_name:eDP-1,no_hide:1,layout_name:scroller
|
|
||||||
|
|
||||||
# Advanced tag configuration with master layout settings
|
|
||||||
tagrule=id:5,layout_name:tile,nmaster:2,mfact:0.6
|
|
||||||
tagrule=id:6,monitor_name:HDMI-A-1,layout_name:monocle,no_render_border:1
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Tip:** For Waybar configuration with persistent tags, see [Status Bar](/docs/visuals/status-bar) documentation.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Layer Rules
|
|
||||||
|
|
||||||
You can set all parameters in one line. Target "layer shell" surfaces like status bars (`waybar`), launchers (`rofi`), or notification daemons.
|
|
||||||
|
|
||||||
**Format:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
layerrule=layer_name:Values,Parameter:Values,Parameter:Values
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Tip:** You can use `mmsg -e` to get the last open layer name for debugging.
|
|
||||||
|
|
||||||
| Parameter | Type | Values | Description |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| `layer_name` | string | layer name | Match name of layer, supports regex |
|
|
||||||
| `animation_type_open` | string | slide, zoom, fade, none | Set open animation |
|
|
||||||
| `animation_type_close` | string | slide, zoom, fade, none | Set close animation |
|
|
||||||
| `noblur` | integer | `0` / `1` | Disable blur |
|
|
||||||
| `noanim` | integer | `0` / `1` | Disable layer animation |
|
|
||||||
| `noshadow` | integer | `0` / `1` | Disable layer shadow |
|
|
||||||
|
|
||||||
> **Tip:** For animation types, see [Animations](/docs/visuals/animations#animation-types). For visual effects, see [Window Effects](/docs/visuals/effects).
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# No blur or animation for slurp selection layer (avoids occlusion and ghosting in screenshots)
|
|
||||||
layerrule=noanim:1,noblur:1,layer_name:selection
|
|
||||||
|
|
||||||
# Zoom animation for Rofi with multiple parameters
|
|
||||||
layerrule=animation_type_open:zoom,noanim:0,layer_name:rofi
|
|
||||||
|
|
||||||
# Disable animations and shadows for notification daemon
|
|
||||||
layerrule=noanim:1,noshadow:1,layer_name:swaync
|
|
||||||
|
|
||||||
# Multiple effects for launcher
|
|
||||||
layerrule=animation_type_open:slide,animation_type_close:fade,noblur:1,layer_name:wofi
|
|
||||||
```
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
---
|
|
||||||
title: Scratchpad
|
|
||||||
description: Manage hidden "scratchpad" windows for quick access.
|
|
||||||
---
|
|
||||||
|
|
||||||
mangowm supports two types of scratchpads: the standard pool (Sway-like) and named scratchpads.
|
|
||||||
|
|
||||||
## Standard Scratchpad
|
|
||||||
|
|
||||||
Any window can be sent to the "scratchpad" pile, which hides it. You can then cycle through them.
|
|
||||||
|
|
||||||
**Keybindings:**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Send current window to scratchpad
|
|
||||||
bind=SUPER,i,minimized
|
|
||||||
|
|
||||||
# Toggle (show/hide) the scratchpad
|
|
||||||
bind=ALT,z,toggle_scratchpad
|
|
||||||
|
|
||||||
# Retrieve window from scratchpad (restore)
|
|
||||||
bind=SUPER+SHIFT,i,restore_minimized
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Named Scratchpad
|
|
||||||
|
|
||||||
Named scratchpads are bound to specific keys and applications. When triggered, mangowm will either launch the app (if not running) or toggle its visibility.
|
|
||||||
|
|
||||||
**1. Define the Window Rule**
|
|
||||||
|
|
||||||
You must identify the app using a unique `appid` or `title` and mark it as a named scratchpad. The application must support setting a custom appid or title at launch. Common examples:
|
|
||||||
|
|
||||||
- `st -c my-appid` — sets the appid
|
|
||||||
- `kitty -T my-title` — sets the window title
|
|
||||||
- `foot --app-id my-appid` — sets the appid
|
|
||||||
|
|
||||||
Use `none` as a placeholder when you only want to match by one field.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Match by appid
|
|
||||||
windowrule=isnamedscratchpad:1,width:1280,height:800,appid:st-yazi
|
|
||||||
|
|
||||||
# Match by title
|
|
||||||
windowrule=isnamedscratchpad:1,width:1000,height:700,title:kitty-scratch
|
|
||||||
```
|
|
||||||
|
|
||||||
**2. Bind the Toggle Key**
|
|
||||||
|
|
||||||
Format: `bind=MOD,KEY,toggle_named_scratchpad,appid,title,command`
|
|
||||||
|
|
||||||
Use `none` for whichever field you are not matching on.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Match by appid: launch 'st' with class 'st-yazi' running 'yazi'
|
|
||||||
bind=alt,h,toggle_named_scratchpad,st-yazi,none,st -c st-yazi -e yazi
|
|
||||||
|
|
||||||
# Match by title: launch 'kitty' with window title 'kitty-scratch'
|
|
||||||
bind=alt,k,toggle_named_scratchpad,none,kitty-scratch,kitty -T kitty-scratch
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Appearance
|
|
||||||
|
|
||||||
You can customize the size of scratchpad windows relative to the screen.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
scratchpad_width_ratio=0.8
|
|
||||||
scratchpad_height_ratio=0.9
|
|
||||||
scratchpadcolor=0x516c93ff
|
|
||||||
```
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
[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
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(define-module (mangowm)
|
(define-module (mangowc)
|
||||||
#:use-module (guix download)
|
#:use-module (guix download)
|
||||||
#:use-module (guix git-download)
|
#:use-module (guix git-download)
|
||||||
#:use-module (guix gexp)
|
#:use-module (guix gexp)
|
||||||
|
|
@ -18,11 +18,11 @@
|
||||||
#:use-module (guix licenses))
|
#:use-module (guix licenses))
|
||||||
|
|
||||||
|
|
||||||
(define-public mangowm-git
|
(define-public mangowc-git
|
||||||
(package
|
(package
|
||||||
(name "mangowm")
|
(name "mangowc")
|
||||||
(version "git")
|
(version "git")
|
||||||
(source (local-file "." "mangowm-checkout"
|
(source (local-file "." "mangowc-checkout"
|
||||||
#:recursive? #t
|
#:recursive? #t
|
||||||
#:select? (or (git-predicate (current-source-directory))
|
#:select? (or (git-predicate (current-source-directory))
|
||||||
(const #t))))
|
(const #t))))
|
||||||
|
|
@ -55,13 +55,10 @@
|
||||||
wlroots
|
wlroots
|
||||||
scenefx))
|
scenefx))
|
||||||
(native-inputs (list pkg-config wayland-protocols))
|
(native-inputs (list pkg-config wayland-protocols))
|
||||||
(home-page "https://github.com/DreamMaoMao/mangowm")
|
(home-page "https://github.com/DreamMaoMao/mangowc")
|
||||||
(synopsis "Wayland compositor based on wlroots and scenefx")
|
(synopsis "Wayland compositor based on wlroots and scenefx")
|
||||||
(description "A Wayland compositor based on wlroots and scenefx,
|
(description "A Wayland compositor based on wlroots and scenefx,
|
||||||
inspired by dwl but aiming to be more feature-rich.")
|
inspired by dwl but aiming to be more feature-rich.")
|
||||||
(license gpl3)))
|
(license gpl3)))
|
||||||
|
|
||||||
(define-deprecated-package mangowc
|
mangowc-git
|
||||||
mangowm-git)
|
|
||||||
|
|
||||||
mangowm-git
|
|
||||||
10
meson.build
10
meson.build
|
|
@ -1,5 +1,5 @@
|
||||||
project('mango', ['c', 'cpp'],
|
project('mango', ['c', 'cpp'],
|
||||||
version : '0.12.7',
|
version : '0.10.8',
|
||||||
)
|
)
|
||||||
|
|
||||||
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 = meson.project_version()
|
latest_tag = run_command(git, 'describe', '--tags', '--abbrev=0', check : false).stdout().strip()
|
||||||
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" 字符串
|
||||||
|
|
@ -147,7 +147,5 @@ executable('mmsg',
|
||||||
)
|
)
|
||||||
|
|
||||||
desktop_install_dir = join_paths(prefix, 'share/wayland-sessions')
|
desktop_install_dir = join_paths(prefix, 'share/wayland-sessions')
|
||||||
portal_install_dir = join_paths(prefix, 'share/xdg-desktop-portal')
|
install_data('mango.desktop', install_dir : desktop_install_dir)
|
||||||
install_data('assets/mango.desktop', install_dir : desktop_install_dir)
|
install_data('config.conf', install_dir : join_paths(sysconfdir, 'mango'))
|
||||||
install_data('assets/mango-portals.conf', install_dir : portal_install_dir)
|
|
||||||
install_data('assets/config.conf', install_dir : join_paths(sysconfdir, 'mango'))
|
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@
|
||||||
|
|
||||||
extern char *argv0;
|
extern char *argv0;
|
||||||
|
|
||||||
/* use main(int32_t argc, char *argv[]) */
|
/* use main(int argc, char *argv[]) */
|
||||||
#define ARGBEGIN \
|
#define ARGBEGIN \
|
||||||
for (argv0 = *argv, argv++, argc--; \
|
for (argv0 = *argv, argv++, argc--; \
|
||||||
argv[0] && argv[0][0] == '-' && argv[0][1]; argc--, argv++) { \
|
argv[0] && argv[0][0] == '-' && argv[0][1]; argc--, argv++) { \
|
||||||
char argc_; \
|
char argc_; \
|
||||||
char **argv_; \
|
char **argv_; \
|
||||||
int32_t brk_; \
|
int brk_; \
|
||||||
if (argv[0][1] == '-' && argv[0][2] == '\0') { \
|
if (argv[0][1] == '-' && argv[0][2] == '\0') { \
|
||||||
argv++; \
|
argv++; \
|
||||||
argc--; \
|
argc--; \
|
||||||
|
|
|
||||||
92
mmsg/mmsg.c
92
mmsg/mmsg.c
|
|
@ -25,31 +25,31 @@ static enum {
|
||||||
WATCH = 1 << 2 | GET,
|
WATCH = 1 << 2 | GET,
|
||||||
} mode = NONE;
|
} mode = NONE;
|
||||||
|
|
||||||
static int32_t Oflag;
|
static int Oflag;
|
||||||
static int32_t Tflag;
|
static int Tflag;
|
||||||
static int32_t Lflag;
|
static int Lflag;
|
||||||
static int32_t oflag;
|
static int oflag;
|
||||||
static int32_t tflag;
|
static int tflag;
|
||||||
static int32_t lflag;
|
static int lflag;
|
||||||
static int32_t cflag;
|
static int cflag;
|
||||||
static int32_t vflag;
|
static int vflag;
|
||||||
static int32_t mflag;
|
static int mflag;
|
||||||
static int32_t fflag;
|
static int fflag;
|
||||||
static int32_t qflag;
|
static int qflag;
|
||||||
static int32_t dflag;
|
static int dflag;
|
||||||
static int32_t xflag;
|
static int xflag;
|
||||||
static int32_t eflag;
|
static int eflag;
|
||||||
static int32_t kflag;
|
static int kflag;
|
||||||
static int32_t bflag;
|
static int bflag;
|
||||||
static int32_t Aflag;
|
static int Aflag;
|
||||||
|
|
||||||
static uint32_t occ, seltags, total_clients, urg;
|
static uint32_t occ, seltags, total_clients, urg;
|
||||||
|
|
||||||
static char *output_name;
|
static char *output_name;
|
||||||
static int32_t tagcount;
|
static int tagcount;
|
||||||
static char *tagset;
|
static char *tagset;
|
||||||
static char *layout_name;
|
static char *layout_name;
|
||||||
static int32_t layoutcount, layout_idx;
|
static int layoutcount, layout_idx;
|
||||||
static char *client_tags;
|
static char *client_tags;
|
||||||
static char *dispatch_cmd;
|
static char *dispatch_cmd;
|
||||||
static char *dispatch_arg1;
|
static char *dispatch_arg1;
|
||||||
|
|
@ -87,7 +87,7 @@ static void noop_description(void *data, struct wl_output *wl_output,
|
||||||
|
|
||||||
// 将 n 转换为 9 位二进制字符串,结果存入 buf(至少长度 10)
|
// 将 n 转换为 9 位二进制字符串,结果存入 buf(至少长度 10)
|
||||||
void bin_str_9bits(char *buf, uint32_t n) {
|
void bin_str_9bits(char *buf, uint32_t n) {
|
||||||
for (int32_t i = 8; i >= 0; i--) {
|
for (int i = 8; i >= 0; i--) {
|
||||||
*buf++ = ((n >> i) & 1) ? '1' : '0';
|
*buf++ = ((n >> i) & 1) ? '1' : '0';
|
||||||
}
|
}
|
||||||
*buf = '\0'; // 字符串结尾
|
*buf = '\0'; // 字符串结尾
|
||||||
|
|
@ -324,7 +324,7 @@ static void dwl_ipc_output_frame(void *data,
|
||||||
if (tflag) {
|
if (tflag) {
|
||||||
uint32_t mask = seltags;
|
uint32_t mask = seltags;
|
||||||
char *t = tagset;
|
char *t = tagset;
|
||||||
int32_t i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (; *t && *t >= '0' && *t <= '9'; t++)
|
for (; *t && *t >= '0' && *t <= '9'; t++)
|
||||||
i = *t - '0' + i * 10;
|
i = *t - '0' + i * 10;
|
||||||
|
|
@ -354,7 +354,7 @@ static void dwl_ipc_output_frame(void *data,
|
||||||
if (cflag) {
|
if (cflag) {
|
||||||
uint32_t and = ~0, xor = 0;
|
uint32_t and = ~0, xor = 0;
|
||||||
char *t = client_tags;
|
char *t = client_tags;
|
||||||
int32_t i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (; *t && *t >= '0' && *t <= '9'; t++)
|
for (; *t && *t >= '0' && *t <= '9'; t++)
|
||||||
i = *t - '0' + i * 10;
|
i = *t - '0' + i * 10;
|
||||||
|
|
@ -500,52 +500,16 @@ static const struct wl_registry_listener registry_listener = {
|
||||||
|
|
||||||
static void usage(void) {
|
static void usage(void) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"mmsg - MangoWM IPC\n"
|
"usage:"
|
||||||
"\n"
|
"\t%s [-OTLq]\n"
|
||||||
"SYNOPSIS:\n"
|
"\t%s [-o <output>] -s [-t <tags>] [-l <layout>] [-c <tags>] [-d "
|
||||||
"\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"
|
||||||
"\tmmsg [-o <output>] (-g | -w) [-OotlcvmfxekbA]\n"
|
"\t%s [-o <output>] (-g | -w) [-OotlcvmfxekbA]\n",
|
||||||
"\n"
|
argv0, argv0, argv0);
|
||||||
"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 mango\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);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t main(int32_t argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
ARGBEGIN {
|
ARGBEGIN {
|
||||||
case 'q':
|
case 'q':
|
||||||
qflag = 1;
|
qflag = 1;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
wayland,
|
wayland,
|
||||||
wayland-protocols,
|
wayland-protocols,
|
||||||
wayland-scanner,
|
wayland-scanner,
|
||||||
libxcb-wm,
|
xcbutilwm,
|
||||||
xwayland,
|
xwayland,
|
||||||
meson,
|
meson,
|
||||||
ninja,
|
ninja,
|
||||||
|
|
@ -57,7 +57,7 @@ stdenv.mkDerivation {
|
||||||
]
|
]
|
||||||
++ lib.optionals enableXWayland [
|
++ lib.optionals enableXWayland [
|
||||||
libX11
|
libX11
|
||||||
libxcb-wm
|
xcbutilwm
|
||||||
xwayland
|
xwayland
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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_variable(pkgconfig:'pkgdatadir')
|
wl_protocol_dir = wayland_protos_dep.get_pkgconfig_variable('pkgdatadir')
|
||||||
wayland_scanner_code = generator(
|
wayland_scanner_code = generator(
|
||||||
wayland_scanner,
|
wayland_scanner,
|
||||||
output: '@BASENAME@-protocol.c',
|
output: '@BASENAME@-protocol.c',
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,29 @@
|
||||||
void client_actual_size(Client *c, int32_t *width, int32_t *height) {
|
void client_actual_size(Client *c, uint32_t *width, uint32_t *height) {
|
||||||
*width = c->animation.current.width - 2 * (int32_t)c->bw;
|
*width = c->animation.current.width - c->bw;
|
||||||
|
|
||||||
*height = c->animation.current.height - 2 * (int32_t)c->bw;
|
*height = c->animation.current.height - c->bw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_rect_size(struct wlr_scene_rect *rect, int32_t width, int32_t height) {
|
void set_rect_size(struct wlr_scene_rect *rect, int width, int height) {
|
||||||
wlr_scene_rect_set_size(rect, GEZERO(width), GEZERO(height));
|
wlr_scene_rect_set_size(rect, GEZERO(width), GEZERO(height));
|
||||||
}
|
}
|
||||||
|
|
||||||
enum corner_location set_client_corner_location(Client *c) {
|
enum corner_location set_client_corner_location(Client *c) {
|
||||||
enum corner_location current_corner_location = CORNER_LOCATION_ALL;
|
enum corner_location current_corner_location = CORNER_LOCATION_ALL;
|
||||||
struct wlr_box target_geom =
|
struct wlr_box target_geom = animations ? c->animation.current : c->geom;
|
||||||
config.animations ? c->animation.current : c->geom;
|
if (target_geom.x + border_radius <= c->mon->m.x) {
|
||||||
if (target_geom.x + config.border_radius <= c->mon->m.x) {
|
current_corner_location &= ~CORNER_LOCATION_LEFT; // 清除左标志位
|
||||||
current_corner_location &= ~CORNER_LOCATION_LEFT;
|
|
||||||
}
|
}
|
||||||
if (target_geom.x + target_geom.width - config.border_radius >=
|
if (target_geom.x + target_geom.width - border_radius >=
|
||||||
c->mon->m.x + c->mon->m.width) {
|
c->mon->m.x + c->mon->m.width) {
|
||||||
current_corner_location &= ~CORNER_LOCATION_RIGHT;
|
current_corner_location &= ~CORNER_LOCATION_RIGHT; // 清除右标志位
|
||||||
}
|
}
|
||||||
if (target_geom.y + config.border_radius <= c->mon->m.y) {
|
if (target_geom.y + border_radius <= c->mon->m.y) {
|
||||||
current_corner_location &= ~CORNER_LOCATION_TOP;
|
current_corner_location &= ~CORNER_LOCATION_TOP; // 清除上标志位
|
||||||
}
|
}
|
||||||
if (target_geom.y + target_geom.height - config.border_radius >=
|
if (target_geom.y + target_geom.height - border_radius >=
|
||||||
c->mon->m.y + c->mon->m.height) {
|
c->mon->m.y + c->mon->m.height) {
|
||||||
current_corner_location &= ~CORNER_LOCATION_BOTTOM;
|
current_corner_location &= ~CORNER_LOCATION_BOTTOM; // 清除下标志位
|
||||||
}
|
}
|
||||||
return current_corner_location;
|
return current_corner_location;
|
||||||
}
|
}
|
||||||
|
|
@ -48,23 +47,22 @@ bool is_horizontal_right_stack_layout(Monitor *m) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t is_special_animation_rule(Client *c) {
|
int is_special_animaiton_rule(Client *c) {
|
||||||
|
|
||||||
if (is_scroller_layout(c->mon) && !c->isfloating) {
|
if (is_scroller_layout(c->mon) && !c->isfloating) {
|
||||||
return DOWN;
|
return DOWN;
|
||||||
} else if (c->mon->visible_tiling_clients == 1 && !c->isfloating) {
|
} else if (c->mon->visible_tiling_clients == 1 && !c->isfloating) {
|
||||||
return DOWN;
|
return DOWN;
|
||||||
} else if (c->mon->visible_tiling_clients == 2 && !c->isfloating &&
|
} else if (c->mon->visible_tiling_clients == 2 && !c->isfloating &&
|
||||||
!config.new_is_master && is_horizontal_stack_layout(c->mon)) {
|
!new_is_master && is_horizontal_stack_layout(c->mon)) {
|
||||||
return RIGHT;
|
return RIGHT;
|
||||||
} else if (!c->isfloating && config.new_is_master &&
|
} else if (!c->isfloating && new_is_master &&
|
||||||
is_horizontal_stack_layout(c->mon)) {
|
is_horizontal_stack_layout(c->mon)) {
|
||||||
return LEFT;
|
return LEFT;
|
||||||
} else if (c->mon->visible_tiling_clients == 2 && !c->isfloating &&
|
} else if (c->mon->visible_tiling_clients == 2 && !c->isfloating &&
|
||||||
!config.new_is_master &&
|
!new_is_master && is_horizontal_right_stack_layout(c->mon)) {
|
||||||
is_horizontal_right_stack_layout(c->mon)) {
|
|
||||||
return LEFT;
|
return LEFT;
|
||||||
} else if (!c->isfloating && config.new_is_master &&
|
} else if (!c->isfloating && new_is_master &&
|
||||||
is_horizontal_right_stack_layout(c->mon)) {
|
is_horizontal_right_stack_layout(c->mon)) {
|
||||||
return RIGHT;
|
return RIGHT;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -72,15 +70,14 @@ int32_t is_special_animation_rule(Client *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_client_open_animation(Client *c, struct wlr_box geo) {
|
void set_client_open_animaiton(Client *c, struct wlr_box geo) {
|
||||||
int32_t slide_direction;
|
int slide_direction;
|
||||||
int32_t horizontal, horizontal_value;
|
int horizontal, horizontal_value;
|
||||||
int32_t vertical, vertical_value;
|
int vertical, vertical_value;
|
||||||
int32_t special_direction;
|
int special_direction;
|
||||||
int32_t center_x, center_y;
|
int center_x, center_y;
|
||||||
|
|
||||||
if ((!c->animation_type_open &&
|
if ((!c->animation_type_open && strcmp(animation_type_open, "fade") == 0) ||
|
||||||
strcmp(config.animation_type_open, "fade") == 0) ||
|
|
||||||
(c->animation_type_open &&
|
(c->animation_type_open &&
|
||||||
strcmp(c->animation_type_open, "fade") == 0)) {
|
strcmp(c->animation_type_open, "fade") == 0)) {
|
||||||
c->animainit_geom.width = geo.width;
|
c->animainit_geom.width = geo.width;
|
||||||
|
|
@ -89,17 +86,17 @@ void set_client_open_animation(Client *c, struct wlr_box geo) {
|
||||||
c->animainit_geom.y = geo.y;
|
c->animainit_geom.y = geo.y;
|
||||||
return;
|
return;
|
||||||
} else if ((!c->animation_type_open &&
|
} else if ((!c->animation_type_open &&
|
||||||
strcmp(config.animation_type_open, "zoom") == 0) ||
|
strcmp(animation_type_open, "zoom") == 0) ||
|
||||||
(c->animation_type_open &&
|
(c->animation_type_open &&
|
||||||
strcmp(c->animation_type_open, "zoom") == 0)) {
|
strcmp(c->animation_type_open, "zoom") == 0)) {
|
||||||
c->animainit_geom.width = geo.width * config.zoom_initial_ratio;
|
c->animainit_geom.width = geo.width * zoom_initial_ratio;
|
||||||
c->animainit_geom.height = geo.height * config.zoom_initial_ratio;
|
c->animainit_geom.height = geo.height * zoom_initial_ratio;
|
||||||
c->animainit_geom.x = geo.x + (geo.width - c->animainit_geom.width) / 2;
|
c->animainit_geom.x = geo.x + (geo.width - c->animainit_geom.width) / 2;
|
||||||
c->animainit_geom.y =
|
c->animainit_geom.y =
|
||||||
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_animation_rule(c);
|
special_direction = is_special_animaiton_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) {
|
||||||
|
|
@ -150,15 +147,15 @@ void set_client_open_animation(Client *c, struct wlr_box geo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void snap_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx,
|
void snap_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int sx,
|
||||||
int32_t sy, void *data) {
|
int sy, void *data) {
|
||||||
BufferData *buffer_data = (BufferData *)data;
|
BufferData *buffer_data = (BufferData *)data;
|
||||||
wlr_scene_buffer_set_dest_size(buffer, buffer_data->width,
|
wlr_scene_buffer_set_dest_size(buffer, buffer_data->width,
|
||||||
buffer_data->height);
|
buffer_data->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx,
|
void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int sx, int sy,
|
||||||
int32_t sy, void *data) {
|
void *data) {
|
||||||
BufferData *buffer_data = (BufferData *)data;
|
BufferData *buffer_data = (BufferData *)data;
|
||||||
|
|
||||||
if (buffer_data->should_scale && buffer_data->height_scale < 1 &&
|
if (buffer_data->should_scale && buffer_data->height_scale < 1 &&
|
||||||
|
|
@ -186,8 +183,8 @@ void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx,
|
||||||
|
|
||||||
if (buffer_data->should_scale) {
|
if (buffer_data->should_scale) {
|
||||||
|
|
||||||
int32_t surface_width = surface->current.width;
|
uint32_t surface_width = surface->current.width;
|
||||||
int32_t surface_height = surface->current.height;
|
uint32_t surface_height = surface->current.height;
|
||||||
|
|
||||||
surface_width = buffer_data->width_scale < 1
|
surface_width = buffer_data->width_scale < 1
|
||||||
? surface_width
|
? surface_width
|
||||||
|
|
@ -226,7 +223,7 @@ void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int32_t sx,
|
||||||
if (wlr_xdg_popup_try_from_wlr_surface(surface) != NULL)
|
if (wlr_xdg_popup_try_from_wlr_surface(surface) != NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wlr_scene_buffer_set_corner_radius(buffer, config.border_radius,
|
wlr_scene_buffer_set_corner_radius(buffer, border_radius,
|
||||||
buffer_data->corner_location);
|
buffer_data->corner_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,8 +240,7 @@ void buffer_set_effect(Client *c, BufferData data) {
|
||||||
if (c == grabc)
|
if (c == grabc)
|
||||||
data.should_scale = false;
|
data.should_scale = false;
|
||||||
|
|
||||||
if (c->isnoradius || c->isfullscreen ||
|
if (c->isfullscreen || (no_radius_when_single && c->mon &&
|
||||||
(config.no_radius_when_single && c->mon &&
|
|
||||||
c->mon->visible_tiling_clients == 1)) {
|
c->mon->visible_tiling_clients == 1)) {
|
||||||
data.corner_location = CORNER_LOCATION_NONE;
|
data.corner_location = CORNER_LOCATION_NONE;
|
||||||
}
|
}
|
||||||
|
|
@ -258,7 +254,7 @@ void client_draw_shadow(Client *c) {
|
||||||
if (c->iskilling || !client_surface(c)->mapped || c->isnoshadow)
|
if (c->iskilling || !client_surface(c)->mapped || c->isnoshadow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!config.shadows || (!c->isfloating && config.shadow_only_floating)) {
|
if (!shadows || (!c->isfloating && shadow_only_floating)) {
|
||||||
if (c->shadow->node.enabled)
|
if (c->shadow->node.enabled)
|
||||||
wlr_scene_node_set_enabled(&c->shadow->node, false);
|
wlr_scene_node_set_enabled(&c->shadow->node, false);
|
||||||
return;
|
return;
|
||||||
|
|
@ -269,40 +265,43 @@ void client_draw_shadow(Client *c) {
|
||||||
|
|
||||||
bool hit_no_border = check_hit_no_border(c);
|
bool hit_no_border = check_hit_no_border(c);
|
||||||
enum corner_location current_corner_location =
|
enum corner_location current_corner_location =
|
||||||
c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
c->isfullscreen || (no_radius_when_single && c->mon &&
|
||||||
c->mon->visible_tiling_clients == 1)
|
c->mon->visible_tiling_clients == 1)
|
||||||
? CORNER_LOCATION_NONE
|
? CORNER_LOCATION_NONE
|
||||||
: CORNER_LOCATION_ALL;
|
: CORNER_LOCATION_ALL;
|
||||||
|
|
||||||
int32_t bwoffset = c->bw != 0 && hit_no_border ? (int32_t)c->bw : 0;
|
uint32_t bwoffset = c->bw != 0 && hit_no_border ? c->bw : 0;
|
||||||
|
|
||||||
int32_t width, height;
|
uint32_t width, height;
|
||||||
client_actual_size(c, &width, &height);
|
client_actual_size(c, &width, &height);
|
||||||
|
|
||||||
int32_t delta = config.shadows_size + (int32_t)c->bw - bwoffset;
|
uint32_t delta = shadows_size + c->bw - bwoffset;
|
||||||
|
|
||||||
|
/* we calculate where to clip the shadow */
|
||||||
struct wlr_box client_box = {
|
struct wlr_box client_box = {
|
||||||
.x = bwoffset,
|
.x = bwoffset,
|
||||||
.y = bwoffset,
|
.y = bwoffset,
|
||||||
.width = width + (int32_t)c->bw - bwoffset,
|
.width = width - 2 * bwoffset,
|
||||||
.height = height + (int32_t)c->bw - bwoffset,
|
.height = height - 2 * bwoffset,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_box shadow_box = {
|
struct wlr_box shadow_box = {
|
||||||
.x = config.shadows_position_x + bwoffset,
|
.x = shadows_position_x,
|
||||||
.y = config.shadows_position_y + bwoffset,
|
.y = shadows_position_y,
|
||||||
.width = width + 2 * delta,
|
.width = width + 2 * delta,
|
||||||
.height = height + 2 * delta,
|
.height = height + 2 * delta,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_box intersection_box;
|
struct wlr_box intersection_box;
|
||||||
wlr_box_intersection(&intersection_box, &client_box, &shadow_box);
|
wlr_box_intersection(&intersection_box, &client_box, &shadow_box);
|
||||||
intersection_box.x -= config.shadows_position_x + bwoffset;
|
/* clipped region takes shadow relative coords, so we translate everything
|
||||||
intersection_box.y -= config.shadows_position_y + bwoffset;
|
* by its position */
|
||||||
|
intersection_box.x -= shadows_position_x;
|
||||||
|
intersection_box.y -= shadows_position_y;
|
||||||
|
|
||||||
struct clipped_region clipped_region = {
|
struct clipped_region clipped_region = {
|
||||||
.area = intersection_box,
|
.area = intersection_box,
|
||||||
.corner_radius = config.border_radius,
|
.corner_radius = border_radius,
|
||||||
.corners = current_corner_location,
|
.corners = current_corner_location,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -313,7 +312,7 @@ void client_draw_shadow(Client *c) {
|
||||||
.height = shadow_box.height,
|
.height = shadow_box.height,
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t right_offset, bottom_offset, left_offset, top_offset;
|
int right_offset, bottom_offset, left_offset, top_offset;
|
||||||
|
|
||||||
if (c == grabc) {
|
if (c == grabc) {
|
||||||
right_offset = 0;
|
right_offset = 0;
|
||||||
|
|
@ -356,31 +355,32 @@ void apply_border(Client *c) {
|
||||||
|
|
||||||
bool hit_no_border = check_hit_no_border(c);
|
bool hit_no_border = check_hit_no_border(c);
|
||||||
enum corner_location current_corner_location;
|
enum corner_location current_corner_location;
|
||||||
if (c->isfullscreen || (config.no_radius_when_single && c->mon &&
|
if (c->isfullscreen || (no_radius_when_single && c->mon &&
|
||||||
c->mon->visible_tiling_clients == 1)) {
|
c->mon->visible_tiling_clients == 1)) {
|
||||||
current_corner_location = CORNER_LOCATION_NONE;
|
current_corner_location = CORNER_LOCATION_NONE;
|
||||||
} else {
|
} else {
|
||||||
current_corner_location = set_client_corner_location(c);
|
current_corner_location = set_client_corner_location(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hit_no_border && config.smartgaps) {
|
// Handle no-border cases
|
||||||
|
if (hit_no_border && smartgaps) {
|
||||||
c->bw = 0;
|
c->bw = 0;
|
||||||
c->fake_no_border = true;
|
c->fake_no_border = true;
|
||||||
} else if (hit_no_border && !config.smartgaps) {
|
} else if (hit_no_border && !smartgaps) {
|
||||||
wlr_scene_rect_set_size(c->border, 0, 0);
|
wlr_scene_rect_set_size(c->border, 0, 0);
|
||||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
||||||
c->fake_no_border = true;
|
c->fake_no_border = true;
|
||||||
return;
|
return;
|
||||||
} else if (!c->isfullscreen && VISIBLEON(c, c->mon)) {
|
} else if (!c->isfullscreen && VISIBLEON(c, c->mon)) {
|
||||||
c->bw = c->isnoborder ? 0 : config.borderpx;
|
c->bw = c->isnoborder ? 0 : borderpx;
|
||||||
c->fake_no_border = false;
|
c->fake_no_border = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_box clip_box = c->animation.current;
|
struct wlr_box clip_box = c->animation.current;
|
||||||
// 一但在GEZERO如果使用无符号,那么其他数据也会转换为无符号导致没有负数出错
|
// 一但在GEZERO如果使用无符号,那么其他数据也会转换为无符号导致没有负数出错
|
||||||
int32_t bw = (int32_t)c->bw;
|
int bw = (int)c->bw;
|
||||||
|
|
||||||
int32_t right_offset, bottom_offset, left_offset, top_offset;
|
int right_offset, bottom_offset, left_offset, top_offset;
|
||||||
|
|
||||||
if (c == grabc) {
|
if (c == grabc) {
|
||||||
right_offset = 0;
|
right_offset = 0;
|
||||||
|
|
@ -399,27 +399,25 @@ void apply_border(Client *c) {
|
||||||
top_offset = GEZERO(c->mon->m.y - c->animation.current.y);
|
top_offset = GEZERO(c->mon->m.y - c->animation.current.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t inner_surface_width = GEZERO(clip_box.width - 2 * bw);
|
int inner_surface_width = GEZERO(clip_box.width - 2 * bw);
|
||||||
int32_t inner_surface_height = GEZERO(clip_box.height - 2 * bw);
|
int inner_surface_height = GEZERO(clip_box.height - 2 * bw);
|
||||||
|
|
||||||
int32_t inner_surface_x = GEZERO(bw - left_offset);
|
int inner_surface_x = GEZERO(bw - left_offset);
|
||||||
int32_t inner_surface_y = GEZERO(bw - top_offset);
|
int inner_surface_y = GEZERO(bw - top_offset);
|
||||||
|
|
||||||
int32_t rect_x = left_offset;
|
int rect_x = left_offset;
|
||||||
int32_t rect_y = top_offset;
|
int rect_y = top_offset;
|
||||||
|
|
||||||
int32_t rect_width =
|
int rect_width =
|
||||||
GEZERO(c->animation.current.width - left_offset - right_offset);
|
GEZERO(c->animation.current.width - left_offset - right_offset);
|
||||||
int32_t rect_height =
|
int rect_height =
|
||||||
GEZERO(c->animation.current.height - top_offset - bottom_offset);
|
GEZERO(c->animation.current.height - top_offset - bottom_offset);
|
||||||
|
|
||||||
if (left_offset > c->bw)
|
if (left_offset > c->bw)
|
||||||
inner_surface_width =
|
inner_surface_width = inner_surface_width - left_offset + c->bw;
|
||||||
inner_surface_width - left_offset + (int32_t)c->bw;
|
|
||||||
|
|
||||||
if (top_offset > c->bw)
|
if (top_offset > c->bw)
|
||||||
inner_surface_height =
|
inner_surface_height = inner_surface_height - top_offset + c->bw;
|
||||||
inner_surface_height - top_offset + (int32_t)c->bw;
|
|
||||||
|
|
||||||
if (right_offset > 0) {
|
if (right_offset > 0) {
|
||||||
inner_surface_width =
|
inner_surface_width =
|
||||||
|
|
@ -434,37 +432,37 @@ void apply_border(Client *c) {
|
||||||
struct clipped_region clipped_region = {
|
struct clipped_region clipped_region = {
|
||||||
.area = {inner_surface_x, inner_surface_y, inner_surface_width,
|
.area = {inner_surface_x, inner_surface_y, inner_surface_width,
|
||||||
inner_surface_height},
|
inner_surface_height},
|
||||||
.corner_radius = config.border_radius,
|
.corner_radius = border_radius,
|
||||||
.corners = current_corner_location,
|
.corners = current_corner_location,
|
||||||
};
|
};
|
||||||
|
|
||||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
||||||
wlr_scene_rect_set_size(c->border, rect_width, rect_height);
|
wlr_scene_rect_set_size(c->border, rect_width, rect_height);
|
||||||
wlr_scene_node_set_position(&c->border->node, rect_x, rect_y);
|
wlr_scene_node_set_position(&c->border->node, rect_x, rect_y);
|
||||||
wlr_scene_rect_set_corner_radius(c->border, config.border_radius,
|
wlr_scene_rect_set_corner_radius(c->border, border_radius,
|
||||||
current_corner_location);
|
current_corner_location);
|
||||||
wlr_scene_rect_set_clipped_region(c->border, clipped_region);
|
wlr_scene_rect_set_clipped_region(c->border, clipped_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) {
|
struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) {
|
||||||
int32_t offsetx = 0, offsety = 0, offsetw = 0, offseth = 0;
|
int offsetx = 0, offsety = 0, offsetw = 0, offseth = 0;
|
||||||
struct ivec2 offset = {0, 0, 0, 0};
|
struct ivec2 offset = {0, 0, 0, 0};
|
||||||
|
|
||||||
if (!ISSCROLLTILED(c) && !c->animation.tagining && !c->animation.tagouted &&
|
if (!ISSCROLLTILED(c) && !c->animation.tagining && !c->animation.tagouted &&
|
||||||
!c->animation.tagouting)
|
!c->animation.tagouting)
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
int32_t bottom_out_offset =
|
int bottom_out_offset =
|
||||||
GEZERO(c->animation.current.y + c->animation.current.height -
|
GEZERO(c->animation.current.y + c->animation.current.height -
|
||||||
c->mon->m.y - c->mon->m.height);
|
c->mon->m.y - c->mon->m.height);
|
||||||
int32_t right_out_offset =
|
int right_out_offset =
|
||||||
GEZERO(c->animation.current.x + c->animation.current.width -
|
GEZERO(c->animation.current.x + c->animation.current.width -
|
||||||
c->mon->m.x - c->mon->m.width);
|
c->mon->m.x - c->mon->m.width);
|
||||||
int32_t left_out_offset = GEZERO(c->mon->m.x - c->animation.current.x);
|
int left_out_offset = GEZERO(c->mon->m.x - c->animation.current.x);
|
||||||
int32_t top_out_offset = GEZERO(c->mon->m.y - c->animation.current.y);
|
int top_out_offset = GEZERO(c->mon->m.y - c->animation.current.y);
|
||||||
|
|
||||||
// 必须转换为int,否计算会没有负数导致判断错误
|
// 必须转换为int,否计算会没有负数导致判断错误
|
||||||
int32_t bw = (int32_t)c->bw;
|
int bw = (int)c->bw;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
计算窗口表面超出屏幕四个方向的偏差,避免窗口超出屏幕
|
计算窗口表面超出屏幕四个方向的偏差,避免窗口超出屏幕
|
||||||
|
|
@ -523,7 +521,9 @@ void client_apply_clip(Client *c, float factor) {
|
||||||
enum corner_location current_corner_location =
|
enum corner_location current_corner_location =
|
||||||
set_client_corner_location(c);
|
set_client_corner_location(c);
|
||||||
|
|
||||||
if (!config.animations) {
|
int bw = (int)c->bw;
|
||||||
|
|
||||||
|
if (!animations) {
|
||||||
c->animation.running = false;
|
c->animation.running = false;
|
||||||
c->need_output_flush = false;
|
c->need_output_flush = false;
|
||||||
c->animainit_geom = c->current = c->pending = c->animation.current =
|
c->animainit_geom = c->current = c->pending = c->animation.current =
|
||||||
|
|
@ -548,7 +548,7 @@ void client_apply_clip(Client *c, float factor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取窗口动画实时位置矩形
|
// 获取窗口动画实时位置矩形
|
||||||
int32_t width, height;
|
uint32_t width, height;
|
||||||
client_actual_size(c, &width, &height);
|
client_actual_size(c, &width, &height);
|
||||||
|
|
||||||
// 计算出除了边框的窗口实际剪切大小
|
// 计算出除了边框的窗口实际剪切大小
|
||||||
|
|
@ -557,8 +557,8 @@ void client_apply_clip(Client *c, float factor) {
|
||||||
clip_box = (struct wlr_box){
|
clip_box = (struct wlr_box){
|
||||||
.x = geometry.x,
|
.x = geometry.x,
|
||||||
.y = geometry.y,
|
.y = geometry.y,
|
||||||
.width = width,
|
.width = width - bw,
|
||||||
.height = height,
|
.height = height - bw,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (client_is_x11(c)) {
|
if (client_is_x11(c)) {
|
||||||
|
|
@ -591,8 +591,8 @@ void client_apply_clip(Client *c, float factor) {
|
||||||
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip_box);
|
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip_box);
|
||||||
|
|
||||||
// 获取剪切后的表面的实际大小用于计算缩放
|
// 获取剪切后的表面的实际大小用于计算缩放
|
||||||
int32_t acutal_surface_width = geometry.width - offset.x - offset.width;
|
int acutal_surface_width = geometry.width - offset.x - offset.width;
|
||||||
int32_t acutal_surface_height = geometry.height - offset.y - offset.height;
|
int acutal_surface_height = geometry.height - offset.y - offset.height;
|
||||||
|
|
||||||
if (acutal_surface_width <= 0 || acutal_surface_height <= 0)
|
if (acutal_surface_width <= 0 || acutal_surface_height <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
@ -624,23 +624,24 @@ void fadeout_client_animation_next_tick(Client *c) {
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
int32_t passed_time = timespec_to_ms(&now) - c->animation.time_started;
|
uint32_t passed_time = timespec_to_ms(&now) - c->animation.time_started;
|
||||||
double animation_passed =
|
double animation_passed =
|
||||||
c->animation.duration
|
c->animation.duration
|
||||||
? (double)passed_time / (double)c->animation.duration
|
? (double)passed_time / (double)c->animation.duration
|
||||||
: 1.0;
|
: 1.0;
|
||||||
|
|
||||||
int32_t type = c->animation.action = c->animation.action;
|
int type = c->animation.action = c->animation.action;
|
||||||
double factor = find_animation_curve_at(animation_passed, type);
|
double factor = find_animation_curve_at(animation_passed, type);
|
||||||
|
|
||||||
int32_t width = c->animation.initial.width +
|
uint32_t width = c->animation.initial.width +
|
||||||
(c->current.width - c->animation.initial.width) * factor;
|
(c->current.width - c->animation.initial.width) * factor;
|
||||||
int32_t height = c->animation.initial.height +
|
uint32_t height =
|
||||||
|
c->animation.initial.height +
|
||||||
(c->current.height - c->animation.initial.height) * factor;
|
(c->current.height - c->animation.initial.height) * factor;
|
||||||
|
|
||||||
int32_t x = c->animation.initial.x +
|
uint32_t x = c->animation.initial.x +
|
||||||
(c->current.x - c->animation.initial.x) * factor;
|
(c->current.x - c->animation.initial.x) * factor;
|
||||||
int32_t y = c->animation.initial.y +
|
uint32_t y = c->animation.initial.y +
|
||||||
(c->current.y - c->animation.initial.y) * factor;
|
(c->current.y - c->animation.initial.y) * factor;
|
||||||
|
|
||||||
wlr_scene_node_set_position(&c->scene->node, x, y);
|
wlr_scene_node_set_position(&c->scene->node, x, y);
|
||||||
|
|
@ -655,19 +656,19 @@ void fadeout_client_animation_next_tick(Client *c) {
|
||||||
double opacity_eased_progress =
|
double opacity_eased_progress =
|
||||||
find_animation_curve_at(animation_passed, OPAFADEOUT);
|
find_animation_curve_at(animation_passed, OPAFADEOUT);
|
||||||
|
|
||||||
double percent = config.fadeout_begin_opacity -
|
double percent = fadeout_begin_opacity -
|
||||||
(opacity_eased_progress * config.fadeout_begin_opacity);
|
(opacity_eased_progress * fadeout_begin_opacity);
|
||||||
|
|
||||||
double opacity = MAX(percent, 0);
|
double opacity = MAX(percent, 0);
|
||||||
|
|
||||||
if (config.animation_fade_out && !c->nofadeout)
|
if (animation_fade_out && !c->nofadeout)
|
||||||
wlr_scene_node_for_each_buffer(&c->scene->node,
|
wlr_scene_node_for_each_buffer(&c->scene->node,
|
||||||
scene_buffer_apply_opacity, &opacity);
|
scene_buffer_apply_opacity, &opacity);
|
||||||
|
|
||||||
if ((c->animation_type_close &&
|
if ((c->animation_type_close &&
|
||||||
strcmp(c->animation_type_close, "zoom") == 0) ||
|
strcmp(c->animation_type_close, "zoom") == 0) ||
|
||||||
(!c->animation_type_close &&
|
(!c->animation_type_close &&
|
||||||
strcmp(config.animation_type_close, "zoom") == 0)) {
|
strcmp(animation_type_close, "zoom") == 0)) {
|
||||||
|
|
||||||
buffer_data.width = width;
|
buffer_data.width = width;
|
||||||
buffer_data.height = height;
|
buffer_data.height = height;
|
||||||
|
|
@ -690,22 +691,23 @@ void client_animation_next_tick(Client *c) {
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
int32_t passed_time = timespec_to_ms(&now) - c->animation.time_started;
|
uint32_t passed_time = timespec_to_ms(&now) - c->animation.time_started;
|
||||||
double animation_passed =
|
double animation_passed =
|
||||||
c->animation.duration
|
c->animation.duration
|
||||||
? (double)passed_time / (double)c->animation.duration
|
? (double)passed_time / (double)c->animation.duration
|
||||||
: 1.0;
|
: 1.0;
|
||||||
|
|
||||||
int32_t type = c->animation.action == NONE ? MOVE : c->animation.action;
|
int type = c->animation.action == NONE ? MOVE : c->animation.action;
|
||||||
double factor = find_animation_curve_at(animation_passed, type);
|
double factor = find_animation_curve_at(animation_passed, type);
|
||||||
|
|
||||||
Client *pointer_c = NULL;
|
Client *pointer_c = NULL;
|
||||||
double sx = 0, sy = 0;
|
double sx = 0, sy = 0;
|
||||||
struct wlr_surface *surface = NULL;
|
struct wlr_surface *surface = NULL;
|
||||||
|
|
||||||
int32_t width = c->animation.initial.width +
|
uint32_t width = c->animation.initial.width +
|
||||||
(c->current.width - c->animation.initial.width) * factor;
|
(c->current.width - c->animation.initial.width) * factor;
|
||||||
int32_t height = c->animation.initial.height +
|
uint32_t height =
|
||||||
|
c->animation.initial.height +
|
||||||
(c->current.height - c->animation.initial.height) * factor;
|
(c->current.height - c->animation.initial.height) * factor;
|
||||||
|
|
||||||
int32_t x = c->animation.initial.x +
|
int32_t x = c->animation.initial.x +
|
||||||
|
|
@ -768,75 +770,75 @@ void init_fadeout_client(Client *c) {
|
||||||
if ((c->animation_type_close &&
|
if ((c->animation_type_close &&
|
||||||
strcmp(c->animation_type_close, "none") == 0) ||
|
strcmp(c->animation_type_close, "none") == 0) ||
|
||||||
(!c->animation_type_close &&
|
(!c->animation_type_close &&
|
||||||
strcmp(config.animation_type_close, "none") == 0)) {
|
strcmp(animation_type_close, "none") == 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Client *fadeout_client = ecalloc(1, sizeof(*fadeout_client));
|
Client *fadeout_cient = ecalloc(1, sizeof(*fadeout_cient));
|
||||||
|
|
||||||
wlr_scene_node_set_enabled(&c->scene->node, true);
|
wlr_scene_node_set_enabled(&c->scene->node, true);
|
||||||
client_set_border_color(c, config.bordercolor);
|
client_set_border_color(c, bordercolor);
|
||||||
fadeout_client->scene =
|
fadeout_cient->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_client->scene) {
|
if (!fadeout_cient->scene) {
|
||||||
free(fadeout_client);
|
free(fadeout_cient);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fadeout_client->animation.duration = config.animation_duration_close;
|
fadeout_cient->animation.duration = animation_duration_close;
|
||||||
fadeout_client->geom = fadeout_client->current =
|
fadeout_cient->geom = fadeout_cient->current =
|
||||||
fadeout_client->animainit_geom = fadeout_client->animation.initial =
|
fadeout_cient->animainit_geom = fadeout_cient->animation.initial =
|
||||||
c->animation.current;
|
c->animation.current;
|
||||||
fadeout_client->mon = c->mon;
|
fadeout_cient->mon = c->mon;
|
||||||
fadeout_client->animation_type_close = c->animation_type_close;
|
fadeout_cient->animation_type_close = c->animation_type_close;
|
||||||
fadeout_client->animation.action = CLOSE;
|
fadeout_cient->animation.action = CLOSE;
|
||||||
fadeout_client->bw = c->bw;
|
fadeout_cient->bw = c->bw;
|
||||||
fadeout_client->nofadeout = c->nofadeout;
|
fadeout_cient->nofadeout = c->nofadeout;
|
||||||
|
|
||||||
// 这里snap节点的坐标设置是使用的相对坐标,所以不能加上原来坐标
|
// 这里snap节点的坐标设置是使用的相对坐标,所以不能加上原来坐标
|
||||||
// 这跟普通node有区别
|
// 这跟普通node有区别
|
||||||
|
|
||||||
fadeout_client->animation.initial.x = 0;
|
fadeout_cient->animation.initial.x = 0;
|
||||||
fadeout_client->animation.initial.y = 0;
|
fadeout_cient->animation.initial.y = 0;
|
||||||
|
|
||||||
if ((!c->animation_type_close &&
|
if ((!c->animation_type_close &&
|
||||||
strcmp(config.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_client->current.x = 0;
|
fadeout_cient->current.x = 0;
|
||||||
fadeout_client->current.y = 0;
|
fadeout_cient->current.y = 0;
|
||||||
fadeout_client->current.width = 0;
|
fadeout_cient->current.width = 0;
|
||||||
fadeout_client->current.height = 0;
|
fadeout_cient->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(config.animation_type_close, "slide") == 0)) {
|
strcmp(animation_type_close, "slide") == 0)) {
|
||||||
fadeout_client->current.y =
|
fadeout_cient->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_client->current.x = 0; // x无偏差,垂直划出
|
fadeout_cient->current.x = 0; // x无偏差,垂直划出
|
||||||
} else {
|
} else {
|
||||||
fadeout_client->current.y =
|
fadeout_cient->current.y =
|
||||||
(fadeout_client->geom.height -
|
(fadeout_cient->geom.height -
|
||||||
fadeout_client->geom.height * config.zoom_end_ratio) /
|
fadeout_cient->geom.height * zoom_end_ratio) /
|
||||||
2;
|
2;
|
||||||
fadeout_client->current.x =
|
fadeout_cient->current.x =
|
||||||
(fadeout_client->geom.width -
|
(fadeout_cient->geom.width -
|
||||||
fadeout_client->geom.width * config.zoom_end_ratio) /
|
fadeout_cient->geom.width * zoom_end_ratio) /
|
||||||
2;
|
2;
|
||||||
fadeout_client->current.width =
|
fadeout_cient->current.width =
|
||||||
fadeout_client->geom.width * config.zoom_end_ratio;
|
fadeout_cient->geom.width * zoom_end_ratio;
|
||||||
fadeout_client->current.height =
|
fadeout_cient->current.height =
|
||||||
fadeout_client->geom.height * config.zoom_end_ratio;
|
fadeout_cient->geom.height * zoom_end_ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
fadeout_client->animation.time_started = get_now_in_ms();
|
fadeout_cient->animation.time_started = get_now_in_ms();
|
||||||
wlr_scene_node_set_enabled(&fadeout_client->scene->node, true);
|
wlr_scene_node_set_enabled(&fadeout_cient->scene->node, true);
|
||||||
wl_list_insert(&fadeout_clients, &fadeout_client->fadeout_link);
|
wl_list_insert(&fadeout_clients, &fadeout_cient->fadeout_link);
|
||||||
|
|
||||||
// 请求刷新屏幕
|
// 请求刷新屏幕
|
||||||
request_fresh_all_monitors();
|
request_fresh_all_monitors();
|
||||||
|
|
@ -866,11 +868,12 @@ void client_set_pending_state(Client *c) {
|
||||||
if (!c || c->iskilling)
|
if (!c || c->iskilling)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!config.animations) {
|
// 判断是否需要动画
|
||||||
|
if (!animations) {
|
||||||
c->animation.should_animate = false;
|
c->animation.should_animate = false;
|
||||||
} else if (config.animations && c->animation.tagining) {
|
} else if (animations && c->animation.tagining) {
|
||||||
c->animation.should_animate = true;
|
c->animation.should_animate = true;
|
||||||
} else if (!config.animations || c == grabc ||
|
} else if (!animations || c == grabc ||
|
||||||
(!c->is_pending_open_animation &&
|
(!c->is_pending_open_animation &&
|
||||||
wlr_box_equal(&c->current, &c->pending))) {
|
wlr_box_equal(&c->current, &c->pending))) {
|
||||||
c->animation.should_animate = false;
|
c->animation.should_animate = false;
|
||||||
|
|
@ -881,7 +884,7 @@ void client_set_pending_state(Client *c) {
|
||||||
if (((c->animation_type_open &&
|
if (((c->animation_type_open &&
|
||||||
strcmp(c->animation_type_open, "none") == 0) ||
|
strcmp(c->animation_type_open, "none") == 0) ||
|
||||||
(!c->animation_type_open &&
|
(!c->animation_type_open &&
|
||||||
strcmp(config.animation_type_open, "none") == 0)) &&
|
strcmp(animation_type_open, "none") == 0)) &&
|
||||||
c->animation.action == OPEN) {
|
c->animation.action == OPEN) {
|
||||||
c->animation.duration = 0;
|
c->animation.duration = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -906,7 +909,7 @@ void client_set_pending_state(Client *c) {
|
||||||
c->dirty = true;
|
c->dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(Client *c, struct wlr_box geo, int32_t interact) {
|
void resize(Client *c, struct wlr_box geo, int interact) {
|
||||||
|
|
||||||
// 动画设置的起始函数,这里用来计算一些动画的起始值
|
// 动画设置的起始函数,这里用来计算一些动画的起始值
|
||||||
// 动画起始位置大小是由于c->animainit_geom确定的
|
// 动画起始位置大小是由于c->animainit_geom确定的
|
||||||
|
|
@ -928,8 +931,8 @@ void resize(Client *c, struct wlr_box geo, int32_t interact) {
|
||||||
|
|
||||||
if (is_scroller_layout(c->mon) && (!c->isfloating || c == grabc)) {
|
if (is_scroller_layout(c->mon) && (!c->isfloating || c == grabc)) {
|
||||||
c->geom = geo;
|
c->geom = geo;
|
||||||
c->geom.width = MAX(1 + 2 * (int32_t)c->bw, c->geom.width);
|
c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width);
|
||||||
c->geom.height = MAX(1 + 2 * (int32_t)c->bw, c->geom.height);
|
c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height);
|
||||||
} else { // 这里会限制不允许窗口划出屏幕
|
} else { // 这里会限制不允许窗口划出屏幕
|
||||||
c->geom = geo;
|
c->geom = geo;
|
||||||
applybounds(
|
applybounds(
|
||||||
|
|
@ -950,16 +953,16 @@ void resize(Client *c, struct wlr_box geo, int32_t interact) {
|
||||||
!c->animation.tagouting && wlr_box_equal(&c->geom, &c->current)) {
|
!c->animation.tagouting && wlr_box_equal(&c->geom, &c->current)) {
|
||||||
c->animation.action = c->animation.action;
|
c->animation.action = c->animation.action;
|
||||||
} else if (c->animation.tagouting) {
|
} else if (c->animation.tagouting) {
|
||||||
c->animation.duration = config.animation_duration_tag;
|
c->animation.duration = animation_duration_tag;
|
||||||
c->animation.action = TAG;
|
c->animation.action = TAG;
|
||||||
} else if (c->animation.tagining) {
|
} else if (c->animation.tagining) {
|
||||||
c->animation.duration = config.animation_duration_tag;
|
c->animation.duration = animation_duration_tag;
|
||||||
c->animation.action = TAG;
|
c->animation.action = TAG;
|
||||||
} else if (c->is_pending_open_animation) {
|
} else if (c->is_pending_open_animation) {
|
||||||
c->animation.duration = config.animation_duration_open;
|
c->animation.duration = animation_duration_open;
|
||||||
c->animation.action = OPEN;
|
c->animation.action = OPEN;
|
||||||
} else {
|
} else {
|
||||||
c->animation.duration = config.animation_duration_move;
|
c->animation.duration = animation_duration_move;
|
||||||
c->animation.action = MOVE;
|
c->animation.action = MOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -970,7 +973,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_animation(c, c->geom);
|
set_client_open_animaiton(c, c->geom);
|
||||||
} else {
|
} else {
|
||||||
c->animainit_geom = c->animation.current;
|
c->animainit_geom = c->animation.current;
|
||||||
}
|
}
|
||||||
|
|
@ -979,20 +982,10 @@ 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 && config.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);
|
||||||
|
|
||||||
if (c->configure_serial != 0) {
|
|
||||||
c->mon->resizing_count_pending++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == grabc) {
|
if (c == grabc) {
|
||||||
c->animation.running = false;
|
c->animation.running = false;
|
||||||
c->need_output_flush = false;
|
c->need_output_flush = false;
|
||||||
|
|
@ -1047,43 +1040,63 @@ bool client_draw_fadeout_frame(Client *c) {
|
||||||
void client_set_focused_opacity_animation(Client *c) {
|
void client_set_focused_opacity_animation(Client *c) {
|
||||||
float *border_color = get_border_color(c);
|
float *border_color = get_border_color(c);
|
||||||
|
|
||||||
if (!config.animations) {
|
if (!animations) {
|
||||||
setborder_color(c);
|
setborder_color(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->opacity_animation.duration = config.animation_duration_focus;
|
c->opacity_animation.duration = animation_duration_focus;
|
||||||
memcpy(c->opacity_animation.target_border_color, border_color,
|
memcpy(c->opacity_animation.target_border_color, border_color,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_set_unfocused_opacity_animation(Client *c) {
|
void client_set_unfocused_opacity_animation(Client *c) {
|
||||||
|
// Start border color animation to unfocused
|
||||||
float *border_color = get_border_color(c);
|
float *border_color = get_border_color(c);
|
||||||
|
|
||||||
if (!config.animations) {
|
if (!animations) {
|
||||||
setborder_color(c);
|
setborder_color(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->opacity_animation.duration = config.animation_duration_focus;
|
c->opacity_animation.duration = animation_duration_focus;
|
||||||
memcpy(c->opacity_animation.target_border_color, border_color,
|
memcpy(c->opacity_animation.target_border_color, border_color,
|
||||||
sizeof(c->opacity_animation.target_border_color));
|
sizeof(c->opacity_animation.target_border_color));
|
||||||
// Start opacity animation to unfocused
|
// Start opacity animation to unfocused
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
@ -1099,7 +1112,7 @@ bool client_apply_focus_opacity(Client *c) {
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
int32_t passed_time = timespec_to_ms(&now) - c->animation.time_started;
|
uint32_t passed_time = timespec_to_ms(&now) - c->animation.time_started;
|
||||||
double linear_progress =
|
double linear_progress =
|
||||||
c->animation.duration
|
c->animation.duration
|
||||||
? (double)passed_time / (double)c->animation.duration
|
? (double)passed_time / (double)c->animation.duration
|
||||||
|
|
@ -1108,29 +1121,23 @@ bool client_apply_focus_opacity(Client *c) {
|
||||||
double opacity_eased_progress =
|
double opacity_eased_progress =
|
||||||
find_animation_curve_at(linear_progress, OPAFADEIN);
|
find_animation_curve_at(linear_progress, OPAFADEIN);
|
||||||
|
|
||||||
float percent = config.animation_fade_in && !c->nofadein
|
float percent =
|
||||||
? opacity_eased_progress
|
animation_fade_in && !c->nofadein ? opacity_eased_progress : 1.0;
|
||||||
: 1.0;
|
|
||||||
float opacity =
|
float opacity =
|
||||||
c == selmon->sel ? c->focused_opacity : c->unfocused_opacity;
|
c == selmon->sel ? c->focused_opacity : c->unfocused_opacity;
|
||||||
|
|
||||||
float target_opacity = percent * (1.0 - config.fadein_begin_opacity) +
|
float target_opacity =
|
||||||
config.fadein_begin_opacity;
|
percent * (1.0 - fadein_begin_opacity) + fadein_begin_opacity;
|
||||||
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 (config.animations && c->opacity_animation.running) {
|
|
||||||
|
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
int32_t passed_time =
|
uint32_t passed_time =
|
||||||
timespec_to_ms(&now) - c->opacity_animation.time_started;
|
timespec_to_ms(&now) - c->opacity_animation.time_started;
|
||||||
double linear_progress =
|
double linear_progress =
|
||||||
c->opacity_animation.duration
|
c->opacity_animation.duration
|
||||||
|
|
@ -1147,7 +1154,7 @@ bool client_apply_focus_opacity(Client *c) {
|
||||||
client_set_opacity(c, c->opacity_animation.current_opacity);
|
client_set_opacity(c, c->opacity_animation.current_opacity);
|
||||||
|
|
||||||
// Animate border color
|
// Animate border color
|
||||||
for (int32_t i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
c->opacity_animation.current_border_color[i] =
|
c->opacity_animation.current_border_color[i] =
|
||||||
c->opacity_animation.initial_border_color[i] +
|
c->opacity_animation.initial_border_color[i] +
|
||||||
(c->opacity_animation.target_border_color[i] -
|
(c->opacity_animation.target_border_color[i] -
|
||||||
|
|
@ -1155,7 +1162,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;
|
||||||
|
|
@ -1186,7 +1193,7 @@ bool client_draw_frame(Client *c) {
|
||||||
return client_apply_focus_opacity(c);
|
return client_apply_focus_opacity(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.animations && c->animation.running) {
|
if (animations && c->animation.running) {
|
||||||
client_animation_next_tick(c);
|
client_animation_next_tick(c);
|
||||||
} else {
|
} else {
|
||||||
wlr_scene_node_set_position(&c->scene->node, c->pending.x,
|
wlr_scene_node_set_position(&c->scene->node, c->pending.x,
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
struct dvec2 calculate_animation_curve_at(double t, int32_t type) {
|
struct dvec2 calculate_animation_curve_at(double t, int type) {
|
||||||
struct dvec2 point;
|
struct dvec2 point;
|
||||||
double *animation_curve;
|
double *animation_curve;
|
||||||
if (type == MOVE) {
|
if (type == MOVE) {
|
||||||
animation_curve = config.animation_curve_move;
|
animation_curve = animation_curve_move;
|
||||||
} else if (type == OPEN) {
|
} else if (type == OPEN) {
|
||||||
animation_curve = config.animation_curve_open;
|
animation_curve = animation_curve_open;
|
||||||
} else if (type == TAG) {
|
} else if (type == TAG) {
|
||||||
animation_curve = config.animation_curve_tag;
|
animation_curve = animation_curve_tag;
|
||||||
} else if (type == CLOSE) {
|
} else if (type == CLOSE) {
|
||||||
animation_curve = config.animation_curve_close;
|
animation_curve = animation_curve_close;
|
||||||
} else if (type == FOCUS) {
|
} else if (type == FOCUS) {
|
||||||
animation_curve = config.animation_curve_focus;
|
animation_curve = animation_curve_focus;
|
||||||
} else if (type == OPAFADEIN) {
|
} else if (type == OPAFADEIN) {
|
||||||
animation_curve = config.animation_curve_opafadein;
|
animation_curve = animation_curve_opafadein;
|
||||||
} else if (type == OPAFADEOUT) {
|
} else if (type == OPAFADEOUT) {
|
||||||
animation_curve = config.animation_curve_opafadeout;
|
animation_curve = animation_curve_opafadeout;
|
||||||
} else {
|
} else {
|
||||||
animation_curve = config.animation_curve_move;
|
animation_curve = animation_curve_move;
|
||||||
}
|
}
|
||||||
|
|
||||||
point.x = 3 * t * (1 - t) * (1 - t) * animation_curve[0] +
|
point.x = 3 * t * (1 - t) * (1 - t) * animation_curve[0] +
|
||||||
|
|
@ -41,41 +41,41 @@ void init_baked_points(void) {
|
||||||
baked_points_opafadeout =
|
baked_points_opafadeout =
|
||||||
calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_opafadeout));
|
calloc(BAKED_POINTS_COUNT, sizeof(*baked_points_opafadeout));
|
||||||
|
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
baked_points_move[i] = calculate_animation_curve_at(
|
baked_points_move[i] = calculate_animation_curve_at(
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), MOVE);
|
(double)i / (BAKED_POINTS_COUNT - 1), MOVE);
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
baked_points_open[i] = calculate_animation_curve_at(
|
baked_points_open[i] = calculate_animation_curve_at(
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), OPEN);
|
(double)i / (BAKED_POINTS_COUNT - 1), OPEN);
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
baked_points_tag[i] = calculate_animation_curve_at(
|
baked_points_tag[i] = calculate_animation_curve_at(
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), TAG);
|
(double)i / (BAKED_POINTS_COUNT - 1), TAG);
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
baked_points_close[i] = calculate_animation_curve_at(
|
baked_points_close[i] = calculate_animation_curve_at(
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), CLOSE);
|
(double)i / (BAKED_POINTS_COUNT - 1), CLOSE);
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
baked_points_focus[i] = calculate_animation_curve_at(
|
baked_points_focus[i] = calculate_animation_curve_at(
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), FOCUS);
|
(double)i / (BAKED_POINTS_COUNT - 1), FOCUS);
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
baked_points_opafadein[i] = calculate_animation_curve_at(
|
baked_points_opafadein[i] = calculate_animation_curve_at(
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), OPAFADEIN);
|
(double)i / (BAKED_POINTS_COUNT - 1), OPAFADEIN);
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
for (uint32_t i = 0; i < BAKED_POINTS_COUNT; i++) {
|
||||||
baked_points_opafadeout[i] = calculate_animation_curve_at(
|
baked_points_opafadeout[i] = calculate_animation_curve_at(
|
||||||
(double)i / (BAKED_POINTS_COUNT - 1), OPAFADEOUT);
|
(double)i / (BAKED_POINTS_COUNT - 1), OPAFADEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double find_animation_curve_at(double t, int32_t type) {
|
double find_animation_curve_at(double t, int type) {
|
||||||
int32_t down = 0;
|
uint32_t down = 0;
|
||||||
int32_t up = BAKED_POINTS_COUNT - 1;
|
uint32_t up = BAKED_POINTS_COUNT - 1;
|
||||||
|
|
||||||
int32_t middle = (up + down) / 2;
|
uint32_t middle = (up + down) / 2;
|
||||||
struct dvec2 *baked_points;
|
struct dvec2 *baked_points;
|
||||||
if (type == MOVE) {
|
if (type == MOVE) {
|
||||||
baked_points = baked_points_move;
|
baked_points = baked_points_move;
|
||||||
|
|
@ -106,8 +106,7 @@ double find_animation_curve_at(double t, int32_t type) {
|
||||||
return baked_points[up].y;
|
return baked_points[up].y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly,
|
||||||
int32_t ly,
|
|
||||||
struct wlr_scene_tree *snapshot_tree) {
|
struct wlr_scene_tree *snapshot_tree) {
|
||||||
if (!node->enabled && node->type != WLR_SCENE_NODE_TREE) {
|
if (!node->enabled && node->type != WLR_SCENE_NODE_TREE) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
void layer_actual_size(LayerSurface *l, int32_t *width, int32_t *height) {
|
void layer_actual_size(LayerSurface *l, uint32_t *width, uint32_t *height) {
|
||||||
struct wlr_box box;
|
struct wlr_box box;
|
||||||
|
|
||||||
if (l->animation.running) {
|
if (l->animation.running) {
|
||||||
|
|
@ -42,7 +42,7 @@ void get_layer_target_geometry(LayerSurface *l, struct wlr_box *target_box) {
|
||||||
.height = state->desired_height};
|
.height = state->desired_height};
|
||||||
|
|
||||||
// 水平方向定位
|
// 水平方向定位
|
||||||
const int32_t both_horiz =
|
const uint32_t both_horiz =
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
||||||
if (box.width == 0) {
|
if (box.width == 0) {
|
||||||
box.x = bounds.x;
|
box.x = bounds.x;
|
||||||
|
|
@ -57,7 +57,7 @@ void get_layer_target_geometry(LayerSurface *l, struct wlr_box *target_box) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 垂直方向定位
|
// 垂直方向定位
|
||||||
const int32_t both_vert =
|
const uint32_t both_vert =
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
||||||
if (box.height == 0) {
|
if (box.height == 0) {
|
||||||
box.y = bounds.y;
|
box.y = bounds.y;
|
||||||
|
|
@ -101,10 +101,10 @@ void get_layer_target_geometry(LayerSurface *l, struct wlr_box *target_box) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_layer_dir_animaiton(LayerSurface *l, struct wlr_box *geo) {
|
void set_layer_dir_animaiton(LayerSurface *l, struct wlr_box *geo) {
|
||||||
int32_t slide_direction;
|
int slide_direction;
|
||||||
int32_t horizontal, horizontal_value;
|
int horizontal, horizontal_value;
|
||||||
int32_t vertical, vertical_value;
|
int vertical, vertical_value;
|
||||||
int32_t center_x, center_y;
|
int center_x, center_y;
|
||||||
|
|
||||||
if (!l)
|
if (!l)
|
||||||
return;
|
return;
|
||||||
|
|
@ -156,16 +156,17 @@ void layer_draw_shadow(LayerSurface *l) {
|
||||||
if (!l->mapped || !l->shadow)
|
if (!l->mapped || !l->shadow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!config.shadows || !config.layer_shadows || l->noshadow) {
|
if (!shadows || !layer_shadows || l->noshadow) {
|
||||||
wlr_scene_shadow_set_size(l->shadow, 0, 0);
|
wlr_scene_shadow_set_size(l->shadow, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t width, height;
|
uint32_t width, height;
|
||||||
layer_actual_size(l, &width, &height);
|
layer_actual_size(l, &width, &height);
|
||||||
|
|
||||||
int32_t delta = config.shadows_size;
|
uint32_t delta = shadows_size;
|
||||||
|
|
||||||
|
/* we calculate where to clip the shadow */
|
||||||
struct wlr_box layer_box = {
|
struct wlr_box layer_box = {
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = 0,
|
.y = 0,
|
||||||
|
|
@ -174,21 +175,23 @@ void layer_draw_shadow(LayerSurface *l) {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_box shadow_box = {
|
struct wlr_box shadow_box = {
|
||||||
.x = config.shadows_position_x,
|
.x = shadows_position_x,
|
||||||
.y = config.shadows_position_y,
|
.y = shadows_position_y,
|
||||||
.width = width + 2 * delta,
|
.width = width + 2 * delta,
|
||||||
.height = height + 2 * delta,
|
.height = height + 2 * delta,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_box intersection_box;
|
struct wlr_box intersection_box;
|
||||||
wlr_box_intersection(&intersection_box, &layer_box, &shadow_box);
|
wlr_box_intersection(&intersection_box, &layer_box, &shadow_box);
|
||||||
intersection_box.x -= config.shadows_position_x;
|
/* clipped region takes shadow relative coords, so we translate everything
|
||||||
intersection_box.y -= config.shadows_position_y;
|
* by its position */
|
||||||
|
intersection_box.x -= shadows_position_x;
|
||||||
|
intersection_box.y -= shadows_position_y;
|
||||||
|
|
||||||
struct clipped_region clipped_region = {
|
struct clipped_region clipped_region = {
|
||||||
.area = intersection_box,
|
.area = intersection_box,
|
||||||
.corner_radius = config.border_radius,
|
.corner_radius = border_radius,
|
||||||
.corners = config.border_radius_location_default,
|
.corners = border_radius_location_default,
|
||||||
};
|
};
|
||||||
|
|
||||||
wlr_scene_node_set_position(&l->shadow->node, shadow_box.x, shadow_box.y);
|
wlr_scene_node_set_position(&l->shadow->node, shadow_box.x, shadow_box.y);
|
||||||
|
|
@ -197,8 +200,8 @@ void layer_draw_shadow(LayerSurface *l) {
|
||||||
wlr_scene_shadow_set_clipped_region(l->shadow, clipped_region);
|
wlr_scene_shadow_set_clipped_region(l->shadow, clipped_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
void layer_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
void layer_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int sx,
|
||||||
int32_t sx, int32_t sy, void *data) {
|
int sy, void *data) {
|
||||||
BufferData *buffer_data = (BufferData *)data;
|
BufferData *buffer_data = (BufferData *)data;
|
||||||
|
|
||||||
struct wlr_scene_surface *scene_surface =
|
struct wlr_scene_surface *scene_surface =
|
||||||
|
|
@ -209,8 +212,8 @@ void layer_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
||||||
|
|
||||||
struct wlr_surface *surface = scene_surface->surface;
|
struct wlr_surface *surface = scene_surface->surface;
|
||||||
|
|
||||||
int32_t surface_width = surface->current.width * buffer_data->width_scale;
|
uint32_t surface_width = surface->current.width * buffer_data->width_scale;
|
||||||
int32_t surface_height =
|
uint32_t surface_height =
|
||||||
surface->current.height * buffer_data->height_scale;
|
surface->current.height * buffer_data->height_scale;
|
||||||
|
|
||||||
if (surface_height > 0 && surface_width > 0) {
|
if (surface_height > 0 && surface_width > 0) {
|
||||||
|
|
@ -219,8 +222,7 @@ void layer_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
void layer_fadeout_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
void layer_fadeout_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer,
|
||||||
int32_t sx, int32_t sy,
|
int sx, int sy, void *data) {
|
||||||
void *data) {
|
|
||||||
BufferData *buffer_data = (BufferData *)data;
|
BufferData *buffer_data = (BufferData *)data;
|
||||||
wlr_scene_buffer_set_dest_size(buffer, buffer_data->width,
|
wlr_scene_buffer_set_dest_size(buffer, buffer_data->width,
|
||||||
buffer_data->height);
|
buffer_data->height);
|
||||||
|
|
@ -233,22 +235,23 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) {
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
int32_t passed_time = timespec_to_ms(&now) - l->animation.time_started;
|
uint32_t passed_time = timespec_to_ms(&now) - l->animation.time_started;
|
||||||
double animation_passed =
|
double animation_passed =
|
||||||
l->animation.duration
|
l->animation.duration
|
||||||
? (double)passed_time / (double)l->animation.duration
|
? (double)passed_time / (double)l->animation.duration
|
||||||
: 1.0;
|
: 1.0;
|
||||||
|
|
||||||
int32_t type = l->animation.action = l->animation.action;
|
int type = l->animation.action = l->animation.action;
|
||||||
double factor = find_animation_curve_at(animation_passed, type);
|
double factor = find_animation_curve_at(animation_passed, type);
|
||||||
int32_t width = l->animation.initial.width +
|
uint32_t width = l->animation.initial.width +
|
||||||
(l->current.width - l->animation.initial.width) * factor;
|
(l->current.width - l->animation.initial.width) * factor;
|
||||||
int32_t height = l->animation.initial.height +
|
uint32_t height =
|
||||||
|
l->animation.initial.height +
|
||||||
(l->current.height - l->animation.initial.height) * factor;
|
(l->current.height - l->animation.initial.height) * factor;
|
||||||
|
|
||||||
int32_t x = l->animation.initial.x +
|
uint32_t x = l->animation.initial.x +
|
||||||
(l->current.x - l->animation.initial.x) * factor;
|
(l->current.x - l->animation.initial.x) * factor;
|
||||||
int32_t y = l->animation.initial.y +
|
uint32_t y = l->animation.initial.y +
|
||||||
(l->current.y - l->animation.initial.y) * factor;
|
(l->current.y - l->animation.initial.y) * factor;
|
||||||
|
|
||||||
wlr_scene_node_set_position(&l->scene->node, x, y);
|
wlr_scene_node_set_position(&l->scene->node, x, y);
|
||||||
|
|
@ -258,7 +261,7 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) {
|
||||||
buffer_data.height = height;
|
buffer_data.height = height;
|
||||||
|
|
||||||
if ((!l->animation_type_close &&
|
if ((!l->animation_type_close &&
|
||||||
strcmp(config.layer_animation_type_close, "zoom") == 0) ||
|
strcmp(layer_animation_type_close, "zoom") == 0) ||
|
||||||
(l->animation_type_close &&
|
(l->animation_type_close &&
|
||||||
strcmp(l->animation_type_close, "zoom") == 0)) {
|
strcmp(l->animation_type_close, "zoom") == 0)) {
|
||||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||||
|
|
@ -276,12 +279,12 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) {
|
||||||
double opacity_eased_progress =
|
double opacity_eased_progress =
|
||||||
find_animation_curve_at(animation_passed, OPAFADEOUT);
|
find_animation_curve_at(animation_passed, OPAFADEOUT);
|
||||||
|
|
||||||
double percent = config.fadeout_begin_opacity -
|
double percent = fadeout_begin_opacity -
|
||||||
(opacity_eased_progress * config.fadeout_begin_opacity);
|
(opacity_eased_progress * fadeout_begin_opacity);
|
||||||
|
|
||||||
double opacity = MAX(percent, 0.0f);
|
double opacity = MAX(percent, 0.0f);
|
||||||
|
|
||||||
if (config.animation_fade_out)
|
if (animation_fade_out)
|
||||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||||
scene_buffer_apply_opacity, &opacity);
|
scene_buffer_apply_opacity, &opacity);
|
||||||
|
|
||||||
|
|
@ -301,34 +304,35 @@ void layer_animation_next_tick(LayerSurface *l) {
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
int32_t passed_time = timespec_to_ms(&now) - l->animation.time_started;
|
uint32_t passed_time = timespec_to_ms(&now) - l->animation.time_started;
|
||||||
double animation_passed =
|
double animation_passed =
|
||||||
l->animation.duration
|
l->animation.duration
|
||||||
? (double)passed_time / (double)l->animation.duration
|
? (double)passed_time / (double)l->animation.duration
|
||||||
: 1.0;
|
: 1.0;
|
||||||
|
|
||||||
int32_t type = l->animation.action == NONE ? MOVE : l->animation.action;
|
int type = l->animation.action == NONE ? MOVE : l->animation.action;
|
||||||
double factor = find_animation_curve_at(animation_passed, type);
|
double factor = find_animation_curve_at(animation_passed, type);
|
||||||
|
|
||||||
int32_t width = l->animation.initial.width +
|
uint32_t width = l->animation.initial.width +
|
||||||
(l->current.width - l->animation.initial.width) * factor;
|
(l->current.width - l->animation.initial.width) * factor;
|
||||||
int32_t height = l->animation.initial.height +
|
uint32_t height =
|
||||||
|
l->animation.initial.height +
|
||||||
(l->current.height - l->animation.initial.height) * factor;
|
(l->current.height - l->animation.initial.height) * factor;
|
||||||
|
|
||||||
int32_t x = l->animation.initial.x +
|
uint32_t x = l->animation.initial.x +
|
||||||
(l->current.x - l->animation.initial.x) * factor;
|
(l->current.x - l->animation.initial.x) * factor;
|
||||||
int32_t y = l->animation.initial.y +
|
uint32_t y = l->animation.initial.y +
|
||||||
(l->current.y - l->animation.initial.y) * factor;
|
(l->current.y - l->animation.initial.y) * factor;
|
||||||
|
|
||||||
double opacity_eased_progress =
|
double opacity_eased_progress =
|
||||||
find_animation_curve_at(animation_passed, OPAFADEIN);
|
find_animation_curve_at(animation_passed, OPAFADEIN);
|
||||||
|
|
||||||
double opacity =
|
double opacity =
|
||||||
MIN(config.fadein_begin_opacity +
|
MIN(fadein_begin_opacity +
|
||||||
opacity_eased_progress * (1.0 - config.fadein_begin_opacity),
|
opacity_eased_progress * (1.0 - fadein_begin_opacity),
|
||||||
1.0f);
|
1.0f);
|
||||||
|
|
||||||
if (config.animation_fade_in)
|
if (animation_fade_in)
|
||||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||||
scene_buffer_apply_opacity, &opacity);
|
scene_buffer_apply_opacity, &opacity);
|
||||||
|
|
||||||
|
|
@ -344,7 +348,7 @@ void layer_animation_next_tick(LayerSurface *l) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!l->animation_type_open &&
|
if ((!l->animation_type_open &&
|
||||||
strcmp(config.layer_animation_type_open, "zoom") == 0) ||
|
strcmp(layer_animation_type_open, "zoom") == 0) ||
|
||||||
(l->animation_type_open &&
|
(l->animation_type_open &&
|
||||||
strcmp(l->animation_type_open, "zoom") == 0)) {
|
strcmp(l->animation_type_open, "zoom") == 0)) {
|
||||||
wlr_scene_node_for_each_buffer(
|
wlr_scene_node_for_each_buffer(
|
||||||
|
|
@ -367,7 +371,7 @@ void layer_animation_next_tick(LayerSurface *l) {
|
||||||
|
|
||||||
void init_fadeout_layers(LayerSurface *l) {
|
void init_fadeout_layers(LayerSurface *l) {
|
||||||
|
|
||||||
if (!config.animations || !config.layer_animations || l->noanim) {
|
if (!animations || !layer_animations || l->noanim) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,7 +381,7 @@ void init_fadeout_layers(LayerSurface *l) {
|
||||||
if ((l->animation_type_close &&
|
if ((l->animation_type_close &&
|
||||||
strcmp(l->animation_type_close, "none") == 0) ||
|
strcmp(l->animation_type_close, "none") == 0) ||
|
||||||
(!l->animation_type_close &&
|
(!l->animation_type_close &&
|
||||||
strcmp(config.layer_animation_type_close, "none") == 0)) {
|
strcmp(layer_animation_type_close, "none") == 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -400,7 +404,7 @@ void init_fadeout_layers(LayerSurface *l) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fadeout_layer->animation.duration = config.animation_duration_close;
|
fadeout_layer->animation.duration = animation_duration_close;
|
||||||
fadeout_layer->geom = fadeout_layer->current =
|
fadeout_layer->geom = fadeout_layer->current =
|
||||||
fadeout_layer->animainit_geom = fadeout_layer->animation.initial =
|
fadeout_layer->animainit_geom = fadeout_layer->animation.initial =
|
||||||
l->animation.current;
|
l->animation.current;
|
||||||
|
|
@ -416,14 +420,14 @@ void init_fadeout_layers(LayerSurface *l) {
|
||||||
fadeout_layer->animation.initial.y = 0;
|
fadeout_layer->animation.initial.y = 0;
|
||||||
|
|
||||||
if ((!l->animation_type_close &&
|
if ((!l->animation_type_close &&
|
||||||
strcmp(config.layer_animation_type_close, "zoom") == 0) ||
|
strcmp(layer_animation_type_close, "zoom") == 0) ||
|
||||||
(l->animation_type_close &&
|
(l->animation_type_close &&
|
||||||
strcmp(l->animation_type_close, "zoom") == 0)) {
|
strcmp(l->animation_type_close, "zoom") == 0)) {
|
||||||
// 算出要设置的绝对坐标和大小
|
// 算出要设置的绝对坐标和大小
|
||||||
fadeout_layer->current.width =
|
fadeout_layer->current.width =
|
||||||
(float)l->animation.current.width * config.zoom_end_ratio;
|
(float)l->animation.current.width * zoom_end_ratio;
|
||||||
fadeout_layer->current.height =
|
fadeout_layer->current.height =
|
||||||
(float)l->animation.current.height * config.zoom_end_ratio;
|
(float)l->animation.current.height * zoom_end_ratio;
|
||||||
fadeout_layer->current.x = usable_area.x + usable_area.width / 2 -
|
fadeout_layer->current.x = usable_area.x + usable_area.width / 2 -
|
||||||
fadeout_layer->current.width / 2;
|
fadeout_layer->current.width / 2;
|
||||||
fadeout_layer->current.y = usable_area.y + usable_area.height / 2 -
|
fadeout_layer->current.y = usable_area.y + usable_area.height / 2 -
|
||||||
|
|
@ -435,7 +439,7 @@ void init_fadeout_layers(LayerSurface *l) {
|
||||||
fadeout_layer->current.y - l->animation.current.y;
|
fadeout_layer->current.y - l->animation.current.y;
|
||||||
|
|
||||||
} else if ((!l->animation_type_close &&
|
} else if ((!l->animation_type_close &&
|
||||||
strcmp(config.layer_animation_type_close, "slide") == 0) ||
|
strcmp(layer_animation_type_close, "slide") == 0) ||
|
||||||
(l->animation_type_close &&
|
(l->animation_type_close &&
|
||||||
strcmp(l->animation_type_close, "slide") == 0)) {
|
strcmp(l->animation_type_close, "slide") == 0)) {
|
||||||
// 获取slide动画的结束绝对坐标和大小
|
// 获取slide动画的结束绝对坐标和大小
|
||||||
|
|
@ -463,7 +467,6 @@ void init_fadeout_layers(LayerSurface *l) {
|
||||||
wl_list_insert(&fadeout_layers, &fadeout_layer->fadeout_link);
|
wl_list_insert(&fadeout_layers, &fadeout_layer->fadeout_link);
|
||||||
|
|
||||||
// 请求刷新屏幕
|
// 请求刷新屏幕
|
||||||
if (l->mon)
|
|
||||||
wlr_output_schedule_frame(l->mon->wlr_output);
|
wlr_output_schedule_frame(l->mon->wlr_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -480,18 +483,17 @@ void layer_set_pending_state(LayerSurface *l) {
|
||||||
if (l->animation.action == OPEN && !l->animation.running) {
|
if (l->animation.action == OPEN && !l->animation.running) {
|
||||||
|
|
||||||
if ((!l->animation_type_open &&
|
if ((!l->animation_type_open &&
|
||||||
strcmp(config.layer_animation_type_open, "zoom") == 0) ||
|
strcmp(layer_animation_type_open, "zoom") == 0) ||
|
||||||
(l->animation_type_open &&
|
(l->animation_type_open &&
|
||||||
strcmp(l->animation_type_open, "zoom") == 0)) {
|
strcmp(l->animation_type_open, "zoom") == 0)) {
|
||||||
l->animainit_geom.width = l->geom.width * config.zoom_initial_ratio;
|
l->animainit_geom.width = l->geom.width * zoom_initial_ratio;
|
||||||
l->animainit_geom.height =
|
l->animainit_geom.height = l->geom.height * zoom_initial_ratio;
|
||||||
l->geom.height * config.zoom_initial_ratio;
|
|
||||||
l->animainit_geom.x = usable_area.x + usable_area.width / 2 -
|
l->animainit_geom.x = usable_area.x + usable_area.width / 2 -
|
||||||
l->animainit_geom.width / 2;
|
l->animainit_geom.width / 2;
|
||||||
l->animainit_geom.y = usable_area.y + usable_area.height / 2 -
|
l->animainit_geom.y = usable_area.y + usable_area.height / 2 -
|
||||||
l->animainit_geom.height / 2;
|
l->animainit_geom.height / 2;
|
||||||
} else if ((!l->animation_type_open &&
|
} else if ((!l->animation_type_open &&
|
||||||
strcmp(config.layer_animation_type_open, "slide") == 0) ||
|
strcmp(layer_animation_type_open, "slide") == 0) ||
|
||||||
(l->animation_type_open &&
|
(l->animation_type_open &&
|
||||||
strcmp(l->animation_type_open, "slide") == 0)) {
|
strcmp(l->animation_type_open, "slide") == 0)) {
|
||||||
|
|
||||||
|
|
@ -505,7 +507,8 @@ void layer_set_pending_state(LayerSurface *l) {
|
||||||
} else {
|
} else {
|
||||||
l->animainit_geom = l->animation.current;
|
l->animainit_geom = l->animation.current;
|
||||||
}
|
}
|
||||||
if (!config.animations || !config.layer_animations || l->noanim ||
|
// 判断是否需要动画
|
||||||
|
if (!animations || !layer_animations || l->noanim ||
|
||||||
l->layer_surface->current.layer ==
|
l->layer_surface->current.layer ==
|
||||||
ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ||
|
ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ||
|
||||||
l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) {
|
l->layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) {
|
||||||
|
|
@ -517,7 +520,7 @@ void layer_set_pending_state(LayerSurface *l) {
|
||||||
if (((l->animation_type_open &&
|
if (((l->animation_type_open &&
|
||||||
strcmp(l->animation_type_open, "none") == 0) ||
|
strcmp(l->animation_type_open, "none") == 0) ||
|
||||||
(!l->animation_type_open &&
|
(!l->animation_type_open &&
|
||||||
strcmp(config.layer_animation_type_open, "none") == 0)) &&
|
strcmp(layer_animation_type_open, "none") == 0)) &&
|
||||||
l->animation.action == OPEN) {
|
l->animation.action == OPEN) {
|
||||||
l->animation.should_animate = false;
|
l->animation.should_animate = false;
|
||||||
}
|
}
|
||||||
|
|
@ -547,7 +550,6 @@ void layer_commit(LayerSurface *l) {
|
||||||
l->animation.should_animate = false;
|
l->animation.should_animate = false;
|
||||||
}
|
}
|
||||||
// 请求刷新屏幕
|
// 请求刷新屏幕
|
||||||
if (l->mon)
|
|
||||||
wlr_output_schedule_frame(l->mon->wlr_output);
|
wlr_output_schedule_frame(l->mon->wlr_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -564,8 +566,7 @@ bool layer_draw_frame(LayerSurface *l) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.animations && config.layer_animations && l->animation.running &&
|
if (animations && layer_animations && l->animation.running && !l->noanim) {
|
||||||
!l->noanim) {
|
|
||||||
layer_animation_next_tick(l);
|
layer_animation_next_tick(l);
|
||||||
layer_draw_shadow(l);
|
layer_draw_shadow(l);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ void set_tagin_animation(Monitor *m, Client *c) {
|
||||||
|
|
||||||
if (m->pertag->curtag > m->pertag->prevtag) {
|
if (m->pertag->curtag > m->pertag->prevtag) {
|
||||||
|
|
||||||
c->animainit_geom.x = config.tag_animation_direction == VERTICAL
|
c->animainit_geom.x = tag_animation_direction == VERTICAL
|
||||||
? c->animation.current.x
|
? c->animation.current.x
|
||||||
: MAX(c->mon->m.x + c->mon->m.width,
|
: MAX(c->mon->m.x + c->mon->m.width,
|
||||||
c->geom.x + c->mon->m.width);
|
c->geom.x + c->mon->m.width);
|
||||||
c->animainit_geom.y = config.tag_animation_direction == VERTICAL
|
c->animainit_geom.y = tag_animation_direction == VERTICAL
|
||||||
? MAX(c->mon->m.y + c->mon->m.height,
|
? MAX(c->mon->m.y + c->mon->m.height,
|
||||||
c->geom.y + c->mon->m.height)
|
c->geom.y + c->mon->m.height)
|
||||||
: c->animation.current.y;
|
: c->animation.current.y;
|
||||||
|
|
@ -19,11 +19,11 @@ void set_tagin_animation(Monitor *m, Client *c) {
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
c->animainit_geom.x =
|
c->animainit_geom.x =
|
||||||
config.tag_animation_direction == VERTICAL
|
tag_animation_direction == VERTICAL
|
||||||
? c->animation.current.x
|
? c->animation.current.x
|
||||||
: MIN(m->m.x - c->geom.width, c->geom.x - c->mon->m.width);
|
: MIN(m->m.x - c->geom.width, c->geom.x - c->mon->m.width);
|
||||||
c->animainit_geom.y =
|
c->animainit_geom.y =
|
||||||
config.tag_animation_direction == VERTICAL
|
tag_animation_direction == VERTICAL
|
||||||
? MIN(m->m.y - c->geom.height, c->geom.y - c->mon->m.height)
|
? MIN(m->m.y - c->geom.height, c->geom.y - c->mon->m.height)
|
||||||
: c->animation.current.y;
|
: c->animation.current.y;
|
||||||
}
|
}
|
||||||
|
|
@ -39,8 +39,7 @@ void set_arrange_visible(Monitor *m, Client *c, bool want_animation) {
|
||||||
client_set_suspended(c, false);
|
client_set_suspended(c, false);
|
||||||
|
|
||||||
if (!c->animation.tag_from_rule && want_animation &&
|
if (!c->animation.tag_from_rule && want_animation &&
|
||||||
m->pertag->prevtag != 0 && m->pertag->curtag != 0 &&
|
m->pertag->prevtag != 0 && m->pertag->curtag != 0 && animations) {
|
||||||
config.animations) {
|
|
||||||
c->animation.tagining = true;
|
c->animation.tagining = true;
|
||||||
set_tagin_animation(m, c);
|
set_tagin_animation(m, c);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -58,10 +57,10 @@ void set_tagout_animation(Monitor *m, Client *c) {
|
||||||
if (m->pertag->curtag > m->pertag->prevtag) {
|
if (m->pertag->curtag > m->pertag->prevtag) {
|
||||||
c->pending = c->geom;
|
c->pending = c->geom;
|
||||||
c->pending.x =
|
c->pending.x =
|
||||||
config.tag_animation_direction == VERTICAL
|
tag_animation_direction == VERTICAL
|
||||||
? c->animation.current.x
|
? c->animation.current.x
|
||||||
: MIN(c->mon->m.x - c->geom.width, c->geom.x - c->mon->m.width);
|
: MIN(c->mon->m.x - c->geom.width, c->geom.x - c->mon->m.width);
|
||||||
c->pending.y = config.tag_animation_direction == VERTICAL
|
c->pending.y = tag_animation_direction == VERTICAL
|
||||||
? MIN(c->mon->m.y - c->geom.height,
|
? MIN(c->mon->m.y - c->geom.height,
|
||||||
c->geom.y - c->mon->m.height)
|
c->geom.y - c->mon->m.height)
|
||||||
: c->animation.current.y;
|
: c->animation.current.y;
|
||||||
|
|
@ -69,11 +68,11 @@ void set_tagout_animation(Monitor *m, Client *c) {
|
||||||
resize(c, c->geom, 0);
|
resize(c, c->geom, 0);
|
||||||
} else {
|
} else {
|
||||||
c->pending = c->geom;
|
c->pending = c->geom;
|
||||||
c->pending.x = config.tag_animation_direction == VERTICAL
|
c->pending.x = tag_animation_direction == VERTICAL
|
||||||
? c->animation.current.x
|
? c->animation.current.x
|
||||||
: MAX(c->mon->m.x + c->mon->m.width,
|
: MAX(c->mon->m.x + c->mon->m.width,
|
||||||
c->geom.x + c->mon->m.width);
|
c->geom.x + c->mon->m.width);
|
||||||
c->pending.y = config.tag_animation_direction == VERTICAL
|
c->pending.y = tag_animation_direction == VERTICAL
|
||||||
? MAX(c->mon->m.y + c->mon->m.height,
|
? MAX(c->mon->m.y + c->mon->m.height,
|
||||||
c->geom.y + c->mon->m.height)
|
c->geom.y + c->mon->m.height)
|
||||||
: c->animation.current.y;
|
: c->animation.current.y;
|
||||||
|
|
@ -83,8 +82,7 @@ void set_tagout_animation(Monitor *m, Client *c) {
|
||||||
|
|
||||||
void set_arrange_hidden(Monitor *m, Client *c, bool want_animation) {
|
void set_arrange_hidden(Monitor *m, Client *c, bool want_animation) {
|
||||||
if ((c->tags & (1 << (m->pertag->prevtag - 1))) &&
|
if ((c->tags & (1 << (m->pertag->prevtag - 1))) &&
|
||||||
m->pertag->prevtag != 0 && m->pertag->curtag != 0 &&
|
m->pertag->prevtag != 0 && m->pertag->curtag != 0 && animations) {
|
||||||
config.animations) {
|
|
||||||
c->animation.tagouting = true;
|
c->animation.tagouting = true;
|
||||||
c->animation.tagining = false;
|
c->animation.tagining = false;
|
||||||
set_tagout_animation(m, c);
|
set_tagout_animation(m, c);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Leave these functions first; they're used in the others */
|
/* Leave these functions first; they're used in the others */
|
||||||
static inline int32_t client_is_x11(Client *c) {
|
static inline int client_is_x11(Client *c) {
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
return c->type == X11;
|
return c->type == X11;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -21,15 +21,14 @@ static inline struct wlr_surface *client_surface(Client *c) {
|
||||||
return c->surface.xdg->surface;
|
return c->surface.xdg->surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t toplevel_from_wlr_surface(struct wlr_surface *s,
|
static inline int toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc,
|
||||||
Client **pc,
|
|
||||||
LayerSurface **pl) {
|
LayerSurface **pl) {
|
||||||
struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface;
|
struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface;
|
||||||
struct wlr_surface *root_surface;
|
struct wlr_surface *root_surface;
|
||||||
struct wlr_layer_surface_v1 *layer_surface;
|
struct wlr_layer_surface_v1 *layer_surface;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
LayerSurface *l = NULL;
|
LayerSurface *l = NULL;
|
||||||
int32_t type = -1;
|
int type = -1;
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
struct wlr_xwayland_surface *xsurface;
|
struct wlr_xwayland_surface *xsurface;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -89,7 +88,7 @@ end:
|
||||||
|
|
||||||
/* The others */
|
/* The others */
|
||||||
static inline void client_activate_surface(struct wlr_surface *s,
|
static inline void client_activate_surface(struct wlr_surface *s,
|
||||||
int32_t activated) {
|
int activated) {
|
||||||
struct wlr_xdg_toplevel *toplevel;
|
struct wlr_xdg_toplevel *toplevel;
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
struct wlr_xwayland_surface *xsurface;
|
struct wlr_xwayland_surface *xsurface;
|
||||||
|
|
@ -114,7 +113,7 @@ static inline const char *client_get_appid(Client *c) {
|
||||||
: "broken";
|
: "broken";
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_get_pid(Client *c) {
|
static inline int client_get_pid(Client *c) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c))
|
if (client_is_x11(c))
|
||||||
|
|
@ -128,8 +127,8 @@ static inline void client_get_clip(Client *c, struct wlr_box *clip) {
|
||||||
*clip = (struct wlr_box){
|
*clip = (struct wlr_box){
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = 0,
|
.y = 0,
|
||||||
.width = c->geom.width - 2 * c->bw,
|
.width = c->geom.width - c->bw,
|
||||||
.height = c->geom.height - 2 * c->bw,
|
.height = c->geom.height - c->bw,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
|
|
@ -170,7 +169,7 @@ static inline Client *client_get_parent(Client *c) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_has_children(Client *c) {
|
static inline int client_has_children(Client *c) {
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c))
|
if (client_is_x11(c))
|
||||||
return !wl_list_empty(&c->surface.xwayland->children);
|
return !wl_list_empty(&c->surface.xwayland->children);
|
||||||
|
|
@ -190,7 +189,7 @@ static inline const char *client_get_title(Client *c) {
|
||||||
: "broken";
|
: "broken";
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_is_float_type(Client *c) {
|
static inline int client_is_float_type(Client *c) {
|
||||||
struct wlr_xdg_toplevel *toplevel;
|
struct wlr_xdg_toplevel *toplevel;
|
||||||
struct wlr_xdg_toplevel_state state;
|
struct wlr_xdg_toplevel_state state;
|
||||||
|
|
||||||
|
|
@ -230,12 +229,12 @@ static inline int32_t client_is_float_type(Client *c) {
|
||||||
state.min_height == state.max_height));
|
state.min_height == state.max_height));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_is_rendered_on_mon(Client *c, Monitor *m) {
|
static inline int client_is_rendered_on_mon(Client *c, Monitor *m) {
|
||||||
/* This is needed for when you don't want to check formal assignment,
|
/* This is needed for when you don't want to check formal assignment,
|
||||||
* but rather actual displaying of the pixels.
|
* but rather actual displaying of the pixels.
|
||||||
* Usually VISIBLEON suffices and is also faster. */
|
* Usually VISIBLEON suffices and is also faster. */
|
||||||
struct wlr_surface_output *s;
|
struct wlr_surface_output *s;
|
||||||
int32_t unused_lx, unused_ly;
|
int unused_lx, unused_ly;
|
||||||
if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly))
|
if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly))
|
||||||
return 0;
|
return 0;
|
||||||
wl_list_for_each(s, &client_surface(c)->current_outputs,
|
wl_list_for_each(s, &client_surface(c)->current_outputs,
|
||||||
|
|
@ -243,7 +242,32 @@ static inline int32_t client_is_rendered_on_mon(Client *c, Monitor *m) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_is_unmanaged(Client *c) {
|
static inline int client_is_stopped(Client *c) {
|
||||||
|
int pid;
|
||||||
|
siginfo_t in = {0};
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);
|
||||||
|
if (waitid(P_PID, pid, &in, WNOHANG | WCONTINUED | WSTOPPED | WNOWAIT) <
|
||||||
|
0) {
|
||||||
|
/* This process is not our child process, while is very unluckely that
|
||||||
|
* it is stopped, in order to do not skip frames assume that it is. */
|
||||||
|
if (errno == ECHILD)
|
||||||
|
return 1;
|
||||||
|
} else if (in.si_pid) {
|
||||||
|
if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED)
|
||||||
|
return 1;
|
||||||
|
if (in.si_code == CLD_CONTINUED)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int client_is_unmanaged(Client *c) {
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c))
|
if (client_is_x11(c))
|
||||||
return c->surface.xwayland->override_redirect;
|
return c->surface.xwayland->override_redirect;
|
||||||
|
|
@ -275,7 +299,7 @@ static inline void client_set_border_color(Client *c,
|
||||||
wlr_scene_rect_set_color(c->border, color);
|
wlr_scene_rect_set_color(c->border, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void client_set_fullscreen(Client *c, int32_t fullscreen) {
|
static inline void client_set_fullscreen(Client *c, int fullscreen) {
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c)) {
|
if (client_is_x11(c)) {
|
||||||
wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen);
|
wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen);
|
||||||
|
|
@ -294,24 +318,9 @@ 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 1;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((int32_t)width == c->surface.xdg->toplevel->current.width &&
|
if ((int32_t)width == c->surface.xdg->toplevel->current.width &&
|
||||||
|
|
@ -370,7 +379,7 @@ static inline void client_set_tiled(Client *c, uint32_t edges) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void client_set_suspended(Client *c, int32_t suspended) {
|
static inline void client_set_suspended(Client *c, int suspended) {
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c))
|
if (client_is_x11(c))
|
||||||
return;
|
return;
|
||||||
|
|
@ -379,7 +388,7 @@ static inline void client_set_suspended(Client *c, int32_t suspended) {
|
||||||
wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended);
|
wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_should_ignore_focus(Client *c) {
|
static inline int client_should_ignore_focus(Client *c) {
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c)) {
|
if (client_is_x11(c)) {
|
||||||
|
|
@ -394,7 +403,7 @@ static inline int32_t client_should_ignore_focus(Client *c) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_is_x11_popup(Client *c) {
|
static inline int client_is_x11_popup(Client *c) {
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c)) {
|
if (client_is_x11(c)) {
|
||||||
|
|
@ -423,7 +432,7 @@ static inline int32_t client_is_x11_popup(Client *c) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_should_global(Client *c) {
|
static inline int client_should_global(Client *c) {
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c)) {
|
if (client_is_x11(c)) {
|
||||||
|
|
@ -436,7 +445,7 @@ static inline int32_t client_should_global(Client *c) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_should_overtop(Client *c) {
|
static inline int client_should_overtop(Client *c) {
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c)) {
|
if (client_is_x11(c)) {
|
||||||
|
|
@ -448,7 +457,7 @@ static inline int32_t client_should_overtop(Client *c) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_wants_focus(Client *c) {
|
static inline int client_wants_focus(Client *c) {
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
return client_is_unmanaged(c) &&
|
return client_is_unmanaged(c) &&
|
||||||
wlr_xwayland_surface_override_redirect_wants_focus(
|
wlr_xwayland_surface_override_redirect_wants_focus(
|
||||||
|
|
@ -459,7 +468,7 @@ static inline int32_t client_wants_focus(Client *c) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t client_wants_fullscreen(Client *c) {
|
static inline int client_wants_fullscreen(Client *c) {
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
if (client_is_x11(c))
|
if (client_is_x11(c))
|
||||||
return c->surface.xwayland->fullscreen;
|
return c->surface.xwayland->fullscreen;
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@ void *ecalloc(size_t nmemb, size_t size) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t fd_set_nonblock(int32_t fd) {
|
int fd_set_nonblock(int fd) {
|
||||||
int32_t flags = fcntl(fd, F_GETFL);
|
int flags = fcntl(fd, F_GETFL);
|
||||||
if (flags < 0) {
|
if (flags < 0) {
|
||||||
perror("fcntl(F_GETFL):");
|
perror("fcntl(F_GETFL):");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -50,8 +50,8 @@ int32_t fd_set_nonblock(int32_t fd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t regex_match(const char *pattern, const char *str) {
|
int regex_match(const char *pattern, const char *str) {
|
||||||
int32_t errnum;
|
int errnum;
|
||||||
PCRE2_SIZE erroffset;
|
PCRE2_SIZE erroffset;
|
||||||
|
|
||||||
if (!pattern || !str) {
|
if (!pattern || !str) {
|
||||||
|
|
@ -70,7 +70,7 @@ int32_t regex_match(const char *pattern, const char *str) {
|
||||||
|
|
||||||
pcre2_match_data *match_data =
|
pcre2_match_data *match_data =
|
||||||
pcre2_match_data_create_from_pattern(re, NULL);
|
pcre2_match_data_create_from_pattern(re, NULL);
|
||||||
int32_t ret =
|
int ret =
|
||||||
pcre2_match(re, (PCRE2_SPTR)str, strlen(str), 0, 0, match_data, NULL);
|
pcre2_match(re, (PCRE2_SPTR)str, strlen(str), 0, 0, match_data, NULL);
|
||||||
|
|
||||||
pcre2_match_data_free(match_data);
|
pcre2_match_data_free(match_data);
|
||||||
|
|
@ -92,85 +92,3 @@ uint32_t get_now_in_ms(void) {
|
||||||
uint32_t timespec_to_ms(struct timespec *ts) {
|
uint32_t timespec_to_ms(struct timespec *ts) {
|
||||||
return (uint32_t)ts->tv_sec * 1000 + (uint32_t)ts->tv_nsec / 1000000;
|
return (uint32_t)ts->tv_sec * 1000 + (uint32_t)ts->tv_nsec / 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *join_strings(char *arr[], const char *sep) {
|
|
||||||
if (!arr || !arr[0]) {
|
|
||||||
char *empty = malloc(1);
|
|
||||||
if (empty)
|
|
||||||
empty[0] = '\0';
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t total_len = 0;
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; arr[i] != NULL; i++) {
|
|
||||||
total_len += strlen(arr[i]);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
if (count > 0) {
|
|
||||||
total_len += strlen(sep) * (count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *result = malloc(total_len + 1);
|
|
||||||
if (!result)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
result[0] = '\0';
|
|
||||||
for (int i = 0; arr[i] != NULL; i++) {
|
|
||||||
if (i > 0)
|
|
||||||
strcat(result, sep);
|
|
||||||
strcat(result, arr[i]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *join_strings_with_suffix(char *arr[], const char *suffix,
|
|
||||||
const char *sep) {
|
|
||||||
if (!arr || !arr[0]) {
|
|
||||||
char *empty = malloc(1);
|
|
||||||
if (empty)
|
|
||||||
empty[0] = '\0';
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t total_len = 0;
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; arr[i] != NULL; i++) {
|
|
||||||
total_len += strlen(arr[i]) + strlen(suffix);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
if (count > 0) {
|
|
||||||
total_len += strlen(sep) * (count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *result = malloc(total_len + 1);
|
|
||||||
if (!result)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
result[0] = '\0';
|
|
||||||
for (int i = 0; arr[i] != NULL; i++) {
|
|
||||||
if (i > 0)
|
|
||||||
strcat(result, sep);
|
|
||||||
strcat(result, arr[i]);
|
|
||||||
strcat(result, suffix);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *string_printf(const char *fmt, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
int len = vsnprintf(NULL, 0, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
if (len < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
char *str = malloc(len + 1);
|
|
||||||
if (!str)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsnprintf(str, len + 1, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,8 @@
|
||||||
|
|
||||||
void die(const char *fmt, ...);
|
void die(const char *fmt, ...);
|
||||||
void *ecalloc(size_t nmemb, size_t size);
|
void *ecalloc(size_t nmemb, size_t size);
|
||||||
int32_t fd_set_nonblock(int32_t fd);
|
int fd_set_nonblock(int fd);
|
||||||
int32_t regex_match(const char *pattern_mb, const char *str_mb);
|
int regex_match(const char *pattern_mb, const char *str_mb);
|
||||||
void wl_list_append(struct wl_list *list, struct wl_list *object);
|
void wl_list_append(struct wl_list *list, struct wl_list *object);
|
||||||
uint32_t get_now_in_ms(void);
|
uint32_t get_now_in_ms(void);
|
||||||
uint32_t timespec_to_ms(struct timespec *ts);
|
uint32_t timespec_to_ms(struct timespec *ts);
|
||||||
char *join_strings(char *arr[], const char *sep);
|
|
||||||
char *join_strings_with_suffix(char *arr[], const char *suffix,
|
|
||||||
const char *sep);
|
|
||||||
char *string_printf(const char *fmt, ...);
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,128 @@
|
||||||
#define MODKEY WLR_MODIFIER_ALT
|
// TODO: remove this file in the future, replace all global variables with
|
||||||
|
// config.xxx
|
||||||
|
|
||||||
static const char *tags[] = {
|
/* speedie's mango config */
|
||||||
"1", "2", "3", "4", "5", "6", "7", "8", "9",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
#define COLOR(hex) \
|
||||||
|
{((hex >> 24) & 0xFF) / 255.0f, ((hex >> 16) & 0xFF) / 255.0f, \
|
||||||
|
((hex >> 8) & 0xFF) / 255.0f, (hex & 0xFF) / 255.0f}
|
||||||
|
|
||||||
|
/* animaion */
|
||||||
|
char *animation_type_open = "slide"; // 是否启用动画 //slide,zoom
|
||||||
|
char *animation_type_close = "slide"; // 是否启用动画 //slide,zoom
|
||||||
|
char *layer_animation_type_open = "slide"; // 是否启用layer动画 //slide,zoom
|
||||||
|
char *layer_animation_type_close = "slide"; // 是否启用layer动画 //slide,zoom
|
||||||
|
int animations = 1; // 是否启用动画
|
||||||
|
int layer_animations = 0; // 是否启用layer动画
|
||||||
|
int tag_animation_direction = HORIZONTAL; // 标签动画方向
|
||||||
|
int animation_fade_in = 1; // Enable animation fade in
|
||||||
|
int animation_fade_out = 1; // Enable animation fade out
|
||||||
|
float zoom_initial_ratio = 0.3; // 动画起始窗口比例
|
||||||
|
float zoom_end_ratio = 0.8; // 动画结束窗口比例
|
||||||
|
float fadein_begin_opacity = 0.5; // Begin opac window ratio for animations
|
||||||
|
float fadeout_begin_opacity = 0.5; // Begin opac window ratio for animations
|
||||||
|
uint32_t animation_duration_move = 500; // Animation move speed
|
||||||
|
uint32_t animation_duration_open = 400; // Animation open speed
|
||||||
|
uint32_t animation_duration_tag = 300; // Animation tag speed
|
||||||
|
uint32_t animation_duration_close = 300; // Animation close speed
|
||||||
|
uint32_t animation_duration_focus = 0; // Animation focus opacity speed
|
||||||
|
double animation_curve_move[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||||
|
double animation_curve_open[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||||
|
double animation_curve_tag[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||||
|
double animation_curve_close[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||||
|
double animation_curve_focus[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||||
|
double animation_curve_opafadein[4] = {0.46, 1.0, 0.29, 0.99}; // 动画曲线
|
||||||
|
double animation_curve_opafadeout[4] = {0.5, 0.5, 0.5, 0.5}; // 动画曲线
|
||||||
|
|
||||||
|
/* appearance */
|
||||||
|
uint32_t axis_bind_apply_timeout = 100; // 滚轮绑定动作的触发的时间间隔
|
||||||
|
uint32_t focus_on_activate = 1; // 收到窗口激活请求是否自动跳转聚焦
|
||||||
|
uint32_t new_is_master = 1; // 新窗口是否插在头部
|
||||||
|
double default_mfact = 0.55f; // master 窗口比例
|
||||||
|
uint32_t default_nmaster = 1; // 默认master数量
|
||||||
|
int center_master_overspread = 0; // 中心master时是否铺满
|
||||||
|
int center_when_single_stack = 1; // 单个stack时是否居中
|
||||||
|
/* logging */
|
||||||
|
int log_level = WLR_ERROR;
|
||||||
|
uint32_t numlockon = 0; // 是否打开右边小键盘
|
||||||
|
uint32_t capslock = 0; // 是否启用快捷键
|
||||||
|
|
||||||
|
uint32_t ov_tab_mode = 0; // alt tab切换模式
|
||||||
|
uint32_t hotarea_size = 10; // 热区大小,10x10
|
||||||
|
uint32_t enable_hotarea = 1; // 是否启用鼠标热区
|
||||||
|
int smartgaps = 0; /* 1 means no outer gap when there is only one window */
|
||||||
|
int sloppyfocus = 1; /* focus follows mouse */
|
||||||
|
uint32_t gappih = 5; /* horiz inner gap between windows */
|
||||||
|
uint32_t gappiv = 5; /* vert inner gap between windows */
|
||||||
|
uint32_t gappoh = 10; /* horiz outer gap between windows and screen edge */
|
||||||
|
uint32_t gappov = 10; /* vert outer gap between windows and screen edge */
|
||||||
|
float scratchpad_width_ratio = 0.8;
|
||||||
|
float scratchpad_height_ratio = 0.9;
|
||||||
|
|
||||||
|
int scroller_structs = 20;
|
||||||
|
float scroller_default_proportion = 0.9;
|
||||||
|
float scroller_default_proportion_single = 1.0;
|
||||||
|
int scroller_ignore_proportion_single = 0;
|
||||||
|
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;
|
||||||
|
int enable_floating_snap = 0;
|
||||||
|
int drag_tile_to_tile = 0;
|
||||||
|
uint32_t cursor_size = 24;
|
||||||
|
uint32_t cursor_hide_timeout = 0;
|
||||||
|
|
||||||
|
uint32_t swipe_min_threshold = 1;
|
||||||
|
|
||||||
|
int inhibit_regardless_of_visibility =
|
||||||
|
0; /* 1 means idle inhibitors will disable idle tracking even if it's
|
||||||
|
surface isn't visible */
|
||||||
|
uint32_t borderpx = 4; /* border pixel of windows */
|
||||||
|
float rootcolor[] = COLOR(0x323232ff);
|
||||||
|
float bordercolor[] = COLOR(0x444444ff);
|
||||||
|
float focuscolor[] = COLOR(0xc66b25ff);
|
||||||
|
float maximizescreencolor[] = COLOR(0x89aa61ff);
|
||||||
|
float urgentcolor[] = COLOR(0xad401fff);
|
||||||
|
float scratchpadcolor[] = COLOR(0x516c93ff);
|
||||||
|
float globalcolor[] = COLOR(0xb153a7ff);
|
||||||
|
float overlaycolor[] = COLOR(0x14a57cff);
|
||||||
|
// char *cursor_theme = "Bibata-Modern-Ice";
|
||||||
|
|
||||||
|
int overviewgappi = 5; /* overview时 窗口与边缘 缝隙大小 */
|
||||||
|
int overviewgappo = 30; /* overview时 窗口与窗口 缝隙大小 */
|
||||||
|
|
||||||
|
/* To conform the xdg-protocol, set the alpha to zero to restore the old
|
||||||
|
* behavior */
|
||||||
|
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;
|
||||||
|
int allow_lock_transparent = 0;
|
||||||
|
double drag_refresh_interval = 30.0;
|
||||||
|
int allow_tearing = TEARING_DISABLED;
|
||||||
|
int allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
|
||||||
|
|
||||||
|
/* keyboard */
|
||||||
|
|
||||||
|
/*
|
||||||
|
only layout can modify after fisrt init
|
||||||
|
other fields change will be ignored.
|
||||||
|
*/
|
||||||
|
char xkb_rules_rules[256];
|
||||||
|
char xkb_rules_model[256];
|
||||||
|
char xkb_rules_layout[256];
|
||||||
|
char xkb_rules_variant[256];
|
||||||
|
char xkb_rules_options[256];
|
||||||
|
|
||||||
|
/* keyboard */
|
||||||
static const struct xkb_rule_names xkb_fallback_rules = {
|
static const struct xkb_rule_names xkb_fallback_rules = {
|
||||||
.layout = "us",
|
.layout = "us",
|
||||||
.variant = NULL,
|
.variant = NULL,
|
||||||
|
|
@ -11,3 +130,105 @@ static const struct xkb_rule_names xkb_fallback_rules = {
|
||||||
.rules = NULL,
|
.rules = NULL,
|
||||||
.options = NULL,
|
.options = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct xkb_rule_names xkb_default_rules = {
|
||||||
|
.options = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct xkb_rule_names xkb_rules = {
|
||||||
|
/* can specify fields: rules, model, layout, variant, options */
|
||||||
|
/* example:
|
||||||
|
.options = "ctrl:nocaps",
|
||||||
|
*/
|
||||||
|
.rules = xkb_rules_rules, .model = xkb_rules_model,
|
||||||
|
.layout = xkb_rules_layout, .variant = xkb_rules_variant,
|
||||||
|
.options = xkb_rules_options,
|
||||||
|
};
|
||||||
|
|
||||||
|
int repeat_rate = 25;
|
||||||
|
int repeat_delay = 600;
|
||||||
|
|
||||||
|
/* Trackpad */
|
||||||
|
int disable_trackpad = 0;
|
||||||
|
int tap_to_click = 1;
|
||||||
|
int tap_and_drag = 1;
|
||||||
|
int drag_lock = 1;
|
||||||
|
int mouse_natural_scrolling = 0;
|
||||||
|
int trackpad_natural_scrolling = 0;
|
||||||
|
int disable_while_typing = 1;
|
||||||
|
int left_handed = 0;
|
||||||
|
int middle_button_emulation = 0;
|
||||||
|
int single_scratchpad = 1;
|
||||||
|
int edge_scroller_pointer_focus = 1;
|
||||||
|
|
||||||
|
/* You can choose between:
|
||||||
|
LIBINPUT_CONFIG_SCROLL_NO_SCROLL
|
||||||
|
LIBINPUT_CONFIG_SCROLL_2FG
|
||||||
|
LIBINPUT_CONFIG_SCROLL_EDGE
|
||||||
|
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN
|
||||||
|
*/
|
||||||
|
enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
|
||||||
|
uint32_t scroll_button = 274;
|
||||||
|
|
||||||
|
/* You can choose between:
|
||||||
|
LIBINPUT_CONFIG_CLICK_METHOD_NONE
|
||||||
|
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS
|
||||||
|
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER
|
||||||
|
*/
|
||||||
|
enum libinput_config_click_method click_method =
|
||||||
|
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||||
|
|
||||||
|
/* You can choose between:
|
||||||
|
LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
|
||||||
|
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED
|
||||||
|
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE
|
||||||
|
*/
|
||||||
|
uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
|
||||||
|
|
||||||
|
/* You can choose between:
|
||||||
|
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT
|
||||||
|
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE
|
||||||
|
*/
|
||||||
|
enum libinput_config_accel_profile accel_profile =
|
||||||
|
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
|
||||||
|
double accel_speed = 0.0;
|
||||||
|
/* You can choose between:
|
||||||
|
LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle
|
||||||
|
LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right
|
||||||
|
*/
|
||||||
|
enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
|
||||||
|
|
||||||
|
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
|
||||||
|
#define MODKEY WLR_MODIFIER_ALT
|
||||||
|
|
||||||
|
static const char *tags[] = {
|
||||||
|
"1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
|
};
|
||||||
|
|
||||||
|
float focused_opacity = 1.0;
|
||||||
|
float unfocused_opacity = 1.0;
|
||||||
|
|
||||||
|
int border_radius = 0;
|
||||||
|
int border_radius_location_default = CORNER_LOCATION_ALL;
|
||||||
|
int blur = 0;
|
||||||
|
int blur_layer = 0;
|
||||||
|
int blur_optimized = 1;
|
||||||
|
|
||||||
|
struct blur_data blur_params;
|
||||||
|
|
||||||
|
int blur_params_num_passes = 1;
|
||||||
|
int blur_params_radius = 5;
|
||||||
|
float blur_params_noise = 0.02;
|
||||||
|
float blur_params_brightness = 0.9;
|
||||||
|
float blur_params_contrast = 0.9;
|
||||||
|
float blur_params_saturation = 1.2;
|
||||||
|
|
||||||
|
int shadows = 0;
|
||||||
|
int shadow_only_floating = 1;
|
||||||
|
int layer_shadows = 0;
|
||||||
|
uint32_t shadows_size = 10;
|
||||||
|
double shadows_blur = 15;
|
||||||
|
int shadows_position_x = 0;
|
||||||
|
int shadows_position_y = 0;
|
||||||
|
float shadowscolor[] = COLOR(0x000000ff);
|
||||||
|
;
|
||||||
|
|
|
||||||
|
|
@ -1,72 +1,71 @@
|
||||||
int32_t minimized(const Arg *arg);
|
int minimized(const Arg *arg);
|
||||||
int32_t restore_minimized(const Arg *arg);
|
int restore_minimized(const Arg *arg);
|
||||||
int32_t toggle_scratchpad(const Arg *arg);
|
int toggle_scratchpad(const Arg *arg);
|
||||||
int32_t focusdir(const Arg *arg);
|
int focusdir(const Arg *arg);
|
||||||
int32_t toggleoverview(const Arg *arg);
|
int toggleoverview(const Arg *arg);
|
||||||
int32_t set_proportion(const Arg *arg);
|
int set_proportion(const Arg *arg);
|
||||||
int32_t switch_proportion_preset(const Arg *arg);
|
int switch_proportion_preset(const Arg *arg);
|
||||||
int32_t zoom(const Arg *arg);
|
int zoom(const Arg *arg);
|
||||||
int32_t tagsilent(const Arg *arg);
|
int tagsilent(const Arg *arg);
|
||||||
int32_t tagtoleft(const Arg *arg);
|
int tagtoleft(const Arg *arg);
|
||||||
int32_t tagtoright(const Arg *arg);
|
int tagtoright(const Arg *arg);
|
||||||
int32_t tagcrossmon(const Arg *arg);
|
int tagcrossmon(const Arg *arg);
|
||||||
int32_t viewtoleft(const Arg *arg);
|
int viewtoleft(const Arg *arg);
|
||||||
int32_t viewtoright(const Arg *arg);
|
int viewtoright(const Arg *arg);
|
||||||
int32_t viewtoleft_have_client(const Arg *arg);
|
int viewtoleft_have_client(const Arg *arg);
|
||||||
int32_t viewtoright_have_client(const Arg *arg);
|
int viewtoright_have_client(const Arg *arg);
|
||||||
int32_t viewcrossmon(const Arg *arg);
|
int viewcrossmon(const Arg *arg);
|
||||||
int32_t togglefloating(const Arg *arg);
|
int togglefloating(const Arg *arg);
|
||||||
int32_t togglefullscreen(const Arg *arg);
|
int togglefullscreen(const Arg *arg);
|
||||||
int32_t togglemaximizescreen(const Arg *arg);
|
int togglemaximizescreen(const Arg *arg);
|
||||||
int32_t togglegaps(const Arg *arg);
|
int togglegaps(const Arg *arg);
|
||||||
int32_t tagmon(const Arg *arg);
|
int tagmon(const Arg *arg);
|
||||||
int32_t spawn(const Arg *arg);
|
int spawn(const Arg *arg);
|
||||||
int32_t spawn_shell(const Arg *arg);
|
int spawn_shell(const Arg *arg);
|
||||||
int32_t spawn_on_empty(const Arg *arg);
|
int spawn_on_empty(const Arg *arg);
|
||||||
int32_t setkeymode(const Arg *arg);
|
int setkeymode(const Arg *arg);
|
||||||
int32_t switch_keyboard_layout(const Arg *arg);
|
int switch_keyboard_layout(const Arg *arg);
|
||||||
int32_t setlayout(const Arg *arg);
|
int setlayout(const Arg *arg);
|
||||||
int32_t switch_layout(const Arg *arg);
|
int switch_layout(const Arg *arg);
|
||||||
int32_t setmfact(const Arg *arg);
|
int setmfact(const Arg *arg);
|
||||||
int32_t quit(const Arg *arg);
|
int quit(const Arg *arg);
|
||||||
int32_t moveresize(const Arg *arg);
|
int moveresize(const Arg *arg);
|
||||||
int32_t exchange_client(const Arg *arg);
|
int exchange_client(const Arg *arg);
|
||||||
int32_t exchange_stack_client(const Arg *arg);
|
int exchange_stack_client(const Arg *arg);
|
||||||
int32_t killclient(const Arg *arg);
|
int killclient(const Arg *arg);
|
||||||
int32_t toggleglobal(const Arg *arg);
|
int toggleglobal(const Arg *arg);
|
||||||
int32_t incnmaster(const Arg *arg);
|
int incnmaster(const Arg *arg);
|
||||||
int32_t focusmon(const Arg *arg);
|
int focusmon(const Arg *arg);
|
||||||
int32_t focusstack(const Arg *arg);
|
int focusstack(const Arg *arg);
|
||||||
int32_t chvt(const Arg *arg);
|
int chvt(const Arg *arg);
|
||||||
int32_t reload_config(const Arg *arg);
|
int reload_config(const Arg *arg);
|
||||||
int32_t smartmovewin(const Arg *arg);
|
int smartmovewin(const Arg *arg);
|
||||||
int32_t smartresizewin(const Arg *arg);
|
int smartresizewin(const Arg *arg);
|
||||||
int32_t centerwin(const Arg *arg);
|
int centerwin(const Arg *arg);
|
||||||
int32_t bind_to_view(const Arg *arg);
|
int bind_to_view(const Arg *arg);
|
||||||
int32_t toggletag(const Arg *arg);
|
int toggletag(const Arg *arg);
|
||||||
int32_t toggleview(const Arg *arg);
|
int toggleview(const Arg *arg);
|
||||||
int32_t tag(const Arg *arg);
|
int tag(const Arg *arg);
|
||||||
int32_t comboview(const Arg *arg);
|
int comboview(const Arg *arg);
|
||||||
int32_t incgaps(const Arg *arg);
|
int incgaps(const Arg *arg);
|
||||||
int32_t incigaps(const Arg *arg);
|
int incigaps(const Arg *arg);
|
||||||
int32_t incihgaps(const Arg *arg);
|
int incihgaps(const Arg *arg);
|
||||||
int32_t incivgaps(const Arg *arg);
|
int incivgaps(const Arg *arg);
|
||||||
int32_t incogaps(const Arg *arg);
|
int incogaps(const Arg *arg);
|
||||||
int32_t incohgaps(const Arg *arg);
|
int incohgaps(const Arg *arg);
|
||||||
int32_t incovgaps(const Arg *arg);
|
int incovgaps(const Arg *arg);
|
||||||
int32_t defaultgaps(const Arg *arg);
|
int defaultgaps(const Arg *arg);
|
||||||
int32_t togglefakefullscreen(const Arg *arg);
|
int togglefakefullscreen(const Arg *arg);
|
||||||
int32_t toggleoverlay(const Arg *arg);
|
int toggleoverlay(const Arg *arg);
|
||||||
int32_t movewin(const Arg *arg);
|
int movewin(const Arg *arg);
|
||||||
int32_t resizewin(const Arg *arg);
|
int resizewin(const Arg *arg);
|
||||||
int32_t toggle_named_scratchpad(const Arg *arg);
|
int toggle_named_scratchpad(const Arg *arg);
|
||||||
int32_t toggle_render_border(const Arg *arg);
|
int toggle_render_border(const Arg *arg);
|
||||||
int32_t create_virtual_output(const Arg *arg);
|
int create_virtual_output(const Arg *arg);
|
||||||
int32_t destroy_all_virtual_output(const Arg *arg);
|
int destroy_all_virtual_output(const Arg *arg);
|
||||||
int32_t focuslast(const Arg *arg);
|
int focuslast(const Arg *arg);
|
||||||
int32_t toggle_trackpad_enable(const Arg *arg);
|
int toggle_trackpad_enable(const Arg *arg);
|
||||||
int32_t setoption(const Arg *arg);
|
int setoption(const Arg *arg);
|
||||||
int32_t disable_monitor(const Arg *arg);
|
int disable_monitor(const Arg *arg);
|
||||||
int32_t enable_monitor(const Arg *arg);
|
int enable_monitor(const Arg *arg);
|
||||||
int32_t toggle_monitor(const Arg *arg);
|
int toggle_monitor(const Arg *arg);
|
||||||
int32_t scroller_stack(const Arg *arg);
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -112,7 +112,7 @@ void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) {
|
||||||
Client *c = NULL, *focused = NULL;
|
Client *c = NULL, *focused = NULL;
|
||||||
struct wlr_keyboard *keyboard;
|
struct wlr_keyboard *keyboard;
|
||||||
xkb_layout_index_t current;
|
xkb_layout_index_t current;
|
||||||
int32_t tagmask, state, numclients, focused_client, tag;
|
int tagmask, state, numclients, focused_client, tag;
|
||||||
const char *title, *appid, *symbol;
|
const char *title, *appid, *symbol;
|
||||||
char kb_layout[32];
|
char kb_layout[32];
|
||||||
focused = focustop(monitor);
|
focused = focustop(monitor);
|
||||||
|
|
@ -238,7 +238,7 @@ void dwl_ipc_output_set_client_tags(struct wl_client *client,
|
||||||
selected_client->tags = newtags;
|
selected_client->tags = newtags;
|
||||||
if (selmon == monitor)
|
if (selmon == monitor)
|
||||||
focusclient(focustop(monitor), 1);
|
focusclient(focustop(monitor), 1);
|
||||||
arrange(selmon, false, false);
|
arrange(selmon, false);
|
||||||
printstatus();
|
printstatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,7 +257,7 @@ void dwl_ipc_output_set_layout(struct wl_client *client,
|
||||||
|
|
||||||
monitor->pertag->ltidxs[monitor->pertag->curtag] = &layouts[index];
|
monitor->pertag->ltidxs[monitor->pertag->curtag] = &layouts[index];
|
||||||
clear_fullscreen_and_maximized_state(monitor);
|
clear_fullscreen_and_maximized_state(monitor);
|
||||||
arrange(monitor, false, false);
|
arrange(monitor, false);
|
||||||
printstatus();
|
printstatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,7 +287,7 @@ void dwl_ipc_output_dispatch(struct wl_client *client,
|
||||||
const char *arg3, const char *arg4,
|
const char *arg3, const char *arg4,
|
||||||
const char *arg5) {
|
const char *arg5) {
|
||||||
|
|
||||||
int32_t (*func)(const Arg *);
|
int (*func)(const Arg *);
|
||||||
Arg arg;
|
Arg arg;
|
||||||
func = parse_func_name((char *)dispatch, &arg, (char *)arg1, (char *)arg2,
|
func = parse_func_name((char *)dispatch, &arg, (char *)arg1, (char *)arg2,
|
||||||
(char *)arg3, (char *)arg4, (char *)arg5);
|
(char *)arg3, (char *)arg4, (char *)arg5);
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ static void remove_workspace_by_tag(uint32_t tag, Monitor *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_workspace_by_tag(int32_t tag, Monitor *m) {
|
static void add_workspace_by_tag(int tag, Monitor *m) {
|
||||||
const char *name = get_name_from_tag(tag);
|
const char *name = get_name_from_tag(tag);
|
||||||
|
|
||||||
struct workspace *workspace = ecalloc(1, sizeof(*workspace));
|
struct workspace *workspace = ecalloc(1, sizeof(*workspace));
|
||||||
|
|
@ -162,7 +162,7 @@ void dwl_ext_workspace_printstatus(Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void refresh_monitors_workspaces_status(Monitor *m) {
|
void refresh_monitors_workspaces_status(Monitor *m) {
|
||||||
int32_t i;
|
int i;
|
||||||
|
|
||||||
if (m->isoverview) {
|
if (m->isoverview) {
|
||||||
for (i = 1; i <= LENGTH(tags); i++) {
|
for (i = 1; i <= LENGTH(tags); i++) {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ void handle_foreign_activate_request(struct wl_listener *listener, void *data) {
|
||||||
c->is_scratchpad_show = 0;
|
c->is_scratchpad_show = 0;
|
||||||
setborder_color(c);
|
setborder_color(c);
|
||||||
show_hide_client(c);
|
show_hide_client(c);
|
||||||
arrange(c->mon, true, false);
|
arrange(c->mon, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ void handle_foreign_minimize_request(struct wl_listener *listener, void *data) {
|
||||||
c->is_scratchpad_show = 0;
|
c->is_scratchpad_show = 0;
|
||||||
setborder_color(c);
|
setborder_color(c);
|
||||||
show_hide_client(c);
|
show_hide_client(c);
|
||||||
arrange(c->mon, true, false);
|
arrange(c->mon, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ void handle_tearing_new_object(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
bool check_tearing_frame_allow(Monitor *m) {
|
bool check_tearing_frame_allow(Monitor *m) {
|
||||||
/* never allow tearing when disabled */
|
/* never allow tearing when disabled */
|
||||||
if (!config.allow_tearing) {
|
if (!allow_tearing) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ bool check_tearing_frame_allow(Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allow tearing for any window when requested or forced */
|
/* allow tearing for any window when requested or forced */
|
||||||
if (config.allow_tearing == TEARING_ENABLED) {
|
if (allow_tearing == TEARING_ENABLED) {
|
||||||
if (c->force_tearing == STATE_UNSPECIFIED) {
|
if (c->force_tearing == STATE_UNSPECIFIED) {
|
||||||
return c->tearing_hint;
|
return c->tearing_hint;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -87,8 +87,7 @@ bool check_tearing_frame_allow(Monitor *m) {
|
||||||
|
|
||||||
if (c->force_tearing == STATE_UNSPECIFIED) {
|
if (c->force_tearing == STATE_UNSPECIFIED) {
|
||||||
/* honor the tearing hint or the fullscreen-force preference */
|
/* honor the tearing hint or the fullscreen-force preference */
|
||||||
return c->tearing_hint ||
|
return c->tearing_hint || allow_tearing == TEARING_FULLSCREEN_ONLY;
|
||||||
config.allow_tearing == TEARING_FULLSCREEN_ONLY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* honor tearing as requested by action */
|
/* honor tearing as requested by action */
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,15 @@ Monitor *output_from_wlr_output(struct wlr_output *wlr_output) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Monitor *output_nearest_to(int lx, int ly) {
|
||||||
|
double closest_x, closest_y;
|
||||||
|
wlr_output_layout_closest_point(output_layout, NULL, lx, ly, &closest_x,
|
||||||
|
&closest_y);
|
||||||
|
|
||||||
|
return output_from_wlr_output(
|
||||||
|
wlr_output_layout_output_at(output_layout, closest_x, closest_y));
|
||||||
|
}
|
||||||
|
|
||||||
bool output_is_usable(Monitor *m) { return m && m->wlr_output->enabled; }
|
bool output_is_usable(Monitor *m) { return m && m->wlr_output->enabled; }
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
@ -216,7 +225,7 @@ static void update_popup_position(struct dwl_input_method_popup *popup) {
|
||||||
Monitor *output = NULL;
|
Monitor *output = NULL;
|
||||||
struct wlr_xdg_positioner_rules pointer_rules;
|
struct wlr_xdg_positioner_rules pointer_rules;
|
||||||
struct wlr_box output_box;
|
struct wlr_box output_box;
|
||||||
int32_t lx, ly;
|
int lx, ly;
|
||||||
struct wlr_box popup_box;
|
struct wlr_box popup_box;
|
||||||
|
|
||||||
if (!text_input || !relay->focused_surface ||
|
if (!text_input || !relay->focused_surface ||
|
||||||
|
|
@ -246,7 +255,7 @@ static void update_popup_position(struct dwl_input_method_popup *popup) {
|
||||||
cursor_rect = (struct wlr_box){0};
|
cursor_rect = (struct wlr_box){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
output = get_monitor_nearest_to(cursor_rect.x, cursor_rect.y);
|
output = output_nearest_to(cursor_rect.x, cursor_rect.y);
|
||||||
if (!output_is_usable(output)) {
|
if (!output_is_usable(output)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
bool check_hit_no_border(Client *c) {
|
bool check_hit_no_border(Client *c) {
|
||||||
int32_t i;
|
int i;
|
||||||
bool hit_no_border = false;
|
bool hit_no_border = false;
|
||||||
if (!render_border) {
|
if (!render_border) {
|
||||||
hit_no_border = true;
|
hit_no_border = true;
|
||||||
|
|
@ -12,9 +12,7 @@ bool check_hit_no_border(Client *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.no_border_when_single && c && c->mon &&
|
if (no_border_when_single && c && c->mon && c->mon->visible_clients == 1) {
|
||||||
((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;
|
||||||
|
|
@ -39,7 +37,7 @@ Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) {
|
||||||
const char *appid, *title;
|
const char *appid, *title;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (!config.scratchpad_cross_monitor && c->mon != selmon) {
|
if (!scratchpad_cross_monitor && c->mon != selmon) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,19 +74,16 @@ Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) {
|
||||||
return target_client;
|
return target_client;
|
||||||
}
|
}
|
||||||
struct wlr_box // 计算客户端居中坐标
|
struct wlr_box // 计算客户端居中坐标
|
||||||
setclient_coordinate_center(Client *c, Monitor *tm, struct wlr_box geom,
|
setclient_coordinate_center(Client *c, struct wlr_box geom, int offsetx,
|
||||||
int32_t offsetx, int32_t offsety) {
|
int offsety) {
|
||||||
struct wlr_box tempbox;
|
struct wlr_box tempbox;
|
||||||
int32_t offset = 0;
|
int offset = 0;
|
||||||
int32_t len = 0;
|
int len = 0;
|
||||||
Monitor *m = tm ? tm : selmon;
|
Monitor *m = c->mon ? c->mon : selmon;
|
||||||
|
|
||||||
if (!m)
|
|
||||||
return geom;
|
|
||||||
|
|
||||||
uint32_t cbw = check_hit_no_border(c) ? c->bw : 0;
|
uint32_t cbw = check_hit_no_border(c) ? c->bw : 0;
|
||||||
|
|
||||||
if (!c->no_force_center && m) {
|
if (!c->no_force_center) {
|
||||||
tempbox.x = m->w.x + (m->w.width - geom.width) / 2;
|
tempbox.x = m->w.x + (m->w.width - geom.width) / 2;
|
||||||
tempbox.y = m->w.y + (m->w.height - geom.height) / 2;
|
tempbox.y = m->w.y + (m->w.height - geom.height) / 2;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -140,9 +135,9 @@ static bool is_window_rule_matches(const ConfigWinRule *r, const char *appid,
|
||||||
Client *center_tiled_select(Monitor *m) {
|
Client *center_tiled_select(Monitor *m) {
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
Client *target_c = NULL;
|
Client *target_c = NULL;
|
||||||
int64_t mini_distance = -1;
|
long int mini_distance = -1;
|
||||||
int32_t dirx, diry;
|
int dirx, diry;
|
||||||
int64_t distance;
|
long int distance;
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (c && VISIBLEON(c, m) && ISSCROLLTILED(c) &&
|
if (c && VISIBLEON(c, m) && ISSCROLLTILED(c) &&
|
||||||
client_surface(c)->mapped && !c->isfloating &&
|
client_surface(c)->mapped && !c->isfloating &&
|
||||||
|
|
@ -162,12 +157,12 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
||||||
bool ignore_align) {
|
bool ignore_align) {
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
Client **tempClients = NULL; // 初始化为 NULL
|
Client **tempClients = NULL; // 初始化为 NULL
|
||||||
int32_t last = -1;
|
int last = -1;
|
||||||
|
|
||||||
// 第一次遍历,计算客户端数量
|
// 第一次遍历,计算客户端数量
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (c && (findfloating || !c->isfloating) && !c->isunglobal &&
|
if (c && (findfloating || !c->isfloating) && !c->isunglobal &&
|
||||||
(config.focus_cross_monitor || c->mon == tc->mon) &&
|
(focus_cross_monitor || c->mon == tc->mon) &&
|
||||||
(c->tags & c->mon->tagset[c->mon->seltags])) {
|
(c->tags & c->mon->tagset[c->mon->seltags])) {
|
||||||
last++;
|
last++;
|
||||||
}
|
}
|
||||||
|
|
@ -188,30 +183,30 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
||||||
last = -1;
|
last = -1;
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (c && (findfloating || !c->isfloating) && !c->isunglobal &&
|
if (c && (findfloating || !c->isfloating) && !c->isunglobal &&
|
||||||
(config.focus_cross_monitor || c->mon == tc->mon) &&
|
(focus_cross_monitor || c->mon == tc->mon) &&
|
||||||
(c->tags & c->mon->tagset[c->mon->seltags])) {
|
(c->tags & c->mon->tagset[c->mon->seltags])) {
|
||||||
last++;
|
last++;
|
||||||
tempClients[last] = c;
|
tempClients[last] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t sel_x = tc->geom.x;
|
int sel_x = tc->geom.x;
|
||||||
int32_t sel_y = tc->geom.y;
|
int sel_y = tc->geom.y;
|
||||||
int64_t distance = LLONG_MAX;
|
long long int distance = LLONG_MAX;
|
||||||
int64_t same_monitor_distance = LLONG_MAX;
|
long long int same_monitor_distance = LLONG_MAX;
|
||||||
Client *tempFocusClients = NULL;
|
Client *tempFocusClients = NULL;
|
||||||
Client *tempSameMonitorFocusClients = NULL;
|
Client *tempSameMonitorFocusClients = NULL;
|
||||||
|
|
||||||
switch (arg->i) {
|
switch (arg->i) {
|
||||||
case UP:
|
case UP:
|
||||||
if (!ignore_align) {
|
if (!ignore_align) {
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
for (int _i = 0; _i <= last; _i++) {
|
||||||
if (tempClients[_i]->geom.y < sel_y &&
|
if (tempClients[_i]->geom.y < sel_y &&
|
||||||
tempClients[_i]->geom.x == sel_x &&
|
tempClients[_i]->geom.x == sel_x &&
|
||||||
tempClients[_i]->mon == tc->mon) {
|
tempClients[_i]->mon == tc->mon) {
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
int dis_x = tempClients[_i]->geom.x - sel_x;
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
int dis_y = tempClients[_i]->geom.y - sel_y;
|
||||||
int64_t tmp_distance =
|
long long int tmp_distance =
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||||
if (tmp_distance < distance) {
|
if (tmp_distance < distance) {
|
||||||
distance = tmp_distance;
|
distance = tmp_distance;
|
||||||
|
|
@ -221,32 +216,11 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tempFocusClients) {
|
if (!tempFocusClients) {
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
for (int _i = 0; _i <= last; _i++) {
|
||||||
if (tempClients[_i]->geom.y < sel_y &&
|
|
||||||
tempClients[_i]->mon == tc->mon &&
|
|
||||||
client_is_in_same_stack(tc, tempClients[_i], NULL)) {
|
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
|
||||||
int64_t tmp_distance =
|
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
|
||||||
if (tmp_distance < distance) {
|
|
||||||
distance = tmp_distance;
|
|
||||||
tempFocusClients = tempClients[_i];
|
|
||||||
}
|
|
||||||
if (tempClients[_i]->mon == tc->mon &&
|
|
||||||
tmp_distance < same_monitor_distance) {
|
|
||||||
same_monitor_distance = tmp_distance;
|
|
||||||
tempSameMonitorFocusClients = tempClients[_i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!tempFocusClients) {
|
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
|
||||||
if (tempClients[_i]->geom.y < sel_y) {
|
if (tempClients[_i]->geom.y < sel_y) {
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
int dis_x = tempClients[_i]->geom.x - sel_x;
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
int dis_y = tempClients[_i]->geom.y - sel_y;
|
||||||
int64_t tmp_distance =
|
long long int tmp_distance =
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||||
if (tmp_distance < distance) {
|
if (tmp_distance < distance) {
|
||||||
distance = tmp_distance;
|
distance = tmp_distance;
|
||||||
|
|
@ -263,13 +237,13 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
||||||
break;
|
break;
|
||||||
case DOWN:
|
case DOWN:
|
||||||
if (!ignore_align) {
|
if (!ignore_align) {
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
for (int _i = 0; _i <= last; _i++) {
|
||||||
if (tempClients[_i]->geom.y > sel_y &&
|
if (tempClients[_i]->geom.y > sel_y &&
|
||||||
tempClients[_i]->geom.x == sel_x &&
|
tempClients[_i]->geom.x == sel_x &&
|
||||||
tempClients[_i]->mon == tc->mon) {
|
tempClients[_i]->mon == tc->mon) {
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
int dis_x = tempClients[_i]->geom.x - sel_x;
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
int dis_y = tempClients[_i]->geom.y - sel_y;
|
||||||
int64_t tmp_distance =
|
long long int tmp_distance =
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||||
if (tmp_distance < distance) {
|
if (tmp_distance < distance) {
|
||||||
distance = tmp_distance;
|
distance = tmp_distance;
|
||||||
|
|
@ -279,32 +253,11 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tempFocusClients) {
|
if (!tempFocusClients) {
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
for (int _i = 0; _i <= last; _i++) {
|
||||||
if (tempClients[_i]->geom.y > sel_y &&
|
|
||||||
tempClients[_i]->mon == tc->mon &&
|
|
||||||
client_is_in_same_stack(tc, tempClients[_i], NULL)) {
|
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
|
||||||
int64_t tmp_distance =
|
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
|
||||||
if (tmp_distance < distance) {
|
|
||||||
distance = tmp_distance;
|
|
||||||
tempFocusClients = tempClients[_i];
|
|
||||||
}
|
|
||||||
if (tempClients[_i]->mon == tc->mon &&
|
|
||||||
tmp_distance < same_monitor_distance) {
|
|
||||||
same_monitor_distance = tmp_distance;
|
|
||||||
tempSameMonitorFocusClients = tempClients[_i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!tempFocusClients) {
|
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
|
||||||
if (tempClients[_i]->geom.y > sel_y) {
|
if (tempClients[_i]->geom.y > sel_y) {
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
int dis_x = tempClients[_i]->geom.x - sel_x;
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
int dis_y = tempClients[_i]->geom.y - sel_y;
|
||||||
int64_t tmp_distance =
|
long long int tmp_distance =
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||||
if (tmp_distance < distance) {
|
if (tmp_distance < distance) {
|
||||||
distance = tmp_distance;
|
distance = tmp_distance;
|
||||||
|
|
@ -321,13 +274,13 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
||||||
break;
|
break;
|
||||||
case LEFT:
|
case LEFT:
|
||||||
if (!ignore_align) {
|
if (!ignore_align) {
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
for (int _i = 0; _i <= last; _i++) {
|
||||||
if (tempClients[_i]->geom.x < sel_x &&
|
if (tempClients[_i]->geom.x < sel_x &&
|
||||||
tempClients[_i]->geom.y == sel_y &&
|
tempClients[_i]->geom.y == sel_y &&
|
||||||
tempClients[_i]->mon == tc->mon) {
|
tempClients[_i]->mon == tc->mon) {
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
int dis_x = tempClients[_i]->geom.x - sel_x;
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
int dis_y = tempClients[_i]->geom.y - sel_y;
|
||||||
int64_t tmp_distance =
|
long long int tmp_distance =
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||||
if (tmp_distance < distance) {
|
if (tmp_distance < distance) {
|
||||||
distance = tmp_distance;
|
distance = tmp_distance;
|
||||||
|
|
@ -337,32 +290,11 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tempFocusClients) {
|
if (!tempFocusClients) {
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
for (int _i = 0; _i <= last; _i++) {
|
||||||
if (tempClients[_i]->geom.x < sel_x &&
|
|
||||||
tempClients[_i]->mon == tc->mon &&
|
|
||||||
client_is_in_same_stack(tc, tempClients[_i], NULL)) {
|
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
|
||||||
int64_t tmp_distance =
|
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
|
||||||
if (tmp_distance < distance) {
|
|
||||||
distance = tmp_distance;
|
|
||||||
tempFocusClients = tempClients[_i];
|
|
||||||
}
|
|
||||||
if (tempClients[_i]->mon == tc->mon &&
|
|
||||||
tmp_distance < same_monitor_distance) {
|
|
||||||
same_monitor_distance = tmp_distance;
|
|
||||||
tempSameMonitorFocusClients = tempClients[_i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!tempFocusClients) {
|
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
|
||||||
if (tempClients[_i]->geom.x < sel_x) {
|
if (tempClients[_i]->geom.x < sel_x) {
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
int dis_x = tempClients[_i]->geom.x - sel_x;
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
int dis_y = tempClients[_i]->geom.y - sel_y;
|
||||||
int64_t tmp_distance =
|
long long int tmp_distance =
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||||
if (tmp_distance < distance) {
|
if (tmp_distance < distance) {
|
||||||
distance = tmp_distance;
|
distance = tmp_distance;
|
||||||
|
|
@ -379,13 +311,13 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
||||||
break;
|
break;
|
||||||
case RIGHT:
|
case RIGHT:
|
||||||
if (!ignore_align) {
|
if (!ignore_align) {
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
for (int _i = 0; _i <= last; _i++) {
|
||||||
if (tempClients[_i]->geom.x > sel_x &&
|
if (tempClients[_i]->geom.x > sel_x &&
|
||||||
tempClients[_i]->geom.y == sel_y &&
|
tempClients[_i]->geom.y == sel_y &&
|
||||||
tempClients[_i]->mon == tc->mon) {
|
tempClients[_i]->mon == tc->mon) {
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
int dis_x = tempClients[_i]->geom.x - sel_x;
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
int dis_y = tempClients[_i]->geom.y - sel_y;
|
||||||
int64_t tmp_distance =
|
long long int tmp_distance =
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||||
if (tmp_distance < distance) {
|
if (tmp_distance < distance) {
|
||||||
distance = tmp_distance;
|
distance = tmp_distance;
|
||||||
|
|
@ -395,32 +327,11 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tempFocusClients) {
|
if (!tempFocusClients) {
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
for (int _i = 0; _i <= last; _i++) {
|
||||||
if (tempClients[_i]->geom.x > sel_x &&
|
|
||||||
tempClients[_i]->mon == tc->mon &&
|
|
||||||
client_is_in_same_stack(tc, tempClients[_i], NULL)) {
|
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
|
||||||
int64_t tmp_distance =
|
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
|
||||||
if (tmp_distance < distance) {
|
|
||||||
distance = tmp_distance;
|
|
||||||
tempFocusClients = tempClients[_i];
|
|
||||||
}
|
|
||||||
if (tempClients[_i]->mon == tc->mon &&
|
|
||||||
tmp_distance < same_monitor_distance) {
|
|
||||||
same_monitor_distance = tmp_distance;
|
|
||||||
tempSameMonitorFocusClients = tempClients[_i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!tempFocusClients) {
|
|
||||||
for (int32_t _i = 0; _i <= last; _i++) {
|
|
||||||
if (tempClients[_i]->geom.x > sel_x) {
|
if (tempClients[_i]->geom.x > sel_x) {
|
||||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
int dis_x = tempClients[_i]->geom.x - sel_x;
|
||||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
int dis_y = tempClients[_i]->geom.y - sel_y;
|
||||||
int64_t tmp_distance =
|
long long int tmp_distance =
|
||||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||||
if (tmp_distance < distance) {
|
if (tmp_distance < distance) {
|
||||||
distance = tmp_distance;
|
distance = tmp_distance;
|
||||||
|
|
@ -458,9 +369,7 @@ Client *direction_select(const Arg *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return find_client_by_direction(
|
return find_client_by_direction(
|
||||||
tc, arg, true,
|
tc, arg, true, is_scroller_layout(selmon) && !selmon->isoverview);
|
||||||
(is_scroller_layout(selmon) || is_centertile_layout(selmon)) &&
|
|
||||||
!selmon->isoverview);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We probably should change the name of this, it sounds like
|
/* We probably should change the name of this, it sounds like
|
||||||
|
|
@ -487,9 +396,6 @@ Client *get_next_stack_client(Client *c, bool reverse) {
|
||||||
if (&next->link == &clients)
|
if (&next->link == &clients)
|
||||||
continue; /* wrap past the sentinel node */
|
continue; /* wrap past the sentinel node */
|
||||||
|
|
||||||
if (next->isunglobal)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (next != c && next->mon && VISIBLEON(next, c->mon))
|
if (next != c && next->mon && VISIBLEON(next, c->mon))
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
@ -498,9 +404,6 @@ Client *get_next_stack_client(Client *c, bool reverse) {
|
||||||
if (&next->link == &clients)
|
if (&next->link == &clients)
|
||||||
continue; /* wrap past the sentinel node */
|
continue; /* wrap past the sentinel node */
|
||||||
|
|
||||||
if (next->isunglobal)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (next != c && next->mon && VISIBLEON(next, c->mon))
|
if (next != c && next->mon && VISIBLEON(next, c->mon))
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
@ -511,124 +414,20 @@ Client *get_next_stack_client(Client *c, bool reverse) {
|
||||||
float *get_border_color(Client *c) {
|
float *get_border_color(Client *c) {
|
||||||
|
|
||||||
if (c->mon != selmon) {
|
if (c->mon != selmon) {
|
||||||
return config.bordercolor;
|
return bordercolor;
|
||||||
} else if (c->isurgent) {
|
} else if (c->isurgent) {
|
||||||
return config.urgentcolor;
|
return urgentcolor;
|
||||||
} else if (c->is_in_scratchpad && selmon && c == selmon->sel) {
|
} else if (c->is_in_scratchpad && selmon && c == selmon->sel) {
|
||||||
return config.scratchpadcolor;
|
return scratchpadcolor;
|
||||||
} else if (c->isglobal && selmon && c == selmon->sel) {
|
} else if (c->isglobal && selmon && c == selmon->sel) {
|
||||||
return config.globalcolor;
|
return globalcolor;
|
||||||
} else if (c->isoverlay && selmon && c == selmon->sel) {
|
} else if (c->isoverlay && selmon && c == selmon->sel) {
|
||||||
return config.overlaycolor;
|
return overlaycolor;
|
||||||
} else if (c->ismaximizescreen && selmon && c == selmon->sel) {
|
} else if (c->ismaximizescreen && selmon && c == selmon->sel) {
|
||||||
return config.maximizescreencolor;
|
return maximizescreencolor;
|
||||||
} else if (selmon && c == selmon->sel) {
|
} else if (selmon && c == selmon->sel) {
|
||||||
return config.focuscolor;
|
return focuscolor;
|
||||||
} else {
|
} else {
|
||||||
return config.bordercolor;
|
return bordercolor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t is_single_bit_set(uint32_t x) { return x && !(x & (x - 1)); }
|
|
||||||
|
|
||||||
bool client_only_in_one_tag(Client *c) {
|
|
||||||
uint32_t masked = c->tags & TAGMASK;
|
|
||||||
if (is_single_bit_set(masked)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Client *get_scroll_stack_head(Client *c) {
|
|
||||||
Client *scroller_stack_head = c;
|
|
||||||
|
|
||||||
if (!scroller_stack_head)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
while (scroller_stack_head->prev_in_stack) {
|
|
||||||
scroller_stack_head = scroller_stack_head->prev_in_stack;
|
|
||||||
}
|
|
||||||
return scroller_stack_head;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc) {
|
|
||||||
if (!sc || !tc)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
uint32_t id = sc->mon->pertag->ltidxs[sc->mon->pertag->curtag]->id;
|
|
||||||
|
|
||||||
if (id != SCROLLER && id != VERTICAL_SCROLLER && id != TILE &&
|
|
||||||
id != VERTICAL_TILE && id != DECK && id != VERTICAL_DECK &&
|
|
||||||
id != CENTER_TILE && id != RIGHT_TILE && id != TGMIX)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (id == SCROLLER || id == VERTICAL_SCROLLER) {
|
|
||||||
Client *source_stack_head = get_scroll_stack_head(sc);
|
|
||||||
Client *target_stack_head = get_scroll_stack_head(tc);
|
|
||||||
Client *fc_head = fc ? get_scroll_stack_head(fc) : NULL;
|
|
||||||
if (fc && fc->prev_in_stack && fc_head == source_stack_head)
|
|
||||||
return false;
|
|
||||||
if (source_stack_head == target_stack_head)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == TILE || id == VERTICAL_TILE || id == DECK ||
|
|
||||||
id == VERTICAL_DECK || id == RIGHT_TILE) {
|
|
||||||
if (tc->ismaster ^ sc->ismaster)
|
|
||||||
return false;
|
|
||||||
if (fc && !(fc->ismaster ^ sc->ismaster))
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == TGMIX) {
|
|
||||||
if (tc->ismaster ^ sc->ismaster)
|
|
||||||
return false;
|
|
||||||
if (fc && !(fc->ismaster ^ sc->ismaster))
|
|
||||||
return false;
|
|
||||||
if (!sc->ismaster && sc->mon->visible_tiling_clients <= 3)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == CENTER_TILE) {
|
|
||||||
if (tc->ismaster ^ sc->ismaster)
|
|
||||||
return false;
|
|
||||||
if (fc && !(fc->ismaster ^ sc->ismaster))
|
|
||||||
return false;
|
|
||||||
if (sc->geom.x == tc->geom.x)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Client *get_focused_stack_client(Client *sc) {
|
|
||||||
if (!sc || sc->isfloating)
|
|
||||||
return sc;
|
|
||||||
|
|
||||||
Client *tc = NULL;
|
|
||||||
Client *fc = focustop(sc->mon);
|
|
||||||
|
|
||||||
if (fc->isfloating || sc->isfloating)
|
|
||||||
return sc;
|
|
||||||
|
|
||||||
wl_list_for_each(tc, &fstack, flink) {
|
|
||||||
if (tc->iskilling || tc->isunglobal)
|
|
||||||
continue;
|
|
||||||
if (!VISIBLEON(tc, sc->mon))
|
|
||||||
continue;
|
|
||||||
if (tc == fc)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (client_is_in_same_stack(sc, tc, fc)) {
|
|
||||||
return tc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sc;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,11 @@ pid_t getparentprocess(pid_t p) {
|
||||||
return (pid_t)v;
|
return (pid_t)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t isdescprocess(pid_t p, pid_t c) {
|
int isdescprocess(pid_t p, pid_t c) {
|
||||||
while (p != c && c != 0)
|
while (p != c && c != 0)
|
||||||
c = getparentprocess(c);
|
c = getparentprocess(c);
|
||||||
|
|
||||||
return (int32_t)c;
|
return (int)c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_layout_abbr(char *abbr, const char *full_name) {
|
void get_layout_abbr(char *abbr, const char *full_name) {
|
||||||
|
|
@ -31,7 +31,7 @@ void get_layout_abbr(char *abbr, const char *full_name) {
|
||||||
abbr[0] = '\0';
|
abbr[0] = '\0';
|
||||||
|
|
||||||
// 1. 尝试在映射表中查找
|
// 1. 尝试在映射表中查找
|
||||||
for (int32_t i = 0; layout_mappings[i].full_name != NULL; i++) {
|
for (int i = 0; layout_mappings[i].full_name != NULL; i++) {
|
||||||
if (strcmp(full_name, layout_mappings[i].full_name) == 0) {
|
if (strcmp(full_name, layout_mappings[i].full_name) == 0) {
|
||||||
strcpy(abbr, layout_mappings[i].abbr);
|
strcpy(abbr, layout_mappings[i].abbr);
|
||||||
return;
|
return;
|
||||||
|
|
@ -83,7 +83,7 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
||||||
struct wlr_surface *surface = NULL;
|
struct wlr_surface *surface = NULL;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
LayerSurface *l = NULL;
|
LayerSurface *l = NULL;
|
||||||
int32_t layer;
|
int layer;
|
||||||
|
|
||||||
for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
|
for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
|
||||||
|
|
||||||
|
|
@ -93,13 +93,14 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
||||||
if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
|
if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!node->enabled)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (node->type == WLR_SCENE_NODE_BUFFER)
|
if (node->type == WLR_SCENE_NODE_BUFFER)
|
||||||
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,
|
||||||
|
|
@ -115,13 +116,6 @@ 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)
|
||||||
|
|
|
||||||
|
|
@ -26,14 +26,6 @@ bool is_scroller_layout(Monitor *m) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_centertile_layout(Monitor *m) {
|
|
||||||
|
|
||||||
if (m->pertag->ltidxs[m->pertag->curtag]->id == CENTER_TILE)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t get_tag_status(uint32_t tag, Monitor *m) {
|
uint32_t get_tag_status(uint32_t tag, Monitor *m) {
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
uint32_t status = 0;
|
uint32_t status = 0;
|
||||||
|
|
@ -96,81 +88,3 @@ Monitor *xytomon(double x, double y) {
|
||||||
struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
|
struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
|
||||||
return o ? o->data : NULL;
|
return o ? o->data : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor *get_monitor_nearest_to(int32_t lx, int32_t ly) {
|
|
||||||
double closest_x, closest_y;
|
|
||||||
wlr_output_layout_closest_point(output_layout, NULL, lx, ly, &closest_x,
|
|
||||||
&closest_y);
|
|
||||||
|
|
||||||
return output_from_wlr_output(
|
|
||||||
wlr_output_layout_output_at(output_layout, closest_x, closest_y));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool match_monitor_spec(char *spec, Monitor *m) {
|
|
||||||
if (!spec || !m)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// if the spec does not contain a colon, treat it as a match on the monitor
|
|
||||||
// name
|
|
||||||
if (strchr(spec, ':') == NULL) {
|
|
||||||
return regex_match(spec, m->wlr_output->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *spec_copy = strdup(spec);
|
|
||||||
if (!spec_copy)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
char *name_rule = NULL;
|
|
||||||
char *make_rule = NULL;
|
|
||||||
char *model_rule = NULL;
|
|
||||||
char *serial_rule = NULL;
|
|
||||||
|
|
||||||
char *token = strtok(spec_copy, "&&");
|
|
||||||
while (token) {
|
|
||||||
char *colon = strchr(token, ':');
|
|
||||||
if (colon) {
|
|
||||||
*colon = '\0';
|
|
||||||
char *key = token;
|
|
||||||
char *value = colon + 1;
|
|
||||||
|
|
||||||
if (strcmp(key, "name") == 0)
|
|
||||||
name_rule = strdup(value);
|
|
||||||
else if (strcmp(key, "make") == 0)
|
|
||||||
make_rule = strdup(value);
|
|
||||||
else if (strcmp(key, "model") == 0)
|
|
||||||
model_rule = strdup(value);
|
|
||||||
else if (strcmp(key, "serial") == 0)
|
|
||||||
serial_rule = strdup(value);
|
|
||||||
}
|
|
||||||
token = strtok(NULL, "&&");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool match = true;
|
|
||||||
|
|
||||||
if (name_rule) {
|
|
||||||
if (!regex_match(name_rule, m->wlr_output->name))
|
|
||||||
match = false;
|
|
||||||
}
|
|
||||||
if (make_rule) {
|
|
||||||
if (!m->wlr_output->make || strcmp(make_rule, m->wlr_output->make) != 0)
|
|
||||||
match = false;
|
|
||||||
}
|
|
||||||
if (model_rule) {
|
|
||||||
if (!m->wlr_output->model ||
|
|
||||||
strcmp(model_rule, m->wlr_output->model) != 0)
|
|
||||||
match = false;
|
|
||||||
}
|
|
||||||
if (serial_rule) {
|
|
||||||
if (!m->wlr_output->serial ||
|
|
||||||
strcmp(serial_rule, m->wlr_output->serial) != 0)
|
|
||||||
match = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(spec_copy);
|
|
||||||
free(name_rule);
|
|
||||||
free(make_rule);
|
|
||||||
free(model_rule);
|
|
||||||
free(serial_rule);
|
|
||||||
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
|
|
@ -1,99 +1,8 @@
|
||||||
void save_old_size_per(Monitor *m) {
|
|
||||||
Client *c = NULL;
|
|
||||||
|
|
||||||
wl_list_for_each(c, &clients, link) {
|
|
||||||
if (VISIBLEON(c, m) && ISTILED(c)) {
|
|
||||||
c->old_master_inner_per = c->master_inner_per;
|
|
||||||
c->old_stack_inner_per = c->stack_inner_per;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void restore_size_per(Monitor *m, Client *c) {
|
|
||||||
Client *fc = NULL;
|
|
||||||
|
|
||||||
if (!m || !c)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!m->wlr_output->enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
wl_list_for_each(fc, &clients, link) {
|
|
||||||
if (VISIBLEON(fc, m) && ISTILED(fc)) {
|
|
||||||
fc->old_ismaster = fc->ismaster;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c->old_master_inner_per = c->master_inner_per;
|
|
||||||
c->old_stack_inner_per = c->stack_inner_per;
|
|
||||||
|
|
||||||
pre_caculate_before_arrange(m, false, false, true);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
wl_list_for_each(fc, &clients, link) {
|
|
||||||
if (VISIBLEON(fc, m) && ISTILED(fc) && !c->ismaster) {
|
|
||||||
set_size_per(m, fc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// it is possible that the current floating window is moved to another tag,
|
|
||||||
// but the tag has not executed save_old_size_per
|
|
||||||
// so it must be judged whether their old size values are initial values
|
|
||||||
|
|
||||||
if (!c->ismaster && c->old_stack_inner_per < 1.0 &&
|
|
||||||
c->old_stack_inner_per > 0.0f && c->stack_inner_per < 1.0 &&
|
|
||||||
c->stack_inner_per > 0.0f) {
|
|
||||||
c->stack_inner_per = (1.0 - c->stack_inner_per) *
|
|
||||||
c->old_stack_inner_per /
|
|
||||||
(1.0 - c->old_stack_inner_per);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->ismaster && c->old_master_inner_per < 1.0 &&
|
|
||||||
c->old_master_inner_per > 0.0f && c->master_inner_per < 1.0 &&
|
|
||||||
c->master_inner_per > 0.0f) {
|
|
||||||
c->master_inner_per = (1.0 - c->master_inner_per) *
|
|
||||||
c->old_master_inner_per /
|
|
||||||
(1.0 - c->old_master_inner_per);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_for_each(fc, &clients, link) {
|
|
||||||
if (VISIBLEON(fc, m) && ISTILED(fc) && fc != c && !fc->ismaster &&
|
|
||||||
fc->old_ismaster && fc->old_stack_inner_per < 1.0 &&
|
|
||||||
fc->old_stack_inner_per > 0.0f && fc->stack_inner_per < 1.0 &&
|
|
||||||
fc->stack_inner_per > 0.0f) {
|
|
||||||
fc->stack_inner_per = (1.0 - fc->stack_inner_per) *
|
|
||||||
fc->old_stack_inner_per /
|
|
||||||
(1.0 - fc->old_stack_inner_per);
|
|
||||||
fc->old_ismaster = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
if (!m || !c)
|
|
||||||
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;
|
||||||
|
|
@ -109,9 +18,8 @@ void set_size_per(Monitor *m, Client *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
|
void resize_tile_master_horizontal(Client *grabc, bool isdrag, int offsetx,
|
||||||
int32_t offsety, uint32_t time,
|
int offsety, uint32_t time, int type) {
|
||||||
int32_t type) {
|
|
||||||
Client *tc = NULL;
|
Client *tc = NULL;
|
||||||
float delta_x, delta_y;
|
float delta_x, delta_y;
|
||||||
Client *next = NULL;
|
Client *next = NULL;
|
||||||
|
|
@ -130,7 +38,8 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!begin_find_nextnext && VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
|
if (!begin_find_nextnext && VISIBLEON(tc, grabc->mon) &&
|
||||||
|
ISTILED(tc)) { // 根据你的实际字段名调整
|
||||||
next = tc;
|
next = tc;
|
||||||
begin_find_nextnext = true;
|
begin_find_nextnext = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -146,7 +55,8 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!begin_find_prevprev && VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
|
if (!begin_find_prevprev && VISIBLEON(tc, grabc->mon) &&
|
||||||
|
ISTILED(tc)) { // 根据你的实际字段名调整
|
||||||
prev = tc;
|
prev = tc;
|
||||||
begin_find_prevprev = true;
|
begin_find_prevprev = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -282,23 +192,6 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
// 应用到所有平铺窗口
|
// 应用到所有平铺窗口
|
||||||
wl_list_for_each(tc, &clients, link) {
|
wl_list_for_each(tc, &clients, link) {
|
||||||
if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
|
if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
|
||||||
|
|
||||||
if (!isdrag && tc != grabc) {
|
|
||||||
if (!tc->ismaster && new_stack_inner_per != 1.0f &&
|
|
||||||
grabc->old_stack_inner_per != 1.0f &&
|
|
||||||
(type != CENTER_TILE ||
|
|
||||||
!(grabc->isleftstack ^ tc->isleftstack)))
|
|
||||||
tc->stack_inner_per = (1 - new_stack_inner_per) /
|
|
||||||
(1 - grabc->old_stack_inner_per) *
|
|
||||||
tc->stack_inner_per;
|
|
||||||
if (tc->ismaster && new_master_inner_per != 1.0f &&
|
|
||||||
grabc->old_master_inner_per != 1.0f)
|
|
||||||
tc->master_inner_per =
|
|
||||||
(1.0f - new_master_inner_per) /
|
|
||||||
(1.0f - grabc->old_master_inner_per) *
|
|
||||||
tc->master_inner_per;
|
|
||||||
}
|
|
||||||
|
|
||||||
tc->master_mfact_per = new_master_mfact_per;
|
tc->master_mfact_per = new_master_mfact_per;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -307,20 +200,20 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
grabc->stack_inner_per = new_stack_inner_per;
|
grabc->stack_inner_per = new_stack_inner_per;
|
||||||
|
|
||||||
if (!isdrag) {
|
if (!isdrag) {
|
||||||
arrange(grabc->mon, false, false);
|
arrange(grabc->mon, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_apply_drap_time == 0 ||
|
if (last_apply_drap_time == 0 ||
|
||||||
time - last_apply_drap_time > config.drag_tile_refresh_interval) {
|
time - last_apply_drap_time > drag_refresh_interval) {
|
||||||
arrange(grabc->mon, false, false);
|
arrange(grabc->mon, false);
|
||||||
last_apply_drap_time = time;
|
last_apply_drap_time = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
|
void resize_tile_master_vertical(Client *grabc, bool isdrag, int offsetx,
|
||||||
int32_t offsety, uint32_t time, int32_t type) {
|
int offsety, uint32_t time, int type) {
|
||||||
Client *tc = NULL;
|
Client *tc = NULL;
|
||||||
float delta_x, delta_y;
|
float delta_x, delta_y;
|
||||||
Client *next = NULL;
|
Client *next = NULL;
|
||||||
|
|
@ -331,7 +224,8 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
for (node = grabc->link.next; node != &clients; node = node->next) {
|
for (node = grabc->link.next; node != &clients; node = node->next) {
|
||||||
tc = wl_container_of(node, tc, link);
|
tc = wl_container_of(node, tc, link);
|
||||||
|
|
||||||
if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
|
if (VISIBLEON(tc, grabc->mon) &&
|
||||||
|
ISTILED(tc)) { // 根据你的实际字段名调整
|
||||||
next = tc;
|
next = tc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -341,7 +235,8 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
for (node = grabc->link.prev; node != &clients; node = node->prev) {
|
for (node = grabc->link.prev; node != &clients; node = node->prev) {
|
||||||
tc = wl_container_of(node, tc, link);
|
tc = wl_container_of(node, tc, link);
|
||||||
|
|
||||||
if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
|
if (VISIBLEON(tc, grabc->mon) &&
|
||||||
|
ISTILED(tc)) { // 根据你的实际字段名调整
|
||||||
prev = tc;
|
prev = tc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -454,20 +349,6 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
// 应用到所有平铺窗口
|
// 应用到所有平铺窗口
|
||||||
wl_list_for_each(tc, &clients, link) {
|
wl_list_for_each(tc, &clients, link) {
|
||||||
if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
|
if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
|
||||||
if (!isdrag && tc != grabc && type != CENTER_TILE) {
|
|
||||||
if (!tc->ismaster && new_stack_inner_per != 1.0f &&
|
|
||||||
grabc->old_stack_inner_per != 1.0f)
|
|
||||||
tc->stack_inner_per = (1 - new_stack_inner_per) /
|
|
||||||
(1 - grabc->old_stack_inner_per) *
|
|
||||||
tc->stack_inner_per;
|
|
||||||
if (tc->ismaster && new_master_inner_per != 1.0f &&
|
|
||||||
grabc->old_master_inner_per != 1.0f)
|
|
||||||
tc->master_inner_per =
|
|
||||||
(1.0f - new_master_inner_per) /
|
|
||||||
(1.0f - grabc->old_master_inner_per) *
|
|
||||||
tc->master_inner_per;
|
|
||||||
}
|
|
||||||
|
|
||||||
tc->master_mfact_per = new_master_mfact_per;
|
tc->master_mfact_per = new_master_mfact_per;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -476,28 +357,25 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
grabc->stack_inner_per = new_stack_inner_per;
|
grabc->stack_inner_per = new_stack_inner_per;
|
||||||
|
|
||||||
if (!isdrag) {
|
if (!isdrag) {
|
||||||
arrange(grabc->mon, false, false);
|
arrange(grabc->mon, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_apply_drap_time == 0 ||
|
if (last_apply_drap_time == 0 ||
|
||||||
time - last_apply_drap_time > config.drag_tile_refresh_interval) {
|
time - last_apply_drap_time > drag_refresh_interval) {
|
||||||
arrange(grabc->mon, false, false);
|
arrange(grabc->mon, false);
|
||||||
last_apply_drap_time = time;
|
last_apply_drap_time = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
void resize_tile_scroller(Client *grabc, bool isdrag, int offsetx, int offsety,
|
||||||
int32_t offsety, uint32_t time, bool isvertical) {
|
uint32_t time, bool isvertical) {
|
||||||
Client *tc = NULL;
|
|
||||||
float delta_x, delta_y;
|
float delta_x, delta_y;
|
||||||
float new_scroller_proportion;
|
float new_scroller_proportion;
|
||||||
float new_stack_proportion;
|
|
||||||
Client *stack_head = get_scroll_stack_head(grabc);
|
|
||||||
|
|
||||||
if (grabc && grabc->mon->visible_tiling_clients == 1 &&
|
if (grabc && grabc->mon->visible_tiling_clients == 1 &&
|
||||||
!config.scroller_ignore_proportion_single)
|
!scroller_ignore_proportion_single)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!start_drag_window && isdrag) {
|
if (!start_drag_window && isdrag) {
|
||||||
|
|
@ -506,8 +384,7 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
start_drag_window = true;
|
start_drag_window = true;
|
||||||
|
|
||||||
// 记录初始状态
|
// 记录初始状态
|
||||||
stack_head->old_scroller_pproportion = stack_head->scroller_proportion;
|
grabc->old_scroller_pproportion = grabc->scroller_proportion;
|
||||||
grabc->old_stack_proportion = grabc->stack_proportion;
|
|
||||||
|
|
||||||
grabc->cursor_in_left_half =
|
grabc->cursor_in_left_half =
|
||||||
cursor->x < grabc->geom.x + grabc->geom.width / 2;
|
cursor->x < grabc->geom.x + grabc->geom.width / 2;
|
||||||
|
|
@ -527,26 +404,15 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
grabc->old_master_inner_per = grabc->master_inner_per;
|
grabc->old_master_inner_per = grabc->master_inner_per;
|
||||||
grabc->old_stack_inner_per = grabc->stack_inner_per;
|
grabc->old_stack_inner_per = grabc->stack_inner_per;
|
||||||
grabc->drag_begin_geom = grabc->geom;
|
grabc->drag_begin_geom = grabc->geom;
|
||||||
stack_head->old_scroller_pproportion =
|
grabc->old_scroller_pproportion = grabc->scroller_proportion;
|
||||||
stack_head->scroller_proportion;
|
|
||||||
grabc->old_stack_proportion = grabc->stack_proportion;
|
|
||||||
grabc->cursor_in_upper_half = false;
|
grabc->cursor_in_upper_half = false;
|
||||||
grabc->cursor_in_left_half = false;
|
grabc->cursor_in_left_half = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isvertical) {
|
delta_x = (float)(offsetx) * (grabc->old_scroller_pproportion) /
|
||||||
delta_y = (float)(offsety) *
|
|
||||||
(stack_head->old_scroller_pproportion) /
|
|
||||||
grabc->drag_begin_geom.height;
|
|
||||||
delta_x = (float)(offsetx) * (grabc->old_stack_proportion) /
|
|
||||||
grabc->drag_begin_geom.width;
|
grabc->drag_begin_geom.width;
|
||||||
} else {
|
delta_y = (float)(offsety) * (grabc->old_scroller_pproportion) /
|
||||||
delta_x = (float)(offsetx) *
|
|
||||||
(stack_head->old_scroller_pproportion) /
|
|
||||||
grabc->drag_begin_geom.width;
|
|
||||||
delta_y = (float)(offsety) * (grabc->old_stack_proportion) /
|
|
||||||
grabc->drag_begin_geom.height;
|
grabc->drag_begin_geom.height;
|
||||||
}
|
|
||||||
|
|
||||||
bool moving_up;
|
bool moving_up;
|
||||||
bool moving_down;
|
bool moving_down;
|
||||||
|
|
@ -581,107 +447,34 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
delta_x = -fabsf(delta_x);
|
delta_x = -fabsf(delta_x);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isvertical) {
|
|
||||||
if (!grabc->next_in_stack && grabc->prev_in_stack && !isdrag) {
|
|
||||||
delta_x = delta_x * -1.0f;
|
|
||||||
}
|
|
||||||
if (!grabc->next_in_stack && grabc->prev_in_stack && isdrag) {
|
|
||||||
if (moving_right) {
|
|
||||||
delta_x = -fabsf(delta_x);
|
|
||||||
} else {
|
|
||||||
delta_x = fabsf(delta_x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!grabc->prev_in_stack && grabc->next_in_stack && isdrag) {
|
|
||||||
if (moving_left) {
|
|
||||||
delta_x = -fabsf(delta_x);
|
|
||||||
} else {
|
|
||||||
delta_x = fabsf(delta_x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isdrag) {
|
|
||||||
if (moving_up) {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (!grabc->next_in_stack && grabc->prev_in_stack && !isdrag) {
|
|
||||||
delta_y = delta_y * -1.0f;
|
|
||||||
}
|
|
||||||
if (!grabc->next_in_stack && grabc->prev_in_stack && isdrag) {
|
|
||||||
if (moving_down) {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!grabc->prev_in_stack && grabc->next_in_stack && isdrag) {
|
|
||||||
if (moving_up) {
|
|
||||||
delta_y = -fabsf(delta_y);
|
|
||||||
} else {
|
|
||||||
delta_y = fabsf(delta_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isdrag) {
|
|
||||||
if (moving_left) {
|
|
||||||
delta_x = -fabsf(delta_x);
|
|
||||||
} else {
|
|
||||||
delta_x = fabsf(delta_x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直接设置新的比例,基于初始值 + 变化量
|
// 直接设置新的比例,基于初始值 + 变化量
|
||||||
if (isvertical) {
|
if (isvertical) {
|
||||||
new_scroller_proportion =
|
new_scroller_proportion = grabc->old_scroller_pproportion + delta_y;
|
||||||
stack_head->old_scroller_pproportion + delta_y;
|
|
||||||
new_stack_proportion = grabc->old_stack_proportion + delta_x;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
new_scroller_proportion =
|
new_scroller_proportion = grabc->old_scroller_pproportion + delta_x;
|
||||||
stack_head->old_scroller_pproportion + delta_x;
|
|
||||||
new_stack_proportion = grabc->old_stack_proportion + delta_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应用限制,确保比例在合理范围内
|
// 应用限制,确保比例在合理范围内
|
||||||
new_scroller_proportion =
|
new_scroller_proportion =
|
||||||
fmaxf(0.1f, fminf(1.0f, new_scroller_proportion));
|
fmaxf(0.1f, fminf(1.0f, new_scroller_proportion));
|
||||||
new_stack_proportion = fmaxf(0.1f, fminf(0.9f, new_stack_proportion));
|
|
||||||
|
|
||||||
grabc->stack_proportion = new_stack_proportion;
|
grabc->scroller_proportion = new_scroller_proportion;
|
||||||
|
|
||||||
stack_head->scroller_proportion = new_scroller_proportion;
|
|
||||||
|
|
||||||
wl_list_for_each(tc, &clients, link) {
|
|
||||||
if (!isdrag && new_stack_proportion != 1.0f &&
|
|
||||||
grabc->old_stack_proportion != 1.0f && tc != grabc &&
|
|
||||||
ISTILED(tc) && get_scroll_stack_head(tc) == stack_head) {
|
|
||||||
tc->stack_proportion = (1.0f - new_stack_proportion) /
|
|
||||||
(1.0f - grabc->old_stack_proportion) *
|
|
||||||
tc->stack_proportion;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isdrag) {
|
if (!isdrag) {
|
||||||
arrange(grabc->mon, false, false);
|
arrange(grabc->mon, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_apply_drap_time == 0 ||
|
if (last_apply_drap_time == 0 ||
|
||||||
time - last_apply_drap_time > config.drag_tile_refresh_interval) {
|
time - last_apply_drap_time > drag_refresh_interval) {
|
||||||
arrange(grabc->mon, false, false);
|
arrange(grabc->mon, false);
|
||||||
last_apply_drap_time = time;
|
last_apply_drap_time = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize_tile_client(Client *grabc, bool isdrag, int32_t offsetx,
|
void resize_tile_client(Client *grabc, bool isdrag, int offsetx, int offsety,
|
||||||
int32_t offsety, uint32_t time) {
|
uint32_t time) {
|
||||||
|
|
||||||
if (!grabc || grabc->isfullscreen || grabc->ismaximizescreen)
|
if (!grabc || grabc->isfullscreen || grabc->ismaximizescreen)
|
||||||
return;
|
return;
|
||||||
|
|
@ -709,26 +502,14 @@ void resize_tile_client(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there are no calculation omissions,
|
void reset_size_per_mon(Monitor *m, int tile_cilent_num,
|
||||||
these two functions will never be triggered.
|
|
||||||
Just in case to facilitate the final investigation*/
|
|
||||||
|
|
||||||
void check_size_per_valid(Client *c) {
|
|
||||||
if (c->ismaster) {
|
|
||||||
assert(c->master_inner_per > 0.0f && c->master_inner_per <= 1.0f);
|
|
||||||
} else {
|
|
||||||
assert(c->stack_inner_per > 0.0f && c->stack_inner_per <= 1.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset_size_per_mon(Monitor *m, int32_t tile_cilent_num,
|
|
||||||
double total_left_stack_hight_percent,
|
double total_left_stack_hight_percent,
|
||||||
double total_right_stack_hight_percent,
|
double total_right_stack_hight_percent,
|
||||||
double total_stack_hight_percent,
|
double total_stack_hight_percent,
|
||||||
double total_master_inner_percent, int32_t master_num,
|
double total_master_inner_percent, int master_num,
|
||||||
int32_t stack_num) {
|
int stack_num) {
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
int32_t i = 0;
|
int i = 0;
|
||||||
uint32_t stack_index = 0;
|
uint32_t stack_index = 0;
|
||||||
uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
|
uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
|
||||||
|
|
||||||
|
|
@ -736,7 +517,6 @@ void reset_size_per_mon(Monitor *m, int32_t tile_cilent_num,
|
||||||
|
|
||||||
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)) {
|
||||||
|
|
||||||
if (total_master_inner_percent > 0.0 && i < nmasters) {
|
if (total_master_inner_percent > 0.0 && i < nmasters) {
|
||||||
c->ismaster = true;
|
c->ismaster = true;
|
||||||
c->stack_inner_per = stack_num ? 1.0f / stack_num : 1.0f;
|
c->stack_inner_per = stack_num ? 1.0f / stack_num : 1.0f;
|
||||||
|
|
@ -752,20 +532,17 @@ void reset_size_per_mon(Monitor *m, int32_t tile_cilent_num,
|
||||||
: 1.0f;
|
: 1.0f;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
check_size_per_valid(c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
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)) {
|
||||||
|
|
||||||
if (total_master_inner_percent > 0.0 && i < nmasters) {
|
if (total_master_inner_percent > 0.0 && i < nmasters) {
|
||||||
c->ismaster = true;
|
c->ismaster = true;
|
||||||
if ((stack_index % 2) ^ (tile_cilent_num % 2 == 0)) {
|
if ((stack_index % 2) ^ (tile_cilent_num % 2 == 0)) {
|
||||||
c->stack_inner_per =
|
c->stack_inner_per =
|
||||||
stack_num > 1 ? 1.0f / ((stack_num - 1) / 2.0f)
|
stack_num > 1 ? 1.0f / ((stack_num - 1) / 2) : 1.0f;
|
||||||
: 1.0f;
|
|
||||||
} else {
|
} else {
|
||||||
c->stack_inner_per =
|
c->stack_inner_per =
|
||||||
stack_num > 1 ? 2.0f / stack_num : 1.0f;
|
stack_num > 1 ? 2.0f / stack_num : 1.0f;
|
||||||
|
|
@ -794,53 +571,42 @@ void reset_size_per_mon(Monitor *m, int32_t tile_cilent_num,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
check_size_per_valid(c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
void // 17
|
||||||
bool from_view, bool only_caculate) {
|
arrange(Monitor *m, bool want_animation) {
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
double total_stack_inner_percent = 0;
|
double total_stack_inner_percent = 0;
|
||||||
double total_master_inner_percent = 0;
|
double total_master_inner_percent = 0;
|
||||||
double total_right_stack_hight_percent = 0;
|
double total_right_stack_hight_percent = 0;
|
||||||
double total_left_stack_hight_percent = 0;
|
double total_left_stack_hight_percent = 0;
|
||||||
int32_t i = 0;
|
int i = 0;
|
||||||
int32_t nmasters = 0;
|
int nmasters = 0;
|
||||||
int32_t stack_index = 0;
|
int stack_index = 0;
|
||||||
int32_t master_num = 0;
|
int master_num = 0;
|
||||||
int32_t stack_num = 0;
|
int stack_num = 0;
|
||||||
|
|
||||||
|
if (!m)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m->wlr_output->enabled)
|
||||||
|
return;
|
||||||
m->visible_clients = 0;
|
m->visible_clients = 0;
|
||||||
m->visible_tiling_clients = 0;
|
m->visible_tiling_clients = 0;
|
||||||
m->visible_scroll_tiling_clients = 0;
|
m->visible_scroll_tiling_clients = 0;
|
||||||
|
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
|
|
||||||
if (!client_only_in_one_tag(c) || c->isglobal || c->isunglobal) {
|
|
||||||
exit_scroller_stack(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from_view && (c->isglobal || c->isunglobal)) {
|
|
||||||
set_size_per(m, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->mon == m && (c->isglobal || c->isunglobal)) {
|
if (c->mon == m && (c->isglobal || c->isunglobal)) {
|
||||||
c->tags = m->tagset[m->seltags];
|
c->tags = m->tagset[m->seltags];
|
||||||
}
|
if (c->mon->sel == NULL)
|
||||||
|
focusclient(c, 0);
|
||||||
if (from_view && m->sel == NULL && c->isglobal && VISIBLEON(c, m)) {
|
|
||||||
focusclient(c, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VISIBLEON(c, m)) {
|
if (VISIBLEON(c, m)) {
|
||||||
if (from_view && !client_only_in_one_tag(c)) {
|
|
||||||
set_size_per(m, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!c->isunglobal)
|
if (!c->isunglobal)
|
||||||
m->visible_clients++;
|
m->visible_clients++;
|
||||||
|
|
||||||
|
|
@ -848,7 +614,7 @@ void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
||||||
m->visible_tiling_clients++;
|
m->visible_tiling_clients++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ISSCROLLTILED(c) && !c->prev_in_stack) {
|
if (ISSCROLLTILED(c)) {
|
||||||
m->visible_scroll_tiling_clients++;
|
m->visible_scroll_tiling_clients++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -886,17 +652,14 @@ void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!only_caculate)
|
|
||||||
set_arrange_visible(m, c, want_animation);
|
set_arrange_visible(m, c, want_animation);
|
||||||
} else {
|
} else {
|
||||||
if (!only_caculate)
|
|
||||||
set_arrange_hidden(m, c, want_animation);
|
set_arrange_hidden(m, c, want_animation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!only_caculate && c->mon == m && c->ismaximizescreen &&
|
if (c->mon == m && c->ismaximizescreen && !c->animation.tagouted &&
|
||||||
!c->animation.tagouted && !c->animation.tagouting &&
|
!c->animation.tagouting && VISIBLEON(c, m)) {
|
||||||
VISIBLEON(c, m)) {
|
|
||||||
reset_maximizescreen_size(c);
|
reset_maximizescreen_size(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -905,18 +668,6 @@ void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
||||||
m, m->visible_tiling_clients, total_left_stack_hight_percent,
|
m, m->visible_tiling_clients, total_left_stack_hight_percent,
|
||||||
total_right_stack_hight_percent, total_stack_inner_percent,
|
total_right_stack_hight_percent, total_stack_inner_percent,
|
||||||
total_master_inner_percent, master_num, stack_num);
|
total_master_inner_percent, master_num, stack_num);
|
||||||
}
|
|
||||||
|
|
||||||
void // 17
|
|
||||||
arrange(Monitor *m, bool want_animation, bool from_view) {
|
|
||||||
|
|
||||||
if (!m)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!m->wlr_output->enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pre_caculate_before_arrange(m, want_animation, from_view, false);
|
|
||||||
|
|
||||||
if (m->isoverview) {
|
if (m->isoverview) {
|
||||||
overviewlayout.arrange(m);
|
overviewlayout.arrange(m);
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,13 @@
|
||||||
// 网格布局窗口大小和位置计算
|
// 网格布局窗口大小和位置计算
|
||||||
void grid(Monitor *m) {
|
void grid(Monitor *m) {
|
||||||
int32_t i, n;
|
uint32_t i, n;
|
||||||
int32_t cx, cy, cw, ch;
|
uint32_t cx, cy, cw, ch;
|
||||||
int32_t dx;
|
uint32_t dx;
|
||||||
int32_t cols, rows, overcols;
|
uint32_t cols, rows, overcols;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
n = 0;
|
n = 0;
|
||||||
int32_t target_gappo =
|
int target_gappo = enablegaps ? m->isoverview ? overviewgappo : gappoh : 0;
|
||||||
enablegaps ? m->isoverview ? config.overviewgappo : config.gappoh : 0;
|
int target_gappi = enablegaps ? m->isoverview ? overviewgappi : gappih : 0;
|
||||||
int32_t target_gappi =
|
|
||||||
enablegaps ? m->isoverview ? config.overviewgappi : config.gappih : 0;
|
|
||||||
float single_width_ratio = m->isoverview ? 0.7 : 0.9;
|
float single_width_ratio = m->isoverview ? 0.7 : 0.9;
|
||||||
float single_height_ratio = m->isoverview ? 0.8 : 0.9;
|
float single_height_ratio = m->isoverview ? 0.8 : 0.9;
|
||||||
|
|
||||||
|
|
@ -112,23 +110,19 @@ void grid(Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void deck(Monitor *m) {
|
void deck(Monitor *m) {
|
||||||
int32_t mw, my;
|
uint32_t mw, my;
|
||||||
int32_t i, n = 0;
|
int i, n = 0;
|
||||||
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;
|
uint32_t cur_gappih = enablegaps ? m->gappih : 0;
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
uint32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
uint32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||||
|
|
||||||
cur_gappih =
|
cur_gappih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
||||||
cur_gappoh =
|
cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
|
||||||
cur_gappov =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
|
||||||
|
|
||||||
n = m->visible_tiling_clients;
|
n = m->visible_tiling_clients;
|
||||||
|
|
||||||
|
|
@ -146,8 +140,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 > nmasters)
|
if (n > m->nmaster)
|
||||||
mw = nmasters ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0;
|
mw = m->nmaster ? 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;
|
||||||
|
|
||||||
|
|
@ -155,7 +149,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 < nmasters) {
|
if (i < m->nmaster) {
|
||||||
c->master_mfact_per = mfact;
|
c->master_mfact_per = mfact;
|
||||||
// Master area clients
|
// Master area clients
|
||||||
resize(
|
resize(
|
||||||
|
|
@ -164,7 +158,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, nmasters) - i)},
|
(MIN(n, m->nmaster) - i)},
|
||||||
0);
|
0);
|
||||||
my += c->geom.height;
|
my += c->geom.height;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -187,19 +181,16 @@ void deck(Monitor *m) {
|
||||||
void horizontal_scroll_adjust_fullandmax(Client *c,
|
void horizontal_scroll_adjust_fullandmax(Client *c,
|
||||||
struct wlr_box *target_geom) {
|
struct wlr_box *target_geom) {
|
||||||
Monitor *m = c->mon;
|
Monitor *m = c->mon;
|
||||||
int32_t cur_gappih = enablegaps ? m->gappih : 0;
|
uint32_t cur_gappih = enablegaps ? m->gappih : 0;
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
uint32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
uint32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||||
|
|
||||||
cur_gappih = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
cur_gappih =
|
||||||
? 0
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappih;
|
||||||
: cur_gappih;
|
cur_gappoh =
|
||||||
cur_gappoh = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappoh;
|
||||||
? 0
|
cur_gappov =
|
||||||
: cur_gappoh;
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappov;
|
||||||
cur_gappov = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
|
||||||
? 0
|
|
||||||
: cur_gappov;
|
|
||||||
|
|
||||||
if (c->isfullscreen) {
|
if (c->isfullscreen) {
|
||||||
target_geom->height = m->m.height;
|
target_geom->height = m->m.height;
|
||||||
|
|
@ -219,94 +210,28 @@ void horizontal_scroll_adjust_fullandmax(Client *c,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arrange_stack(Client *scroller_stack_head, struct wlr_box geometry,
|
|
||||||
int32_t gappiv) {
|
|
||||||
int32_t stack_size = 0;
|
|
||||||
Client *iter = scroller_stack_head;
|
|
||||||
|
|
||||||
while (iter) {
|
|
||||||
stack_size++;
|
|
||||||
iter = iter->next_in_stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stack_size == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
float total_proportion = 0.0f;
|
|
||||||
iter = scroller_stack_head;
|
|
||||||
while (iter) {
|
|
||||||
if (iter->stack_proportion <= 0.0f || iter->stack_proportion >= 1.0f) {
|
|
||||||
iter->stack_proportion =
|
|
||||||
stack_size == 1 ? 1.0f : 1.0f / (stack_size - 1);
|
|
||||||
}
|
|
||||||
total_proportion += iter->stack_proportion;
|
|
||||||
iter = iter->next_in_stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
iter = scroller_stack_head;
|
|
||||||
while (iter) {
|
|
||||||
iter->stack_proportion = iter->stack_proportion / total_proportion;
|
|
||||||
iter = iter->next_in_stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t client_height;
|
|
||||||
int32_t current_y = geometry.y;
|
|
||||||
int32_t remain_client_height = geometry.height - (stack_size - 1) * gappiv;
|
|
||||||
float remain_proportion = 1.0f;
|
|
||||||
|
|
||||||
iter = scroller_stack_head;
|
|
||||||
while (iter) {
|
|
||||||
|
|
||||||
client_height =
|
|
||||||
remain_client_height * (iter->stack_proportion / remain_proportion);
|
|
||||||
|
|
||||||
struct wlr_box client_geom = {.x = geometry.x,
|
|
||||||
.y = current_y,
|
|
||||||
.width = geometry.width,
|
|
||||||
.height = client_height};
|
|
||||||
resize(iter, client_geom, 0);
|
|
||||||
remain_proportion -= iter->stack_proportion;
|
|
||||||
remain_client_height -= client_height;
|
|
||||||
current_y += client_height + gappiv;
|
|
||||||
iter = iter->next_in_stack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void horizontal_check_scroller_root_inside_mon(Client *c,
|
|
||||||
struct wlr_box *geometry) {
|
|
||||||
if (!GEOMINSIDEMON(geometry, c->mon)) {
|
|
||||||
geometry->x = c->mon->w.x + (c->mon->w.width - geometry->width) / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动布局
|
// 滚动布局
|
||||||
void scroller(Monitor *m) {
|
void scroller(Monitor *m) {
|
||||||
int32_t i, n, j;
|
uint32_t i, n, j;
|
||||||
float single_proportion = 1.0;
|
float single_proportion = 1.0;
|
||||||
|
|
||||||
Client *c = NULL, *root_client = NULL;
|
Client *c = NULL, *root_client = NULL;
|
||||||
Client **tempClients = NULL; // 初始化为 NULL
|
Client **tempClients = NULL; // 初始化为 NULL
|
||||||
struct wlr_box target_geom;
|
struct wlr_box target_geom;
|
||||||
int32_t focus_client_index = 0;
|
int focus_client_index = 0;
|
||||||
bool need_scroller = false;
|
bool need_scroller = false;
|
||||||
bool over_overspread_to_left = false;
|
uint32_t cur_gappih = enablegaps ? m->gappih : 0;
|
||||||
int32_t cur_gappih = enablegaps ? m->gappih : 0;
|
uint32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
uint32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
|
||||||
int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
|
||||||
|
|
||||||
cur_gappih = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
cur_gappih =
|
||||||
? 0
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappih;
|
||||||
: cur_gappih;
|
cur_gappoh =
|
||||||
cur_gappoh = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappoh;
|
||||||
? 0
|
cur_gappov =
|
||||||
: cur_gappoh;
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappov;
|
||||||
cur_gappov = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
|
||||||
? 0
|
|
||||||
: cur_gappov;
|
|
||||||
|
|
||||||
int32_t max_client_width =
|
uint32_t max_client_width = m->w.width - 2 * scroller_structs - cur_gappih;
|
||||||
m->w.width - 2 * config.scroller_structs - cur_gappih;
|
|
||||||
|
|
||||||
n = m->visible_scroll_tiling_clients;
|
n = m->visible_scroll_tiling_clients;
|
||||||
|
|
||||||
|
|
@ -324,26 +249,25 @@ void scroller(Monitor *m) {
|
||||||
// 第二次遍历,填充 tempClients
|
// 第二次遍历,填充 tempClients
|
||||||
j = 0;
|
j = 0;
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (VISIBLEON(c, m) && ISSCROLLTILED(c) && !c->prev_in_stack) {
|
if (VISIBLEON(c, m) && ISSCROLLTILED(c)) {
|
||||||
tempClients[j] = c;
|
tempClients[j] = c;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == 1 && !config.scroller_ignore_proportion_single &&
|
if (n == 1 && !scroller_ignore_proportion_single &&
|
||||||
!tempClients[0]->isfullscreen && !tempClients[0]->ismaximizescreen) {
|
!tempClients[0]->isfullscreen && !tempClients[0]->ismaximizescreen) {
|
||||||
c = tempClients[0];
|
c = tempClients[0];
|
||||||
|
|
||||||
single_proportion = c->scroller_proportion_single > 0.0f
|
single_proportion = c->scroller_proportion_single > 0.0f
|
||||||
? c->scroller_proportion_single
|
? c->scroller_proportion_single
|
||||||
: config.scroller_default_proportion_single;
|
: scroller_default_proportion_single;
|
||||||
|
|
||||||
target_geom.height = m->w.height - 2 * cur_gappov;
|
target_geom.height = m->w.height - 2 * cur_gappov;
|
||||||
target_geom.width = (m->w.width - 2 * cur_gappoh) * single_proportion;
|
target_geom.width = (m->w.width - 2 * cur_gappoh) * single_proportion;
|
||||||
target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2;
|
target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2;
|
||||||
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;
|
||||||
horizontal_check_scroller_root_inside_mon(c, &target_geom);
|
resize(c, target_geom, 0);
|
||||||
arrange_stack(c, target_geom, cur_gappiv);
|
|
||||||
free(tempClients); // 释放内存
|
free(tempClients); // 释放内存
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -357,11 +281,6 @@ void scroller(Monitor *m) {
|
||||||
root_client = center_tiled_select(m);
|
root_client = center_tiled_select(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// root_client might be in a stack, find the stack head
|
|
||||||
if (root_client) {
|
|
||||||
root_client = get_scroll_stack_head(root_client);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!root_client) {
|
if (!root_client) {
|
||||||
free(tempClients); // 释放内存
|
free(tempClients); // 释放内存
|
||||||
return;
|
return;
|
||||||
|
|
@ -370,9 +289,9 @@ void scroller(Monitor *m) {
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
c = tempClients[i];
|
c = tempClients[i];
|
||||||
if (root_client == c) {
|
if (root_client == c) {
|
||||||
if (c->geom.x >= m->w.x + config.scroller_structs &&
|
if (c->geom.x >= m->w.x + scroller_structs &&
|
||||||
c->geom.x + c->geom.width <=
|
c->geom.x + c->geom.width <=
|
||||||
m->w.x + m->w.width - config.scroller_structs) {
|
m->w.x + m->w.width - scroller_structs) {
|
||||||
need_scroller = false;
|
need_scroller = false;
|
||||||
} else {
|
} else {
|
||||||
need_scroller = true;
|
need_scroller = true;
|
||||||
|
|
@ -382,48 +301,7 @@ void scroller(Monitor *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool need_apply_overspread =
|
if (n == 1 && scroller_ignore_proportion_single) {
|
||||||
config.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 =
|
|
||||||
config.scroller_focus_center || m->visible_scroll_tiling_clients == 1 ||
|
|
||||||
(config.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 * config.scroller_structs - cur_gappih)));
|
|
||||||
|
|
||||||
if (n == 1 && config.scroller_ignore_proportion_single) {
|
|
||||||
need_scroller = true;
|
need_scroller = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -437,47 +315,31 @@ void scroller(Monitor *m) {
|
||||||
&target_geom);
|
&target_geom);
|
||||||
if (tempClients[focus_client_index]->isfullscreen) {
|
if (tempClients[focus_client_index]->isfullscreen) {
|
||||||
target_geom.x = m->m.x;
|
target_geom.x = m->m.x;
|
||||||
horizontal_check_scroller_root_inside_mon(
|
resize(tempClients[focus_client_index], target_geom, 0);
|
||||||
tempClients[focus_client_index], &target_geom);
|
|
||||||
arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv);
|
|
||||||
} else if (tempClients[focus_client_index]->ismaximizescreen) {
|
} else if (tempClients[focus_client_index]->ismaximizescreen) {
|
||||||
target_geom.x = m->w.x + cur_gappoh;
|
target_geom.x = m->w.x + cur_gappoh;
|
||||||
horizontal_check_scroller_root_inside_mon(
|
resize(tempClients[focus_client_index], target_geom, 0);
|
||||||
tempClients[focus_client_index], &target_geom);
|
|
||||||
arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv);
|
|
||||||
} else if (need_scroller) {
|
} else if (need_scroller) {
|
||||||
if (need_apply_center) {
|
if (scroller_focus_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 + config.scroller_structs;
|
|
||||||
} else {
|
} else {
|
||||||
target_geom.x =
|
target_geom.x = root_client->geom.x > m->w.x + (m->w.width) / 2
|
||||||
m->w.x +
|
|
||||||
(m->w.width -
|
|
||||||
tempClients[focus_client_index]->scroller_proportion *
|
|
||||||
max_client_width -
|
|
||||||
config.scroller_structs);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
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 -
|
||||||
tempClients[focus_client_index]
|
root_client->scroller_proportion *
|
||||||
->scroller_proportion *
|
|
||||||
max_client_width -
|
max_client_width -
|
||||||
config.scroller_structs)
|
scroller_structs)
|
||||||
: m->w.x + config.scroller_structs;
|
: m->w.x + scroller_structs;
|
||||||
}
|
}
|
||||||
horizontal_check_scroller_root_inside_mon(
|
resize(tempClients[focus_client_index], target_geom, 0);
|
||||||
tempClients[focus_client_index], &target_geom);
|
|
||||||
arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv);
|
|
||||||
} else {
|
} else {
|
||||||
target_geom.x = c->geom.x;
|
target_geom.x = c->geom.x;
|
||||||
horizontal_check_scroller_root_inside_mon(
|
resize(tempClients[focus_client_index], target_geom, 0);
|
||||||
tempClients[focus_client_index], &target_geom);
|
|
||||||
arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i <= focus_client_index; i++) {
|
for (i = 1; i <= focus_client_index; i++) {
|
||||||
|
|
@ -487,7 +349,7 @@ void scroller(Monitor *m) {
|
||||||
target_geom.x = tempClients[focus_client_index - i + 1]->geom.x -
|
target_geom.x = tempClients[focus_client_index - i + 1]->geom.x -
|
||||||
cur_gappih - target_geom.width;
|
cur_gappih - target_geom.width;
|
||||||
|
|
||||||
arrange_stack(c, target_geom, cur_gappiv);
|
resize(c, target_geom, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i < n - focus_client_index; i++) {
|
for (i = 1; i < n - focus_client_index; i++) {
|
||||||
|
|
@ -497,19 +359,19 @@ void scroller(Monitor *m) {
|
||||||
target_geom.x = tempClients[focus_client_index + i - 1]->geom.x +
|
target_geom.x = tempClients[focus_client_index + i - 1]->geom.x +
|
||||||
cur_gappih +
|
cur_gappih +
|
||||||
tempClients[focus_client_index + i - 1]->geom.width;
|
tempClients[focus_client_index + i - 1]->geom.width;
|
||||||
arrange_stack(c, target_geom, cur_gappiv);
|
resize(c, target_geom, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(tempClients); // 最后释放内存
|
free(tempClients); // 最后释放内存
|
||||||
}
|
}
|
||||||
|
|
||||||
void center_tile(Monitor *m) {
|
void center_tile(Monitor *m) {
|
||||||
int32_t i, n = 0, h, r, ie = enablegaps, mw, mx, my, oty, ety, tw;
|
uint32_t i, n = 0, h, r, ie = enablegaps, mw, mx, my, oty, ety, tw;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
Client *fc = NULL;
|
Client *fc = NULL;
|
||||||
double mfact = 0;
|
double mfact = 0;
|
||||||
int32_t master_num = 0;
|
int master_num = 0;
|
||||||
int32_t stack_num = 0;
|
int stack_num = 0;
|
||||||
|
|
||||||
n = m->visible_tiling_clients;
|
n = m->visible_tiling_clients;
|
||||||
master_num = m->pertag->nmasters[m->pertag->curtag];
|
master_num = m->pertag->nmasters[m->pertag->curtag];
|
||||||
|
|
@ -527,22 +389,18 @@ void center_tile(Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 间隙参数处理
|
// 间隙参数处理
|
||||||
int32_t cur_gappiv = enablegaps ? m->gappiv : 0; // 内部垂直间隙
|
uint32_t cur_gappiv = enablegaps ? m->gappiv : 0; // 内部垂直间隙
|
||||||
int32_t cur_gappih = enablegaps ? m->gappih : 0; // 内部水平间隙
|
uint32_t cur_gappih = enablegaps ? m->gappih : 0; // 内部水平间隙
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0; // 外部垂直间隙
|
uint32_t cur_gappov = enablegaps ? m->gappov : 0; // 外部垂直间隙
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0; // 外部水平间隙
|
uint32_t cur_gappoh = enablegaps ? m->gappoh : 0; // 外部水平间隙
|
||||||
|
|
||||||
// 智能间隙处理
|
// 智能间隙处理
|
||||||
cur_gappiv =
|
cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
cur_gappih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
||||||
cur_gappih =
|
cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
||||||
cur_gappov =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
|
||||||
cur_gappoh =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
|
||||||
|
|
||||||
int32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
|
uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
|
||||||
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
|
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
|
||||||
: m->pertag->mfacts[m->pertag->curtag];
|
: m->pertag->mfacts[m->pertag->curtag];
|
||||||
|
|
||||||
|
|
@ -553,18 +411,17 @@ void center_tile(Monitor *m) {
|
||||||
tw = mw;
|
tw = mw;
|
||||||
|
|
||||||
// 判断是否需要主区域铺满
|
// 判断是否需要主区域铺满
|
||||||
int32_t should_overspread =
|
int should_overspread = center_master_overspread && (n <= nmasters);
|
||||||
config.center_master_overspread && (n <= nmasters);
|
|
||||||
|
|
||||||
int32_t master_surplus_height =
|
uint32_t master_surplus_height =
|
||||||
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
||||||
float master_surplus_ratio = 1.0;
|
float master_surplus_ratio = 1.0;
|
||||||
|
|
||||||
int32_t slave_left_surplus_height =
|
uint32_t slave_left_surplus_height =
|
||||||
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num / 2 - 1));
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num / 2 - 1));
|
||||||
float slave_left_surplus_ratio = 1.0;
|
float slave_left_surplus_ratio = 1.0;
|
||||||
|
|
||||||
int32_t slave_right_surplus_height =
|
uint32_t slave_right_surplus_height =
|
||||||
(m->w.height - 2 * cur_gappov -
|
(m->w.height - 2 * cur_gappov -
|
||||||
cur_gappiv * ie * ((stack_num + 1) / 2 - 1));
|
cur_gappiv * ie * ((stack_num + 1) / 2 - 1));
|
||||||
float slave_right_surplus_ratio = 1.0;
|
float slave_right_surplus_ratio = 1.0;
|
||||||
|
|
@ -580,7 +437,7 @@ void center_tile(Monitor *m) {
|
||||||
mx = cur_gappoh + tw + cur_gappih * ie;
|
mx = cur_gappoh + tw + cur_gappih * ie;
|
||||||
} else if (n - nmasters == 1) {
|
} else if (n - nmasters == 1) {
|
||||||
// 单个堆叠窗口的处理
|
// 单个堆叠窗口的处理
|
||||||
if (config.center_when_single_stack) {
|
if (center_when_single_stack) {
|
||||||
// stack在右边,master居中,左边空着
|
// stack在右边,master居中,左边空着
|
||||||
tw = (m->w.width - mw) / 2 - cur_gappoh - cur_gappih * ie;
|
tw = (m->w.width - mw) / 2 - cur_gappoh - cur_gappih * ie;
|
||||||
mx = cur_gappoh + tw + cur_gappih * ie; // master居中
|
mx = cur_gappoh + tw + cur_gappih * ie; // master居中
|
||||||
|
|
@ -637,7 +494,7 @@ void center_tile(Monitor *m) {
|
||||||
my += c->geom.height + cur_gappiv * ie;
|
my += c->geom.height + cur_gappiv * ie;
|
||||||
} else {
|
} else {
|
||||||
// 堆叠区域窗口
|
// 堆叠区域窗口
|
||||||
int32_t stack_index = i - nmasters;
|
uint32_t stack_index = i - nmasters;
|
||||||
|
|
||||||
if (n - nmasters == 1) {
|
if (n - nmasters == 1) {
|
||||||
// 单个堆叠窗口
|
// 单个堆叠窗口
|
||||||
|
|
@ -656,8 +513,8 @@ void center_tile(Monitor *m) {
|
||||||
c->master_mfact_per = mfact;
|
c->master_mfact_per = mfact;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t stack_x;
|
int stack_x;
|
||||||
if (config.center_when_single_stack) {
|
if (center_when_single_stack) {
|
||||||
// 放在右侧(master居中时,stack在右边)
|
// 放在右侧(master居中时,stack在右边)
|
||||||
stack_x = m->w.x + mx + mw + cur_gappih * ie;
|
stack_x = m->w.x + mx + mw + cur_gappih * ie;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -696,7 +553,7 @@ void center_tile(Monitor *m) {
|
||||||
c->master_mfact_per = mfact;
|
c->master_mfact_per = mfact;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t stack_x = m->w.x + mx + mw + cur_gappih * ie;
|
int stack_x = m->w.x + mx + mw + cur_gappih * ie;
|
||||||
|
|
||||||
resize(c,
|
resize(c,
|
||||||
(struct wlr_box){.x = stack_x,
|
(struct wlr_box){.x = stack_x,
|
||||||
|
|
@ -725,7 +582,7 @@ void center_tile(Monitor *m) {
|
||||||
c->master_mfact_per = mfact;
|
c->master_mfact_per = mfact;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t stack_x = m->w.x + cur_gappoh;
|
int stack_x = m->w.x + cur_gappoh;
|
||||||
resize(c,
|
resize(c,
|
||||||
(struct wlr_box){.x = stack_x,
|
(struct wlr_box){.x = stack_x,
|
||||||
.y = m->w.y + oty,
|
.y = m->w.y + oty,
|
||||||
|
|
@ -741,12 +598,12 @@ void center_tile(Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void tile(Monitor *m) {
|
void tile(Monitor *m) {
|
||||||
int32_t i, n = 0, h, r, ie = enablegaps, mw, my, ty;
|
uint32_t i, n = 0, h, r, ie = enablegaps, mw, my, ty;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
Client *fc = NULL;
|
Client *fc = NULL;
|
||||||
double mfact = 0;
|
double mfact = 0;
|
||||||
int32_t master_num = 0;
|
int master_num = 0;
|
||||||
int32_t stack_num = 0;
|
int stack_num = 0;
|
||||||
|
|
||||||
n = m->visible_tiling_clients;
|
n = m->visible_tiling_clients;
|
||||||
master_num = m->pertag->nmasters[m->pertag->curtag];
|
master_num = m->pertag->nmasters[m->pertag->curtag];
|
||||||
|
|
@ -756,19 +613,15 @@ void tile(Monitor *m) {
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
uint32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
||||||
int32_t cur_gappih = enablegaps ? m->gappih : 0;
|
uint32_t cur_gappih = enablegaps ? m->gappih : 0;
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
uint32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
uint32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||||
|
|
||||||
cur_gappiv =
|
cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
cur_gappih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
||||||
cur_gappih =
|
cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
||||||
cur_gappov =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
|
||||||
cur_gappoh =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
|
||||||
|
|
||||||
wl_list_for_each(fc, &clients, link) {
|
wl_list_for_each(fc, &clients, link) {
|
||||||
|
|
||||||
|
|
@ -788,11 +641,11 @@ void tile(Monitor *m) {
|
||||||
i = 0;
|
i = 0;
|
||||||
my = ty = cur_gappov;
|
my = ty = cur_gappov;
|
||||||
|
|
||||||
int32_t master_surplus_height =
|
uint32_t master_surplus_height =
|
||||||
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
||||||
float master_surplus_ratio = 1.0;
|
float master_surplus_ratio = 1.0;
|
||||||
|
|
||||||
int32_t slave_surplus_height =
|
uint32_t slave_surplus_height =
|
||||||
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1));
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1));
|
||||||
float slave_surplus_ratio = 1.0;
|
float slave_surplus_ratio = 1.0;
|
||||||
|
|
||||||
|
|
@ -855,12 +708,12 @@ void tile(Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void right_tile(Monitor *m) {
|
void right_tile(Monitor *m) {
|
||||||
int32_t i, n = 0, h, r, ie = enablegaps, mw, my, ty;
|
uint32_t i, n = 0, h, r, ie = enablegaps, mw, my, ty;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
Client *fc = NULL;
|
Client *fc = NULL;
|
||||||
double mfact = 0;
|
double mfact = 0;
|
||||||
int32_t master_num = 0;
|
int master_num = 0;
|
||||||
int32_t stack_num = 0;
|
int stack_num = 0;
|
||||||
|
|
||||||
n = m->visible_tiling_clients;
|
n = m->visible_tiling_clients;
|
||||||
master_num = m->pertag->nmasters[m->pertag->curtag];
|
master_num = m->pertag->nmasters[m->pertag->curtag];
|
||||||
|
|
@ -870,19 +723,15 @@ void right_tile(Monitor *m) {
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
uint32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
||||||
int32_t cur_gappih = enablegaps ? m->gappih : 0;
|
uint32_t cur_gappih = enablegaps ? m->gappih : 0;
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
uint32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
uint32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||||
|
|
||||||
cur_gappiv =
|
cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
cur_gappih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
||||||
cur_gappih =
|
cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
||||||
cur_gappov =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
|
||||||
cur_gappoh =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
|
||||||
|
|
||||||
wl_list_for_each(fc, &clients, link) {
|
wl_list_for_each(fc, &clients, link) {
|
||||||
|
|
||||||
|
|
@ -902,11 +751,11 @@ void right_tile(Monitor *m) {
|
||||||
i = 0;
|
i = 0;
|
||||||
my = ty = cur_gappov;
|
my = ty = cur_gappov;
|
||||||
|
|
||||||
int32_t master_surplus_height =
|
uint32_t master_surplus_height =
|
||||||
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
||||||
float master_surplus_ratio = 1.0;
|
float master_surplus_ratio = 1.0;
|
||||||
|
|
||||||
int32_t slave_surplus_height =
|
uint32_t slave_surplus_height =
|
||||||
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1));
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1));
|
||||||
float slave_surplus_ratio = 1.0;
|
float slave_surplus_ratio = 1.0;
|
||||||
|
|
||||||
|
|
@ -974,13 +823,11 @@ monocle(Monitor *m) {
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
struct wlr_box geom;
|
struct wlr_box geom;
|
||||||
|
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
uint32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
uint32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||||
|
|
||||||
cur_gappoh =
|
cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
||||||
cur_gappov =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
|
||||||
|
|
||||||
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))
|
||||||
|
|
@ -996,7 +843,7 @@ monocle(Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgmix(Monitor *m) {
|
void tgmix(Monitor *m) {
|
||||||
int32_t n = m->visible_tiling_clients;
|
uint32_t n = m->visible_tiling_clients;
|
||||||
if (n <= 3) {
|
if (n <= 3) {
|
||||||
tile(m);
|
tile(m);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ static void tgmix(Monitor *m);
|
||||||
Layout overviewlayout = {"", overview, "overview"};
|
Layout overviewlayout = {"", overview, "overview"};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TILE,
|
|
||||||
SCROLLER,
|
SCROLLER,
|
||||||
|
TILE,
|
||||||
GRID,
|
GRID,
|
||||||
MONOCLE,
|
MONOCLE,
|
||||||
DECK,
|
DECK,
|
||||||
|
|
@ -34,8 +34,8 @@ enum {
|
||||||
Layout layouts[] = {
|
Layout layouts[] = {
|
||||||
// 最少两个,不能删除少于两个
|
// 最少两个,不能删除少于两个
|
||||||
/* symbol arrange function name */
|
/* symbol arrange function name */
|
||||||
{"T", tile, "tile", TILE}, // 平铺布局
|
|
||||||
{"S", scroller, "scroller", SCROLLER}, // 滚动布局
|
{"S", scroller, "scroller", SCROLLER}, // 滚动布局
|
||||||
|
{"T", tile, "tile", TILE}, // 平铺布局
|
||||||
{"G", grid, "grid", GRID}, // 格子布局
|
{"G", grid, "grid", GRID}, // 格子布局
|
||||||
{"M", monocle, "monocle", MONOCLE}, // 单屏布局
|
{"M", monocle, "monocle", MONOCLE}, // 单屏布局
|
||||||
{"K", deck, "deck", DECK}, // 卡片布局
|
{"K", deck, "deck", DECK}, // 卡片布局
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
void vertical_tile(Monitor *m) {
|
void vertical_tile(Monitor *m) {
|
||||||
int32_t i, n = 0, w, r, ie = enablegaps, mh, mx, tx;
|
uint32_t i, n = 0, w, r, ie = enablegaps, mh, mx, tx;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
Client *fc = NULL;
|
Client *fc = NULL;
|
||||||
double mfact = 0;
|
double mfact = 0;
|
||||||
int32_t master_num = 0;
|
int master_num = 0;
|
||||||
int32_t stack_num = 0;
|
int stack_num = 0;
|
||||||
|
|
||||||
n = m->visible_tiling_clients;
|
n = m->visible_tiling_clients;
|
||||||
master_num = m->pertag->nmasters[m->pertag->curtag];
|
master_num = m->pertag->nmasters[m->pertag->curtag];
|
||||||
|
|
@ -14,19 +14,15 @@ void vertical_tile(Monitor *m) {
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int32_t cur_gapih = enablegaps ? m->gappih : 0;
|
uint32_t cur_gapih = enablegaps ? m->gappih : 0;
|
||||||
int32_t cur_gapiv = enablegaps ? m->gappiv : 0;
|
uint32_t cur_gapiv = enablegaps ? m->gappiv : 0;
|
||||||
int32_t cur_gapoh = enablegaps ? m->gappoh : 0;
|
uint32_t cur_gapoh = enablegaps ? m->gappoh : 0;
|
||||||
int32_t cur_gapov = enablegaps ? m->gappov : 0;
|
uint32_t cur_gapov = enablegaps ? m->gappov : 0;
|
||||||
|
|
||||||
cur_gapih =
|
cur_gapih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapih;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapih;
|
cur_gapiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapiv;
|
||||||
cur_gapiv =
|
cur_gapoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapoh;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapiv;
|
cur_gapov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapov;
|
||||||
cur_gapoh =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapoh;
|
|
||||||
cur_gapov =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapov;
|
|
||||||
|
|
||||||
wl_list_for_each(fc, &clients, link) {
|
wl_list_for_each(fc, &clients, link) {
|
||||||
if (VISIBLEON(fc, m) && ISTILED(fc))
|
if (VISIBLEON(fc, m) && ISTILED(fc))
|
||||||
|
|
@ -44,14 +40,14 @@ void vertical_tile(Monitor *m) {
|
||||||
mh = m->w.height - 2 * cur_gapov + cur_gapiv * ie;
|
mh = m->w.height - 2 * cur_gapov + cur_gapiv * ie;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
mx = tx = cur_gapoh;
|
mx = tx = cur_gapih;
|
||||||
|
|
||||||
int32_t master_surplus_width =
|
uint32_t master_surplus_width =
|
||||||
(m->w.width - 2 * cur_gapoh - cur_gapih * ie * (master_num - 1));
|
(m->w.width - 2 * cur_gapih - cur_gapih * ie * (master_num - 1));
|
||||||
float master_surplus_ratio = 1.0;
|
float master_surplus_ratio = 1.0;
|
||||||
|
|
||||||
int32_t slave_surplus_width =
|
uint32_t slave_surplus_width =
|
||||||
(m->w.width - 2 * cur_gapoh - cur_gapih * ie * (stack_num - 1));
|
(m->w.width - 2 * cur_gapih - cur_gapih * ie * (stack_num - 1));
|
||||||
float slave_surplus_ratio = 1.0;
|
float slave_surplus_ratio = 1.0;
|
||||||
|
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
|
|
@ -109,23 +105,19 @@ void vertical_tile(Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void vertical_deck(Monitor *m) {
|
void vertical_deck(Monitor *m) {
|
||||||
int32_t mh, mx;
|
uint32_t mh, mx;
|
||||||
int32_t i, n = 0;
|
int i, n = 0;
|
||||||
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;
|
uint32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
uint32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
uint32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||||
|
|
||||||
cur_gappiv =
|
cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
||||||
cur_gappoh =
|
cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
|
||||||
cur_gappov =
|
|
||||||
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
|
||||||
|
|
||||||
n = m->visible_tiling_clients;
|
n = m->visible_tiling_clients;
|
||||||
|
|
||||||
|
|
@ -142,8 +134,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 > nmasters)
|
if (n > m->nmaster)
|
||||||
mh = nmasters ? round((m->w.height - 2 * cur_gappov) * mfact) : 0;
|
mh = m->nmaster ? 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;
|
||||||
|
|
||||||
|
|
@ -151,13 +143,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 < nmasters) {
|
if (i < m->nmaster) {
|
||||||
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, nmasters) - i),
|
(MIN(n, m->nmaster) - i),
|
||||||
.height = mh},
|
.height = mh},
|
||||||
0);
|
0);
|
||||||
mx += c->geom.width;
|
mx += c->geom.width;
|
||||||
|
|
@ -178,19 +170,16 @@ void vertical_deck(Monitor *m) {
|
||||||
|
|
||||||
void vertical_scroll_adjust_fullandmax(Client *c, struct wlr_box *target_geom) {
|
void vertical_scroll_adjust_fullandmax(Client *c, struct wlr_box *target_geom) {
|
||||||
Monitor *m = c->mon;
|
Monitor *m = c->mon;
|
||||||
int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
uint32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
uint32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
uint32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||||
|
|
||||||
cur_gappiv = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
cur_gappiv =
|
||||||
? 0
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappiv;
|
||||||
: cur_gappiv;
|
cur_gappov =
|
||||||
cur_gappov = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappov;
|
||||||
? 0
|
cur_gappoh =
|
||||||
: cur_gappov;
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappoh;
|
||||||
cur_gappoh = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
|
||||||
? 0
|
|
||||||
: cur_gappoh;
|
|
||||||
|
|
||||||
if (c->isfullscreen) {
|
if (c->isfullscreen) {
|
||||||
target_geom->width = m->m.width;
|
target_geom->width = m->m.width;
|
||||||
|
|
@ -210,94 +199,29 @@ void vertical_scroll_adjust_fullandmax(Client *c, struct wlr_box *target_geom) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arrange_stack_vertical(Client *scroller_stack_head,
|
|
||||||
struct wlr_box geometry, int32_t gappih) {
|
|
||||||
int32_t stack_size = 0;
|
|
||||||
Client *iter = scroller_stack_head;
|
|
||||||
|
|
||||||
while (iter) {
|
|
||||||
stack_size++;
|
|
||||||
iter = iter->next_in_stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stack_size == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
float total_proportion = 0.0f;
|
|
||||||
iter = scroller_stack_head;
|
|
||||||
while (iter) {
|
|
||||||
if (iter->stack_proportion <= 0.0f || iter->stack_proportion >= 1.0f) {
|
|
||||||
iter->stack_proportion =
|
|
||||||
stack_size == 1 ? 1.0f : 1.0f / (stack_size - 1);
|
|
||||||
}
|
|
||||||
total_proportion += iter->stack_proportion;
|
|
||||||
iter = iter->next_in_stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
iter = scroller_stack_head;
|
|
||||||
while (iter) {
|
|
||||||
iter->stack_proportion = iter->stack_proportion / total_proportion;
|
|
||||||
iter = iter->next_in_stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t client_width;
|
|
||||||
int32_t current_x = geometry.x;
|
|
||||||
int32_t remain_client_width = geometry.width - (stack_size - 1) * gappih;
|
|
||||||
float remain_proportion = 1.0f;
|
|
||||||
|
|
||||||
iter = scroller_stack_head;
|
|
||||||
while (iter) {
|
|
||||||
|
|
||||||
client_width =
|
|
||||||
remain_client_width * (iter->stack_proportion / remain_proportion);
|
|
||||||
|
|
||||||
struct wlr_box client_geom = {.y = geometry.y,
|
|
||||||
.x = current_x,
|
|
||||||
.height = geometry.height,
|
|
||||||
.width = client_width};
|
|
||||||
resize(iter, client_geom, 0);
|
|
||||||
remain_proportion -= iter->stack_proportion;
|
|
||||||
remain_client_width -= client_width;
|
|
||||||
current_x += client_width + gappih;
|
|
||||||
iter = iter->next_in_stack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vertical_check_scroller_root_inside_mon(Client *c,
|
|
||||||
struct wlr_box *geometry) {
|
|
||||||
if (!GEOMINSIDEMON(geometry, c->mon)) {
|
|
||||||
geometry->y = c->mon->w.y + (c->mon->w.height - geometry->height) / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 竖屏滚动布局
|
// 竖屏滚动布局
|
||||||
void vertical_scroller(Monitor *m) {
|
void vertical_scroller(Monitor *m) {
|
||||||
int32_t i, n, j;
|
uint32_t i, n, j;
|
||||||
float single_proportion = 1.0;
|
float single_proportion = 1.0;
|
||||||
|
|
||||||
Client *c = NULL, *root_client = NULL;
|
Client *c = NULL, *root_client = NULL;
|
||||||
Client **tempClients = NULL;
|
Client **tempClients = NULL;
|
||||||
struct wlr_box target_geom;
|
struct wlr_box target_geom;
|
||||||
int32_t focus_client_index = 0;
|
int focus_client_index = 0;
|
||||||
bool need_scroller = false;
|
bool need_scroller = false;
|
||||||
bool over_overspread_to_up = false;
|
uint32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
||||||
int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
uint32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
uint32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
|
||||||
int32_t cur_gappih = enablegaps ? m->gappih : 0;
|
|
||||||
|
|
||||||
cur_gappiv = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
cur_gappiv =
|
||||||
? 0
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappiv;
|
||||||
: cur_gappiv;
|
cur_gappov =
|
||||||
cur_gappov = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappov;
|
||||||
? 0
|
cur_gappoh =
|
||||||
: cur_gappov;
|
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappoh;
|
||||||
cur_gappoh = config.smartgaps && m->visible_scroll_tiling_clients == 1
|
|
||||||
? 0
|
|
||||||
: cur_gappoh;
|
|
||||||
|
|
||||||
int32_t max_client_height =
|
uint32_t max_client_height =
|
||||||
m->w.height - 2 * config.scroller_structs - cur_gappiv;
|
m->w.height - 2 * scroller_structs - cur_gappiv;
|
||||||
|
|
||||||
n = m->visible_scroll_tiling_clients;
|
n = m->visible_scroll_tiling_clients;
|
||||||
|
|
||||||
|
|
@ -312,26 +236,25 @@ void vertical_scroller(Monitor *m) {
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (VISIBLEON(c, m) && ISSCROLLTILED(c) && !c->prev_in_stack) {
|
if (VISIBLEON(c, m) && ISSCROLLTILED(c)) {
|
||||||
tempClients[j] = c;
|
tempClients[j] = c;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == 1 && !config.scroller_ignore_proportion_single &&
|
if (n == 1 && !scroller_ignore_proportion_single &&
|
||||||
!tempClients[0]->isfullscreen && !tempClients[0]->ismaximizescreen) {
|
!tempClients[0]->isfullscreen && !tempClients[0]->ismaximizescreen) {
|
||||||
c = tempClients[0];
|
c = tempClients[0];
|
||||||
|
|
||||||
single_proportion = c->scroller_proportion_single > 0.0f
|
single_proportion = c->scroller_proportion_single > 0.0f
|
||||||
? c->scroller_proportion_single
|
? c->scroller_proportion_single
|
||||||
: config.scroller_default_proportion_single;
|
: scroller_default_proportion_single;
|
||||||
|
|
||||||
target_geom.width = m->w.width - 2 * cur_gappoh;
|
target_geom.width = m->w.width - 2 * cur_gappoh;
|
||||||
target_geom.height = (m->w.height - 2 * cur_gappov) * single_proportion;
|
target_geom.height = (m->w.height - 2 * cur_gappov) * single_proportion;
|
||||||
target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2;
|
target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2;
|
||||||
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;
|
||||||
vertical_check_scroller_root_inside_mon(c, &target_geom);
|
resize(c, target_geom, 0);
|
||||||
arrange_stack_vertical(c, target_geom, cur_gappih);
|
|
||||||
free(tempClients);
|
free(tempClients);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -345,11 +268,6 @@ void vertical_scroller(Monitor *m) {
|
||||||
root_client = center_tiled_select(m);
|
root_client = center_tiled_select(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// root_client might be in a stack, find the stack head
|
|
||||||
if (root_client) {
|
|
||||||
root_client = get_scroll_stack_head(root_client);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!root_client) {
|
if (!root_client) {
|
||||||
free(tempClients);
|
free(tempClients);
|
||||||
return;
|
return;
|
||||||
|
|
@ -358,9 +276,9 @@ void vertical_scroller(Monitor *m) {
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
c = tempClients[i];
|
c = tempClients[i];
|
||||||
if (root_client == c) {
|
if (root_client == c) {
|
||||||
if (c->geom.y >= m->w.y + config.scroller_structs &&
|
if (c->geom.y >= m->w.y + scroller_structs &&
|
||||||
c->geom.y + c->geom.height <=
|
c->geom.y + c->geom.height <=
|
||||||
m->w.y + m->w.height - config.scroller_structs) {
|
m->w.y + m->w.height - scroller_structs) {
|
||||||
need_scroller = false;
|
need_scroller = false;
|
||||||
} else {
|
} else {
|
||||||
need_scroller = true;
|
need_scroller = true;
|
||||||
|
|
@ -370,48 +288,7 @@ void vertical_scroller(Monitor *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool need_apply_overspread =
|
if (n == 1 && scroller_ignore_proportion_single) {
|
||||||
config.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 =
|
|
||||||
config.scroller_focus_center || m->visible_scroll_tiling_clients == 1 ||
|
|
||||||
(config.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 * config.scroller_structs - cur_gappiv)));
|
|
||||||
|
|
||||||
if (n == 1 && config.scroller_ignore_proportion_single) {
|
|
||||||
need_scroller = true;
|
need_scroller = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -426,49 +303,31 @@ void vertical_scroller(Monitor *m) {
|
||||||
|
|
||||||
if (tempClients[focus_client_index]->isfullscreen) {
|
if (tempClients[focus_client_index]->isfullscreen) {
|
||||||
target_geom.y = m->m.y;
|
target_geom.y = m->m.y;
|
||||||
vertical_check_scroller_root_inside_mon(tempClients[focus_client_index],
|
resize(tempClients[focus_client_index], target_geom, 0);
|
||||||
&target_geom);
|
|
||||||
arrange_stack_vertical(tempClients[focus_client_index], target_geom,
|
|
||||||
cur_gappih);
|
|
||||||
} else if (tempClients[focus_client_index]->ismaximizescreen) {
|
} else if (tempClients[focus_client_index]->ismaximizescreen) {
|
||||||
target_geom.y = m->w.y + cur_gappov;
|
target_geom.y = m->w.y + cur_gappov;
|
||||||
vertical_check_scroller_root_inside_mon(tempClients[focus_client_index],
|
resize(tempClients[focus_client_index], target_geom, 0);
|
||||||
&target_geom);
|
|
||||||
arrange_stack_vertical(tempClients[focus_client_index], target_geom,
|
|
||||||
cur_gappih);
|
|
||||||
} else if (need_scroller) {
|
} else if (need_scroller) {
|
||||||
if (need_apply_center) {
|
if (scroller_focus_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 + config.scroller_structs;
|
|
||||||
} else {
|
|
||||||
target_geom.y =
|
|
||||||
m->w.y +
|
|
||||||
(m->w.height -
|
|
||||||
tempClients[focus_client_index]->scroller_proportion *
|
|
||||||
max_client_height -
|
|
||||||
config.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 -
|
||||||
tempClients[focus_client_index]
|
root_client->scroller_proportion *
|
||||||
->scroller_proportion *
|
|
||||||
max_client_height -
|
max_client_height -
|
||||||
config.scroller_structs)
|
scroller_structs)
|
||||||
: m->w.y + config.scroller_structs;
|
: m->w.y + scroller_structs;
|
||||||
}
|
}
|
||||||
vertical_check_scroller_root_inside_mon(tempClients[focus_client_index],
|
resize(tempClients[focus_client_index], target_geom, 0);
|
||||||
&target_geom);
|
|
||||||
arrange_stack_vertical(tempClients[focus_client_index], target_geom,
|
|
||||||
cur_gappih);
|
|
||||||
} else {
|
} else {
|
||||||
target_geom.y = c->geom.y;
|
target_geom.y = c->geom.y;
|
||||||
vertical_check_scroller_root_inside_mon(tempClients[focus_client_index],
|
resize(tempClients[focus_client_index], target_geom, 0);
|
||||||
&target_geom);
|
|
||||||
arrange_stack_vertical(tempClients[focus_client_index], target_geom,
|
|
||||||
cur_gappih);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i <= focus_client_index; i++) {
|
for (i = 1; i <= focus_client_index; i++) {
|
||||||
|
|
@ -478,7 +337,7 @@ void vertical_scroller(Monitor *m) {
|
||||||
target_geom.y = tempClients[focus_client_index - i + 1]->geom.y -
|
target_geom.y = tempClients[focus_client_index - i + 1]->geom.y -
|
||||||
cur_gappiv - target_geom.height;
|
cur_gappiv - target_geom.height;
|
||||||
|
|
||||||
arrange_stack_vertical(c, target_geom, cur_gappih);
|
resize(c, target_geom, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i < n - focus_client_index; i++) {
|
for (i = 1; i < n - focus_client_index; i++) {
|
||||||
|
|
@ -488,22 +347,20 @@ void vertical_scroller(Monitor *m) {
|
||||||
target_geom.y = tempClients[focus_client_index + i - 1]->geom.y +
|
target_geom.y = tempClients[focus_client_index + i - 1]->geom.y +
|
||||||
cur_gappiv +
|
cur_gappiv +
|
||||||
tempClients[focus_client_index + i - 1]->geom.height;
|
tempClients[focus_client_index + i - 1]->geom.height;
|
||||||
arrange_stack_vertical(c, target_geom, cur_gappih);
|
resize(c, target_geom, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(tempClients);
|
free(tempClients);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vertical_grid(Monitor *m) {
|
void vertical_grid(Monitor *m) {
|
||||||
int32_t i, n;
|
uint32_t i, n;
|
||||||
int32_t cx, cy, cw, ch;
|
uint32_t cx, cy, cw, ch;
|
||||||
int32_t dy;
|
uint32_t dy;
|
||||||
int32_t rows, cols, overrows;
|
uint32_t rows, cols, overrows;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
int32_t target_gappo =
|
int target_gappo = enablegaps ? m->isoverview ? overviewgappo : gappov : 0;
|
||||||
enablegaps ? m->isoverview ? config.overviewgappo : config.gappov : 0;
|
int target_gappi = enablegaps ? m->isoverview ? overviewgappi : gappiv : 0;
|
||||||
int32_t target_gappi =
|
|
||||||
enablegaps ? m->isoverview ? config.overviewgappi : config.gappiv : 0;
|
|
||||||
float single_width_ratio = m->isoverview ? 0.7 : 0.9;
|
float single_width_ratio = m->isoverview ? 0.7 : 0.9;
|
||||||
float single_height_ratio = m->isoverview ? 0.8 : 0.9;
|
float single_height_ratio = m->isoverview ? 0.8 : 0.9;
|
||||||
|
|
||||||
|
|
|
||||||
1968
src/mango.c
1968
src/mango.c
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue