mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-07-06 00:06:43 -04:00
Merge branch 'mangowm:main' into main
This commit is contained in:
commit
bd5b7b04f7
24 changed files with 1422 additions and 381 deletions
10
README.md
10
README.md
|
|
@ -48,7 +48,7 @@ https://github.com/user-attachments/assets/bb83004a-0563-4b48-ad89-6461a9b78b1f
|
||||||
- vertical_tile
|
- vertical_tile
|
||||||
- vertical_grid
|
- vertical_grid
|
||||||
- vertical_scroller
|
- vertical_scroller
|
||||||
- tgmix
|
- dwindle
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
|
|
@ -95,6 +95,12 @@ Finally, install the package:
|
||||||
emerge --ask --verbose gui-wm/mangowm
|
emerge --ask --verbose gui-wm/mangowm
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## openSUSE
|
||||||
|
The package is in the community-maintained repository called obs.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo opi in mangowm
|
||||||
|
```
|
||||||
## Fedora Linux
|
## Fedora Linux
|
||||||
The package is in the third-party Terra repository.
|
The package is in the third-party Terra repository.
|
||||||
First, add the [Terra Repository](https://terra.fyralabs.com/).
|
First, add the [Terra Repository](https://terra.fyralabs.com/).
|
||||||
|
|
@ -148,7 +154,7 @@ 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/mangowm/mango.git
|
||||||
cd mangowm
|
cd mango
|
||||||
meson build -Dprefix=/usr
|
meson build -Dprefix=/usr
|
||||||
sudo ninja -C build install
|
sudo ninja -C build install
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ enable_floating_snap=0
|
||||||
snap_distance=30
|
snap_distance=30
|
||||||
cursor_size=24
|
cursor_size=24
|
||||||
drag_tile_to_tile=1
|
drag_tile_to_tile=1
|
||||||
|
drag_tile_small=1
|
||||||
|
|
||||||
# keyboard
|
# keyboard
|
||||||
repeat_rate=25
|
repeat_rate=25
|
||||||
|
|
@ -119,6 +120,7 @@ scratchpad_height_ratio=0.9
|
||||||
borderpx=4
|
borderpx=4
|
||||||
rootcolor=0x201b14ff
|
rootcolor=0x201b14ff
|
||||||
bordercolor=0x444444ff
|
bordercolor=0x444444ff
|
||||||
|
dropcolor=0x8FBA7C55
|
||||||
focuscolor=0xc9b890ff
|
focuscolor=0xc9b890ff
|
||||||
maximizescreencolor=0x89aa61ff
|
maximizescreencolor=0x89aa61ff
|
||||||
urgentcolor=0xad401fff
|
urgentcolor=0xad401fff
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,19 @@ xkb_rules_options=caps:escape,ctrl:nocaps
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Mouse Settings
|
||||||
|
|
||||||
|
Configuration for external mice.
|
||||||
|
|
||||||
|
| Setting | Default | Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `mouse_natural_scrolling` | `0` | Invert scrolling direction. |
|
||||||
|
| `mouse_accel_profile` | `2` | `0` (None), `1` (Flat), `2` (Adaptive). |
|
||||||
|
| `mouse_accel_speed` | `0.0` | Speed adjustment (-1.0 to 1.0). |
|
||||||
|
| `left_handed` | `0` | Swap left and right buttons. |
|
||||||
|
| `axis_scroll_factor` | `1.0` | Scroll factor for axis scroll speed (0.1–10.0). |
|
||||||
|
---
|
||||||
|
|
||||||
### Trackpad Settings
|
### Trackpad Settings
|
||||||
|
|
||||||
Specific settings for laptop touchpads. Some settings may require a relogin to take effect.
|
Specific settings for laptop touchpads. Some settings may require a relogin to take effect.
|
||||||
|
|
@ -45,15 +58,19 @@ Specific settings for laptop touchpads. Some settings may require a relogin to t
|
||||||
| `tap_to_click` | `1` | Tap to trigger a left click. |
|
| `tap_to_click` | `1` | Tap to trigger a left click. |
|
||||||
| `tap_and_drag` | `1` | Tap and hold to drag items. |
|
| `tap_and_drag` | `1` | Tap and hold to drag items. |
|
||||||
| `trackpad_natural_scrolling` | `0` | Invert scrolling direction (natural scrolling). |
|
| `trackpad_natural_scrolling` | `0` | Invert scrolling direction (natural scrolling). |
|
||||||
|
| `trackpad_accel_profile` | `2` | `0` (None), `1` (Flat), `2` (Adaptive). |
|
||||||
|
| `trackpad_accel_speed` | `0.0` | Speed adjustment (-1.0 to 1.0). |
|
||||||
| `scroll_button` | `274` | The mouse button that use for scrolling(272 to 279).
|
| `scroll_button` | `274` | The mouse button that use for scrolling(272 to 279).
|
||||||
| `scroll_method` | `1` | `1` (Two-finger), `2` (Edge), `4` (Button). |
|
| `scroll_method` | `1` | `1` (Two-finger), `2` (Edge), `4` (Button). |
|
||||||
| `click_method` | `1` | `1` (Button areas), `2` (Clickfinger). |
|
| `click_method` | `1` | `1` (Button areas), `2` (Clickfinger). |
|
||||||
|
| `send_events_mode` | `0` | `0` (Enabled), `1` (Disabled), `2` (Disabled on external mouse). |
|
||||||
| `drag_lock` | `1` | Lock dragging after tapping. |
|
| `drag_lock` | `1` | Lock dragging after tapping. |
|
||||||
| `disable_while_typing` | `1` | Disable trackpad while typing. |
|
| `disable_while_typing` | `1` | Disable trackpad while typing. |
|
||||||
| `left_handed` | `0` | Swap left/right buttons. |
|
| `left_handed` | `0` | Swap left/right buttons. |
|
||||||
| `middle_button_emulation` | `0` | Emulate middle button. |
|
| `middle_button_emulation` | `0` | Emulate middle button. |
|
||||||
| `swipe_min_threshold` | `1` | Minimum swipe threshold. |
|
| `swipe_min_threshold` | `1` | Minimum swipe threshold when use gesture. |
|
||||||
|
| `button_map` | `0` | `0` (Left/right/middle), `1` (Left/middle/right). |
|
||||||
|
| `trackpad_scroll_factor` | `1.0` | Scroll factor for trackpad scroll speed (0.1–10.0). |
|
||||||
---
|
---
|
||||||
|
|
||||||
**Detailed descriptions:**
|
**Detailed descriptions:**
|
||||||
|
|
@ -79,9 +96,9 @@ Specific settings for laptop touchpads. Some settings may require a relogin to t
|
||||||
- `1` — Button areas: use software-defined areas on the touchpad to generate button events.
|
- `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.
|
- `2` — Clickfinger: the number of fingers determines which button is pressed.
|
||||||
|
|
||||||
- `accel_profile` values:
|
- `mouse_accel_profile` or `trackpad_scroll_profile` values:
|
||||||
- `0` — No acceleration.
|
- `0` — No acceleration.
|
||||||
- `1` — Flat: no dynamic acceleration. Pointer speed = original input speed × (1 + `accel_speed`).
|
- `1` — Flat: no dynamic acceleration. Pointer speed = original input speed × (1 + `mouse_accel_speed`).
|
||||||
- `2` — Adaptive: slow movement results in less acceleration, fast movement results in more.
|
- `2` — Adaptive: slow movement results in less acceleration, fast movement results in more.
|
||||||
|
|
||||||
- `button_map` values:
|
- `button_map` values:
|
||||||
|
|
@ -94,24 +111,6 @@ Specific settings for laptop touchpads. Some settings may require a relogin to t
|
||||||
- `2` — Disable this device when an external pointer device is plugged in.
|
- `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
|
## Keyboard Layout Switching
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ description: Advanced settings for XWayland, focus behavior, and system integrat
|
||||||
| `warpcursor` | `1` | Warp the cursor to the center of the window when focus changes via keyboard. |
|
| `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). |
|
| `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_tile_to_tile` | `0` | Allow dragging a tiled window onto another to swap their positions. |
|
||||||
|
| `drag_tile_small` | `1` | Allow dragging a tiled window temporarily to small size.|
|
||||||
| `drag_corner` | `3` | Corner for drag-to-tile detection (0: none, 1–3: corners, 4: auto-detect). |
|
| `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. |
|
| `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_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
|
## Multi-Monitor & Tags
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,10 @@ blur_optimized=0
|
||||||
|
|
||||||
### My games are lagging or stuttering
|
### My games are lagging or stuttering
|
||||||
|
|
||||||
Try enabling **SyncObj** timeline support and **Adaptive Sync** (VRR) if your monitor supports it.
|
Try enabling **SyncObj** timeline support.
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
syncobj_enable=1
|
syncobj_enable=1
|
||||||
adaptive_sync=1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ mmsg -s -t 2^
|
||||||
|
|
||||||
### Layouts
|
### 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).
|
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), `DW` (Dwindle).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Switch to Scroller
|
# Switch to Scroller
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ To get a fully functional desktop experience, we recommend installing the follow
|
||||||
| Terminal Emulator | foot, wezterm, alacritty, kitty, ghostty |
|
| Terminal Emulator | foot, wezterm, alacritty, kitty, ghostty |
|
||||||
| Status Bar | waybar, eww, quickshell, ags |
|
| Status Bar | waybar, eww, quickshell, ags |
|
||||||
| Desktop Shell | Noctalia, DankMaterialShell |
|
| Desktop Shell | Noctalia, DankMaterialShell |
|
||||||
| Wallpaper Setup | swww, swaybg |
|
| Wallpaper Setup | awww(swww), swaybg |
|
||||||
| Notification Daemon | swaync, dunst, mako |
|
| Notification Daemon | swaync, dunst, mako |
|
||||||
| Desktop Portal | xdg-desktop-portal, xdg-desktop-portal-wlr, xdg-desktop-portal-gtk |
|
| Desktop Portal | xdg-desktop-portal, xdg-desktop-portal-wlr, xdg-desktop-portal-gtk |
|
||||||
| Clipboard | wl-clipboard, wl-clip-persist, cliphist |
|
| Clipboard | wl-clipboard, wl-clip-persist, cliphist |
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ rootcolor=0x323232ff
|
||||||
# Inactive window border
|
# Inactive window border
|
||||||
bordercolor=0x444444ff
|
bordercolor=0x444444ff
|
||||||
|
|
||||||
|
# Drop shadow when dragging windows
|
||||||
|
dropcolor=0x8FBA7C55
|
||||||
|
|
||||||
# Active window border
|
# Active window border
|
||||||
focuscolor=0xc66b25ff
|
focuscolor=0xc66b25ff
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ mangowm supports a variety of layouts that can be assigned per tag.
|
||||||
- `vertical_scroller`
|
- `vertical_scroller`
|
||||||
- `vertical_grid`
|
- `vertical_grid`
|
||||||
- `vertical_deck`
|
- `vertical_deck`
|
||||||
- `tgmix`
|
- `dwindle`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -83,6 +83,35 @@ default_nmaster=1
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Dwindle Layout
|
||||||
|
|
||||||
|
The Dwindle layout arranges windows as a binary tree of recursive splits. Each new window splits the focused window's container, producing a spiral-like tiling.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
| Setting | Default | Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `dwindle_split_ratio` | `0.5` | Ratio used for new splits (`0.05`–`0.95`). |
|
||||||
|
| `dwindle_smart_split` | `0` | Pick the split axis from the cursor's position inside the focused window. The new window appears on the cursor's side. |
|
||||||
|
| `dwindle_hsplit` | `0` | Side-by-side splits: where the new window goes. `0` = follow cursor, `1` = right, `2` = left. |
|
||||||
|
| `dwindle_vsplit` | `0` | Top/bottom splits: where the new window goes. `0` = follow cursor, `1` = below, `2` = above. |
|
||||||
|
| `dwindle_preserve_split` | `0` | Keep the sibling's split orientation when a window is closed. |
|
||||||
|
| `dwindle_smart_resize` | `0` | When dragging to resize, move the split toward the cursor regardless of which side was grabbed. |
|
||||||
|
| `dwindle_drop_simple_split` | `1` | Drag-to-tile drop preview. `1` = 2-zone preview matching `dwindle_split_ratio`, `0` = 4-quadrant preview. |
|
||||||
|
|
||||||
|
```ini
|
||||||
|
# Example dwindle configuration
|
||||||
|
dwindle_split_ratio=0.5
|
||||||
|
dwindle_smart_split=0
|
||||||
|
dwindle_hsplit=0
|
||||||
|
dwindle_vsplit=0
|
||||||
|
dwindle_preserve_split=0
|
||||||
|
dwindle_smart_resize=0
|
||||||
|
dwindle_drop_simple_split=1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Switching Layouts
|
## Switching Layouts
|
||||||
|
|
||||||
You can switch layouts dynamically or set a default for specific tags using [Tag Rules](/docs/window-management/rules#tag-rules).
|
You can switch layouts dynamically or set a default for specific tags using [Tag Rules](/docs/window-management/rules#tag-rules).
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
project('mango', ['c', 'cpp'],
|
project('mango', ['c', 'cpp'],
|
||||||
version : '0.12.8',
|
version : '0.12.9',
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('protocols')
|
subdir('protocols')
|
||||||
|
|
|
||||||
|
|
@ -510,6 +510,163 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void client_set_drop_area(Client *c) {
|
||||||
|
bool first_draw = false;
|
||||||
|
int32_t drop_direction = UNDIR;
|
||||||
|
|
||||||
|
if (!c || !c->mon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!c->enable_drop_area_draw && !c->droparea->node.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c->enable_drop_area_draw && c->droparea->node.enabled) {
|
||||||
|
wlr_scene_node_lower_to_bottom(&c->droparea->node);
|
||||||
|
wlr_scene_node_set_enabled(&c->droparea->node, false);
|
||||||
|
return;
|
||||||
|
} else if (c->enable_drop_area_draw && !c->droparea->node.enabled) {
|
||||||
|
wlr_scene_node_raise_to_top(&c->droparea->node);
|
||||||
|
wlr_scene_node_set_enabled(&c->droparea->node, true);
|
||||||
|
first_draw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t bw = (int32_t)c->bw;
|
||||||
|
int32_t client_width = c->geom.width - 2 * bw;
|
||||||
|
int32_t client_height = c->geom.height - 2 * bw;
|
||||||
|
|
||||||
|
// 光标在窗口客户区内的相对坐标
|
||||||
|
double rel_x = cursor->x - c->geom.x - bw;
|
||||||
|
double rel_y = cursor->y - c->geom.y - bw;
|
||||||
|
|
||||||
|
struct wlr_box drop_box;
|
||||||
|
|
||||||
|
const Layout *cur_layout = c->mon->pertag->ltidxs[c->mon->pertag->curtag];
|
||||||
|
bool dwindle_familiar =
|
||||||
|
cur_layout->id == DWINDLE && config.dwindle_drop_simple_split;
|
||||||
|
|
||||||
|
uint32_t nmaster = c->mon->pertag->nmasters[c->mon->pertag->curtag];
|
||||||
|
|
||||||
|
bool should_swap =
|
||||||
|
(cur_layout->id == DECK || cur_layout->id == VERTICAL_DECK ||
|
||||||
|
cur_layout->id == MONOCLE || cur_layout->id == GRID ||
|
||||||
|
cur_layout->id == VERTICAL_GRID) ||
|
||||||
|
((cur_layout->id == TILE || cur_layout->id == VERTICAL_TILE ||
|
||||||
|
cur_layout->id == CENTER_TILE || cur_layout->id == RIGHT_TILE) &&
|
||||||
|
nmaster == 1 && c->ismaster);
|
||||||
|
|
||||||
|
if (dwindle_familiar) {
|
||||||
|
bool split_h = c->geom.width >= c->geom.height;
|
||||||
|
float ratio = config.dwindle_split_ratio;
|
||||||
|
if (split_h) {
|
||||||
|
if (rel_x < client_width * 0.5) {
|
||||||
|
drop_direction = LEFT;
|
||||||
|
drop_box.x = bw;
|
||||||
|
drop_box.y = bw;
|
||||||
|
drop_box.width = (int32_t)(client_width * ratio);
|
||||||
|
drop_box.height = client_height;
|
||||||
|
} else {
|
||||||
|
drop_direction = RIGHT;
|
||||||
|
drop_box.x = bw + (int32_t)(client_width * ratio);
|
||||||
|
drop_box.y = bw;
|
||||||
|
drop_box.width = client_width - (int32_t)(client_width * ratio);
|
||||||
|
drop_box.height = client_height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rel_y < client_height * 0.5) {
|
||||||
|
drop_direction = UP;
|
||||||
|
drop_box.x = bw;
|
||||||
|
drop_box.y = bw;
|
||||||
|
drop_box.width = client_width;
|
||||||
|
drop_box.height = (int32_t)(client_height * ratio);
|
||||||
|
} else {
|
||||||
|
drop_direction = DOWN;
|
||||||
|
drop_box.x = bw;
|
||||||
|
drop_box.y = bw + (int32_t)(client_height * ratio);
|
||||||
|
drop_box.width = client_width;
|
||||||
|
drop_box.height =
|
||||||
|
client_height - (int32_t)(client_height * ratio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (should_swap) {
|
||||||
|
drop_box.x = bw;
|
||||||
|
drop_box.y = bw;
|
||||||
|
drop_box.width = client_width;
|
||||||
|
drop_box.height = client_height;
|
||||||
|
drop_direction = UNDIR;
|
||||||
|
} else if (cur_layout->id == TILE || cur_layout->id == DECK ||
|
||||||
|
cur_layout->id == CENTER_TILE || cur_layout->id == RIGHT_TILE) {
|
||||||
|
if (rel_y < client_height * 0.5) {
|
||||||
|
drop_direction = UP;
|
||||||
|
drop_box.x = bw;
|
||||||
|
drop_box.y = bw;
|
||||||
|
drop_box.width = client_width;
|
||||||
|
drop_box.height = client_height / 2;
|
||||||
|
} else {
|
||||||
|
drop_direction = DOWN;
|
||||||
|
drop_box.x = bw;
|
||||||
|
drop_box.y = bw + client_height / 2;
|
||||||
|
drop_box.width = client_width;
|
||||||
|
drop_box.height = client_height / 2;
|
||||||
|
}
|
||||||
|
} else if (cur_layout->id == VERTICAL_TILE ||
|
||||||
|
cur_layout->id == VERTICAL_DECK) {
|
||||||
|
if (rel_x < client_width * 0.5) {
|
||||||
|
drop_direction = LEFT;
|
||||||
|
drop_box.x = bw;
|
||||||
|
drop_box.y = bw;
|
||||||
|
drop_box.width = client_width / 2;
|
||||||
|
drop_box.height = client_height;
|
||||||
|
} else {
|
||||||
|
drop_direction = RIGHT;
|
||||||
|
drop_box.x = bw + client_width / 2;
|
||||||
|
drop_box.y = bw;
|
||||||
|
drop_box.width = client_width / 2;
|
||||||
|
drop_box.height = client_height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
double dist_left = rel_x;
|
||||||
|
double dist_right = client_width - rel_x;
|
||||||
|
double dist_top = rel_y;
|
||||||
|
double dist_bottom = client_height - rel_y;
|
||||||
|
|
||||||
|
if (dist_left <= dist_right && dist_left <= dist_top &&
|
||||||
|
dist_left <= dist_bottom) {
|
||||||
|
drop_direction = LEFT;
|
||||||
|
drop_box.x = bw;
|
||||||
|
drop_box.y = bw;
|
||||||
|
drop_box.width = client_width / 2;
|
||||||
|
drop_box.height = client_height;
|
||||||
|
} else if (dist_right <= dist_top && dist_right <= dist_bottom) {
|
||||||
|
drop_direction = RIGHT;
|
||||||
|
drop_box.x = bw + client_width / 2;
|
||||||
|
drop_box.y = bw;
|
||||||
|
drop_box.width = client_width / 2;
|
||||||
|
drop_box.height = client_height;
|
||||||
|
} else if (dist_top <= dist_bottom) {
|
||||||
|
drop_direction = UP;
|
||||||
|
drop_box.x = bw;
|
||||||
|
drop_box.y = bw;
|
||||||
|
drop_box.width = client_width;
|
||||||
|
drop_box.height = client_height / 2;
|
||||||
|
} else {
|
||||||
|
drop_direction = DOWN;
|
||||||
|
drop_box.x = bw;
|
||||||
|
drop_box.y = bw + client_height / 2;
|
||||||
|
drop_box.width = client_width;
|
||||||
|
drop_box.height = client_height / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!first_draw && c->drop_direction == drop_direction) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c->drop_direction = drop_direction;
|
||||||
|
|
||||||
|
wlr_scene_node_set_position(&c->droparea->node, drop_box.x, drop_box.y);
|
||||||
|
wlr_scene_rect_set_size(c->droparea, drop_box.width, drop_box.height);
|
||||||
|
}
|
||||||
|
|
||||||
void client_apply_clip(Client *c, float factor) {
|
void client_apply_clip(Client *c, float factor) {
|
||||||
|
|
||||||
if (c->iskilling || !client_surface(c)->mapped)
|
if (c->iskilling || !client_surface(c)->mapped)
|
||||||
|
|
|
||||||
|
|
@ -312,11 +312,6 @@ static inline uint32_t client_set_size(Client *c, uint32_t width,
|
||||||
int32_t width = c->geom.width - 2 * c->bw;
|
int32_t width = c->geom.width - 2 * c->bw;
|
||||||
int32_t height = c->geom.height - 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 &&
|
if (size_hints &&
|
||||||
c->geom.width - 2 * (int32_t)c->bw < size_hints->min_width)
|
c->geom.width - 2 * (int32_t)c->bw < size_hints->min_width)
|
||||||
width = size_hints->min_width;
|
width = size_hints->min_width;
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,7 @@ typedef struct {
|
||||||
int32_t snap_distance;
|
int32_t snap_distance;
|
||||||
int32_t enable_floating_snap;
|
int32_t enable_floating_snap;
|
||||||
int32_t drag_tile_to_tile;
|
int32_t drag_tile_to_tile;
|
||||||
|
int32_t drag_tile_small;
|
||||||
uint32_t swipe_min_threshold;
|
uint32_t swipe_min_threshold;
|
||||||
float focused_opacity;
|
float focused_opacity;
|
||||||
float unfocused_opacity;
|
float unfocused_opacity;
|
||||||
|
|
@ -241,6 +242,15 @@ typedef struct {
|
||||||
int32_t center_master_overspread;
|
int32_t center_master_overspread;
|
||||||
int32_t center_when_single_stack;
|
int32_t center_when_single_stack;
|
||||||
|
|
||||||
|
/* dwindle layout */
|
||||||
|
int32_t dwindle_vsplit;
|
||||||
|
int32_t dwindle_hsplit;
|
||||||
|
int32_t dwindle_preserve_split;
|
||||||
|
int32_t dwindle_smart_split;
|
||||||
|
int32_t dwindle_smart_resize;
|
||||||
|
int32_t dwindle_drop_simple_split;
|
||||||
|
float dwindle_split_ratio;
|
||||||
|
|
||||||
uint32_t hotarea_size;
|
uint32_t hotarea_size;
|
||||||
uint32_t hotarea_corner;
|
uint32_t hotarea_corner;
|
||||||
uint32_t enable_hotarea;
|
uint32_t enable_hotarea;
|
||||||
|
|
@ -262,26 +272,33 @@ typedef struct {
|
||||||
int32_t repeat_delay;
|
int32_t repeat_delay;
|
||||||
uint32_t numlockon;
|
uint32_t numlockon;
|
||||||
|
|
||||||
/* Trackpad */
|
/* common pointer */
|
||||||
int32_t disable_trackpad;
|
|
||||||
int32_t tap_to_click;
|
|
||||||
int32_t tap_and_drag;
|
|
||||||
int32_t drag_lock;
|
|
||||||
int32_t mouse_natural_scrolling;
|
|
||||||
int32_t trackpad_natural_scrolling;
|
|
||||||
int32_t disable_while_typing;
|
int32_t disable_while_typing;
|
||||||
int32_t left_handed;
|
int32_t left_handed;
|
||||||
int32_t middle_button_emulation;
|
int32_t middle_button_emulation;
|
||||||
uint32_t accel_profile;
|
|
||||||
double accel_speed;
|
|
||||||
uint32_t scroll_method;
|
uint32_t scroll_method;
|
||||||
uint32_t scroll_button;
|
uint32_t scroll_button;
|
||||||
uint32_t click_method;
|
uint32_t click_method;
|
||||||
uint32_t send_events_mode;
|
uint32_t send_events_mode;
|
||||||
uint32_t button_map;
|
|
||||||
|
|
||||||
|
/* mouse */
|
||||||
|
int32_t mouse_natural_scrolling;
|
||||||
|
uint32_t mouse_accel_profile;
|
||||||
|
double mouse_accel_speed;
|
||||||
double axis_scroll_factor;
|
double axis_scroll_factor;
|
||||||
|
|
||||||
|
/* Trackpad */
|
||||||
|
int32_t trackpad_natural_scrolling;
|
||||||
|
uint32_t trackpad_accel_profile;
|
||||||
|
double trackpad_accel_speed;
|
||||||
|
double trackpad_scroll_factor;
|
||||||
|
int32_t disable_trackpad;
|
||||||
|
int32_t tap_to_click;
|
||||||
|
int32_t tap_and_drag;
|
||||||
|
int32_t drag_lock;
|
||||||
|
uint32_t button_map;
|
||||||
|
|
||||||
|
/* window effects */
|
||||||
int32_t blur;
|
int32_t blur;
|
||||||
int32_t blur_layer;
|
int32_t blur_layer;
|
||||||
int32_t blur_optimized;
|
int32_t blur_optimized;
|
||||||
|
|
@ -297,6 +314,7 @@ typedef struct {
|
||||||
int32_t shadows_position_y;
|
int32_t shadows_position_y;
|
||||||
float shadowscolor[4];
|
float shadowscolor[4];
|
||||||
|
|
||||||
|
/* appearance */
|
||||||
int32_t smartgaps;
|
int32_t smartgaps;
|
||||||
uint32_t gappih;
|
uint32_t gappih;
|
||||||
uint32_t gappiv;
|
uint32_t gappiv;
|
||||||
|
|
@ -307,6 +325,7 @@ typedef struct {
|
||||||
float scratchpad_height_ratio;
|
float scratchpad_height_ratio;
|
||||||
float rootcolor[4];
|
float rootcolor[4];
|
||||||
float bordercolor[4];
|
float bordercolor[4];
|
||||||
|
float dropcolor[4];
|
||||||
float focuscolor[4];
|
float focuscolor[4];
|
||||||
float maximizescreencolor[4];
|
float maximizescreencolor[4];
|
||||||
float urgentcolor[4];
|
float urgentcolor[4];
|
||||||
|
|
@ -1440,6 +1459,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->enable_floating_snap = atoi(value);
|
config->enable_floating_snap = atoi(value);
|
||||||
} else if (strcmp(key, "drag_tile_to_tile") == 0) {
|
} else if (strcmp(key, "drag_tile_to_tile") == 0) {
|
||||||
config->drag_tile_to_tile = atoi(value);
|
config->drag_tile_to_tile = atoi(value);
|
||||||
|
} else if (strcmp(key, "drag_tile_small") == 0) {
|
||||||
|
config->drag_tile_small = atoi(value);
|
||||||
} else if (strcmp(key, "swipe_min_threshold") == 0) {
|
} else if (strcmp(key, "swipe_min_threshold") == 0) {
|
||||||
config->swipe_min_threshold = atoi(value);
|
config->swipe_min_threshold = atoi(value);
|
||||||
} else if (strcmp(key, "focused_opacity") == 0) {
|
} else if (strcmp(key, "focused_opacity") == 0) {
|
||||||
|
|
@ -1607,6 +1628,20 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->center_master_overspread = atoi(value);
|
config->center_master_overspread = atoi(value);
|
||||||
} else if (strcmp(key, "center_when_single_stack") == 0) {
|
} else if (strcmp(key, "center_when_single_stack") == 0) {
|
||||||
config->center_when_single_stack = atoi(value);
|
config->center_when_single_stack = atoi(value);
|
||||||
|
} else if (strcmp(key, "dwindle_vsplit") == 0) {
|
||||||
|
config->dwindle_vsplit = atoi(value);
|
||||||
|
} else if (strcmp(key, "dwindle_hsplit") == 0) {
|
||||||
|
config->dwindle_hsplit = atoi(value);
|
||||||
|
} else if (strcmp(key, "dwindle_preserve_split") == 0) {
|
||||||
|
config->dwindle_preserve_split = atoi(value);
|
||||||
|
} else if (strcmp(key, "dwindle_smart_split") == 0) {
|
||||||
|
config->dwindle_smart_split = atoi(value);
|
||||||
|
} else if (strcmp(key, "dwindle_smart_resize") == 0) {
|
||||||
|
config->dwindle_smart_resize = atoi(value);
|
||||||
|
} else if (strcmp(key, "dwindle_drop_simple_split") == 0) {
|
||||||
|
config->dwindle_drop_simple_split = atoi(value);
|
||||||
|
} else if (strcmp(key, "dwindle_split_ratio") == 0) {
|
||||||
|
config->dwindle_split_ratio = atof(value);
|
||||||
} else if (strcmp(key, "hotarea_size") == 0) {
|
} else if (strcmp(key, "hotarea_size") == 0) {
|
||||||
config->hotarea_size = atoi(value);
|
config->hotarea_size = atoi(value);
|
||||||
} else if (strcmp(key, "hotarea_corner") == 0) {
|
} else if (strcmp(key, "hotarea_corner") == 0) {
|
||||||
|
|
@ -1665,10 +1700,14 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->left_handed = atoi(value);
|
config->left_handed = atoi(value);
|
||||||
} else if (strcmp(key, "middle_button_emulation") == 0) {
|
} else if (strcmp(key, "middle_button_emulation") == 0) {
|
||||||
config->middle_button_emulation = atoi(value);
|
config->middle_button_emulation = atoi(value);
|
||||||
} else if (strcmp(key, "accel_profile") == 0) {
|
} else if (strcmp(key, "mouse_accel_profile") == 0) {
|
||||||
config->accel_profile = atoi(value);
|
config->mouse_accel_profile = atoi(value);
|
||||||
} else if (strcmp(key, "accel_speed") == 0) {
|
} else if (strcmp(key, "mouse_accel_speed") == 0) {
|
||||||
config->accel_speed = atof(value);
|
config->mouse_accel_speed = atof(value);
|
||||||
|
} else if (strcmp(key, "trackpad_accel_profile") == 0) {
|
||||||
|
config->trackpad_accel_profile = atoi(value);
|
||||||
|
} else if (strcmp(key, "trackpad_accel_speed") == 0) {
|
||||||
|
config->trackpad_accel_speed = atof(value);
|
||||||
} else if (strcmp(key, "scroll_method") == 0) {
|
} else if (strcmp(key, "scroll_method") == 0) {
|
||||||
config->scroll_method = atoi(value);
|
config->scroll_method = atoi(value);
|
||||||
} else if (strcmp(key, "scroll_button") == 0) {
|
} else if (strcmp(key, "scroll_button") == 0) {
|
||||||
|
|
@ -1681,6 +1720,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->button_map = atoi(value);
|
config->button_map = atoi(value);
|
||||||
} else if (strcmp(key, "axis_scroll_factor") == 0) {
|
} else if (strcmp(key, "axis_scroll_factor") == 0) {
|
||||||
config->axis_scroll_factor = atof(value);
|
config->axis_scroll_factor = atof(value);
|
||||||
|
} else if (strcmp(key, "trackpad_scroll_factor") == 0) {
|
||||||
|
config->trackpad_scroll_factor = atof(value);
|
||||||
} else if (strcmp(key, "gappih") == 0) {
|
} else if (strcmp(key, "gappih") == 0) {
|
||||||
config->gappih = atoi(value);
|
config->gappih = atoi(value);
|
||||||
} else if (strcmp(key, "gappiv") == 0) {
|
} else if (strcmp(key, "gappiv") == 0) {
|
||||||
|
|
@ -1730,6 +1771,17 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
} else {
|
} else {
|
||||||
convert_hex_to_rgba(config->bordercolor, color);
|
convert_hex_to_rgba(config->bordercolor, color);
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(key, "dropcolor") == 0) {
|
||||||
|
int64_t color = parse_color(value);
|
||||||
|
if (color == -1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\033[1m\033[31m[ERROR]:\033[33m Invalid dropcolor "
|
||||||
|
"format: %s\n",
|
||||||
|
value);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
convert_hex_to_rgba(config->dropcolor, color);
|
||||||
|
}
|
||||||
} else if (strcmp(key, "focuscolor") == 0) {
|
} else if (strcmp(key, "focuscolor") == 0) {
|
||||||
int64_t color = parse_color(value);
|
int64_t color = parse_color(value);
|
||||||
if (color == -1) {
|
if (color == -1) {
|
||||||
|
|
@ -3154,6 +3206,16 @@ void override_config(void) {
|
||||||
config.center_when_single_stack =
|
config.center_when_single_stack =
|
||||||
CLAMP_INT(config.center_when_single_stack, 0, 1);
|
CLAMP_INT(config.center_when_single_stack, 0, 1);
|
||||||
config.new_is_master = CLAMP_INT(config.new_is_master, 0, 1);
|
config.new_is_master = CLAMP_INT(config.new_is_master, 0, 1);
|
||||||
|
config.dwindle_vsplit = CLAMP_INT(config.dwindle_vsplit, 0, 2);
|
||||||
|
config.dwindle_hsplit = CLAMP_INT(config.dwindle_hsplit, 0, 2);
|
||||||
|
config.dwindle_preserve_split =
|
||||||
|
CLAMP_INT(config.dwindle_preserve_split, 0, 1);
|
||||||
|
config.dwindle_smart_split = CLAMP_INT(config.dwindle_smart_split, 0, 1);
|
||||||
|
config.dwindle_smart_resize = CLAMP_INT(config.dwindle_smart_resize, 0, 1);
|
||||||
|
config.dwindle_drop_simple_split =
|
||||||
|
CLAMP_INT(config.dwindle_drop_simple_split, 0, 1);
|
||||||
|
config.dwindle_split_ratio =
|
||||||
|
CLAMP_FLOAT(config.dwindle_split_ratio, 0.05f, 0.95f);
|
||||||
config.hotarea_size = CLAMP_INT(config.hotarea_size, 1, 1000);
|
config.hotarea_size = CLAMP_INT(config.hotarea_size, 1, 1000);
|
||||||
config.hotarea_corner = CLAMP_INT(config.hotarea_corner, 0, 3);
|
config.hotarea_corner = CLAMP_INT(config.hotarea_corner, 0, 3);
|
||||||
config.enable_hotarea = CLAMP_INT(config.enable_hotarea, 0, 1);
|
config.enable_hotarea = CLAMP_INT(config.enable_hotarea, 0, 1);
|
||||||
|
|
@ -3167,6 +3229,7 @@ void override_config(void) {
|
||||||
config.drag_floating_refresh_interval =
|
config.drag_floating_refresh_interval =
|
||||||
CLAMP_FLOAT(config.drag_floating_refresh_interval, 0.0f, 1000.0f);
|
CLAMP_FLOAT(config.drag_floating_refresh_interval, 0.0f, 1000.0f);
|
||||||
config.drag_tile_to_tile = CLAMP_INT(config.drag_tile_to_tile, 0, 1);
|
config.drag_tile_to_tile = CLAMP_INT(config.drag_tile_to_tile, 0, 1);
|
||||||
|
config.drag_tile_small = CLAMP_INT(config.drag_tile_small, 0, 1);
|
||||||
config.allow_tearing = CLAMP_INT(config.allow_tearing, 0, 2);
|
config.allow_tearing = CLAMP_INT(config.allow_tearing, 0, 2);
|
||||||
config.allow_shortcuts_inhibit =
|
config.allow_shortcuts_inhibit =
|
||||||
CLAMP_INT(config.allow_shortcuts_inhibit, 0, 1);
|
CLAMP_INT(config.allow_shortcuts_inhibit, 0, 1);
|
||||||
|
|
@ -3214,8 +3277,13 @@ void override_config(void) {
|
||||||
config.swipe_min_threshold = CLAMP_INT(config.swipe_min_threshold, 1, 1000);
|
config.swipe_min_threshold = CLAMP_INT(config.swipe_min_threshold, 1, 1000);
|
||||||
config.mouse_natural_scrolling =
|
config.mouse_natural_scrolling =
|
||||||
CLAMP_INT(config.mouse_natural_scrolling, 0, 1);
|
CLAMP_INT(config.mouse_natural_scrolling, 0, 1);
|
||||||
config.accel_profile = CLAMP_INT(config.accel_profile, 0, 2);
|
config.mouse_accel_profile = CLAMP_INT(config.mouse_accel_profile, 0, 2);
|
||||||
config.accel_speed = CLAMP_FLOAT(config.accel_speed, -1.0f, 1.0f);
|
config.mouse_accel_speed =
|
||||||
|
CLAMP_FLOAT(config.mouse_accel_speed, -1.0f, 1.0f);
|
||||||
|
config.trackpad_accel_profile =
|
||||||
|
CLAMP_INT(config.trackpad_accel_profile, 0, 2);
|
||||||
|
config.trackpad_accel_speed =
|
||||||
|
CLAMP_FLOAT(config.trackpad_accel_speed, -1.0f, 1.0f);
|
||||||
config.scroll_method = CLAMP_INT(config.scroll_method, 0, 4);
|
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, 279);
|
||||||
config.click_method = CLAMP_INT(config.click_method, 0, 2);
|
config.click_method = CLAMP_INT(config.click_method, 0, 2);
|
||||||
|
|
@ -3223,6 +3291,8 @@ void override_config(void) {
|
||||||
config.button_map = CLAMP_INT(config.button_map, 0, 1);
|
config.button_map = CLAMP_INT(config.button_map, 0, 1);
|
||||||
config.axis_scroll_factor =
|
config.axis_scroll_factor =
|
||||||
CLAMP_FLOAT(config.axis_scroll_factor, 0.1f, 10.0f);
|
CLAMP_FLOAT(config.axis_scroll_factor, 0.1f, 10.0f);
|
||||||
|
config.trackpad_scroll_factor =
|
||||||
|
CLAMP_FLOAT(config.trackpad_scroll_factor, 0.1f, 10.0f);
|
||||||
config.gappih = CLAMP_INT(config.gappih, 0, 1000);
|
config.gappih = CLAMP_INT(config.gappih, 0, 1000);
|
||||||
config.gappiv = CLAMP_INT(config.gappiv, 0, 1000);
|
config.gappiv = CLAMP_INT(config.gappiv, 0, 1000);
|
||||||
config.gappoh = CLAMP_INT(config.gappoh, 0, 1000);
|
config.gappoh = CLAMP_INT(config.gappoh, 0, 1000);
|
||||||
|
|
@ -3285,6 +3355,14 @@ void set_value_default() {
|
||||||
config.center_master_overspread = 0;
|
config.center_master_overspread = 0;
|
||||||
config.center_when_single_stack = 1;
|
config.center_when_single_stack = 1;
|
||||||
|
|
||||||
|
config.dwindle_vsplit = 0;
|
||||||
|
config.dwindle_hsplit = 0;
|
||||||
|
config.dwindle_preserve_split = 0;
|
||||||
|
config.dwindle_smart_split = 0;
|
||||||
|
config.dwindle_smart_resize = 0;
|
||||||
|
config.dwindle_drop_simple_split = 1;
|
||||||
|
config.dwindle_split_ratio = 0.5f;
|
||||||
|
|
||||||
config.log_level = WLR_ERROR;
|
config.log_level = WLR_ERROR;
|
||||||
config.numlockon = 0;
|
config.numlockon = 0;
|
||||||
config.capslock = 0;
|
config.capslock = 0;
|
||||||
|
|
@ -3315,6 +3393,7 @@ void set_value_default() {
|
||||||
config.scratchpad_cross_monitor = 0;
|
config.scratchpad_cross_monitor = 0;
|
||||||
config.focus_cross_tag = 0;
|
config.focus_cross_tag = 0;
|
||||||
config.axis_scroll_factor = 1.0;
|
config.axis_scroll_factor = 1.0;
|
||||||
|
config.trackpad_scroll_factor = 1.0;
|
||||||
config.view_current_to_back = 0;
|
config.view_current_to_back = 0;
|
||||||
config.single_scratchpad = 1;
|
config.single_scratchpad = 1;
|
||||||
config.xwayland_persistence = 1;
|
config.xwayland_persistence = 1;
|
||||||
|
|
@ -3328,6 +3407,7 @@ void set_value_default() {
|
||||||
config.no_radius_when_single = 0;
|
config.no_radius_when_single = 0;
|
||||||
config.snap_distance = 30;
|
config.snap_distance = 30;
|
||||||
config.drag_tile_to_tile = 0;
|
config.drag_tile_to_tile = 0;
|
||||||
|
config.drag_tile_small = 1;
|
||||||
config.enable_floating_snap = 0;
|
config.enable_floating_snap = 0;
|
||||||
config.swipe_min_threshold = 1;
|
config.swipe_min_threshold = 1;
|
||||||
|
|
||||||
|
|
@ -3355,8 +3435,10 @@ void set_value_default() {
|
||||||
config.disable_while_typing = 1;
|
config.disable_while_typing = 1;
|
||||||
config.left_handed = 0;
|
config.left_handed = 0;
|
||||||
config.middle_button_emulation = 0;
|
config.middle_button_emulation = 0;
|
||||||
config.accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
|
config.mouse_accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
|
||||||
config.accel_speed = 0.0;
|
config.mouse_accel_speed = 0.0;
|
||||||
|
config.trackpad_accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
|
||||||
|
config.trackpad_accel_speed = 0.0;
|
||||||
config.scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
|
config.scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
|
||||||
config.scroll_button = 274;
|
config.scroll_button = 274;
|
||||||
config.click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
config.click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||||
|
|
@ -3426,6 +3508,10 @@ void set_value_default() {
|
||||||
config.bordercolor[1] = 0x44 / 255.0f;
|
config.bordercolor[1] = 0x44 / 255.0f;
|
||||||
config.bordercolor[2] = 0x44 / 255.0f;
|
config.bordercolor[2] = 0x44 / 255.0f;
|
||||||
config.bordercolor[3] = 1.0f;
|
config.bordercolor[3] = 1.0f;
|
||||||
|
config.dropcolor[0] = 0x8f / 255.0f;
|
||||||
|
config.dropcolor[1] = 0xba / 255.0f;
|
||||||
|
config.dropcolor[2] = 0x7c / 255.0f;
|
||||||
|
config.dropcolor[3] = 0.5f;
|
||||||
config.focuscolor[0] = 0xc6 / 255.0f;
|
config.focuscolor[0] = 0xc6 / 255.0f;
|
||||||
config.focuscolor[1] = 0x6b / 255.0f;
|
config.focuscolor[1] = 0x6b / 255.0f;
|
||||||
config.focuscolor[2] = 0x25 / 255.0f;
|
config.focuscolor[2] = 0x25 / 255.0f;
|
||||||
|
|
@ -3675,7 +3761,7 @@ void reapply_rootbg(void) {
|
||||||
wlr_scene_rect_set_color(root_bg, config.rootcolor);
|
wlr_scene_rect_set_color(root_bg, config.rootcolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reapply_border(void) {
|
void reapply_property(void) {
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
|
|
||||||
// reset border width when config change
|
// reset border width when config change
|
||||||
|
|
@ -3684,6 +3770,8 @@ void reapply_border(void) {
|
||||||
if (!c->isnoborder && !c->isfullscreen) {
|
if (!c->isnoborder && !c->isfullscreen) {
|
||||||
c->bw = config.borderpx;
|
c->bw = config.borderpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_scene_rect_set_color(c->droparea, config.dropcolor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3829,7 +3917,7 @@ void reset_option(void) {
|
||||||
run_exec();
|
run_exec();
|
||||||
|
|
||||||
reapply_cursor_style();
|
reapply_cursor_style();
|
||||||
reapply_border();
|
reapply_property();
|
||||||
reapply_rootbg();
|
reapply_rootbg();
|
||||||
reapply_keyboard();
|
reapply_keyboard();
|
||||||
reapply_pointer();
|
reapply_pointer();
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,10 @@ int32_t exchange_client(const Arg *arg) {
|
||||||
|
|
||||||
Client *tc = direction_select(arg);
|
Client *tc = direction_select(arg);
|
||||||
tc = get_focused_stack_client(tc);
|
tc = get_focused_stack_client(tc);
|
||||||
|
|
||||||
|
if (!tc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
exchange_two_client(c, tc);
|
exchange_two_client(c, tc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -378,11 +382,20 @@ int32_t moveresize(const Arg *arg) {
|
||||||
grabc->drag_to_tile = true;
|
grabc->drag_to_tile = true;
|
||||||
exit_scroller_stack(grabc);
|
exit_scroller_stack(grabc);
|
||||||
setfloating(grabc, 1);
|
setfloating(grabc, 1);
|
||||||
|
grabc->drag_tile_float_backup_geom = grabc->float_geom;
|
||||||
grabc->old_stack_inner_per = 0.0f;
|
grabc->old_stack_inner_per = 0.0f;
|
||||||
grabc->old_master_inner_per = 0.0f;
|
grabc->old_master_inner_per = 0.0f;
|
||||||
set_size_per(grabc->mon, grabc);
|
set_size_per(grabc->mon, grabc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (grabc && grabc->drag_to_tile && config.drag_tile_small) {
|
||||||
|
grabc->geom.x = cursor->x - 150;
|
||||||
|
grabc->geom.y = cursor->y - 150;
|
||||||
|
grabc->geom.width = 300;
|
||||||
|
grabc->geom.height = 300;
|
||||||
|
resize(grabc, grabc->geom, 1);
|
||||||
|
}
|
||||||
|
|
||||||
switch (cursor_mode = arg->ui) {
|
switch (cursor_mode = arg->ui) {
|
||||||
case CurMove:
|
case CurMove:
|
||||||
|
|
||||||
|
|
@ -1124,7 +1137,7 @@ int32_t tag(const Arg *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tagmon(const Arg *arg) {
|
int32_t tagmon(const Arg *arg) {
|
||||||
Monitor *m = NULL, *cm = NULL;
|
Monitor *m = NULL, *cm = NULL, *oldmon = NULL;
|
||||||
if (!selmon)
|
if (!selmon)
|
||||||
return 0;
|
return 0;
|
||||||
Client *c = focustop(selmon);
|
Client *c = focustop(selmon);
|
||||||
|
|
@ -1132,6 +1145,8 @@ int32_t tagmon(const Arg *arg) {
|
||||||
if (!c)
|
if (!c)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
oldmon = c->mon;
|
||||||
|
|
||||||
if (arg->i != UNDIR) {
|
if (arg->i != UNDIR) {
|
||||||
m = dirtomon(arg->i);
|
m = dirtomon(arg->i);
|
||||||
} else if (arg->v) {
|
} else if (arg->v) {
|
||||||
|
|
@ -1166,12 +1181,12 @@ int32_t tagmon(const Arg *arg) {
|
||||||
setmon(c, m, newtags, true);
|
setmon(c, m, newtags, true);
|
||||||
client_update_oldmonname_record(c, m);
|
client_update_oldmonname_record(c, m);
|
||||||
|
|
||||||
reset_foreign_tolevel(c);
|
reset_foreign_tolevel(c, oldmon, c->mon);
|
||||||
|
|
||||||
c->float_geom.width =
|
c->float_geom.width =
|
||||||
(int32_t)(c->float_geom.width * c->mon->w.width / selmon->w.width);
|
(int32_t)(c->float_geom.width * c->mon->w.width / oldmon->w.width);
|
||||||
c->float_geom.height =
|
c->float_geom.height =
|
||||||
(int32_t)(c->float_geom.height * c->mon->w.height / selmon->w.height);
|
(int32_t)(c->float_geom.height * c->mon->w.height / oldmon->w.height);
|
||||||
selmon = c->mon;
|
selmon = c->mon;
|
||||||
c->float_geom = setclient_coordinate_center(c, c->mon, c->float_geom, 0, 0);
|
c->float_geom = setclient_coordinate_center(c, c->mon, c->float_geom, 0, 0);
|
||||||
|
|
||||||
|
|
@ -1787,21 +1802,15 @@ int32_t toggle_monitor(const Arg *arg) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t scroller_stack(const Arg *arg) {
|
int32_t scroller_apply_stack(Client *c, Client *target_client,
|
||||||
if (!selmon)
|
int32_t direction) {
|
||||||
return 0;
|
|
||||||
Client *c = selmon->sel;
|
|
||||||
Client *stack_head = NULL;
|
|
||||||
Client *source_stack_head = NULL;
|
|
||||||
if (!c || !c->mon || c->isfloating || !is_scroller_layout(selmon))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
Client *source_stack_head = NULL;
|
||||||
|
Client *stack_head = NULL;
|
||||||
bool is_horizontal_layout =
|
bool is_horizontal_layout =
|
||||||
c->mon->pertag->ltidxs[c->mon->pertag->curtag]->id == SCROLLER ? true
|
c->mon->pertag->ltidxs[c->mon->pertag->curtag]->id == SCROLLER ? true
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
Client *target_client = find_client_by_direction(c, arg, false, true);
|
|
||||||
|
|
||||||
if (target_client) {
|
if (target_client) {
|
||||||
stack_head = get_scroll_stack_head(target_client);
|
stack_head = get_scroll_stack_head(target_client);
|
||||||
}
|
}
|
||||||
|
|
@ -1820,32 +1829,32 @@ int32_t scroller_stack(const Arg *arg) {
|
||||||
setmaximizescreen(c, 0);
|
setmaximizescreen(c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->prev_in_stack) {
|
if (c->prev_in_stack && direction != UNDIR) {
|
||||||
if ((is_horizontal_layout && arg->i == LEFT) ||
|
if ((is_horizontal_layout && direction == LEFT) ||
|
||||||
(!is_horizontal_layout && arg->i == UP)) {
|
(!is_horizontal_layout && direction == UP)) {
|
||||||
exit_scroller_stack(c);
|
exit_scroller_stack(c);
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
wl_list_insert(source_stack_head->link.prev, &c->link);
|
wl_list_insert(source_stack_head->link.prev, &c->link);
|
||||||
arrange(selmon, false, false);
|
arrange(selmon, false, false);
|
||||||
|
|
||||||
} else if ((is_horizontal_layout && arg->i == RIGHT) ||
|
} else if ((is_horizontal_layout && direction == RIGHT) ||
|
||||||
(!is_horizontal_layout && arg->i == DOWN)) {
|
(!is_horizontal_layout && direction == DOWN)) {
|
||||||
exit_scroller_stack(c);
|
exit_scroller_stack(c);
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
wl_list_insert(&source_stack_head->link, &c->link);
|
wl_list_insert(&source_stack_head->link, &c->link);
|
||||||
arrange(selmon, false, false);
|
arrange(selmon, false, false);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else if (c->next_in_stack) {
|
} else if (c->next_in_stack && direction != UNDIR) {
|
||||||
Client *next_in_stack = c->next_in_stack;
|
Client *next_in_stack = c->next_in_stack;
|
||||||
if ((is_horizontal_layout && arg->i == LEFT) ||
|
if ((is_horizontal_layout && direction == LEFT) ||
|
||||||
(!is_horizontal_layout && arg->i == UP)) {
|
(!is_horizontal_layout && direction == UP)) {
|
||||||
exit_scroller_stack(c);
|
exit_scroller_stack(c);
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
wl_list_insert(next_in_stack->link.prev, &c->link);
|
wl_list_insert(next_in_stack->link.prev, &c->link);
|
||||||
arrange(selmon, false, false);
|
arrange(selmon, false, false);
|
||||||
} else if ((is_horizontal_layout && arg->i == RIGHT) ||
|
} else if ((is_horizontal_layout && direction == RIGHT) ||
|
||||||
(!is_horizontal_layout && arg->i == DOWN)) {
|
(!is_horizontal_layout && direction == DOWN)) {
|
||||||
exit_scroller_stack(c);
|
exit_scroller_stack(c);
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
wl_list_insert(&next_in_stack->link, &c->link);
|
wl_list_insert(&next_in_stack->link, &c->link);
|
||||||
|
|
@ -1856,37 +1865,31 @@ int32_t scroller_stack(const Arg *arg) {
|
||||||
|
|
||||||
if (!target_client || target_client->mon != c->mon) {
|
if (!target_client || target_client->mon != c->mon) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
c->isglobal = target_client->isglobal = 0;
|
|
||||||
c->isunglobal = target_client->isglobal = 0;
|
|
||||||
c->tags = target_client->tags = get_tags_first_tag(target_client->tags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_scroller_stack(c);
|
|
||||||
|
|
||||||
// Find the tail of target_client's stack
|
// Find the tail of target_client's stack
|
||||||
Client *stack_tail = target_client;
|
Client *stack_tail = target_client;
|
||||||
while (stack_tail->next_in_stack) {
|
while (stack_tail->next_in_stack) {
|
||||||
stack_tail = stack_tail->next_in_stack;
|
stack_tail = stack_tail->next_in_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add c to the stack
|
scroller_insert_stack(c, stack_tail, false);
|
||||||
stack_tail->next_in_stack = c;
|
|
||||||
c->prev_in_stack = stack_tail;
|
|
||||||
c->next_in_stack = NULL;
|
|
||||||
|
|
||||||
if (stack_head->ismaximizescreen) {
|
|
||||||
setmaximizescreen(stack_head, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stack_head->isfullscreen) {
|
|
||||||
setfullscreen(stack_head, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
arrange(selmon, false, false);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t scroller_stack(const Arg *arg) {
|
||||||
|
if (!selmon)
|
||||||
|
return 0;
|
||||||
|
Client *c = selmon->sel;
|
||||||
|
if (!c || !c->mon || c->isfloating || !is_scroller_layout(selmon))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Client *target_client = find_client_by_direction(c, arg, false, true);
|
||||||
|
|
||||||
|
return scroller_apply_stack(c, target_client, arg->i);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t toggle_all_floating(const Arg *arg) {
|
int32_t toggle_all_floating(const Arg *arg) {
|
||||||
if (!selmon || !selmon->sel)
|
if (!selmon || !selmon->sel)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,11 @@
|
||||||
typedef struct Monitor Monitor;
|
typedef struct Monitor Monitor;
|
||||||
|
|
||||||
struct workspace {
|
struct workspace {
|
||||||
struct wl_list link; // Link in global workspaces list
|
struct wl_list link;
|
||||||
uint32_t tag; // Numeric identifier (1-9, 0=overview)
|
uint32_t tag;
|
||||||
Monitor *m; // Associated monitor
|
Monitor *m;
|
||||||
struct wlr_ext_workspace_handle_v1 *ext_workspace; // Protocol object
|
struct wlr_ext_workspace_handle_v1 *ext_workspace;
|
||||||
/* Event listeners */
|
struct wl_listener commit;
|
||||||
struct wl_listener activate;
|
|
||||||
struct wl_listener deactivate;
|
|
||||||
struct wl_listener assign;
|
|
||||||
struct wl_listener remove;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 *ext_manager;
|
struct wlr_ext_workspace_manager_v1 *ext_manager;
|
||||||
|
|
@ -43,30 +39,60 @@ void toggle_workspace(struct workspace *target) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_ext_workspace_activate(struct wl_listener *listener,
|
static void handle_ext_commit(struct wl_listener *listener, void *data) {
|
||||||
void *data) {
|
struct wlr_ext_workspace_v1_commit_event *event = data;
|
||||||
struct workspace *workspace =
|
struct wlr_ext_workspace_v1_request *request;
|
||||||
wl_container_of(listener, workspace, activate);
|
|
||||||
|
|
||||||
if (workspace->m->isoverview) {
|
wl_list_for_each(request, event->requests, link) {
|
||||||
return;
|
switch (request->type) {
|
||||||
|
case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE: {
|
||||||
|
if (!request->activate.workspace) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct workspace *workspace = NULL;
|
||||||
|
struct workspace *w;
|
||||||
|
wl_list_for_each(w, &workspaces, link) {
|
||||||
|
if (w->ext_workspace == request->activate.workspace) {
|
||||||
|
workspace = w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workspace || workspace->m->isoverview) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto_workspace(workspace);
|
goto_workspace(workspace);
|
||||||
wlr_log(WLR_INFO, "ext activating workspace %d", workspace->tag);
|
wlr_log(WLR_INFO, "ext activating workspace %d", workspace->tag);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
case WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE: {
|
||||||
|
if (!request->deactivate.workspace) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_ext_workspace_deactivate(struct wl_listener *listener,
|
struct workspace *workspace = NULL;
|
||||||
void *data) {
|
struct workspace *w;
|
||||||
struct workspace *workspace =
|
wl_list_for_each(w, &workspaces, link) {
|
||||||
wl_container_of(listener, workspace, deactivate);
|
if (w->ext_workspace == request->deactivate.workspace) {
|
||||||
|
workspace = w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (workspace->m->isoverview) {
|
if (!workspace || workspace->m->isoverview) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle_workspace(workspace);
|
toggle_workspace(workspace);
|
||||||
wlr_log(WLR_INFO, "ext deactivating workspace %d", workspace->tag);
|
wlr_log(WLR_INFO, "ext deactivating workspace %d", workspace->tag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *get_name_from_tag(uint32_t tag) {
|
static const char *get_name_from_tag(uint32_t tag) {
|
||||||
|
|
@ -76,8 +102,6 @@ static const char *get_name_from_tag(uint32_t tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_workspace(struct workspace *workspace) {
|
void destroy_workspace(struct workspace *workspace) {
|
||||||
wl_list_remove(&workspace->activate.link);
|
|
||||||
wl_list_remove(&workspace->deactivate.link);
|
|
||||||
wlr_ext_workspace_handle_v1_destroy(workspace->ext_workspace);
|
wlr_ext_workspace_handle_v1_destroy(workspace->ext_workspace);
|
||||||
wl_list_remove(&workspace->link);
|
wl_list_remove(&workspace->link);
|
||||||
free(workspace);
|
free(workspace);
|
||||||
|
|
@ -112,17 +136,12 @@ static void add_workspace_by_tag(int32_t tag, Monitor *m) {
|
||||||
workspace->m = m;
|
workspace->m = m;
|
||||||
workspace->ext_workspace = wlr_ext_workspace_handle_v1_create(
|
workspace->ext_workspace = wlr_ext_workspace_handle_v1_create(
|
||||||
ext_manager, name, EXT_WORKSPACE_ENABLE_CAPS);
|
ext_manager, name, EXT_WORKSPACE_ENABLE_CAPS);
|
||||||
|
|
||||||
|
workspace->ext_workspace->data = workspace;
|
||||||
|
|
||||||
wlr_ext_workspace_handle_v1_set_group(workspace->ext_workspace,
|
wlr_ext_workspace_handle_v1_set_group(workspace->ext_workspace,
|
||||||
m->ext_group);
|
m->ext_group);
|
||||||
wlr_ext_workspace_handle_v1_set_name(workspace->ext_workspace, name);
|
wlr_ext_workspace_handle_v1_set_name(workspace->ext_workspace, name);
|
||||||
|
|
||||||
workspace->activate.notify = handle_ext_workspace_activate;
|
|
||||||
wl_signal_add(&workspace->ext_workspace->events.activate,
|
|
||||||
&workspace->activate);
|
|
||||||
|
|
||||||
workspace->deactivate.notify = handle_ext_workspace_deactivate;
|
|
||||||
wl_signal_add(&workspace->ext_workspace->events.deactivate,
|
|
||||||
&workspace->deactivate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dwl_ext_workspace_printstatus(Monitor *m) {
|
void dwl_ext_workspace_printstatus(Monitor *m) {
|
||||||
|
|
@ -180,8 +199,11 @@ void refresh_monitors_workspaces_status(Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void workspaces_init() {
|
void workspaces_init() {
|
||||||
/* Create the global workspace manager with activation capability */
|
|
||||||
ext_manager = wlr_ext_workspace_manager_v1_create(dpy, 1);
|
ext_manager = wlr_ext_workspace_manager_v1_create(dpy, 1);
|
||||||
/* Initialize the global workspaces list */
|
|
||||||
wl_list_init(&workspaces);
|
wl_list_init(&workspaces);
|
||||||
|
|
||||||
|
static struct wl_listener commit_listener;
|
||||||
|
commit_listener.notify = handle_ext_commit;
|
||||||
|
wl_signal_add(&ext_manager->events.commit, &commit_listener);
|
||||||
}
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ void handle_foreign_activate_request(struct wl_listener *listener, void *data) {
|
||||||
Client *c = wl_container_of(listener, c, foreign_activate_request);
|
Client *c = wl_container_of(listener, c, foreign_activate_request);
|
||||||
uint32_t target;
|
uint32_t target;
|
||||||
|
|
||||||
if (c->swallowing)
|
if (c->swallowing || !c->mon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c->isminimized) {
|
if (c->isminimized) {
|
||||||
|
|
@ -28,7 +28,7 @@ void handle_foreign_maximize_request(struct wl_listener *listener, void *data) {
|
||||||
Client *c = wl_container_of(listener, c, foreign_maximize_request);
|
Client *c = wl_container_of(listener, c, foreign_maximize_request);
|
||||||
struct wlr_foreign_toplevel_handle_v1_maximized_event *event = data;
|
struct wlr_foreign_toplevel_handle_v1_maximized_event *event = data;
|
||||||
|
|
||||||
if (c->swallowing)
|
if (c->swallowing || !c->mon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c->ismaximizescreen && !event->maximized) {
|
if (c->ismaximizescreen && !event->maximized) {
|
||||||
|
|
@ -46,7 +46,7 @@ void handle_foreign_minimize_request(struct wl_listener *listener, void *data) {
|
||||||
Client *c = wl_container_of(listener, c, foreign_minimize_request);
|
Client *c = wl_container_of(listener, c, foreign_minimize_request);
|
||||||
struct wlr_foreign_toplevel_handle_v1_minimized_event *event = data;
|
struct wlr_foreign_toplevel_handle_v1_minimized_event *event = data;
|
||||||
|
|
||||||
if (c->swallowing)
|
if (c->swallowing || !c->mon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!c->isminimized && event->minimized) {
|
if (!c->isminimized && event->minimized) {
|
||||||
|
|
@ -71,7 +71,7 @@ void handle_foreign_fullscreen_request(struct wl_listener *listener,
|
||||||
Client *c = wl_container_of(listener, c, foreign_fullscreen_request);
|
Client *c = wl_container_of(listener, c, foreign_fullscreen_request);
|
||||||
struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data;
|
struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data;
|
||||||
|
|
||||||
if (c->swallowing)
|
if (c->swallowing || !c->mon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c->isfullscreen && !event->fullscreen) {
|
if (c->isfullscreen && !event->fullscreen) {
|
||||||
|
|
@ -98,10 +98,6 @@ void handle_foreign_destroy(struct wl_listener *listener, void *data) {
|
||||||
wl_list_remove(&c->foreign_fullscreen_request.link);
|
wl_list_remove(&c->foreign_fullscreen_request.link);
|
||||||
wl_list_remove(&c->foreign_close_request.link);
|
wl_list_remove(&c->foreign_close_request.link);
|
||||||
wl_list_remove(&c->foreign_destroy.link);
|
wl_list_remove(&c->foreign_destroy.link);
|
||||||
}
|
|
||||||
|
|
||||||
void remove_foreign_topleve(Client *c) {
|
|
||||||
wlr_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel);
|
|
||||||
c->foreign_toplevel = NULL;
|
c->foreign_toplevel = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,7 +140,23 @@ void add_foreign_toplevel(Client *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_foreign_tolevel(Client *c) {
|
void reset_foreign_tolevel(Client *c, Monitor *oldmon, Monitor *newmon) {
|
||||||
remove_foreign_topleve(c);
|
if (!c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!c->foreign_toplevel) {
|
||||||
add_foreign_toplevel(c);
|
add_foreign_toplevel(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldmon == newmon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (oldmon)
|
||||||
|
wlr_foreign_toplevel_handle_v1_output_leave(c->foreign_toplevel,
|
||||||
|
oldmon->wlr_output);
|
||||||
|
|
||||||
|
if (newmon)
|
||||||
|
wlr_foreign_toplevel_handle_v1_output_enter(c->foreign_toplevel,
|
||||||
|
newmon->wlr_output);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
// bash on: https://gitlab.freedesktop.org/tokyo4j/wlroots/-/tree/ext-workspace
|
|
||||||
// TODO: remove this file
|
|
||||||
// refer: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5115
|
|
||||||
|
|
||||||
#include "wlr_ext_workspace_v1.h"
|
#include "wlr_ext_workspace_v1.h"
|
||||||
#include "ext-workspace-v1-protocol.h"
|
#include "ext-workspace-v1-protocol.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
@ -11,27 +7,6 @@
|
||||||
|
|
||||||
#define EXT_WORKSPACE_V1_VERSION 1
|
#define EXT_WORKSPACE_V1_VERSION 1
|
||||||
|
|
||||||
enum wlr_ext_workspace_v1_request_type {
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request {
|
|
||||||
enum wlr_ext_workspace_v1_request_type type;
|
|
||||||
|
|
||||||
// CREATE_WORKSPACE
|
|
||||||
char *name;
|
|
||||||
// CREATE_WORKSPACE / ASSIGN
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
|
||||||
// ACTIVATE / DEACTIVATE / ASSIGN / REMOVE
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
|
||||||
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1_resource.requests
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_group_output {
|
struct wlr_ext_workspace_v1_group_output {
|
||||||
struct wlr_output *output;
|
struct wlr_output *output;
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
struct wlr_ext_workspace_group_handle_v1 *group;
|
||||||
|
|
@ -117,7 +92,7 @@ static void workspace_handle_activate(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE;
|
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE;
|
||||||
req->workspace = workspace_res->workspace;
|
req->activate.workspace = workspace_res->workspace;
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,7 +111,7 @@ workspace_handle_deactivate(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE;
|
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE;
|
||||||
req->workspace = workspace_res->workspace;
|
req->deactivate.workspace = workspace_res->workspace;
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,8 +132,8 @@ static void workspace_handle_assign(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN;
|
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN;
|
||||||
req->group = group_res->group;
|
req->assign.group = group_res->group;
|
||||||
req->workspace = workspace_res->workspace;
|
req->assign.workspace = workspace_res->workspace;
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,7 +151,7 @@ static void workspace_handle_remove(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE;
|
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE;
|
||||||
req->workspace = workspace_res->workspace;
|
req->remove.workspace = workspace_res->workspace;
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,14 +177,14 @@ static void group_handle_create_workspace(struct wl_client *client,
|
||||||
wl_resource_post_no_memory(group_resource);
|
wl_resource_post_no_memory(group_resource);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req->name = strdup(name);
|
req->create_workspace.name = strdup(name);
|
||||||
if (!req->name) {
|
if (!req->create_workspace.name) {
|
||||||
free(req);
|
free(req);
|
||||||
wl_resource_post_no_memory(group_resource);
|
wl_resource_post_no_memory(group_resource);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE;
|
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE;
|
||||||
req->group = group_res->group;
|
req->create_workspace.group = group_res->group;
|
||||||
wl_list_insert(group_res->manager->requests.prev, &req->link);
|
wl_list_insert(group_res->manager->requests.prev, &req->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,10 +288,55 @@ static struct wlr_ext_workspace_group_v1_resource *create_group_resource(
|
||||||
return group_res;
|
return group_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroy_request(struct wlr_ext_workspace_v1_request *req) {
|
static void
|
||||||
|
destroy_requests(struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||||
|
struct wlr_ext_workspace_v1_request *req, *tmp;
|
||||||
|
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
||||||
|
if (req->type == WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE) {
|
||||||
|
free(req->create_workspace.name);
|
||||||
|
}
|
||||||
wl_list_remove(&req->link);
|
wl_list_remove(&req->link);
|
||||||
free(req->name);
|
|
||||||
free(req);
|
free(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_requests_by(struct wlr_ext_workspace_manager_v1_resource *manager_res,
|
||||||
|
struct wlr_ext_workspace_group_handle_v1 *group,
|
||||||
|
struct wlr_ext_workspace_handle_v1 *workspace) {
|
||||||
|
struct wlr_ext_workspace_v1_request *req, *tmp;
|
||||||
|
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
||||||
|
switch (req->type) {
|
||||||
|
case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE:
|
||||||
|
if (group && req->create_workspace.group == group) {
|
||||||
|
req->create_workspace.group = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE:
|
||||||
|
if (workspace && req->activate.workspace == workspace) {
|
||||||
|
req->activate.workspace = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE:
|
||||||
|
if (workspace && req->deactivate.workspace == workspace) {
|
||||||
|
req->deactivate.workspace = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN:
|
||||||
|
if (workspace && req->assign.workspace == workspace) {
|
||||||
|
req->assign.workspace = NULL;
|
||||||
|
}
|
||||||
|
if (group && req->assign.group == group) {
|
||||||
|
req->assign.group = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE:
|
||||||
|
if (workspace && req->remove.workspace == workspace) {
|
||||||
|
req->remove.workspace = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_handle_commit(struct wl_client *client,
|
static void manager_handle_commit(struct wl_client *client,
|
||||||
|
|
@ -327,32 +347,11 @@ static void manager_handle_commit(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
struct wlr_ext_workspace_v1_commit_event commit_event = {
|
||||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
.requests = &manager_res->requests,
|
||||||
switch (req->type) {
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE:;
|
|
||||||
struct wlr_ext_workspace_group_handle_v1_create_workspace_event
|
|
||||||
event = {
|
|
||||||
.name = req->name,
|
|
||||||
};
|
};
|
||||||
wl_signal_emit_mutable(&req->group->events.create_workspace,
|
wl_signal_emit_mutable(&manager_res->manager->events.commit, &commit_event);
|
||||||
&event);
|
destroy_requests(manager_res);
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE:
|
|
||||||
wl_signal_emit_mutable(&req->workspace->events.activate, NULL);
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE:
|
|
||||||
wl_signal_emit_mutable(&req->workspace->events.deactivate, NULL);
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN:
|
|
||||||
wl_signal_emit_mutable(&req->workspace->events.assign, req->group);
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE:
|
|
||||||
wl_signal_emit_mutable(&req->workspace->events.remove, NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
destroy_request(req);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_idle(void *data) {
|
static void handle_idle(void *data) {
|
||||||
|
|
@ -406,10 +405,8 @@ static const struct ext_workspace_manager_v1_interface manager_impl = {
|
||||||
|
|
||||||
static void destroy_manager_resource(
|
static void destroy_manager_resource(
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
destroy_requests(manager_res);
|
||||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
|
||||||
destroy_request(req);
|
|
||||||
}
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp2;
|
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp2;
|
||||||
wl_list_for_each_safe(workspace_res, tmp2,
|
wl_list_for_each_safe(workspace_res, tmp2,
|
||||||
&manager_res->workspace_resources,
|
&manager_res->workspace_resources,
|
||||||
|
|
@ -531,6 +528,7 @@ static void manager_handle_display_destroy(struct wl_listener *listener,
|
||||||
wl_container_of(listener, manager, display_destroy);
|
wl_container_of(listener, manager, display_destroy);
|
||||||
|
|
||||||
wl_signal_emit_mutable(&manager->events.destroy, NULL);
|
wl_signal_emit_mutable(&manager->events.destroy, NULL);
|
||||||
|
assert(wl_list_empty(&manager->events.commit.listener_list));
|
||||||
assert(wl_list_empty(&manager->events.destroy.listener_list));
|
assert(wl_list_empty(&manager->events.destroy.listener_list));
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group, *tmp;
|
struct wlr_ext_workspace_group_handle_v1 *group, *tmp;
|
||||||
|
|
@ -583,6 +581,7 @@ wlr_ext_workspace_manager_v1_create(struct wl_display *display,
|
||||||
wl_list_init(&manager->groups);
|
wl_list_init(&manager->groups);
|
||||||
wl_list_init(&manager->workspaces);
|
wl_list_init(&manager->workspaces);
|
||||||
wl_list_init(&manager->resources);
|
wl_list_init(&manager->resources);
|
||||||
|
wl_signal_init(&manager->events.commit);
|
||||||
wl_signal_init(&manager->events.destroy);
|
wl_signal_init(&manager->events.destroy);
|
||||||
|
|
||||||
return manager;
|
return manager;
|
||||||
|
|
@ -601,7 +600,6 @@ wlr_ext_workspace_group_handle_v1_create(
|
||||||
|
|
||||||
wl_list_init(&group->outputs);
|
wl_list_init(&group->outputs);
|
||||||
wl_list_init(&group->resources);
|
wl_list_init(&group->resources);
|
||||||
wl_signal_init(&group->events.create_workspace);
|
|
||||||
wl_signal_init(&group->events.destroy);
|
wl_signal_init(&group->events.destroy);
|
||||||
|
|
||||||
wl_list_insert(manager->groups.prev, &group->link);
|
wl_list_insert(manager->groups.prev, &group->link);
|
||||||
|
|
@ -689,7 +687,6 @@ void wlr_ext_workspace_group_handle_v1_destroy(
|
||||||
|
|
||||||
wl_signal_emit_mutable(&group->events.destroy, NULL);
|
wl_signal_emit_mutable(&group->events.destroy, NULL);
|
||||||
|
|
||||||
assert(wl_list_empty(&group->events.create_workspace.listener_list));
|
|
||||||
assert(wl_list_empty(&group->events.destroy.listener_list));
|
assert(wl_list_empty(&group->events.destroy.listener_list));
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
struct wlr_ext_workspace_handle_v1 *workspace;
|
||||||
|
|
@ -708,12 +705,7 @@ void wlr_ext_workspace_group_handle_v1_destroy(
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||||
wl_list_for_each(manager_res, &group->manager->resources, link) {
|
wl_list_for_each(manager_res, &group->manager->resources, link) {
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp2;
|
clear_requests_by(manager_res, group, NULL);
|
||||||
wl_list_for_each_safe(req, tmp2, &manager_res->requests, link) {
|
|
||||||
if (req->group == group) {
|
|
||||||
destroy_request(req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output, *tmp3;
|
struct wlr_ext_workspace_v1_group_output *group_output, *tmp3;
|
||||||
|
|
@ -822,13 +814,9 @@ wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
|
||||||
|
|
||||||
wl_list_init(&workspace->resources);
|
wl_list_init(&workspace->resources);
|
||||||
wl_array_init(&workspace->coordinates);
|
wl_array_init(&workspace->coordinates);
|
||||||
wl_signal_init(&workspace->events.activate);
|
|
||||||
wl_signal_init(&workspace->events.deactivate);
|
|
||||||
wl_signal_init(&workspace->events.remove);
|
|
||||||
wl_signal_init(&workspace->events.assign);
|
|
||||||
wl_signal_init(&workspace->events.destroy);
|
wl_signal_init(&workspace->events.destroy);
|
||||||
|
|
||||||
wl_list_insert(&manager->workspaces, &workspace->link);
|
wl_list_insert(manager->workspaces.prev, &workspace->link);
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
wl_list_for_each(manager_res, &manager->resources, link) {
|
||||||
|
|
@ -855,10 +843,6 @@ void wlr_ext_workspace_handle_v1_destroy(
|
||||||
|
|
||||||
wl_signal_emit_mutable(&workspace->events.destroy, NULL);
|
wl_signal_emit_mutable(&workspace->events.destroy, NULL);
|
||||||
|
|
||||||
assert(wl_list_empty(&workspace->events.activate.listener_list));
|
|
||||||
assert(wl_list_empty(&workspace->events.deactivate.listener_list));
|
|
||||||
assert(wl_list_empty(&workspace->events.remove.listener_list));
|
|
||||||
assert(wl_list_empty(&workspace->events.assign.listener_list));
|
|
||||||
assert(wl_list_empty(&workspace->events.destroy.listener_list));
|
assert(wl_list_empty(&workspace->events.destroy.listener_list));
|
||||||
|
|
||||||
if (workspace->group) {
|
if (workspace->group) {
|
||||||
|
|
@ -873,12 +857,7 @@ void wlr_ext_workspace_handle_v1_destroy(
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
||||||
wl_list_for_each(manager_res, &workspace->manager->resources, link) {
|
wl_list_for_each(manager_res, &workspace->manager->resources, link) {
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp2;
|
clear_requests_by(manager_res, NULL, workspace);
|
||||||
wl_list_for_each_safe(req, tmp2, &manager_res->requests, link) {
|
|
||||||
if (req->workspace == workspace) {
|
|
||||||
destroy_request(req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
manager_schedule_done(workspace->manager);
|
||||||
|
|
@ -929,23 +908,22 @@ void wlr_ext_workspace_handle_v1_set_name(
|
||||||
manager_schedule_done(workspace->manager);
|
manager_schedule_done(workspace->manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool array_equal(struct wl_array *a, struct wl_array *b) {
|
|
||||||
return (a->size == b->size) &&
|
|
||||||
(a->size == 0 || memcmp(a->data, b->data, a->size) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_coordinates(
|
void wlr_ext_workspace_handle_v1_set_coordinates(
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
struct wlr_ext_workspace_handle_v1 *workspace, const uint32_t *coords,
|
||||||
struct wl_array *coordinates) {
|
size_t coords_len) {
|
||||||
assert(coordinates);
|
size_t size = coords_len * sizeof(coords[0]);
|
||||||
|
if (size == workspace->coordinates.size &&
|
||||||
if (array_equal(&workspace->coordinates, coordinates)) {
|
(size == 0 || memcmp(workspace->coordinates.data, coords, size) == 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_array_release(&workspace->coordinates);
|
wl_array_release(&workspace->coordinates);
|
||||||
wl_array_init(&workspace->coordinates);
|
wl_array_init(&workspace->coordinates);
|
||||||
wl_array_copy(&workspace->coordinates, coordinates);
|
struct wl_array arr = {
|
||||||
|
.data = (void *)coords,
|
||||||
|
.size = size,
|
||||||
|
};
|
||||||
|
wl_array_copy(&workspace->coordinates, &arr);
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
struct wlr_ext_workspace_v1_resource *workspace_res;
|
||||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,69 @@
|
||||||
// bash on: https://gitlab.freedesktop.org/tokyo4j/wlroots/-/tree/ext-workspace
|
/*
|
||||||
// TODO: remove this file
|
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||||
// refer: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5115
|
* future consistency of this API.
|
||||||
|
*/
|
||||||
|
#ifndef WLR_USE_UNSTABLE
|
||||||
|
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
|
||||||
|
#define WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
|
||||||
|
|
||||||
#include <wayland-protocols/ext-workspace-v1-enum.h>
|
#include <wayland-protocols/ext-workspace-v1-enum.h>
|
||||||
#include <wayland-server-core.h>
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
struct wlr_output;
|
struct wlr_output;
|
||||||
|
|
||||||
|
enum wlr_ext_workspace_v1_request_type {
|
||||||
|
WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE,
|
||||||
|
WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE,
|
||||||
|
WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE,
|
||||||
|
WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN,
|
||||||
|
WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_ext_workspace_v1_request {
|
||||||
|
enum wlr_ext_workspace_v1_request_type type;
|
||||||
|
struct wl_list link; // wlr_ext_workspace_manager_v1_resource.requests
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
struct wlr_ext_workspace_group_handle_v1
|
||||||
|
*group; // NULL if destroyed
|
||||||
|
} create_workspace;
|
||||||
|
struct {
|
||||||
|
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||||
|
} activate;
|
||||||
|
struct {
|
||||||
|
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||||
|
} deactivate;
|
||||||
|
struct {
|
||||||
|
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||||
|
struct wlr_ext_workspace_group_handle_v1
|
||||||
|
*group; // NULL if destroyed
|
||||||
|
} assign;
|
||||||
|
struct {
|
||||||
|
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
||||||
|
} remove;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_ext_workspace_v1_commit_event {
|
||||||
|
struct wl_list *requests; // wlr_ext_workspace_v1_request.link
|
||||||
|
};
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 {
|
struct wlr_ext_workspace_manager_v1 {
|
||||||
struct wl_global *global;
|
struct wl_global *global;
|
||||||
struct wl_list groups; // wlr_ext_workspace_group_handle_v1.link
|
struct wl_list groups; // wlr_ext_workspace_group_handle_v1.link
|
||||||
struct wl_list workspaces; // wlr_ext_workspace_handle_v1.link
|
struct wl_list workspaces; // wlr_ext_workspace_handle_v1.link
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
struct wl_signal commit; // wlr_ext_workspace_v1_commit_event
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
|
void *data;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
||||||
struct wl_event_source *idle_source;
|
struct wl_event_source *idle_source;
|
||||||
|
|
@ -24,21 +72,17 @@ struct wlr_ext_workspace_manager_v1 {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1_create_workspace_event {
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 {
|
struct wlr_ext_workspace_group_handle_v1 {
|
||||||
struct wlr_ext_workspace_manager_v1 *manager;
|
struct wlr_ext_workspace_manager_v1 *manager;
|
||||||
uint32_t caps; // ext_workspace_group_handle_v1_group_capabilities
|
uint32_t caps; // ext_workspace_group_handle_v1_group_capabilities
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal
|
|
||||||
create_workspace; // wlr_ext_workspace_group_handle_v1_create_workspace_event
|
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1.groups
|
struct wl_list link; // wlr_ext_workspace_manager_v1.groups
|
||||||
|
|
||||||
|
void *data;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link
|
struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link
|
||||||
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
||||||
|
|
@ -55,15 +99,13 @@ struct wlr_ext_workspace_handle_v1 {
|
||||||
uint32_t state; // ext_workspace_handle_v1_state
|
uint32_t state; // ext_workspace_handle_v1_state
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal activate;
|
|
||||||
struct wl_signal deactivate;
|
|
||||||
struct wl_signal remove;
|
|
||||||
struct wl_signal assign; // wlr_ext_workspace_group_handle_v1
|
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces
|
struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces
|
||||||
|
|
||||||
|
void *data;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_list resources; // wlr_ext_workspace_v1_resource.link
|
struct wl_list resources; // wlr_ext_workspace_v1_resource.link
|
||||||
};
|
};
|
||||||
|
|
@ -96,11 +138,13 @@ void wlr_ext_workspace_handle_v1_set_group(
|
||||||
void wlr_ext_workspace_handle_v1_set_name(
|
void wlr_ext_workspace_handle_v1_set_name(
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, const char *name);
|
struct wlr_ext_workspace_handle_v1 *workspace, const char *name);
|
||||||
void wlr_ext_workspace_handle_v1_set_coordinates(
|
void wlr_ext_workspace_handle_v1_set_coordinates(
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
struct wlr_ext_workspace_handle_v1 *workspace, const uint32_t *coords,
|
||||||
struct wl_array *coordinates);
|
size_t coords_len);
|
||||||
void wlr_ext_workspace_handle_v1_set_active(
|
void wlr_ext_workspace_handle_v1_set_active(
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
||||||
void wlr_ext_workspace_handle_v1_set_urgent(
|
void wlr_ext_workspace_handle_v1_set_urgent(
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
||||||
void wlr_ext_workspace_handle_v1_set_hidden(
|
void wlr_ext_workspace_handle_v1_set_hidden(
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -558,7 +558,7 @@ bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc) {
|
||||||
|
|
||||||
if (id != SCROLLER && id != VERTICAL_SCROLLER && id != TILE &&
|
if (id != SCROLLER && id != VERTICAL_SCROLLER && id != TILE &&
|
||||||
id != VERTICAL_TILE && id != DECK && id != VERTICAL_DECK &&
|
id != VERTICAL_TILE && id != DECK && id != VERTICAL_DECK &&
|
||||||
id != CENTER_TILE && id != RIGHT_TILE && id != TGMIX)
|
id != CENTER_TILE && id != RIGHT_TILE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (id == SCROLLER || id == VERTICAL_SCROLLER) {
|
if (id == SCROLLER || id == VERTICAL_SCROLLER) {
|
||||||
|
|
@ -583,15 +583,6 @@ bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc) {
|
||||||
return true;
|
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 (id == CENTER_TILE) {
|
||||||
if (tc->ismaster ^ sc->ismaster)
|
if (tc->ismaster ^ sc->ismaster)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -488,6 +488,21 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resize_tile_dwindle(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
|
int32_t offsety, uint32_t time, bool isvertical) {
|
||||||
|
|
||||||
|
if (!isdrag) {
|
||||||
|
dwindle_resize_client_step(grabc->mon, grabc, offsetx, offsety);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_apply_drap_time == 0 ||
|
||||||
|
time - last_apply_drap_time > config.drag_tile_refresh_interval) {
|
||||||
|
dwindle_resize_client(grabc->mon, grabc);
|
||||||
|
last_apply_drap_time = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
int32_t offsety, uint32_t time, bool isvertical) {
|
int32_t offsety, uint32_t time, bool isvertical) {
|
||||||
Client *tc = NULL;
|
Client *tc = NULL;
|
||||||
|
|
@ -692,8 +707,7 @@ void resize_tile_client(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
const Layout *current_layout =
|
const Layout *current_layout =
|
||||||
grabc->mon->pertag->ltidxs[grabc->mon->pertag->curtag];
|
grabc->mon->pertag->ltidxs[grabc->mon->pertag->curtag];
|
||||||
if (current_layout->id == TILE || current_layout->id == DECK ||
|
if (current_layout->id == TILE || current_layout->id == DECK ||
|
||||||
current_layout->id == CENTER_TILE || current_layout->id == RIGHT_TILE ||
|
current_layout->id == CENTER_TILE || current_layout->id == RIGHT_TILE
|
||||||
(current_layout->id == TGMIX && grabc->mon->visible_tiling_clients <= 3)
|
|
||||||
|
|
||||||
) {
|
) {
|
||||||
resize_tile_master_horizontal(grabc, isdrag, offsetx, offsety, time,
|
resize_tile_master_horizontal(grabc, isdrag, offsetx, offsety, time,
|
||||||
|
|
@ -706,6 +720,8 @@ void resize_tile_client(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
resize_tile_scroller(grabc, isdrag, offsetx, offsety, time, false);
|
resize_tile_scroller(grabc, isdrag, offsetx, offsety, time, false);
|
||||||
} else if (current_layout->id == VERTICAL_SCROLLER) {
|
} else if (current_layout->id == VERTICAL_SCROLLER) {
|
||||||
resize_tile_scroller(grabc, isdrag, offsetx, offsety, time, true);
|
resize_tile_scroller(grabc, isdrag, offsetx, offsety, time, true);
|
||||||
|
} else if (current_layout->id == DWINDLE) {
|
||||||
|
resize_tile_dwindle(grabc, isdrag, offsetx, offsety, time, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
433
src/layout/dwindle.h
Normal file
433
src/layout/dwindle.h
Normal file
|
|
@ -0,0 +1,433 @@
|
||||||
|
typedef struct DwindleNode DwindleNode;
|
||||||
|
struct DwindleNode {
|
||||||
|
bool is_split;
|
||||||
|
bool split_h;
|
||||||
|
bool split_locked;
|
||||||
|
float ratio;
|
||||||
|
float drag_init_ratio;
|
||||||
|
int32_t container_x;
|
||||||
|
int32_t container_y;
|
||||||
|
int32_t container_w;
|
||||||
|
int32_t container_h;
|
||||||
|
DwindleNode *parent;
|
||||||
|
DwindleNode *first;
|
||||||
|
DwindleNode *second;
|
||||||
|
Client *client;
|
||||||
|
};
|
||||||
|
|
||||||
|
static DwindleNode *dwindle_locked_h_node = NULL;
|
||||||
|
static DwindleNode *dwindle_locked_v_node = NULL;
|
||||||
|
|
||||||
|
static DwindleNode *dwindle_new_leaf(Client *c) {
|
||||||
|
DwindleNode *n = calloc(1, sizeof(DwindleNode));
|
||||||
|
n->client = c;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DwindleNode *dwindle_find_leaf(DwindleNode *node, Client *c) {
|
||||||
|
if (!node)
|
||||||
|
return NULL;
|
||||||
|
if (!node->is_split)
|
||||||
|
return node->client == c ? node : NULL;
|
||||||
|
DwindleNode *r = dwindle_find_leaf(node->first, c);
|
||||||
|
return r ? r : dwindle_find_leaf(node->second, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DwindleNode *dwindle_first_leaf(DwindleNode *node) {
|
||||||
|
if (!node)
|
||||||
|
return NULL;
|
||||||
|
while (node->is_split)
|
||||||
|
node = node->first;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwindle_free_tree(DwindleNode *node) {
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
dwindle_free_tree(node->first);
|
||||||
|
dwindle_free_tree(node->second);
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwindle_insert(DwindleNode **root, Client *new_c, Client *focused,
|
||||||
|
float ratio, bool as_first, bool split_h,
|
||||||
|
bool lock) {
|
||||||
|
DwindleNode *new_leaf = dwindle_new_leaf(new_c);
|
||||||
|
|
||||||
|
if (!*root) {
|
||||||
|
*root = new_leaf;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DwindleNode *target = focused ? dwindle_find_leaf(*root, focused) : NULL;
|
||||||
|
if (!target)
|
||||||
|
target = dwindle_first_leaf(*root);
|
||||||
|
|
||||||
|
DwindleNode *split = calloc(1, sizeof(DwindleNode));
|
||||||
|
split->is_split = true;
|
||||||
|
split->ratio = ratio;
|
||||||
|
split->split_h = split_h;
|
||||||
|
split->split_locked = lock;
|
||||||
|
|
||||||
|
if (as_first) {
|
||||||
|
split->first = new_leaf;
|
||||||
|
split->second = target;
|
||||||
|
} else {
|
||||||
|
split->first = target;
|
||||||
|
split->second = new_leaf;
|
||||||
|
}
|
||||||
|
split->parent = target->parent;
|
||||||
|
target->parent = split;
|
||||||
|
new_leaf->parent = split;
|
||||||
|
|
||||||
|
if (!split->parent) {
|
||||||
|
*root = split;
|
||||||
|
} else {
|
||||||
|
if (split->parent->first == target)
|
||||||
|
split->parent->first = split;
|
||||||
|
else
|
||||||
|
split->parent->second = split;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwindle_remove(DwindleNode **root, Client *c) {
|
||||||
|
DwindleNode *leaf = dwindle_find_leaf(*root, c);
|
||||||
|
if (!leaf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DwindleNode *parent = leaf->parent;
|
||||||
|
if (!parent) {
|
||||||
|
free(leaf);
|
||||||
|
*root = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DwindleNode *sibling =
|
||||||
|
(parent->first == leaf) ? parent->second : parent->first;
|
||||||
|
DwindleNode *grandparent = parent->parent;
|
||||||
|
sibling->parent = grandparent;
|
||||||
|
|
||||||
|
/* Preserve split direction on sibling split-nodes when requested. */
|
||||||
|
if (!sibling->is_split ||
|
||||||
|
(!config.dwindle_preserve_split && !config.dwindle_smart_split)) {
|
||||||
|
sibling->container_w = 0;
|
||||||
|
sibling->container_h = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!grandparent) {
|
||||||
|
*root = sibling;
|
||||||
|
} else {
|
||||||
|
if (grandparent->first == parent)
|
||||||
|
grandparent->first = sibling;
|
||||||
|
else
|
||||||
|
grandparent->second = sibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(leaf);
|
||||||
|
free(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwindle_assign(DwindleNode *node, int32_t ax, int32_t ay,
|
||||||
|
int32_t aw, int32_t ah, int32_t gap_h,
|
||||||
|
int32_t gap_v) {
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!node->is_split) {
|
||||||
|
if (node->client) {
|
||||||
|
struct wlr_box box = {ax, ay, MAX(1, aw), MAX(1, ah)};
|
||||||
|
resize(node->client, box, 0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node->split_locked && node->container_w == 0 && node->container_h == 0)
|
||||||
|
node->split_h = (aw >= ah);
|
||||||
|
node->container_x = ax;
|
||||||
|
node->container_y = ay;
|
||||||
|
node->container_w = aw;
|
||||||
|
node->container_h = ah;
|
||||||
|
if (node->split_h) {
|
||||||
|
int32_t w1 = MAX(1, (int32_t)(aw * node->ratio) - gap_h / 2);
|
||||||
|
dwindle_assign(node->first, ax, ay, w1, ah, gap_h, gap_v);
|
||||||
|
dwindle_assign(node->second, ax + w1 + gap_h, ay, aw - w1 - gap_h, ah,
|
||||||
|
gap_h, gap_v);
|
||||||
|
} else {
|
||||||
|
int32_t h1 = MAX(1, (int32_t)(ah * node->ratio) - gap_v / 2);
|
||||||
|
dwindle_assign(node->first, ax, ay, aw, h1, gap_h, gap_v);
|
||||||
|
dwindle_assign(node->second, ax, ay + h1 + gap_v, aw, ah - h1 - gap_v,
|
||||||
|
gap_h, gap_v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwindle_move_client(DwindleNode **root, Client *c, Client *target,
|
||||||
|
float ratio, int32_t dir) {
|
||||||
|
if (!c || !target || c == target)
|
||||||
|
return;
|
||||||
|
if (!dwindle_find_leaf(*root, c) || !dwindle_find_leaf(*root, target))
|
||||||
|
return;
|
||||||
|
dwindle_remove(root, c);
|
||||||
|
bool as_first = (dir == UP || dir == LEFT);
|
||||||
|
bool split_h = (dir == LEFT || dir == RIGHT);
|
||||||
|
dwindle_insert(root, c, target, ratio, as_first, split_h, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwindle_swap_clients(DwindleNode **root, Client *a, Client *b) {
|
||||||
|
DwindleNode *la = dwindle_find_leaf(*root, a);
|
||||||
|
DwindleNode *lb = dwindle_find_leaf(*root, b);
|
||||||
|
if (!la || !lb || la == lb)
|
||||||
|
return;
|
||||||
|
la->client = b;
|
||||||
|
lb->client = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwindle_resize_client(Monitor *m, Client *c) {
|
||||||
|
uint32_t tag = m->pertag->curtag;
|
||||||
|
DwindleNode *leaf = dwindle_find_leaf(m->pertag->dwindle_root[tag], c);
|
||||||
|
if (!leaf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!start_drag_window) {
|
||||||
|
start_drag_window = true;
|
||||||
|
dwindle_locked_h_node = NULL;
|
||||||
|
dwindle_locked_v_node = NULL;
|
||||||
|
drag_begin_cursorx = cursor->x;
|
||||||
|
drag_begin_cursory = cursor->y;
|
||||||
|
DwindleNode *node = leaf->parent;
|
||||||
|
while (node) {
|
||||||
|
if (node->split_h && !dwindle_locked_h_node) {
|
||||||
|
dwindle_locked_h_node = node;
|
||||||
|
node->drag_init_ratio = node->ratio;
|
||||||
|
}
|
||||||
|
if (!node->split_h && !dwindle_locked_v_node) {
|
||||||
|
dwindle_locked_v_node = node;
|
||||||
|
node->drag_init_ratio = node->ratio;
|
||||||
|
}
|
||||||
|
if (dwindle_locked_h_node && dwindle_locked_v_node)
|
||||||
|
break;
|
||||||
|
node = node->parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dwindle_locked_h_node && !dwindle_locked_v_node)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dwindle_locked_h_node) {
|
||||||
|
float cw = (float)MAX(1, dwindle_locked_h_node->container_w);
|
||||||
|
float ox = (float)(cursor->x - drag_begin_cursorx);
|
||||||
|
if (config.dwindle_smart_resize) {
|
||||||
|
/* Move the boundary toward the cursor: invert direction when
|
||||||
|
* the drag started on the right side of the split line. */
|
||||||
|
float split_x = dwindle_locked_h_node->container_x +
|
||||||
|
cw * dwindle_locked_h_node->drag_init_ratio;
|
||||||
|
if (drag_begin_cursorx >= split_x)
|
||||||
|
ox = -ox;
|
||||||
|
}
|
||||||
|
dwindle_locked_h_node->ratio =
|
||||||
|
dwindle_locked_h_node->drag_init_ratio + ox / cw;
|
||||||
|
dwindle_locked_h_node->ratio =
|
||||||
|
CLAMP_FLOAT(dwindle_locked_h_node->ratio, 0.05f, 0.95f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwindle_locked_v_node) {
|
||||||
|
float ch = (float)MAX(1, dwindle_locked_v_node->container_h);
|
||||||
|
float oy = (float)(cursor->y - drag_begin_cursory);
|
||||||
|
if (config.dwindle_smart_resize) {
|
||||||
|
/* Same logic for the vertical split line. */
|
||||||
|
float split_y = dwindle_locked_v_node->container_y +
|
||||||
|
ch * dwindle_locked_v_node->drag_init_ratio;
|
||||||
|
if (drag_begin_cursory >= split_y)
|
||||||
|
oy = -oy;
|
||||||
|
}
|
||||||
|
dwindle_locked_v_node->ratio =
|
||||||
|
dwindle_locked_v_node->drag_init_ratio + oy / ch;
|
||||||
|
dwindle_locked_v_node->ratio =
|
||||||
|
CLAMP_FLOAT(dwindle_locked_v_node->ratio, 0.05f, 0.95f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t n = m->visible_tiling_clients;
|
||||||
|
int32_t gap_ih = enablegaps ? m->gappih : 0;
|
||||||
|
int32_t gap_iv = enablegaps ? m->gappiv : 0;
|
||||||
|
int32_t gap_oh = enablegaps ? m->gappoh : 0;
|
||||||
|
int32_t gap_ov = enablegaps ? m->gappov : 0;
|
||||||
|
if (config.smartgaps && n == 1)
|
||||||
|
gap_ih = gap_iv = gap_oh = gap_ov = 0;
|
||||||
|
|
||||||
|
dwindle_assign(m->pertag->dwindle_root[tag], m->w.x + gap_oh,
|
||||||
|
m->w.y + gap_ov, m->w.width - 2 * gap_oh,
|
||||||
|
m->w.height - 2 * gap_ov, gap_ih, gap_iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwindle_resize_client_step(Monitor *m, Client *c, int32_t dx,
|
||||||
|
int32_t dy) {
|
||||||
|
uint32_t tag = m->pertag->curtag;
|
||||||
|
DwindleNode *leaf = dwindle_find_leaf(m->pertag->dwindle_root[tag], c);
|
||||||
|
if (!leaf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DwindleNode *h_node = NULL;
|
||||||
|
DwindleNode *v_node = NULL;
|
||||||
|
DwindleNode *node = leaf->parent;
|
||||||
|
|
||||||
|
while (node) {
|
||||||
|
if (node->split_h && !h_node)
|
||||||
|
h_node = node;
|
||||||
|
if (!node->split_h && !v_node)
|
||||||
|
v_node = node;
|
||||||
|
if (h_node && v_node)
|
||||||
|
break;
|
||||||
|
node = node->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!h_node && !v_node)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (h_node && dx) {
|
||||||
|
float cw = (float)MAX(1, h_node->container_w);
|
||||||
|
float delta = (float)dx / cw;
|
||||||
|
h_node->ratio = CLAMP_FLOAT(h_node->ratio + delta, 0.05f, 0.95f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v_node && dy) {
|
||||||
|
float ch = (float)MAX(1, v_node->container_h);
|
||||||
|
float delta = (float)dy / ch;
|
||||||
|
v_node->ratio = CLAMP_FLOAT(v_node->ratio + delta, 0.05f, 0.95f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t n_clients = m->visible_tiling_clients;
|
||||||
|
int32_t gap_ih = enablegaps ? m->gappih : 0;
|
||||||
|
int32_t gap_iv = enablegaps ? m->gappiv : 0;
|
||||||
|
int32_t gap_oh = enablegaps ? m->gappoh : 0;
|
||||||
|
int32_t gap_ov = enablegaps ? m->gappov : 0;
|
||||||
|
if (config.smartgaps && n_clients == 1)
|
||||||
|
gap_ih = gap_iv = gap_oh = gap_ov = 0;
|
||||||
|
|
||||||
|
dwindle_assign(m->pertag->dwindle_root[tag], m->w.x + gap_oh,
|
||||||
|
m->w.y + gap_ov, m->w.width - 2 * gap_oh,
|
||||||
|
m->w.height - 2 * gap_ov, gap_ih, gap_iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwindle_remove_client(Client *c) {
|
||||||
|
Monitor *m;
|
||||||
|
wl_list_for_each(m, &mons, link) {
|
||||||
|
for (uint32_t t = 0; t < LENGTH(tags) + 1; t++)
|
||||||
|
dwindle_remove(&m->pertag->dwindle_root[t], c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert a new client respecting dwindle_vsplit, dwindle_hsplit, and
|
||||||
|
* dwindle_smart_split config options. */
|
||||||
|
static void dwindle_insert_with_config(DwindleNode **root, Client *new_c,
|
||||||
|
Client *focused, float ratio) {
|
||||||
|
bool as_first = false;
|
||||||
|
bool split_h = false;
|
||||||
|
bool lock = false;
|
||||||
|
|
||||||
|
if (focused) {
|
||||||
|
struct wlr_box *fg = &focused->geom;
|
||||||
|
double fcx = fg->x + fg->width * 0.5;
|
||||||
|
double fcy = fg->y + fg->height * 0.5;
|
||||||
|
|
||||||
|
if (config.dwindle_smart_split) {
|
||||||
|
double nx = (cursor->x - fcx) / (fg->width * 0.5);
|
||||||
|
double ny = (cursor->y - fcy) / (fg->height * 0.5);
|
||||||
|
|
||||||
|
if (fabs(ny) > fabs(nx)) {
|
||||||
|
split_h = false; // vertical split
|
||||||
|
as_first = (ny < 0); // top → new window on top
|
||||||
|
} else {
|
||||||
|
split_h = true; // horizontal split
|
||||||
|
as_first = (nx < 0); // left → new window on left
|
||||||
|
}
|
||||||
|
lock = true; // lock split direction
|
||||||
|
} else {
|
||||||
|
// normal mode, auto split
|
||||||
|
bool likely_h = (fg->width >= fg->height);
|
||||||
|
if (likely_h) {
|
||||||
|
if (config.dwindle_hsplit == 0)
|
||||||
|
as_first = (cursor->x < fcx);
|
||||||
|
else
|
||||||
|
as_first = (config.dwindle_hsplit == 2);
|
||||||
|
} else {
|
||||||
|
if (config.dwindle_vsplit == 0)
|
||||||
|
as_first = (cursor->y < fcy);
|
||||||
|
else
|
||||||
|
as_first = (config.dwindle_vsplit == 2);
|
||||||
|
}
|
||||||
|
// split_h and lock are false, decided by width/height ratio
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dwindle_insert(root, new_c, focused, ratio, as_first, split_h, lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dwindle(Monitor *m) {
|
||||||
|
int32_t n = m->visible_tiling_clients;
|
||||||
|
if (n == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t tag = m->pertag->curtag;
|
||||||
|
DwindleNode **root = &m->pertag->dwindle_root[tag];
|
||||||
|
float ratio = config.dwindle_split_ratio;
|
||||||
|
|
||||||
|
Client *vis[512];
|
||||||
|
int32_t count = 0;
|
||||||
|
Client *c;
|
||||||
|
wl_list_for_each(c, &clients, link) {
|
||||||
|
if (VISIBLEON(c, m) && ISTILED(c))
|
||||||
|
vis[count++] = c;
|
||||||
|
if (count >= 512)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
DwindleNode *leaves[512];
|
||||||
|
int32_t lc = 0;
|
||||||
|
|
||||||
|
DwindleNode *stack[1024];
|
||||||
|
int32_t sp = 0;
|
||||||
|
if (*root)
|
||||||
|
stack[sp++] = *root;
|
||||||
|
while (sp > 0) {
|
||||||
|
DwindleNode *nd = stack[--sp];
|
||||||
|
if (!nd->is_split) {
|
||||||
|
leaves[lc++] = nd;
|
||||||
|
} else {
|
||||||
|
if (nd->second)
|
||||||
|
stack[sp++] = nd->second;
|
||||||
|
if (nd->first)
|
||||||
|
stack[sp++] = nd->first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < lc; i++) {
|
||||||
|
bool found = false;
|
||||||
|
for (int32_t j = 0; j < count; j++)
|
||||||
|
if (vis[j] == leaves[i]->client) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
dwindle_remove(root, leaves[i]->client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Client *focused = focustop(m);
|
||||||
|
if (focused && !dwindle_find_leaf(*root, focused))
|
||||||
|
focused = m->sel;
|
||||||
|
for (int32_t i = 0; i < count; i++) {
|
||||||
|
if (!dwindle_find_leaf(*root, vis[i]))
|
||||||
|
dwindle_insert_with_config(root, vis[i], focused, ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t gap_ih = enablegaps ? m->gappih : 0;
|
||||||
|
int32_t gap_iv = enablegaps ? m->gappiv : 0;
|
||||||
|
int32_t gap_oh = enablegaps ? m->gappoh : 0;
|
||||||
|
int32_t gap_ov = enablegaps ? m->gappov : 0;
|
||||||
|
if (config.smartgaps && n == 1)
|
||||||
|
gap_ih = gap_iv = gap_oh = gap_ov = 0;
|
||||||
|
|
||||||
|
dwindle_assign(*root, m->w.x + gap_oh, m->w.y + gap_ov,
|
||||||
|
m->w.width - 2 * gap_oh, m->w.height - 2 * gap_ov, gap_ih,
|
||||||
|
gap_iv);
|
||||||
|
}
|
||||||
|
|
@ -994,14 +994,3 @@ monocle(Monitor *m) {
|
||||||
if ((c = focustop(m)))
|
if ((c = focustop(m)))
|
||||||
wlr_scene_node_raise_to_top(&c->scene->node);
|
wlr_scene_node_raise_to_top(&c->scene->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tgmix(Monitor *m) {
|
|
||||||
int32_t n = m->visible_tiling_clients;
|
|
||||||
if (n <= 3) {
|
|
||||||
tile(m);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
grid(m);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ static void vertical_overview(Monitor *m);
|
||||||
static void vertical_grid(Monitor *m);
|
static void vertical_grid(Monitor *m);
|
||||||
static void vertical_scroller(Monitor *m);
|
static void vertical_scroller(Monitor *m);
|
||||||
static void vertical_deck(Monitor *mon);
|
static void vertical_deck(Monitor *mon);
|
||||||
static void tgmix(Monitor *m);
|
static void dwindle(Monitor *m);
|
||||||
|
|
||||||
/* layout(s) */
|
/* layout(s) */
|
||||||
Layout overviewlayout = {"", overview, "overview"};
|
Layout overviewlayout = {"", overview, "overview"};
|
||||||
|
|
@ -28,7 +28,7 @@ enum {
|
||||||
VERTICAL_GRID,
|
VERTICAL_GRID,
|
||||||
VERTICAL_DECK,
|
VERTICAL_DECK,
|
||||||
RIGHT_TILE,
|
RIGHT_TILE,
|
||||||
TGMIX,
|
DWINDLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
Layout layouts[] = {
|
Layout layouts[] = {
|
||||||
|
|
@ -46,5 +46,5 @@ Layout layouts[] = {
|
||||||
{"VT", vertical_tile, "vertical_tile", VERTICAL_TILE}, // 垂直平铺布局
|
{"VT", vertical_tile, "vertical_tile", VERTICAL_TILE}, // 垂直平铺布局
|
||||||
{"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局
|
{"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局
|
||||||
{"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局
|
{"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局
|
||||||
{"TG", tgmix, "tgmix", TGMIX}, // 混合布局
|
{"DW", dwindle, "dwindle", DWINDLE},
|
||||||
};
|
};
|
||||||
417
src/mango.c
417
src/mango.c
|
|
@ -314,6 +314,7 @@ struct Client {
|
||||||
Monitor *mon;
|
Monitor *mon;
|
||||||
struct wlr_scene_tree *scene;
|
struct wlr_scene_tree *scene;
|
||||||
struct wlr_scene_rect *border; /* top, bottom, left, right */
|
struct wlr_scene_rect *border; /* top, bottom, left, right */
|
||||||
|
struct wlr_scene_rect *droparea;
|
||||||
struct wlr_scene_shadow *shadow;
|
struct wlr_scene_shadow *shadow;
|
||||||
struct wlr_scene_tree *scene_surface;
|
struct wlr_scene_tree *scene_surface;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
|
@ -422,6 +423,9 @@ struct Client {
|
||||||
bool isfocusing;
|
bool isfocusing;
|
||||||
struct Client *next_in_stack;
|
struct Client *next_in_stack;
|
||||||
struct Client *prev_in_stack;
|
struct Client *prev_in_stack;
|
||||||
|
bool enable_drop_area_draw;
|
||||||
|
int32_t drop_direction;
|
||||||
|
struct wlr_box drag_tile_float_backup_geom;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -539,6 +543,7 @@ struct Monitor {
|
||||||
struct wlr_scene_optimized_blur *blur;
|
struct wlr_scene_optimized_blur *blur;
|
||||||
char last_surface_ws_name[256];
|
char last_surface_ws_name[256];
|
||||||
struct wlr_ext_workspace_group_handle_v1 *ext_group;
|
struct wlr_ext_workspace_group_handle_v1 *ext_group;
|
||||||
|
bool iscleanuping;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -555,6 +560,8 @@ typedef struct {
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
} SessionLock;
|
} SessionLock;
|
||||||
|
|
||||||
|
typedef struct DwindleNode DwindleNode;
|
||||||
|
|
||||||
/* function declarations */
|
/* function declarations */
|
||||||
static void applybounds(
|
static void applybounds(
|
||||||
Client *c,
|
Client *c,
|
||||||
|
|
@ -648,8 +655,7 @@ static void motionnotify(uint32_t time, struct wlr_input_device *device,
|
||||||
double sy_unaccel);
|
double sy_unaccel);
|
||||||
static void motionrelative(struct wl_listener *listener, void *data);
|
static void motionrelative(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
static void reset_foreign_tolevel(Client *c);
|
static void reset_foreign_tolevel(Client *c, Monitor *oldmon, Monitor *newmon);
|
||||||
static void remove_foreign_topleve(Client *c);
|
|
||||||
static void add_foreign_topleve(Client *c);
|
static void add_foreign_topleve(Client *c);
|
||||||
static void exchange_two_client(Client *c1, Client *c2);
|
static void exchange_two_client(Client *c1, Client *c2);
|
||||||
static void outputmgrapply(struct wl_listener *listener, void *data);
|
static void outputmgrapply(struct wl_listener *listener, void *data);
|
||||||
|
|
@ -809,6 +815,13 @@ static void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
||||||
static void client_pending_fullscreen_state(Client *c, int32_t isfullscreen);
|
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_maximized_state(Client *c, int32_t ismaximized);
|
||||||
static void client_pending_minimized_state(Client *c, int32_t isminimized);
|
static void client_pending_minimized_state(Client *c, int32_t isminimized);
|
||||||
|
static void scroller_insert_stack(Client *c, Client *target_client,
|
||||||
|
bool insert_before);
|
||||||
|
static void dwindle_move_client(DwindleNode **root, Client *c, Client *target,
|
||||||
|
float ratio, int32_t dir);
|
||||||
|
static void dwindle_resize_client_step(Monitor *m, Client *c, int32_t dx,
|
||||||
|
int32_t dy);
|
||||||
|
static void dwindle_resize_client(Monitor *m, Client *c);
|
||||||
|
|
||||||
#include "data/static_keymap.h"
|
#include "data/static_keymap.h"
|
||||||
#include "dispatch/bind_declare.h"
|
#include "dispatch/bind_declare.h"
|
||||||
|
|
@ -870,7 +883,7 @@ static KeyboardGroup *kb_group;
|
||||||
static struct wl_list inputdevices;
|
static struct wl_list inputdevices;
|
||||||
static struct wl_list keyboard_shortcut_inhibitors;
|
static struct wl_list keyboard_shortcut_inhibitors;
|
||||||
static uint32_t cursor_mode;
|
static uint32_t cursor_mode;
|
||||||
static Client *grabc;
|
static Client *grabc, *dropc;
|
||||||
static int32_t rzcorner;
|
static int32_t rzcorner;
|
||||||
static int32_t grabcx, grabcy; /* client-relative */
|
static int32_t grabcx, grabcy; /* client-relative */
|
||||||
static int32_t drag_begin_cursorx, drag_begin_cursory; /* client-relative */
|
static int32_t drag_begin_cursorx, drag_begin_cursory; /* client-relative */
|
||||||
|
|
@ -940,6 +953,7 @@ struct Pertag {
|
||||||
int32_t no_hide[LENGTH(tags) + 1]; /* no_hide 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 no_render_border[LENGTH(tags) + 1]; /* no_render_border per tag */
|
||||||
int32_t open_as_floating[LENGTH(tags) + 1]; /* open_as_floating per tag */
|
int32_t open_as_floating[LENGTH(tags) + 1]; /* open_as_floating per tag */
|
||||||
|
struct DwindleNode *dwindle_root[LENGTH(tags) + 1];
|
||||||
const Layout
|
const Layout
|
||||||
*ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */
|
*ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */
|
||||||
};
|
};
|
||||||
|
|
@ -1012,6 +1026,7 @@ static struct wl_event_source *sync_keymap;
|
||||||
#include "ext-protocol/all.h"
|
#include "ext-protocol/all.h"
|
||||||
#include "fetch/fetch.h"
|
#include "fetch/fetch.h"
|
||||||
#include "layout/arrange.h"
|
#include "layout/arrange.h"
|
||||||
|
#include "layout/dwindle.h"
|
||||||
#include "layout/horizontal.h"
|
#include "layout/horizontal.h"
|
||||||
#include "layout/vertical.h"
|
#include "layout/vertical.h"
|
||||||
|
|
||||||
|
|
@ -1143,6 +1158,7 @@ void swallow(Client *c, Client *w) {
|
||||||
c->scroller_proportion = w->scroller_proportion;
|
c->scroller_proportion = w->scroller_proportion;
|
||||||
c->next_in_stack = w->next_in_stack;
|
c->next_in_stack = w->next_in_stack;
|
||||||
c->prev_in_stack = w->prev_in_stack;
|
c->prev_in_stack = w->prev_in_stack;
|
||||||
|
c->isglobal = w->isglobal;
|
||||||
|
|
||||||
if (w->next_in_stack)
|
if (w->next_in_stack)
|
||||||
w->next_in_stack->prev_in_stack = c;
|
w->next_in_stack->prev_in_stack = c;
|
||||||
|
|
@ -1152,8 +1168,12 @@ void swallow(Client *c, Client *w) {
|
||||||
wl_list_insert(&w->link, &c->link);
|
wl_list_insert(&w->link, &c->link);
|
||||||
wl_list_insert(&w->flink, &c->flink);
|
wl_list_insert(&w->flink, &c->flink);
|
||||||
|
|
||||||
if (w->foreign_toplevel)
|
if (w->foreign_toplevel) {
|
||||||
remove_foreign_topleve(w);
|
wlr_foreign_toplevel_handle_v1_output_leave(w->foreign_toplevel,
|
||||||
|
w->mon->wlr_output);
|
||||||
|
wlr_foreign_toplevel_handle_v1_destroy(w->foreign_toplevel);
|
||||||
|
w->foreign_toplevel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
wlr_scene_node_set_enabled(&w->scene->node, false);
|
wlr_scene_node_set_enabled(&w->scene->node, false);
|
||||||
wlr_scene_node_set_enabled(&c->scene->node, true);
|
wlr_scene_node_set_enabled(&c->scene->node, true);
|
||||||
|
|
@ -1161,10 +1181,25 @@ void swallow(Client *c, Client *w) {
|
||||||
|
|
||||||
if (!c->foreign_toplevel && c->mon)
|
if (!c->foreign_toplevel && c->mon)
|
||||||
add_foreign_toplevel(c);
|
add_foreign_toplevel(c);
|
||||||
|
else if (c->foreign_toplevel && c->mon) {
|
||||||
|
wlr_foreign_toplevel_handle_v1_output_enter(c->foreign_toplevel,
|
||||||
|
c->mon->wlr_output);
|
||||||
|
}
|
||||||
|
|
||||||
client_pending_fullscreen_state(c, w->isfullscreen);
|
client_pending_fullscreen_state(c, w->isfullscreen);
|
||||||
client_pending_maximized_state(c, w->ismaximizescreen);
|
client_pending_maximized_state(c, w->ismaximizescreen);
|
||||||
client_pending_minimized_state(c, w->isminimized);
|
client_pending_minimized_state(c, w->isminimized);
|
||||||
|
|
||||||
|
Monitor *m;
|
||||||
|
wl_list_for_each(m, &mons, link) {
|
||||||
|
for (uint32_t t = 0; t < LENGTH(tags) + 1; t++) {
|
||||||
|
DwindleNode **root = &m->pertag->dwindle_root[t];
|
||||||
|
dwindle_remove(root, c);
|
||||||
|
DwindleNode *wn = dwindle_find_leaf(*root, w);
|
||||||
|
if (wn)
|
||||||
|
wn->client = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool switch_scratchpad_client_state(Client *c) {
|
bool switch_scratchpad_client_state(Client *c) {
|
||||||
|
|
@ -1175,7 +1210,7 @@ bool switch_scratchpad_client_state(Client *c) {
|
||||||
Monitor *oldmon = c->mon;
|
Monitor *oldmon = c->mon;
|
||||||
c->scratchpad_switching_mon = true;
|
c->scratchpad_switching_mon = true;
|
||||||
c->mon = selmon;
|
c->mon = selmon;
|
||||||
reset_foreign_tolevel(c);
|
reset_foreign_tolevel(c, oldmon, c->mon);
|
||||||
client_update_oldmonname_record(c, selmon);
|
client_update_oldmonname_record(c, selmon);
|
||||||
|
|
||||||
// 根据新monitor调整窗口尺寸
|
// 根据新monitor调整窗口尺寸
|
||||||
|
|
@ -1569,12 +1604,17 @@ void applyrules(Client *c) {
|
||||||
int32_t fullscreen_state_backup =
|
int32_t fullscreen_state_backup =
|
||||||
c->isfullscreen || client_wants_fullscreen(c);
|
c->isfullscreen || client_wants_fullscreen(c);
|
||||||
|
|
||||||
setmon(c, mon, newtags,
|
bool should_init_get_focus =
|
||||||
!c->isopensilent &&
|
!c->isopensilent &&
|
||||||
!(client_is_x11_popup(c) && client_should_ignore_focus(c)) &&
|
!(client_is_x11_popup(c) && client_should_ignore_focus(c)) && mon &&
|
||||||
mon &&
|
(!c->istagsilent || !newtags || newtags & mon->tagset[mon->seltags]);
|
||||||
(!c->istagsilent || !newtags ||
|
|
||||||
newtags & mon->tagset[mon->seltags]));
|
if (!should_init_get_focus) {
|
||||||
|
wl_list_remove(&c->flink);
|
||||||
|
wl_list_insert(fstack.prev, &c->flink);
|
||||||
|
}
|
||||||
|
|
||||||
|
setmon(c, mon, newtags, should_init_get_focus);
|
||||||
|
|
||||||
if (!c->isfloating) {
|
if (!c->isfloating) {
|
||||||
c->old_stack_inner_per = c->stack_inner_per;
|
c->old_stack_inner_per = c->stack_inner_per;
|
||||||
|
|
@ -1819,6 +1859,9 @@ void arrangelayers(Monitor *m) {
|
||||||
if (!m->wlr_output->enabled)
|
if (!m->wlr_output->enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (m->iscleanuping)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Arrange exclusive surfaces from top->bottom */
|
/* Arrange exclusive surfaces from top->bottom */
|
||||||
for (i = 3; i >= 0; i--)
|
for (i = 3; i >= 0; i--)
|
||||||
arrangelayer(m, &m->layers[i], &usable_area, 1);
|
arrangelayer(m, &m->layers[i], &usable_area, 1);
|
||||||
|
|
@ -1833,9 +1876,21 @@ void arrangelayers(Monitor *m) {
|
||||||
arrangelayer(m, &m->layers[i], &usable_area, 0);
|
arrangelayer(m, &m->layers[i], &usable_area, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool pointer_is_trackpad(struct wlr_pointer *pointer) {
|
||||||
|
struct libinput_device *device;
|
||||||
|
|
||||||
|
if (wlr_input_device_is_libinput(&pointer->base) &&
|
||||||
|
(device = wlr_libinput_get_device_handle(&pointer->base))) {
|
||||||
|
if (libinput_device_config_tap_get_finger_count(device) > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void // 鼠标滚轮事件
|
void // 鼠标滚轮事件
|
||||||
axisnotify(struct wl_listener *listener, void *data) {
|
axisnotify(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
/* This event is forwarded by the cursor when a pointer emits an axis event,
|
/* This event is forwarded by the cursor when a pointer emits an axis event,
|
||||||
* for example when you move the scroll wheel. */
|
* for example when you move the scroll wheel. */
|
||||||
struct wlr_pointer_axis_event *event = data;
|
struct wlr_pointer_axis_event *event = data;
|
||||||
|
|
@ -1844,6 +1899,7 @@ axisnotify(struct wl_listener *listener, void *data) {
|
||||||
AxisBinding *a;
|
AxisBinding *a;
|
||||||
int32_t ji;
|
int32_t ji;
|
||||||
uint32_t adir;
|
uint32_t adir;
|
||||||
|
double target_scroll_factor;
|
||||||
// IDLE_NOTIFY_ACTIVITY;
|
// IDLE_NOTIFY_ACTIVITY;
|
||||||
handlecursoractivity();
|
handlecursoractivity();
|
||||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||||
|
|
@ -1890,12 +1946,17 @@ axisnotify(struct wl_listener *listener, void *data) {
|
||||||
* implemented checking the event's orientation and the delta of the event
|
* implemented checking the event's orientation and the delta of the event
|
||||||
*/
|
*/
|
||||||
/* Notify the client with pointer focus of the axis event. */
|
/* Notify the client with pointer focus of the axis event. */
|
||||||
|
|
||||||
|
target_scroll_factor = pointer_is_trackpad(event->pointer)
|
||||||
|
? config.trackpad_scroll_factor
|
||||||
|
: config.axis_scroll_factor;
|
||||||
|
|
||||||
wlr_seat_pointer_notify_axis(
|
wlr_seat_pointer_notify_axis(
|
||||||
seat, // 滚轮事件发送给客户端也就是窗口
|
seat, // 滚轮事件发送给客户端也就是窗口
|
||||||
event->time_msec, event->orientation,
|
event->time_msec, event->orientation,
|
||||||
event->delta * config.axis_scroll_factor,
|
event->delta * target_scroll_factor,
|
||||||
roundf(event->delta_discrete * config.axis_scroll_factor),
|
roundf(event->delta_discrete * target_scroll_factor), event->source,
|
||||||
event->source, event->relative_direction);
|
event->relative_direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ongesture(struct wlr_pointer_swipe_end_event *event) {
|
int32_t ongesture(struct wlr_pointer_swipe_end_event *event) {
|
||||||
|
|
@ -2018,52 +2079,180 @@ void hold_end(struct wl_listener *listener, void *data) {
|
||||||
event->time_msec, event->cancelled);
|
event->time_msec, event->cancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void place_drag_tile_client(Client *c) {
|
Client *find_closest_tiled_client(Client *c) {
|
||||||
Client *tc = NULL;
|
Client *tc, *closest = NULL;
|
||||||
Client *closest_client = NULL;
|
long min_dist = LONG_MAX;
|
||||||
long min_distant = LONG_MAX;
|
|
||||||
long temp_distant;
|
|
||||||
int32_t x, y;
|
|
||||||
|
|
||||||
wl_list_for_each(tc, &clients, link) {
|
wl_list_for_each(tc, &clients, link) {
|
||||||
if (tc != c && ISTILED(tc) && VISIBLEON(tc, c->mon)) {
|
if (tc == c || !ISTILED(tc) || !VISIBLEON(tc, c->mon))
|
||||||
x = tc->geom.x + (int32_t)(tc->geom.width / 2) - cursor->x;
|
continue;
|
||||||
y = tc->geom.y + (int32_t)(tc->geom.height / 2) - cursor->y;
|
|
||||||
temp_distant = x * x + y * y;
|
if (cursor->x >= tc->geom.x &&
|
||||||
if (temp_distant < min_distant) {
|
cursor->x < tc->geom.x + tc->geom.width &&
|
||||||
min_distant = temp_distant;
|
cursor->y >= tc->geom.y &&
|
||||||
closest_client = tc;
|
cursor->y < tc->geom.y + tc->geom.height) {
|
||||||
|
return tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t dx = tc->geom.x + (int32_t)(tc->geom.width / 2) - cursor->x;
|
||||||
|
int32_t dy = tc->geom.y + (int32_t)(tc->geom.height / 2) - cursor->y;
|
||||||
|
long dist = (long)dx * dx + (long)dy * dy;
|
||||||
|
|
||||||
|
if (dist < min_dist) {
|
||||||
|
min_dist = dist;
|
||||||
|
closest = tc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scroller_insert_stack(Client *c, Client *target_client,
|
||||||
|
bool insert_before) {
|
||||||
|
Client *stack_head = NULL;
|
||||||
|
|
||||||
|
if (!target_client || target_client->mon != c->mon) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
c->isglobal = target_client->isglobal = 0;
|
||||||
|
c->isunglobal = target_client->isunglobal = 0;
|
||||||
|
c->tags = target_client->tags = get_tags_first_tag(target_client->tags);
|
||||||
}
|
}
|
||||||
if (closest_client && closest_client->link.prev != &c->link) {
|
|
||||||
|
if (c->isfullscreen) {
|
||||||
|
setfullscreen(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->ismaximizescreen) {
|
||||||
|
setmaximizescreen(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_scroller_stack(c);
|
||||||
|
stack_head = get_scroll_stack_head(target_client);
|
||||||
|
|
||||||
|
if (insert_before) {
|
||||||
|
if (target_client->prev_in_stack) {
|
||||||
|
target_client->prev_in_stack->next_in_stack = c;
|
||||||
|
}
|
||||||
|
c->prev_in_stack = target_client->prev_in_stack;
|
||||||
|
c->next_in_stack = target_client;
|
||||||
|
target_client->prev_in_stack = c;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (target_client->next_in_stack) {
|
||||||
|
target_client->next_in_stack->prev_in_stack = c;
|
||||||
|
}
|
||||||
|
c->next_in_stack = target_client->next_in_stack;
|
||||||
|
c->prev_in_stack = target_client;
|
||||||
|
target_client->next_in_stack = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack_head->ismaximizescreen) {
|
||||||
|
setmaximizescreen(stack_head, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack_head->isfullscreen) {
|
||||||
|
setfullscreen(stack_head, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
arrange(c->mon, false, false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void try_scroller_drop(Client *c, Client *closest, int vertical) {
|
||||||
|
|
||||||
|
Client *stack_head = get_scroll_stack_head(closest);
|
||||||
|
|
||||||
|
if (vertical) {
|
||||||
|
if (closest->drop_direction == LEFT) {
|
||||||
|
setfloating(c, 0);
|
||||||
|
scroller_insert_stack(c, closest, true);
|
||||||
|
return;
|
||||||
|
} else if (closest->drop_direction == RIGHT) {
|
||||||
|
setfloating(c, 0);
|
||||||
|
scroller_insert_stack(c, closest, false);
|
||||||
|
return;
|
||||||
|
} else if (closest->drop_direction == UP) {
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
c->link.next = &closest_client->link;
|
wl_list_insert(stack_head->link.prev, &c->link);
|
||||||
c->link.prev = closest_client->link.prev;
|
} else if (closest->drop_direction == DOWN) {
|
||||||
closest_client->link.prev->next = &c->link;
|
wl_list_remove(&c->link);
|
||||||
closest_client->link.prev = &c->link;
|
wl_list_insert(&stack_head->link, &c->link);
|
||||||
} else if (closest_client) {
|
|
||||||
exchange_two_client(c, closest_client);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (closest->drop_direction == UP) {
|
||||||
|
setfloating(c, 0);
|
||||||
|
scroller_insert_stack(c, closest, true);
|
||||||
|
return;
|
||||||
|
} else if (closest->drop_direction == DOWN) {
|
||||||
|
setfloating(c, 0);
|
||||||
|
scroller_insert_stack(c, closest, false);
|
||||||
|
return;
|
||||||
|
} else if (closest->drop_direction == LEFT) {
|
||||||
|
wl_list_remove(&c->link);
|
||||||
|
wl_list_insert(stack_head->link.prev, &c->link);
|
||||||
|
} else if (closest->drop_direction == RIGHT) {
|
||||||
|
wl_list_remove(&c->link);
|
||||||
|
wl_list_insert(&stack_head->link, &c->link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setfloating(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void place_drag_tile_client(Client *c) {
|
||||||
|
Client *closest = find_closest_tiled_client(c);
|
||||||
|
|
||||||
|
if (closest && closest->mon) {
|
||||||
|
const Layout *layout =
|
||||||
|
closest->mon->pertag->ltidxs[closest->mon->pertag->curtag];
|
||||||
|
|
||||||
|
if (closest->drop_direction == UNDIR) {
|
||||||
|
setfloating(c, 0);
|
||||||
|
exchange_two_client(c, closest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layout->id == SCROLLER) {
|
||||||
|
try_scroller_drop(c, closest, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (layout->id == VERTICAL_SCROLLER) {
|
||||||
|
try_scroller_drop(c, closest, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (layout->id == DWINDLE) {
|
||||||
|
uint32_t tag = c->mon->pertag->curtag;
|
||||||
|
bool insert_before = (closest->drop_direction == LEFT ||
|
||||||
|
closest->drop_direction == UP);
|
||||||
|
bool split_h = (closest->drop_direction == LEFT ||
|
||||||
|
closest->drop_direction == RIGHT);
|
||||||
|
dwindle_insert(&c->mon->pertag->dwindle_root[tag], c, closest,
|
||||||
|
config.dwindle_split_ratio, insert_before, split_h,
|
||||||
|
!config.dwindle_drop_simple_split);
|
||||||
|
setfloating(c, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest->drop_direction == LEFT || closest->drop_direction == UP) {
|
||||||
|
wl_list_remove(&c->link);
|
||||||
|
wl_list_insert(closest->link.prev, &c->link);
|
||||||
|
} else {
|
||||||
|
wl_list_remove(&c->link);
|
||||||
|
wl_list_insert(&closest->link, &c->link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setfloating(c, 0);
|
setfloating(c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_trackpad_disabled(struct wlr_pointer *pointer) {
|
bool check_trackpad_disabled(struct wlr_pointer *pointer) {
|
||||||
struct libinput_device *device;
|
if (!config.disable_trackpad) {
|
||||||
|
|
||||||
if (!config.disable_trackpad)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (wlr_input_device_is_libinput(&pointer->base) &&
|
|
||||||
(device = wlr_libinput_get_device_handle(&pointer->base))) {
|
|
||||||
|
|
||||||
// 如果是触摸板且被禁用,忽略事件
|
|
||||||
if (libinput_device_config_tap_get_finger_count(device) > 0) {
|
|
||||||
return true; // 不处理事件
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return pointer_is_trackpad(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void // 鼠标按键事件
|
void // 鼠标按键事件
|
||||||
|
|
@ -2172,10 +2361,16 @@ buttonpress(struct wl_listener *listener, void *data) {
|
||||||
last_apply_drap_time = 0;
|
last_apply_drap_time = 0;
|
||||||
if (tmpc->drag_to_tile && config.drag_tile_to_tile) {
|
if (tmpc->drag_to_tile && config.drag_tile_to_tile) {
|
||||||
place_drag_tile_client(tmpc);
|
place_drag_tile_client(tmpc);
|
||||||
|
tmpc->float_geom = tmpc->drag_tile_float_backup_geom;
|
||||||
} else {
|
} else {
|
||||||
apply_window_snap(tmpc);
|
apply_window_snap(tmpc);
|
||||||
}
|
}
|
||||||
tmpc->drag_to_tile = false;
|
tmpc->drag_to_tile = false;
|
||||||
|
if (dropc) {
|
||||||
|
dropc->enable_drop_area_draw = false;
|
||||||
|
client_set_drop_area(dropc);
|
||||||
|
dropc = NULL;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
cursor_mode = CurNormal;
|
cursor_mode = CurNormal;
|
||||||
|
|
@ -2318,6 +2513,8 @@ void cleanupmon(struct wl_listener *listener, void *data) {
|
||||||
LayerSurface *l = NULL, *tmp = NULL;
|
LayerSurface *l = NULL, *tmp = NULL;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
|
m->iscleanuping = true;
|
||||||
|
|
||||||
/* m->layers[i] are intentionally not unlinked */
|
/* m->layers[i] are intentionally not unlinked */
|
||||||
for (i = 0; i < LENGTH(m->layers); i++) {
|
for (i = 0; i < LENGTH(m->layers); i++) {
|
||||||
wl_list_for_each_safe(l, tmp, &m->layers[i], link)
|
wl_list_for_each_safe(l, tmp, &m->layers[i], link)
|
||||||
|
|
@ -2350,6 +2547,9 @@ void cleanupmon(struct wl_listener *listener, void *data) {
|
||||||
m->skip_frame_timeout = NULL;
|
m->skip_frame_timeout = NULL;
|
||||||
}
|
}
|
||||||
m->wlr_output->data = NULL;
|
m->wlr_output->data = NULL;
|
||||||
|
|
||||||
|
for (uint32_t t = 0; t < LENGTH(tags) + 1; t++)
|
||||||
|
dwindle_free_tree(m->pertag->dwindle_root[t]);
|
||||||
free(m->pertag);
|
free(m->pertag);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
@ -2374,7 +2574,13 @@ void closemon(Monitor *m) {
|
||||||
if (c->mon == m) {
|
if (c->mon == m) {
|
||||||
|
|
||||||
if (selmon == NULL) {
|
if (selmon == NULL) {
|
||||||
remove_foreign_topleve(c);
|
if (c->foreign_toplevel) {
|
||||||
|
wlr_foreign_toplevel_handle_v1_output_leave(
|
||||||
|
c->foreign_toplevel, c->mon->wlr_output);
|
||||||
|
wlr_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel);
|
||||||
|
c->foreign_toplevel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
c->mon = NULL;
|
c->mon = NULL;
|
||||||
} else {
|
} else {
|
||||||
client_change_mon(c, selmon);
|
client_change_mon(c, selmon);
|
||||||
|
|
@ -3019,6 +3225,7 @@ void createmon(struct wl_listener *listener, void *data) {
|
||||||
struct wl_event_loop *loop = wl_display_get_event_loop(dpy);
|
struct wl_event_loop *loop = wl_display_get_event_loop(dpy);
|
||||||
m = wlr_output->data = ecalloc(1, sizeof(*m));
|
m = wlr_output->data = ecalloc(1, sizeof(*m));
|
||||||
|
|
||||||
|
m->iscleanuping = false;
|
||||||
m->skip_frame_timeout =
|
m->skip_frame_timeout =
|
||||||
wl_event_loop_add_timer(loop, monitor_skip_frame_timeout_callback, m);
|
wl_event_loop_add_timer(loop, monitor_skip_frame_timeout_callback, m);
|
||||||
m->skiping_frame = false;
|
m->skiping_frame = false;
|
||||||
|
|
@ -3201,6 +3408,22 @@ void destroyinputdevice(struct wl_listener *listener, void *data) {
|
||||||
free(input_dev);
|
free(input_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pointer_set_accel(struct libinput_device *device, bool natural_scrolling,
|
||||||
|
uint32_t mouse_accel_profile, double mouse_accel_speed) {
|
||||||
|
libinput_device_config_scroll_set_natural_scroll_enabled(device,
|
||||||
|
natural_scrolling);
|
||||||
|
if (mouse_accel_profile &&
|
||||||
|
libinput_device_config_accel_is_available(device)) {
|
||||||
|
libinput_device_config_accel_set_profile(device, mouse_accel_profile);
|
||||||
|
libinput_device_config_accel_set_speed(device, mouse_accel_speed);
|
||||||
|
} else {
|
||||||
|
// profile cannot be directly applied to 0, need to set to 1 first
|
||||||
|
libinput_device_config_accel_set_profile(device, 1);
|
||||||
|
libinput_device_config_accel_set_profile(device, 0);
|
||||||
|
libinput_device_config_accel_set_speed(device, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void configure_pointer(struct libinput_device *device) {
|
void configure_pointer(struct libinput_device *device) {
|
||||||
if (libinput_device_config_tap_get_finger_count(device)) {
|
if (libinput_device_config_tap_get_finger_count(device)) {
|
||||||
libinput_device_config_tap_set_enabled(device, config.tap_to_click);
|
libinput_device_config_tap_set_enabled(device, config.tap_to_click);
|
||||||
|
|
@ -3209,11 +3432,12 @@ void configure_pointer(struct libinput_device *device) {
|
||||||
libinput_device_config_tap_set_drag_lock_enabled(device,
|
libinput_device_config_tap_set_drag_lock_enabled(device,
|
||||||
config.drag_lock);
|
config.drag_lock);
|
||||||
libinput_device_config_tap_set_button_map(device, config.button_map);
|
libinput_device_config_tap_set_button_map(device, config.button_map);
|
||||||
libinput_device_config_scroll_set_natural_scroll_enabled(
|
pointer_set_accel(device, config.trackpad_natural_scrolling,
|
||||||
device, config.trackpad_natural_scrolling);
|
config.trackpad_accel_profile,
|
||||||
|
config.trackpad_accel_speed);
|
||||||
} else {
|
} else {
|
||||||
libinput_device_config_scroll_set_natural_scroll_enabled(
|
pointer_set_accel(device, config.mouse_natural_scrolling,
|
||||||
device, config.mouse_natural_scrolling);
|
config.mouse_accel_profile, config.mouse_accel_speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (libinput_device_config_dwt_is_available(device))
|
if (libinput_device_config_dwt_is_available(device))
|
||||||
|
|
@ -3241,17 +3465,6 @@ void configure_pointer(struct libinput_device *device) {
|
||||||
if (libinput_device_config_send_events_get_modes(device))
|
if (libinput_device_config_send_events_get_modes(device))
|
||||||
libinput_device_config_send_events_set_mode(device,
|
libinput_device_config_send_events_set_mode(device,
|
||||||
config.send_events_mode);
|
config.send_events_mode);
|
||||||
|
|
||||||
if (config.accel_profile &&
|
|
||||||
libinput_device_config_accel_is_available(device)) {
|
|
||||||
libinput_device_config_accel_set_profile(device, config.accel_profile);
|
|
||||||
libinput_device_config_accel_set_speed(device, config.accel_speed);
|
|
||||||
} else {
|
|
||||||
// profile cannot be directly applied to 0, need to set to 1 first
|
|
||||||
libinput_device_config_accel_set_profile(device, 1);
|
|
||||||
libinput_device_config_accel_set_profile(device, 0);
|
|
||||||
libinput_device_config_accel_set_speed(device, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void createpointer(struct wlr_pointer *pointer) {
|
void createpointer(struct wlr_pointer *pointer) {
|
||||||
|
|
@ -3577,8 +3790,14 @@ void focusclient(Client *c, int32_t lift) {
|
||||||
wl_list_for_each(um, &mons, link) {
|
wl_list_for_each(um, &mons, link) {
|
||||||
if (um->wlr_output->enabled && um != selmon && um->sel &&
|
if (um->wlr_output->enabled && um != selmon && um->sel &&
|
||||||
!um->sel->iskilling && um->sel->isfocusing) {
|
!um->sel->iskilling && um->sel->isfocusing) {
|
||||||
|
|
||||||
um->sel->isfocusing = false;
|
um->sel->isfocusing = false;
|
||||||
client_set_unfocused_opacity_animation(um->sel);
|
client_set_unfocused_opacity_animation(um->sel);
|
||||||
|
|
||||||
|
if (um->sel->foreign_toplevel) {
|
||||||
|
wlr_foreign_toplevel_handle_v1_set_activated(
|
||||||
|
um->sel->foreign_toplevel, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4032,6 +4251,8 @@ static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int32_t sx,
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_client_properties(Client *c) {
|
void init_client_properties(Client *c) {
|
||||||
|
c->drop_direction = UNDIR;
|
||||||
|
c->enable_drop_area_draw = false;
|
||||||
c->isfocusing = false;
|
c->isfocusing = false;
|
||||||
c->isfloating = 0;
|
c->isfloating = 0;
|
||||||
c->isfakefullscreen = 0;
|
c->isfakefullscreen = 0;
|
||||||
|
|
@ -4173,6 +4394,12 @@ mapnotify(struct wl_listener *listener, void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// extra node
|
// extra node
|
||||||
|
|
||||||
|
c->droparea = wlr_scene_rect_create(c->scene, 0, 0, config.dropcolor);
|
||||||
|
wlr_scene_node_lower_to_bottom(&c->droparea->node);
|
||||||
|
wlr_scene_node_set_position(&c->droparea->node, 0, 0);
|
||||||
|
wlr_scene_node_set_enabled(&c->droparea->node, false);
|
||||||
|
|
||||||
c->border = wlr_scene_rect_create(
|
c->border = wlr_scene_rect_create(
|
||||||
c->scene, 0, 0, c->isurgent ? config.urgentcolor : config.bordercolor);
|
c->scene, 0, 0, c->isurgent ? config.urgentcolor : config.bordercolor);
|
||||||
wlr_scene_node_lower_to_bottom(&c->border->node);
|
wlr_scene_node_lower_to_bottom(&c->border->node);
|
||||||
|
|
@ -4211,6 +4438,7 @@ mapnotify(struct wl_listener *listener, void *data) {
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
wl_list_insert(clients.prev, &c->link); // 尾部入栈
|
wl_list_insert(clients.prev, &c->link); // 尾部入栈
|
||||||
|
|
||||||
wl_list_insert(&fstack, &c->flink);
|
wl_list_insert(&fstack, &c->flink);
|
||||||
|
|
||||||
applyrules(c);
|
applyrules(c);
|
||||||
|
|
@ -4286,7 +4514,11 @@ void set_minimized(Client *c) {
|
||||||
c->is_scratchpad_show = 0;
|
c->is_scratchpad_show = 0;
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), 1);
|
||||||
arrange(c->mon, false, false);
|
arrange(c->mon, false, false);
|
||||||
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, false);
|
|
||||||
|
if (c->foreign_toplevel)
|
||||||
|
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel,
|
||||||
|
false);
|
||||||
|
|
||||||
wl_list_remove(&c->link); // 从原来位置移除
|
wl_list_remove(&c->link); // 从原来位置移除
|
||||||
wl_list_insert(clients.prev, &c->link); // 插入尾部
|
wl_list_insert(clients.prev, &c->link); // 插入尾部
|
||||||
}
|
}
|
||||||
|
|
@ -4362,6 +4594,7 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
|
||||||
double dy, double dx_unaccel, double dy_unaccel) {
|
double dy, double dx_unaccel, double dy_unaccel) {
|
||||||
double sx = 0, sy = 0, sx_confined, sy_confined;
|
double sx = 0, sy = 0, sx_confined, sy_confined;
|
||||||
Client *c = NULL, *w = NULL;
|
Client *c = NULL, *w = NULL;
|
||||||
|
Client *closet_drop_client = NULL;
|
||||||
LayerSurface *l = NULL;
|
LayerSurface *l = NULL;
|
||||||
struct wlr_surface *surface = NULL;
|
struct wlr_surface *surface = NULL;
|
||||||
struct wlr_pointer_constraint_v1 *constraint;
|
struct wlr_pointer_constraint_v1 *constraint;
|
||||||
|
|
@ -4378,9 +4611,14 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
|
||||||
|
|
||||||
if (active_constraint && cursor_mode != CurResize &&
|
if (active_constraint && cursor_mode != CurResize &&
|
||||||
cursor_mode != CurMove) {
|
cursor_mode != CurMove) {
|
||||||
toplevel_from_wlr_surface(active_constraint->surface, &c, NULL);
|
if (active_constraint->surface ==
|
||||||
if (c && active_constraint->surface ==
|
|
||||||
seat->pointer_state.focused_surface) {
|
seat->pointer_state.focused_surface) {
|
||||||
|
|
||||||
|
if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
toplevel_from_wlr_surface(active_constraint->surface, &c, NULL);
|
||||||
|
if (c) {
|
||||||
sx = cursor->x - c->geom.x - c->bw;
|
sx = cursor->x - c->geom.x - c->bw;
|
||||||
sy = cursor->y - c->geom.y - c->bw;
|
sy = cursor->y - c->geom.y - c->bw;
|
||||||
if (wlr_region_confine(&active_constraint->region, sx, sy,
|
if (wlr_region_confine(&active_constraint->region, sx, sy,
|
||||||
|
|
@ -4389,9 +4627,7 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
|
||||||
dx = sx_confined - sx;
|
dx = sx_confined - sx;
|
||||||
dy = sy_confined - sy;
|
dy = sy_confined - sy;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4430,6 +4666,24 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
|
||||||
.y = (int32_t)round(cursor->y) - grabcy,
|
.y = (int32_t)round(cursor->y) - grabcy,
|
||||||
.width = grabc->geom.width,
|
.width = grabc->geom.width,
|
||||||
.height = grabc->geom.height};
|
.height = grabc->geom.height};
|
||||||
|
if (config.drag_tile_to_tile && grabc->drag_to_tile) {
|
||||||
|
closet_drop_client = find_closest_tiled_client(grabc);
|
||||||
|
if (closet_drop_client && dropc && closet_drop_client != dropc) {
|
||||||
|
dropc->enable_drop_area_draw = false;
|
||||||
|
client_set_drop_area(dropc);
|
||||||
|
dropc = closet_drop_client;
|
||||||
|
dropc->enable_drop_area_draw = true;
|
||||||
|
client_set_drop_area(dropc);
|
||||||
|
} else if (closet_drop_client) {
|
||||||
|
dropc = closet_drop_client;
|
||||||
|
dropc->enable_drop_area_draw = true;
|
||||||
|
client_set_drop_area(dropc);
|
||||||
|
} else if (dropc) {
|
||||||
|
dropc->enable_drop_area_draw = false;
|
||||||
|
client_set_drop_area(dropc);
|
||||||
|
dropc = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
resize(grabc, grabc->float_geom, 1);
|
resize(grabc, grabc->float_geom, 1);
|
||||||
return;
|
return;
|
||||||
} else if (cursor_mode == CurResize) {
|
} else if (cursor_mode == CurResize) {
|
||||||
|
|
@ -4890,10 +5144,20 @@ void exchange_two_client(Client *c1, Client *c2) {
|
||||||
tmp_tags = c2->tags;
|
tmp_tags = c2->tags;
|
||||||
setmon(c2, c1->mon, c1->tags, false);
|
setmon(c2, c1->mon, c1->tags, false);
|
||||||
setmon(c1, tmp_mon, tmp_tags, false);
|
setmon(c1, tmp_mon, tmp_tags, false);
|
||||||
|
if (c1->mon &&
|
||||||
|
c1->mon->pertag->ltidxs[c1->mon->pertag->curtag]->id == DWINDLE)
|
||||||
|
dwindle_swap_clients(
|
||||||
|
&c1->mon->pertag->dwindle_root[c1->mon->pertag->curtag], c1,
|
||||||
|
c2);
|
||||||
arrange(c1->mon, false, false);
|
arrange(c1->mon, false, false);
|
||||||
arrange(c2->mon, false, false);
|
arrange(c2->mon, false, false);
|
||||||
focusclient(c1, 0);
|
focusclient(c1, 0);
|
||||||
} else {
|
} else {
|
||||||
|
if (c1->mon &&
|
||||||
|
c1->mon->pertag->ltidxs[c1->mon->pertag->curtag]->id == DWINDLE)
|
||||||
|
dwindle_swap_clients(
|
||||||
|
&c1->mon->pertag->dwindle_root[c1->mon->pertag->curtag], c1,
|
||||||
|
c2);
|
||||||
arrange(c1->mon, false, false);
|
arrange(c1->mon, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5424,7 +5688,7 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) {
|
||||||
arrange(oldmon, false, false);
|
arrange(oldmon, false, false);
|
||||||
if (m) {
|
if (m) {
|
||||||
/* Make sure window actually overlaps with the monitor */
|
/* Make sure window actually overlaps with the monitor */
|
||||||
reset_foreign_tolevel(c);
|
reset_foreign_tolevel(c, oldmon, m);
|
||||||
resize(c, c->geom, 0);
|
resize(c, c->geom, 0);
|
||||||
client_reset_mon_tags(c, m, newtags);
|
client_reset_mon_tags(c, m, newtags);
|
||||||
check_match_tag_floating_rule(c, m);
|
check_match_tag_floating_rule(c, m);
|
||||||
|
|
@ -5471,6 +5735,8 @@ void show_hide_client(Client *c) {
|
||||||
}
|
}
|
||||||
client_pending_minimized_state(c, 0);
|
client_pending_minimized_state(c, 0);
|
||||||
focusclient(c, 1);
|
focusclient(c, 1);
|
||||||
|
|
||||||
|
if (c->foreign_toplevel)
|
||||||
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true);
|
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6056,6 +6322,10 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
||||||
grabc = NULL;
|
grabc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c == dropc) {
|
||||||
|
dropc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
wl_list_for_each(m, &mons, link) {
|
wl_list_for_each(m, &mons, link) {
|
||||||
if (!m->wlr_output->enabled) {
|
if (!m->wlr_output->enabled) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -6126,6 +6396,7 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
||||||
c->next_in_stack = NULL;
|
c->next_in_stack = NULL;
|
||||||
c->prev_in_stack = NULL;
|
c->prev_in_stack = NULL;
|
||||||
|
|
||||||
|
dwindle_remove_client(c);
|
||||||
wlr_scene_node_destroy(&c->scene->node);
|
wlr_scene_node_destroy(&c->scene->node);
|
||||||
printstatus();
|
printstatus();
|
||||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||||
|
|
@ -6244,7 +6515,7 @@ void updatemons(struct wl_listener *listener, void *data) {
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (!c->mon && client_surface(c)->mapped) {
|
if (!c->mon && client_surface(c)->mapped) {
|
||||||
c->mon = selmon;
|
c->mon = selmon;
|
||||||
reset_foreign_tolevel(c);
|
reset_foreign_tolevel(c, NULL, c->mon);
|
||||||
}
|
}
|
||||||
if (c->tags == 0 && !c->is_in_scratchpad) {
|
if (c->tags == 0 && !c->is_in_scratchpad) {
|
||||||
c->tags = selmon->tagset[selmon->seltags];
|
c->tags = selmon->tagset[selmon->seltags];
|
||||||
|
|
@ -6317,10 +6588,14 @@ void view_in_mon(const Arg *arg, bool want_animation, Monitor *m,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg->ui == UINT32_MAX) {
|
if (arg->ui == UINT32_MAX) {
|
||||||
|
if (m->tagset[0] != m->tagset[1]) {
|
||||||
m->pertag->prevtag = get_tags_first_tag_num(m->tagset[m->seltags]);
|
m->pertag->prevtag = get_tags_first_tag_num(m->tagset[m->seltags]);
|
||||||
m->seltags ^= 1; /* toggle sel tagset */
|
m->seltags ^= 1; /* toggle sel tagset */
|
||||||
m->pertag->curtag = get_tags_first_tag_num(m->tagset[m->seltags]);
|
m->pertag->curtag = get_tags_first_tag_num(m->tagset[m->seltags]);
|
||||||
goto toggleseltags;
|
goto toggleseltags;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m->tagset[m->seltags] & arg->ui & TAGMASK) != 0) {
|
if ((m->tagset[m->seltags] & arg->ui & TAGMASK) != 0) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue