Compare commits

..

No commits in common. "main" and "0.12.7" have entirely different histories.
main ... 0.12.7

20 changed files with 159 additions and 737 deletions

View file

@ -137,7 +137,7 @@ And then rebuild your system.
## Other
```bash
git clone -b 0.19.3 https://gitlab.freedesktop.org/wlroots/wlroots.git
git clone -b 0.19.2 https://gitlab.freedesktop.org/wlroots/wlroots.git
cd wlroots
meson build -Dprefix=/usr
sudo ninja -C build install

View file

@ -34,7 +34,7 @@ animation_type_close=slide
animation_fade_in=1
animation_fade_out=1
tag_animation_direction=1
zoom_initial_ratio=0.4
zoom_initial_ratio=0.3
zoom_end_ratio=0.8
fadein_begin_opacity=0.5
fadeout_begin_opacity=0.8

View file

@ -90,7 +90,6 @@ bindr=Super,Super_L,spawn,rofi -show run
| :--- | :--- | :--- |
| `killclient` | - | Close the focused window. |
| `togglefloating` | - | Toggle floating state. |
| `toggle_all_floating` | - | Toggle all visible clients floating state. |
| `togglefullscreen` | - | Toggle fullscreen. |
| `togglefakefullscreen` | - | Toggle "fake" fullscreen (remains constrained). |
| `togglemaximizescreen` | - | Maximize window (keep decoration/bar). |
@ -195,16 +194,6 @@ bind=NONE,XF86AudioMute,spawn,wpctl set-mute @DEFAULT_SINK@ toggle
bind=SHIFT,XF86AudioMute,spawn,wpctl set-mute @DEFAULT_SOURCE@ toggle
```
#### Playback
Requires: `playerctl`
```ini
bind=NONE,XF86AudioNext,spawn,playerctl next
bind=NONE,XF86AudioPrev,spawn,playerctl previous
bind=NONE,XF86AudioPlay,spawn,playerctl play-pause
```
### Floating Window Movement
| Command | Param | Description |
@ -212,4 +201,4 @@ bind=NONE,XF86AudioPlay,spawn,playerctl play-pause
| `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. |
| `resizewin` | `(width,height)` | Resize window. |

View file

@ -45,7 +45,6 @@ Specific settings for laptop touchpads. Some settings may require a relogin to t
| `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_button` | `274` | The mouse button that use for scrolling(272 to 279).
| `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. |
@ -58,16 +57,6 @@ Specific settings for laptop touchpads. Some settings may require a relogin to t
**Detailed descriptions:**
- `scroll_button` values:
- `272` — Left button.
- `273` — Right button.
- `274` — Middle button.
- `275` — Side button.
- `276` — Extra button.
- `277` — Forward button.
- `278` — Back button.
- `279` — Task button.
- `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.

View file

@ -185,7 +185,7 @@ mangowm is available in the **PikaOS package repository**.
You can install it using the `pikman` package manager:
```bash
pikman install mangowm
pikman install mangowc
```
---
@ -214,7 +214,7 @@ 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.3 https://gitlab.freedesktop.org/wlroots/wlroots.git
git clone -b 0.19.2 https://gitlab.freedesktop.org/wlroots/wlroots.git
cd wlroots
meson build -Dprefix=/usr
sudo ninja -C build install

View file

@ -46,7 +46,7 @@ fadeout_begin_opacity=0.5
Adjust the zoom ratios for zoom animations.
```ini
zoom_initial_ratio=0.4
zoom_initial_ratio=0.3
zoom_end_ratio=0.8
```

View file

@ -27,7 +27,7 @@ windowrule=Parameter:Values,Parameter:Values,appid:Values,title:Values
| `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_fakemaximize` | integer | `0` / `1` (default 1) | The state of client set to fake maximized |
| `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 |
@ -179,7 +179,6 @@ tagrule=id:Values,monitor_make:xxx,monitor_model:xxx,Parameter:Values
| `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 |
| `open_as_floating` | integer | `0` / `1` | New open window will be floating|
| `no_hide` | integer | `0` / `1` | Not hide even if the tag is empty |
| `nmaster` | integer | 0, 99 | Number of master windows |
| `mfact` | float | 0.10.9 | Master area factor |

View file

@ -15,7 +15,7 @@
#:use-module (gnu packages ninja)
#:use-module (gnu packages pkg-config)
#:use-module (guix build-system meson)
#:use-module ((guix licenses) #:prefix license:))
#:use-module (guix licenses))
(define-public mangowm-git
@ -36,13 +36,10 @@
(add-before 'configure 'patch-meson
(lambda _
(substitute* "meson.build"
;; MangoWM ignores sysconfdir handling for NixOS.
;; We also need to skip that sysconfdir edits.
(("is_nixos = false")
"is_nixos = true")
;; Unhardcode path. Fixes loading default config.
(("'-DSYSCONFDIR=\\\"@0@\\\"'.format\\('/etc'\\)")
"'-DSYSCONFDIR=\"@0@\"'.format(sysconfdir)")))))))
"'-DSYSCONFDIR=\"@0@\"'.format(sysconfdir)")
(("sysconfdir = sysconfdir.substring\\(prefix.length\\(\\)\\)")
"")))))))
(inputs (list wayland
libinput
libdrm
@ -55,17 +52,14 @@
pcre2
libxcb
xcb-util-wm
wlroots-0.19
wlroots
scenefx))
(native-inputs (list pkg-config wayland-protocols))
(home-page "https://github.com/mangowm/mango")
(home-page "https://github.com/DreamMaoMao/mangowm")
(synopsis "Wayland compositor based on wlroots and scenefx")
(description
"MangoWM is a modern, lightweight, high-performance Wayland compositor
built on dwl crafted for speed, flexibility, and a customizable desktop experience.")
(license (list license:gpl3 ;mangowm itself, dwl
license:expat ;dwm, sway, wlroots
license:cc0)))) ;tinywl
(description "A Wayland compositor based on wlroots and scenefx,
inspired by dwl but aiming to be more feature-rich.")
(license gpl3)))
(define-deprecated-package mangowc
mangowm-git)

View file

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

View file

@ -569,12 +569,12 @@ int32_t main(int32_t argc, char *argv[]) {
mode = WATCH;
break;
case 'o':
if (mode == GET || mode == WATCH)
oflag = 1;
else if (mode == SET)
if (mode == SET)
output_name = EARGF(usage());
else
output_name = ARGF();
if (!output_name)
oflag = 1;
break;
case 't':
tflag = 1;

View file

@ -67,8 +67,8 @@ stdenv.mkDerivation {
meta = {
mainProgram = "mango";
description = "Practical and Powerful wayland compositor (dwm but wayland)";
homepage = "https://github.com/mangowm/mango";
description = "A streamlined but feature-rich Wayland compositor";
homepage = "https://github.com/DreamMaoMao/mango";
license = lib.licenses.gpl3Plus;
maintainers = [];
platforms = lib.platforms.unix;

View file

@ -1,22 +1,18 @@
self:
{
self: {
lib,
config,
pkgs,
...
}:
let
}: let
cfg = config.wayland.windowManager.mango;
selflib = import ./lib.nix lib;
variables = lib.concatStringsSep " " cfg.systemd.variables;
extraCommands = lib.concatStringsSep " && " cfg.systemd.extraCommands;
systemdActivation = "${pkgs.dbus}/bin/dbus-update-activation-environment --systemd ${variables}; ${extraCommands}";
systemdActivation = ''${pkgs.dbus}/bin/dbus-update-activation-environment --systemd ${variables}; ${extraCommands}'';
autostart_sh = pkgs.writeShellScript "autostart.sh" ''
${lib.optionalString cfg.systemd.enable systemdActivation}
${cfg.autostart_sh}
'';
in
{
in {
options = {
wayland.windowManager.mango = with lib; {
enable = mkOption {
@ -58,7 +54,7 @@ in
"XCURSOR_THEME"
"XCURSOR_SIZE"
];
example = [ "--all" ];
example = ["--all"];
description = ''
Environment variables imported into the systemd and D-Bus user environment.
'';
@ -79,195 +75,50 @@ in
'';
};
settings = mkOption {
type =
with lib.types;
let
valueType =
nullOr (oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
])
// {
description = "Mango configuration value";
};
in
valueType;
default = { };
description = ''
Mango configuration written in Nix. Entries with the same key
should be written as lists. Variables and colors names should be
quoted. See <https://mangowc.vercel.app/docs> for more examples.
::: {.note}
This option uses a structured format that is converted to Mango's
configuration syntax. Nested attributes are flattened with underscore separators.
For example: `animation.duration_open = 400` becomes `animation_duration_open = 400`
Keymodes (submaps) are supported via the special `keymode` attribute. Each keymode
is a nested attribute set under `keymode` that contains its own bindings.
:::
'';
example = lib.literalExpression ''
{
# Window effects
blur = 1;
blur_optimized = 1;
blur_params = {
radius = 5;
num_passes = 2;
};
border_radius = 6;
focused_opacity = 1.0;
# Animations - use underscores for multi-part keys
animations = 1;
animation_type_open = "slide";
animation_type_close = "slide";
animation_duration_open = 400;
animation_duration_close = 800;
# Or use nested attrs (will be flattened with underscores)
animation_curve = {
open = "0.46,1.0,0.29,1";
close = "0.08,0.92,0,1";
};
# Use lists for duplicate keys like bind and tagrule
bind = [
"SUPER,r,reload_config"
"Alt,space,spawn,rofi -show drun"
"Alt,Return,spawn,foot"
"ALT,R,setkeymode,resize" # Enter resize mode
];
tagrule = [
"id:1,layout_name:tile"
"id:2,layout_name:scroller"
];
# Keymodes (submaps) for modal keybindings
keymode = {
resize = {
bind = [
"NONE,Left,resizewin,-10,0"
"NONE,Escape,setkeymode,default"
];
};
};
}
'';
};
extraConfig = mkOption {
description = "mango config content";
type = types.lines;
default = "";
description = ''
Extra configuration lines to add to `~/.config/mango/config.conf`.
This is useful for advanced configurations that don't fit the structured
settings format, or for options that aren't yet supported by the module.
'';
example = ''
# Advanced config that doesn't fit structured format
special_option = 1
# menu and terminal
bind=Alt,space,spawn,rofi -show drun
bind=Alt,Return,spawn,foot
'';
};
topPrefixes = mkOption {
type = with lib.types; listOf str;
default = [ ];
description = ''
List of prefixes for attributes that should appear at the top of the config file.
Attributes starting with these prefixes will be sorted to the beginning.
'';
example = [ "source" ];
};
bottomPrefixes = mkOption {
type = with lib.types; listOf str;
default = [ ];
description = ''
List of prefixes for attributes that should appear at the bottom of the config file.
Attributes starting with these prefixes will be sorted to the end.
'';
example = [ "source" ];
};
autostart_sh = mkOption {
description = ''
Shell script to run on mango startup. No shebang needed.
When this option is set, the script will be written to
`~/.config/mango/autostart.sh` and an `exec-once` line
will be automatically added to the config to execute it.
'';
description = "WARRNING: This is a shell script, but no need to add shebang";
type = types.lines;
default = "";
example = ''
waybar &
dunst &
'';
};
};
};
config = lib.mkIf cfg.enable (
let
finalConfigText =
# Support old string-based config during transition period
(
if builtins.isString cfg.settings then
cfg.settings
else
lib.optionalString (cfg.settings != { }) (
selflib.toMango {
topCommandsPrefixes = cfg.topPrefixes;
bottomCommandsPrefixes = cfg.bottomPrefixes;
} cfg.settings
)
)
+ lib.optionalString (cfg.extraConfig != "") cfg.extraConfig
+ lib.optionalString (cfg.autostart_sh != "") "\nexec-once=~/.config/mango/autostart.sh\n";
validatedConfig = pkgs.runCommand "mango-config.conf" { } ''
cp ${pkgs.writeText "mango-config.conf" finalConfigText} "$out"
${cfg.package}/bin/mango -c "$out" -p || exit 1
'';
in
{
# Backwards compatibility warning for old string-based config
warnings = lib.optional (builtins.isString cfg.settings) ''
wayland.windowManager.mango.settings: Using a string for settings is deprecated.
Please migrate to the new structured attribute set format.
See the module documentation for examples, or use the 'extraConfig' option for raw config strings.
The old string format will be removed in a future release.
'';
home.packages = [ cfg.package ];
xdg.configFile = {
"mango/config.conf" =
lib.mkIf (cfg.settings != { } || cfg.extraConfig != "" || cfg.autostart_sh != "")
{
source = validatedConfig;
};
"mango/autostart.sh" = lib.mkIf (cfg.autostart_sh != "") {
source = autostart_sh;
executable = true;
};
config = lib.mkIf cfg.enable {
home.packages = [cfg.package];
xdg.configFile = {
"mango/config.conf" = lib.mkIf (cfg.settings != "") {
text = cfg.settings;
};
systemd.user.targets.mango-session = lib.mkIf cfg.systemd.enable {
Unit = {
Description = "mango compositor session";
Documentation = [ "man:systemd.special(7)" ];
BindsTo = [ "graphical-session.target" ];
Wants = [
"mango/autostart.sh" = lib.mkIf (cfg.autostart_sh != "") {
source = autostart_sh;
executable = true;
};
};
systemd.user.targets.mango-session = lib.mkIf cfg.systemd.enable {
Unit = {
Description = "mango compositor session";
Documentation = ["man:systemd.special(7)"];
BindsTo = ["graphical-session.target"];
Wants =
[
"graphical-session-pre.target"
]
++ lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target";
After = [ "graphical-session-pre.target" ];
Before = lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target";
};
After = ["graphical-session-pre.target"];
Before = lib.optional cfg.systemd.xdgAutostart "xdg-desktop-autostart.target";
};
}
);
};
};
}

View file

@ -1,312 +0,0 @@
lib:
let
inherit (lib)
attrNames
filterAttrs
foldl
generators
partition
removeAttrs
;
inherit (lib.strings)
concatMapStrings
hasPrefix
;
/**
Convert a structured Nix attribute set into Mango's configuration format.
This function takes a nested attribute set and converts it into Mango-compatible
configuration syntax, supporting top, bottom, and regular command sections.
Commands are flattened using the `flattenAttrs` function, and attributes are formatted as
`key = value` pairs. Lists are expanded as duplicate keys to match Mango's expected format.
Configuration:
* `topCommandsPrefixes` - A list of prefixes to define **top** commands (default: `[]`).
* `bottomCommandsPrefixes` - A list of prefixes to define **bottom** commands (default: `[]`).
Attention:
- The function ensures top commands appear **first** and bottom commands **last**.
- The generated configuration is a **single string**, suitable for writing to a config file.
- Lists are converted into multiple entries, ensuring compatibility with Mango.
# Inputs
Structured function argument:
: topCommandsPrefixes (optional, default: `[]`)
: A list of prefixes that define **top** commands. Any key starting with one of these
prefixes will be placed at the beginning of the configuration.
: bottomCommandsPrefixes (optional, default: `[]`)
: A list of prefixes that define **bottom** commands. Any key starting with one of these
prefixes will be placed at the end of the configuration.
Value:
: The attribute set to be converted to Hyprland configuration format.
# Type
```
toMango :: AttrSet -> AttrSet -> String
```
# Examples
:::{.example}
## Basic mangowc configuration
```nix
let
config = {
blur = 1;
blur_params_radius = 5;
border_radius = 6;
animations = 1;
animation_duration_open = 400;
};
in lib.toMango {} config
```
**Output:**
```
animations = 1
animation_duration_open = 400
blur = 1
blur_params_radius = 5
border_radius = 6
```
## Using nested attributes
```nix
let
config = {
blur = 1;
blur_params = {
radius = 5;
num_passes = 2;
noise = 0.02;
};
animation_curve = {
open = "0.46,1.0,0.29,1";
close = "0.08,0.92,0,1";
};
};
in lib.toMango {} config
```
**Output:**
```
animation_curve_close = 0.08,0.92,0,1
animation_curve_open = 0.46,1.0,0.29,1
blur = 1
blur_params_noise = 0.02
blur_params_num_passes = 2
blur_params_radius = 5
```
## Using lists for duplicate keys
```nix
let
config = {
bind = [
"SUPER,r,reload_config"
"Alt,space,spawn,rofi -show drun"
"Alt,Return,spawn,foot"
];
tagrule = [
"id:1,layout_name:tile"
"id:2,layout_name:scroller"
];
};
in lib.toMango {} config
```
**Output:**
```
bind = SUPER,r,reload_config
bind = Alt,space,spawn,rofi -show drun
bind = Alt,Return,spawn,foot
tagrule = id:1,layout_name:tile
tagrule = id:2,layout_name:scroller
```
## Using keymodes (submaps)
```nix
let
config = {
bind = [
"SUPER,Q,killclient"
"ALT,R,setkeymode,resize"
];
keymode = {
resize = {
bind = [
"NONE,Left,resizewin,-10,0"
"NONE,Right,resizewin,10,0"
"NONE,Escape,setkeymode,default"
];
};
};
};
in lib.toMango {} config
```
**Output:**
```
bind = SUPER,Q,killclient
bind = ALT,R,setkeymode,resize
keymode = resize
bind = NONE,Left,resizewin,-10,0
bind = NONE,Right,resizewin,10,0
bind = NONE,Escape,setkeymode,default
```
:::
*/
toMango =
{
topCommandsPrefixes ? [ ],
bottomCommandsPrefixes ? [ ],
}:
attrs:
let
toMango' =
attrs:
let
# Specially configured `toKeyValue` generator with support for duplicate keys
# and a legible key-value separator.
mkCommands = generators.toKeyValue {
mkKeyValue = generators.mkKeyValueDefault { } " = ";
listsAsDuplicateKeys = true;
indent = ""; # No indent, since we don't have nesting
};
# Extract keymode definitions if they exist
keymodes = attrs.keymode or { };
attrsWithoutKeymodes = removeAttrs attrs [ "keymode" ];
# Generate keymode blocks
# Format: keymode=name\nbind=...\nbind=...\n
mkKeymodeBlock =
name: modeAttrs:
let
modeCommands = flattenAttrs (p: k: "${p}_${k}") modeAttrs;
in
"keymode = ${name}\n${mkCommands modeCommands}";
keymodeBlocks =
if keymodes == { } then
""
else
"\n" + concatMapStrings (name: mkKeymodeBlock name keymodes.${name} + "\n") (attrNames keymodes);
# Flatten the attrset, combining keys in a "path" like `"a_b_c" = "x"`.
# Uses `flattenAttrs` with an underscore separator.
commands = flattenAttrs (p: k: "${p}_${k}") attrsWithoutKeymodes;
# General filtering function to check if a key starts with any prefix in a given list.
filterCommands = list: n: foldl (acc: prefix: acc || hasPrefix prefix n) false list;
# Partition keys into top commands and the rest
result = partition (filterCommands topCommandsPrefixes) (attrNames commands);
topCommands = filterAttrs (n: _: builtins.elem n result.right) commands;
remainingCommands = removeAttrs commands result.right;
# Partition remaining commands into bottom commands and regular commands
result2 = partition (filterCommands bottomCommandsPrefixes) result.wrong;
bottomCommands = filterAttrs (n: _: builtins.elem n result2.right) remainingCommands;
regularCommands = removeAttrs remainingCommands result2.right;
in
# Concatenate strings from mapping `mkCommands` over top, regular, and bottom commands.
# Keymodes are appended at the end.
concatMapStrings mkCommands [
topCommands
regularCommands
bottomCommands
]
+ keymodeBlocks;
in
toMango' attrs;
/**
Flatten a nested attribute set into a flat attribute set, using a custom key separator function.
This function recursively traverses a nested attribute set and produces a flat attribute set
where keys are joined using a user-defined function (`pred`). It allows transforming deeply
nested structures into a single-level attribute set while preserving key-value relationships.
Configuration:
* `pred` - A function `(string -> string -> string)` defining how keys should be concatenated.
# Inputs
Structured function argument:
: pred (required)
: A function that determines how parent and child keys should be combined into a single key.
It takes a `prefix` (parent key) and `key` (current key) and returns the joined key.
Value:
: The nested attribute set to be flattened.
# Type
```
flattenAttrs :: (String -> String -> String) -> AttrSet -> AttrSet
```
# Examples
:::{.example}
```nix
let
nested = {
a = "3";
b = { c = "4"; d = "5"; };
};
separator = (prefix: key: "${prefix}.${key}"); # Use dot notation
in lib.flattenAttrs separator nested
```
**Output:**
```nix
{
"a" = "3";
"b.c" = "4";
"b.d" = "5";
}
```
:::
*/
flattenAttrs =
pred: attrs:
let
flattenAttrs' =
prefix: attrs:
builtins.foldl' (
acc: key:
let
value = attrs.${key};
newKey = if prefix == "" then key else pred prefix key;
in
acc // (if builtins.isAttrs value then flattenAttrs' newKey value else { "${newKey}" = value; })
) { } (builtins.attrNames attrs);
in
flattenAttrs' "" attrs;
in
{
inherit flattenAttrs toMango;
}

View file

@ -723,8 +723,6 @@ void client_animation_next_tick(Client *c) {
c->is_pending_open_animation = false;
client_apply_clip(c, factor);
if (animation_passed >= 1.0) {
// clear the open action state
@ -754,6 +752,8 @@ void client_animation_next_tick(Client *c) {
// end flush in next frame, not the current frame
c->need_output_flush = false;
}
client_apply_clip(c, factor);
}
void init_fadeout_client(Client *c) {

View file

@ -294,8 +294,9 @@ static inline uint32_t client_set_size(Client *c, uint32_t width,
uint32_t height) {
#ifdef XWAYLAND
if (client_is_x11(c)) {
struct wlr_xwayland_surface *surface = c->surface.xwayland;
struct wlr_surface_state *state = &surface->surface->current;
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 &&
@ -308,22 +309,6 @@ static inline uint32_t client_set_size(Client *c, uint32_t width,
return 0;
}
xcb_size_hints_t *size_hints = surface->size_hints;
int32_t width = c->geom.width - 2 * c->bw;
int32_t height = c->geom.height - 2 * c->bw;
if (c->mon && c->mon->isoverview && size_hints &&
c->geom.width - 2 * (int32_t)c->bw < size_hints->min_width &&
c->geom.height - 2 * (int32_t)c->bw < size_hints->min_height)
return 0;
if (size_hints &&
c->geom.width - 2 * (int32_t)c->bw < size_hints->min_width)
width = size_hints->min_width;
if (size_hints &&
c->geom.height - 2 * (int32_t)c->bw < size_hints->min_height)
height = size_hints->min_height;
wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x + c->bw,
c->geom.y + c->bw, width, height);
return 1;
@ -365,7 +350,7 @@ static inline void client_set_maximized(Client *c, bool maximized) {
static inline void client_set_tiled(Client *c, uint32_t edges) {
struct wlr_xdg_toplevel *toplevel;
#ifdef XWAYLAND
if (client_is_x11(c) && c->force_fakemaximize) {
if (client_is_x11(c) && c->force_maximize) {
wlr_xwayland_surface_set_maximized(c->surface.xwayland,
edges != WLR_EDGE_NONE,
edges != WLR_EDGE_NONE);
@ -380,7 +365,7 @@ static inline void client_set_tiled(Client *c, uint32_t edges) {
wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges);
}
if (c->force_fakemaximize) {
if (c->force_maximize) {
wlr_xdg_toplevel_set_maximized(toplevel, edges != WLR_EDGE_NONE);
}
}

View file

@ -90,7 +90,7 @@ typedef struct {
int32_t no_force_center;
int32_t isterm;
int32_t allow_csd;
int32_t force_fakemaximize;
int32_t force_maximize;
int32_t force_tiled_state;
int32_t force_tearing;
int32_t noswallow;
@ -168,7 +168,6 @@ typedef struct {
float mfact;
int32_t nmaster;
int32_t no_render_border;
int32_t open_as_floating;
int32_t no_hide;
} ConfigTagRule;
@ -635,14 +634,9 @@ uint32_t parse_mod(const char *mod_str) {
// 分割处理每个部分
token = strtok_r(input_copy, "+", &saveptr);
while (token != NULL) {
// 去除前后空白
trim_whitespace(token);
// 如果 token 变成空字符串则跳过
if (*token == '\0') {
token = strtok_r(NULL, "+", &saveptr);
continue;
}
// 去除空白
while (*token == ' ' || *token == '\t')
token++;
if (strncmp(token, "code:", 5) == 0) {
// 处理 code: 形式
@ -1202,8 +1196,6 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
} else if (strcmp(func_name, "scroller_stack") == 0) {
func = scroller_stack;
(*arg).i = parse_direction(arg_value);
} else if (strcmp(func_name, "toggle_all_floating") == 0) {
func = toggle_all_floating;
} else {
return NULL;
}
@ -1907,7 +1899,6 @@ bool parse_option(Config *config, char *key, char *value) {
rule->nmaster = 0;
rule->mfact = 0.0f;
rule->no_render_border = 0;
rule->open_as_floating = 0;
rule->no_hide = 0;
bool parse_error = false;
@ -1936,8 +1927,6 @@ bool parse_option(Config *config, char *key, char *value) {
rule->monitor_serial = strdup(val);
} else if (strcmp(key, "no_render_border") == 0) {
rule->no_render_border = CLAMP_INT(atoi(val), 0, 1);
} else if (strcmp(key, "open_as_floating") == 0) {
rule->open_as_floating = CLAMP_INT(atoi(val), 0, 1);
} else if (strcmp(key, "no_hide") == 0) {
rule->no_hide = CLAMP_INT(atoi(val), 0, 1);
} else if (strcmp(key, "nmaster") == 0) {
@ -2058,7 +2047,7 @@ bool parse_option(Config *config, char *key, char *value) {
rule->indleinhibit_when_focus = -1;
rule->isterm = -1;
rule->allow_csd = -1;
rule->force_fakemaximize = -1;
rule->force_maximize = -1;
rule->force_tiled_state = -1;
rule->force_tearing = -1;
rule->noswallow = -1;
@ -2172,8 +2161,8 @@ bool parse_option(Config *config, char *key, char *value) {
rule->isterm = atoi(val);
} else if (strcmp(key, "allow_csd") == 0) {
rule->allow_csd = atoi(val);
} else if (strcmp(key, "force_fakemaximize") == 0) {
rule->force_fakemaximize = atoi(val);
} else if (strcmp(key, "force_maximize") == 0) {
rule->force_maximize = atoi(val);
} else if (strcmp(key, "force_tiled_state") == 0) {
rule->force_tiled_state = atoi(val);
} else if (strcmp(key, "force_tearing") == 0) {
@ -3213,7 +3202,7 @@ void override_config(void) {
config.accel_profile = CLAMP_INT(config.accel_profile, 0, 2);
config.accel_speed = CLAMP_FLOAT(config.accel_speed, -1.0f, 1.0f);
config.scroll_method = CLAMP_INT(config.scroll_method, 0, 4);
config.scroll_button = CLAMP_INT(config.scroll_button, 272, 279);
config.scroll_button = CLAMP_INT(config.scroll_button, 272, 276);
config.click_method = CLAMP_INT(config.click_method, 0, 2);
config.send_events_mode = CLAMP_INT(config.send_events_mode, 0, 2);
config.button_map = CLAMP_INT(config.button_map, 0, 1);
@ -3263,7 +3252,7 @@ void set_value_default() {
config.animation_fade_in = 1;
config.animation_fade_out = 1;
config.tag_animation_direction = HORIZONTAL;
config.zoom_initial_ratio = 0.4f;
config.zoom_initial_ratio = 0.3f;
config.zoom_end_ratio = 0.8f;
config.fadein_begin_opacity = 0.5f;
config.fadeout_begin_opacity = 0.5f;
@ -3791,8 +3780,6 @@ void parse_tagrule(Monitor *m) {
m->pertag->mfacts[tr.id] = tr.mfact;
if (tr.no_render_border >= 0)
m->pertag->no_render_border[tr.id] = tr.no_render_border;
if (tr.open_as_floating >= 0)
m->pertag->open_as_floating[tr.id] = tr.open_as_floating;
}
}

View file

@ -70,4 +70,3 @@ int32_t disable_monitor(const Arg *arg);
int32_t enable_monitor(const Arg *arg);
int32_t toggle_monitor(const Arg *arg);
int32_t scroller_stack(const Arg *arg);
int32_t toggle_all_floating(const Arg *arg);

View file

@ -376,11 +376,7 @@ int32_t moveresize(const Arg *arg) {
/* Float the window and tell motionnotify to grab it */
if (grabc->isfloating == 0 && arg->ui == CurMove) {
grabc->drag_to_tile = true;
exit_scroller_stack(grabc);
setfloating(grabc, 1);
grabc->old_stack_inner_per = 0.0f;
grabc->old_master_inner_per = 0.0f;
set_size_per(grabc->mon, grabc);
}
switch (cursor_mode = arg->ui) {
@ -552,7 +548,7 @@ int32_t restore_minimized(const Arg *arg) {
if (selmon && selmon->sel && selmon->sel->is_in_scratchpad &&
selmon->sel->is_scratchpad_show) {
client_pending_minimized_state(selmon->sel, 0);
selmon->sel->isminimized = 0;
selmon->sel->is_scratchpad_show = 0;
selmon->sel->is_in_scratchpad = 0;
selmon->sel->isnamedscratchpad = 0;
@ -863,6 +859,7 @@ int32_t spawn_shell(const Arg *arg) {
}
int32_t spawn(const Arg *arg) {
if (!arg->v)
return 0;
@ -875,21 +872,28 @@ int32_t spawn(const Arg *arg) {
dup2(STDERR_FILENO, STDOUT_FILENO);
setsid();
// 2. 对整个参数字符串进行单词展开
wordexp_t p;
if (wordexp(arg->v, &p, 0) != 0) {
wlr_log(WLR_DEBUG, "mango: wordexp failed for '%s'\n", arg->v);
_exit(EXIT_FAILURE);
// 2. 解析参数
char *argv[64];
int32_t argc = 0;
char *token = strtok((char *)arg->v, " ");
while (token != NULL && argc < 63) {
wordexp_t p;
if (wordexp(token, &p, 0) == 0) {
argv[argc++] = p.we_wordv[0];
} else {
argv[argc++] = token;
}
token = strtok(NULL, " ");
}
argv[argc] = NULL;
// 3. 执行命令p.we_wordv 已经是 argv 数组)
execvp(p.we_wordv[0], p.we_wordv);
// 3. 执行命令
execvp(argv[0], argv);
// 4. execvp 失败时:打印错误,释放 wordexp 资源,然后退出
wlr_log(WLR_DEBUG, "mango: execvp '%s' failed: %s\n", p.we_wordv[0],
// 4. execvp 失败时:打印错误并直接退出(避免 coredump
wlr_log(WLR_DEBUG, "mango: execvp '%s' failed: %s\n", argv[0],
strerror(errno));
wordfree(&p); // 释放 wordexp 分配的内存
_exit(EXIT_FAILURE);
_exit(EXIT_FAILURE); // 使用 _exit 避免缓冲区刷新等操作
}
return 0;
}
@ -1862,27 +1866,3 @@ int32_t scroller_stack(const Arg *arg) {
arrange(selmon, false, false);
return 0;
}
int32_t toggle_all_floating(const Arg *arg) {
if (!selmon || !selmon->sel)
return 0;
Client *c = NULL;
bool should_floating = !selmon->sel->isfloating;
wl_list_for_each(c, &clients, link) {
if (VISIBLEON(c, selmon)) {
if (c->isfloating && !should_floating) {
c->old_master_inner_per = 0.0f;
c->old_stack_inner_per = 0.0f;
set_size_per(selmon, c);
}
if (c->isfloating != should_floating) {
setfloating(c, should_floating);
}
}
}
return 0;
}

View file

@ -1,12 +1,15 @@
bool check_hit_no_border(Client *c) {
int32_t i;
bool hit_no_border = false;
if (!render_border) {
hit_no_border = true;
}
if (c->mon && !c->mon->isoverview &&
c->mon->pertag->no_render_border[get_tags_first_tag_num(c->tags)]) {
hit_no_border = true;
for (i = 0; i < config.tag_rules_count; i++) {
if (c->tags & (1 << (config.tag_rules[i].id - 1)) &&
config.tag_rules[i].no_render_border) {
hit_no_border = true;
}
}
if (config.no_border_when_single && c && c->mon &&
@ -16,7 +19,6 @@ bool check_hit_no_border(Client *c) {
}
return hit_no_border;
}
Client *termforwin(Client *w) {
Client *c = NULL;

View file

@ -391,7 +391,7 @@ struct Client {
struct dwl_opacity_animation opacity_animation;
int32_t isterm, noswallow;
int32_t allow_csd;
int32_t force_fakemaximize;
int32_t force_maximize;
int32_t force_tiled_state;
pid_t pid;
Client *swallowing, *swallowedby;
@ -806,10 +806,6 @@ static int32_t keep_idle_inhibit(void *data);
static void check_keep_idle_inhibit(Client *c);
static void pre_caculate_before_arrange(Monitor *m, bool want_animation,
bool from_view, bool only_caculate);
static void client_pending_fullscreen_state(Client *c, int32_t isfullscreen);
static void client_pending_maximized_state(Client *c, int32_t ismaximized);
static void client_pending_minimized_state(Client *c, int32_t isminimized);
#include "data/static_keymap.h"
#include "dispatch/bind_declare.h"
#include "layout/layout.h"
@ -937,9 +933,8 @@ struct Pertag {
uint32_t curtag, prevtag; /* current and previous tag */
int32_t nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
int32_t no_hide[LENGTH(tags) + 1]; /* no_hide per tag */
int32_t no_render_border[LENGTH(tags) + 1]; /* no_render_border per tag */
int32_t open_as_floating[LENGTH(tags) + 1]; /* open_as_floating per tag */
bool no_hide[LENGTH(tags) + 1]; /* no_hide per tag */
bool no_render_border[LENGTH(tags) + 1]; /* no_render_border per tag */
const Layout
*ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */
};
@ -1067,33 +1062,11 @@ void clear_fullscreen_flag(Client *c) {
}
}
void client_pending_fullscreen_state(Client *c, int32_t isfullscreen) {
c->isfullscreen = isfullscreen;
if (c->foreign_toplevel && !c->iskilling)
wlr_foreign_toplevel_handle_v1_set_fullscreen(c->foreign_toplevel,
isfullscreen);
}
void client_pending_maximized_state(Client *c, int32_t ismaximized) {
c->ismaximizescreen = ismaximized;
if (c->foreign_toplevel && !c->iskilling)
wlr_foreign_toplevel_handle_v1_set_maximized(c->foreign_toplevel,
ismaximized);
}
void client_pending_minimized_state(Client *c, int32_t isminimized) {
c->isminimized = isminimized;
if (c->foreign_toplevel && !c->iskilling)
wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel,
isminimized);
}
void show_scratchpad(Client *c) {
c->is_scratchpad_show = 1;
if (c->isfullscreen || c->ismaximizescreen) {
client_pending_fullscreen_state(c, 0);
client_pending_maximized_state(c, 0);
c->isfullscreen = 0; // 清除窗口全屏标志
c->ismaximizescreen = 0;
c->bw = c->isnoborder ? 0 : config.borderpx;
}
@ -1132,6 +1105,9 @@ void swallow(Client *c, Client *w) {
c->bw = w->bw;
c->isfloating = w->isfloating;
c->isurgent = w->isurgent;
c->isfullscreen = w->isfullscreen;
c->ismaximizescreen = w->ismaximizescreen;
c->isminimized = w->isminimized;
c->is_in_scratchpad = w->is_in_scratchpad;
c->is_scratchpad_show = w->is_scratchpad_show;
c->tags = w->tags;
@ -1143,7 +1119,6 @@ void swallow(Client *c, Client *w) {
c->scroller_proportion = w->scroller_proportion;
c->next_in_stack = w->next_in_stack;
c->prev_in_stack = w->prev_in_stack;
if (w->next_in_stack)
w->next_in_stack->prev_in_stack = c;
if (w->prev_in_stack)
@ -1162,9 +1137,11 @@ void swallow(Client *c, Client *w) {
if (!c->foreign_toplevel && c->mon)
add_foreign_toplevel(c);
client_pending_fullscreen_state(c, w->isfullscreen);
client_pending_maximized_state(c, w->ismaximizescreen);
client_pending_minimized_state(c, w->isminimized);
if (c->isminimized && c->foreign_toplevel) {
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel,
false);
wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, true);
}
}
bool switch_scratchpad_client_state(Client *c) {
@ -1347,7 +1324,7 @@ void toggle_hotarea(int32_t x_root, int32_t y_root) {
static void apply_rule_properties(Client *c, const ConfigWinRule *r) {
APPLY_INT_PROP(c, r, isterm);
APPLY_INT_PROP(c, r, allow_csd);
APPLY_INT_PROP(c, r, force_fakemaximize);
APPLY_INT_PROP(c, r, force_maximize);
APPLY_INT_PROP(c, r, force_tiled_state);
APPLY_INT_PROP(c, r, force_tearing);
APPLY_INT_PROP(c, r, noswallow);
@ -1425,25 +1402,6 @@ void set_float_malposition(Client *tc) {
tc->float_geom.y = tc->geom.y = y;
}
void client_reset_mon_tags(Client *c, Monitor *mon, uint32_t newtags) {
if (!newtags && mon && !mon->isoverview) {
c->tags = mon->tagset[mon->seltags];
} else if (!newtags && mon && mon->isoverview) {
c->tags = mon->ovbk_current_tagset;
} else if (newtags) {
c->tags = newtags;
} else {
c->tags = mon->tagset[mon->seltags];
}
}
void check_match_tag_floating_rule(Client *c, Monitor *mon) {
if (c->tags && !c->isfloating && mon && !c->swallowedby &&
mon->pertag->open_as_floating[get_tags_first_tag_num(c->tags)]) {
c->isfloating = 1;
}
}
void applyrules(Client *c) {
/* rule matching */
const char *appid, *title;
@ -1568,7 +1526,6 @@ void applyrules(Client *c) {
int32_t fullscreen_state_backup =
c->isfullscreen || client_wants_fullscreen(c);
setmon(c, mon, newtags,
!c->isopensilent &&
!(client_is_x11_popup(c) && client_should_ignore_focus(c)) &&
@ -1576,11 +1533,6 @@ void applyrules(Client *c) {
(!c->istagsilent || !newtags ||
newtags & mon->tagset[mon->seltags]));
if (!c->isfloating) {
c->old_stack_inner_per = c->stack_inner_per;
c->old_master_inner_per = c->master_inner_per;
}
if (c->mon &&
!(c->mon == selmon && c->tags & c->mon->tagset[c->mon->seltags]) &&
!c->isopensilent && !c->istagsilent) {
@ -4090,12 +4042,12 @@ void init_client_properties(Client *c) {
c->master_mfact_per = 0.0f;
c->master_inner_per = 0.0f;
c->stack_inner_per = 0.0f;
c->old_stack_inner_per = 0.0f;
c->old_master_inner_per = 0.0f;
c->old_master_mfact_per = 0.0f;
c->old_stack_inner_per = 1.0f;
c->old_master_inner_per = 1.0f;
c->old_master_mfact_per = 1.0f;
c->isterm = 0;
c->allow_csd = 0;
c->force_fakemaximize = 0;
c->force_maximize = 0;
c->force_tiled_state = 1;
c->force_tearing = 0;
c->allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
@ -4253,7 +4205,7 @@ void maximizenotify(struct wl_listener *listener, void *data) {
void unminimize(Client *c) {
if (c && c->is_in_scratchpad && c->is_scratchpad_show) {
client_pending_minimized_state(c, 0);
c->isminimized = 0;
c->is_scratchpad_show = 0;
c->is_in_scratchpad = 0;
c->isnamedscratchpad = 0;
@ -4281,12 +4233,13 @@ void set_minimized(Client *c) {
c->oldtags = c->mon->tagset[c->mon->seltags];
c->mini_restore_tag = c->tags;
c->tags = 0;
client_pending_minimized_state(c, 1);
c->isminimized = 1;
c->is_in_scratchpad = 1;
c->is_scratchpad_show = 0;
focusclient(focustop(selmon), 1);
arrange(c->mon, false, false);
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, false);
wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, true);
wl_list_remove(&c->link); // 从原来位置移除
wl_list_insert(clients.prev, &c->link); // 插入尾部
}
@ -5062,12 +5015,12 @@ setfloating(Client *c, int32_t floating) {
if (floating == 1 && c != grabc) {
if (c->isfullscreen) {
client_pending_fullscreen_state(c, 0);
client_set_fullscreen(c, 0);
if (c->isfullscreen || c->ismaximizescreen) {
c->isfullscreen = 0; // 清除窗口全屏标志
c->ismaximizescreen = 0;
c->bw = c->isnoborder ? 0 : config.borderpx;
}
client_pending_maximized_state(c, 0);
exit_scroller_stack(c);
// 重新计算居中的坐标
@ -5109,8 +5062,7 @@ setfloating(Client *c, int32_t floating) {
// 让当前tag中的全屏窗口退出全屏参与平铺
wl_list_for_each(fc, &clients,
link) if (fc && fc != c && VISIBLEON(fc, c->mon) &&
c->tags & fc->tags && ISFULLSCREEN(fc) &&
old_floating_state) {
c->tags & fc->tags && ISFULLSCREEN(fc)) {
clear_fullscreen_flag(fc);
}
}
@ -5124,8 +5076,7 @@ setfloating(Client *c, int32_t floating) {
layers[c->isfloating ? LyrTop : LyrTile]);
}
if (!c->isfloating && old_floating_state &&
(c->old_stack_inner_per > 0.0f || c->old_master_inner_per > 0.0f)) {
if (!c->isfloating && old_floating_state) {
restore_size_per(c->mon, c);
}
@ -5133,7 +5084,7 @@ setfloating(Client *c, int32_t floating) {
save_old_size_per(c->mon);
}
if (!c->force_fakemaximize)
if (!c->force_maximize)
client_set_maximized(c, false);
if (!c->isfloating || c->force_tiled_state) {
@ -5144,12 +5095,6 @@ setfloating(Client *c, int32_t floating) {
}
arrange(c->mon, false, false);
if (!c->isfloating) {
c->old_master_inner_per = c->master_inner_per;
c->old_stack_inner_per = c->stack_inner_per;
}
setborder_color(c);
printstatus();
}
@ -5192,17 +5137,18 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
return;
int32_t old_maximizescreen_state = c->ismaximizescreen;
client_pending_maximized_state(c, maximizescreen);
c->ismaximizescreen = maximizescreen;
if (maximizescreen) {
if (c->isfullscreen) {
client_pending_fullscreen_state(c, 0);
client_set_fullscreen(c, 0);
}
if (c->isfullscreen)
setfullscreen(c, 0);
exit_scroller_stack(c);
if (c->isfloating)
c->float_geom = c->geom;
maximizescreen_box.x = c->mon->w.x + config.gappoh;
maximizescreen_box.y = c->mon->w.y + config.gappov;
maximizescreen_box.width = c->mon->w.width - 2 * config.gappoh;
@ -5210,8 +5156,10 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
wlr_scene_node_raise_to_top(&c->scene->node);
if (!is_scroller_layout(c->mon) || c->isfloating)
resize(c, maximizescreen_box, 0);
c->ismaximizescreen = 1;
} else {
c->bw = c->isnoborder ? 0 : config.borderpx;
c->ismaximizescreen = 0;
if (c->isfloating)
setfloating(c, 1);
}
@ -5226,9 +5174,9 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
save_old_size_per(c->mon);
}
if (!c->force_fakemaximize && !c->ismaximizescreen) {
if (!c->force_maximize && !c->ismaximizescreen) {
client_set_maximized(c, false);
} else if (!c->force_fakemaximize && c->ismaximizescreen) {
} else if (!c->force_maximize && c->ismaximizescreen) {
client_set_maximized(c, true);
}
@ -5259,25 +5207,26 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自
c->isfullscreen = fullscreen;
client_set_fullscreen(c, fullscreen);
client_pending_fullscreen_state(c, fullscreen);
if (fullscreen) {
if (c->ismaximizescreen && !c->force_fakemaximize) {
client_set_maximized(c, false);
}
client_pending_maximized_state(c, 0);
if (c->ismaximizescreen)
setmaximizescreen(c, 0);
exit_scroller_stack(c);
if (c->isfloating)
c->float_geom = c->geom;
c->isfakefullscreen = 0;
c->bw = 0;
wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层
if (!is_scroller_layout(c->mon) || c->isfloating)
resize(c, c->mon->m, 1);
c->isfullscreen = 1;
} else {
c->bw = c->isnoborder ? 0 : config.borderpx;
c->isfullscreen = 0;
if (c->isfloating)
setfloating(c, 1);
}
@ -5426,8 +5375,15 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) {
/* Make sure window actually overlaps with the monitor */
reset_foreign_tolevel(c);
resize(c, c->geom, 0);
client_reset_mon_tags(c, m, newtags);
check_match_tag_floating_rule(c, m);
if (!newtags && !m->isoverview) {
c->tags = m->tagset[m->seltags];
} else if (!newtags && m->isoverview) {
c->tags = m->ovbk_current_tagset;
} else if (newtags) {
c->tags = newtags;
} else {
c->tags = m->tagset[m->seltags];
}
setfloating(c, c->isfloating);
setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */
}
@ -5469,7 +5425,8 @@ void show_hide_client(Client *c) {
c->tags = c->oldtags;
arrange(c->mon, false, false);
}
client_pending_minimized_state(c, 0);
c->isminimized = 0;
wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel, false);
focusclient(c, 1);
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true);
}
@ -5893,8 +5850,8 @@ void overview_backup(Client *c) {
c->isfloating = 0;
}
if (c->isfullscreen || c->ismaximizescreen) {
client_pending_fullscreen_state(c, 0); // 清除窗口全屏标志
client_pending_maximized_state(c, 0);
c->isfullscreen = 0; // 清除窗口全屏标志
c->ismaximizescreen = 0;
}
c->bw = c->isnoborder ? 0 : config.borderpx;
@ -5924,8 +5881,8 @@ void overview_restore(Client *c, const Arg *arg) {
} else if (want_restore_fullscreen(c) && c->isfullscreen) {
setfullscreen(c, 1);
} else {
client_pending_fullscreen_state(c, 0);
client_pending_maximized_state(c, 0);
c->isfullscreen = 0;
c->ismaximizescreen = 0;
setfullscreen(c, false);
}
} else {
@ -6498,11 +6455,13 @@ void activatex11(struct wl_listener *listener, void *data) {
return;
if (c->isminimized) {
client_pending_minimized_state(c, 0);
c->isminimized = 0;
c->tags = c->mini_restore_tag;
c->is_scratchpad_show = 0;
c->is_in_scratchpad = 0;
c->isnamedscratchpad = 0;
wlr_foreign_toplevel_handle_v1_set_minimized(c->foreign_toplevel,
false);
setborder_color(c);
if (VISIBLEON(c, c->mon)) {
need_arrange = true;