Compare commits

...

15 commits
0.14.2 ... main

Author SHA1 Message Date
DreamMaoMao
792bfac475 fix: can't resize tile scroller window when only two tiled client 2026-06-11 23:14:50 +08:00
DreamMaoMao
03e68ba069 opt: optimize marco use in client tile resize 2026-06-11 12:39:17 +08:00
DreamMaoMao
33cda5afea opt:optimize edge focus judge 2026-06-11 12:37:48 +08:00
DreamMaoMao
94db68ef88 fix: floating window can't get pointer focus when cross monitor 2026-06-11 11:08:44 +08:00
DreamMaoMao
cd6e2883db
Merge pull request #1027 from xtheeq/docs-update
Some checks failed
Sync website / sync-website (push) Has been cancelled
Sync wiki / sync-wiki (push) Has been cancelled
docs: fix wayfreeze link page
2026-06-10 11:45:58 +08:00
DreamMaoMao
ef59224cdb fix: deck layout caculate error when multi master 2026-06-09 21:56:48 +08:00
DreamMaoMao
52732c928b fix: grid layout cant fullscreen 2026-06-09 21:50:16 +08:00
xtheeq
47f30454e6 docs: fix wayfreeze link page 2026-06-08 20:33:21 +05:30
DreamMaoMao
7faf9b6239 Merge pull request #1025 from osamamragab/main
feat: add hide cursor on keypress option (#871)
2026-06-08 21:44:13 +08:00
DreamMaoMao
36398a1af2 opt: optimize unmanaged client init 2026-06-08 19:29:00 +08:00
Osama Ragab
a429420b73 feat: add hide cursor on keypress option (#871) 2026-06-08 13:28:34 +08:00
DreamMaoMao
b8fa9a3043 Merge pull request #1025 from osamamragab/main
Some checks failed
Sync website / sync-website (push) Has been cancelled
Sync wiki / sync-wiki (push) Has been cancelled
feat: add hide cursor on keypress option (#871)
2026-06-08 13:28:34 +08:00
DreamMaoMao
009e2d2111 opt: optimzie xwayland position set 2026-06-08 13:05:04 +08:00
DreamMaoMao
27f4f64173 opt: not need send output enter when layer map
scene scene-graph API will auto do this
2026-06-08 11:40:51 +08:00
DreamMaoMao
ccb58a4f1a docs: fix some error im sample 2026-06-07 18:08:55 +08:00
10 changed files with 134 additions and 108 deletions

View file

@ -21,6 +21,7 @@ description: Advanced settings for XWayland, focus behavior, and system integrat
| `sloppyfocus` | `1` | Focus follows the mouse cursor. | | `sloppyfocus` | `1` | Focus follows the mouse cursor. |
| `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). |
| `cursor_hide_on_keypress` | `0` | Hide the cursor on keypress. |
| `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_tile_small` | `1` | Allow dragging a tiled window temporarily to small size.|
| `drag_corner` | `3` | Corner for drag-to-tile detection (0: none, 13: corners, 4: auto-detect). | | `drag_corner` | `3` | Corner for drag-to-tile detection (0: none, 13: corners, 4: auto-detect). |

View file

@ -14,7 +14,7 @@ Instead, compose your own workflow from small Wayland utilities and bind them to
| [`slurp`](https://github.com/emersion/slurp) | Interactively select a region for `grim` | | [`slurp`](https://github.com/emersion/slurp) | Interactively select a region for `grim` |
| [`wl-copy`](https://github.com/bugaevc/wl-clipboard) | Copy screenshots directly to the clipboard | | [`wl-copy`](https://github.com/bugaevc/wl-clipboard) | Copy screenshots directly to the clipboard |
| [`satty`](https://github.com/gabm/Satty) | Annotate screenshots before saving | | [`satty`](https://github.com/gabm/Satty) | Annotate screenshots before saving |
| [`wayfreeze`](https://github.com/nicbk/wayfreeze) | Freeze the screen before capture | | [`wayfreeze`](https://github.com/Jappie3/wayfreeze) | Freeze the screen before capture |
Install the required with your package manager or from source. Install the required with your package manager or from source.

View file

@ -115,7 +115,7 @@ windowrule=width:1000,height:900,appid:yesplaymusic,title:Demons
# Global keybindings for OBS Studio # Global keybindings for OBS Studio
windowrule=globalkeybinding:ctrl+alt-o,appid:com.obsproject.Studio windowrule=globalkeybinding:ctrl+alt-o,appid:com.obsproject.Studio
windowrule=globalkeybinding:ctrl+alt+n,appid:com.obsproject.Studio windowrule=globalkeybinding:ctrl+alt-n,appid:com.obsproject.Studio
windowrule=isopensilent:1,appid:com.obsproject.Studio windowrule=isopensilent:1,appid:com.obsproject.Studio
# Force tearing for games # Force tearing for games

View file

@ -51,7 +51,7 @@ static void finish_exchange_arrange_and_focus(Client *c1, Client *c2,
} }
void client_tile_resize(Client *c, struct wlr_box geo, int32_t interact) { void client_tile_resize(Client *c, struct wlr_box geo, int32_t interact) {
if (!ISSCROLLTILED(c)) if (!ISFAKETILED(c))
return; return;
if (!c->isfullscreen && !c->ismaximizescreen) { if (!c->isfullscreen && !c->ismaximizescreen) {

View file

@ -261,6 +261,7 @@ typedef struct {
int32_t overviewgappi; int32_t overviewgappi;
int32_t overviewgappo; int32_t overviewgappo;
uint32_t cursor_hide_timeout; uint32_t cursor_hide_timeout;
uint32_t cursor_hide_on_keypress;
uint32_t axis_bind_apply_timeout; uint32_t axis_bind_apply_timeout;
uint32_t focus_on_activate; uint32_t focus_on_activate;
@ -1714,6 +1715,8 @@ bool parse_option(Config *config, char *key, char *value) {
config->overviewgappo = atoi(value); config->overviewgappo = atoi(value);
} else if (strcmp(key, "cursor_hide_timeout") == 0) { } else if (strcmp(key, "cursor_hide_timeout") == 0) {
config->cursor_hide_timeout = atoi(value); config->cursor_hide_timeout = atoi(value);
} else if (strcmp(key, "cursor_hide_on_keypress") == 0) {
config->cursor_hide_on_keypress = atoi(value);
} else if (strcmp(key, "axis_bind_apply_timeout") == 0) { } else if (strcmp(key, "axis_bind_apply_timeout") == 0) {
config->axis_bind_apply_timeout = atoi(value); config->axis_bind_apply_timeout = atoi(value);
} else if (strcmp(key, "focus_on_activate") == 0) { } else if (strcmp(key, "focus_on_activate") == 0) {
@ -3346,6 +3349,8 @@ void override_config(void) {
CLAMP_INT(config.no_radius_when_single, 0, 1); CLAMP_INT(config.no_radius_when_single, 0, 1);
config.cursor_hide_timeout = config.cursor_hide_timeout =
CLAMP_INT(config.cursor_hide_timeout, 0, 36000); CLAMP_INT(config.cursor_hide_timeout, 0, 36000);
config.cursor_hide_on_keypress =
CLAMP_INT(config.cursor_hide_on_keypress, 0, 1);
config.single_scratchpad = CLAMP_INT(config.single_scratchpad, 0, 1); config.single_scratchpad = CLAMP_INT(config.single_scratchpad, 0, 1);
config.repeat_rate = CLAMP_INT(config.repeat_rate, 1, 1000); config.repeat_rate = CLAMP_INT(config.repeat_rate, 1, 1000);
config.repeat_delay = CLAMP_INT(config.repeat_delay, 1, 20000); config.repeat_delay = CLAMP_INT(config.repeat_delay, 1, 20000);
@ -3507,6 +3512,7 @@ void set_value_default() {
config.overviewgappi = 5; config.overviewgappi = 5;
config.overviewgappo = 30; config.overviewgappo = 30;
config.cursor_hide_timeout = 0; config.cursor_hide_timeout = 0;
config.cursor_hide_on_keypress = 0;
config.warpcursor = 1; config.warpcursor = 1;
config.drag_corner = 3; config.drag_corner = 3;

View file

@ -91,9 +91,9 @@ setclient_coordinate_center(Client *c, Monitor *tm, struct wlr_box geom,
if (!m) if (!m)
return geom; return geom;
uint32_t cbw = check_hit_no_border(c) ? c->bw : 0; uint32_t cbw = c && check_hit_no_border(c) ? c->bw : 0;
if (!c->no_force_center && m) { if ((!c || !c->no_force_center) && m) {
tempbox.x = m->w.x + (m->w.width - geom.width) / 2; tempbox.x = m->w.x + (m->w.width - geom.width) / 2;
tempbox.y = m->w.y + (m->w.height - geom.height) / 2; tempbox.y = m->w.y + (m->w.height - geom.height) / 2;
} else { } else {

View file

@ -751,6 +751,7 @@ void resize_tile_grid_fair(Client *grabc, bool isdrag, int32_t offsetx,
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) {
if (!grabc || grabc->isfullscreen || grabc->ismaximizescreen) if (!grabc || grabc->isfullscreen || grabc->ismaximizescreen)
return; return;
if (grabc->mon->isoverview) if (grabc->mon->isoverview)
@ -772,7 +773,7 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
Client *stack_head_client = headnode->client; Client *stack_head_client = headnode->client;
if (m->visible_tiling_clients == 1 && if (m->visible_scroll_tiling_clients == 1 &&
!config.scroller_ignore_proportion_single) !config.scroller_ignore_proportion_single)
return; return;

View file

@ -500,16 +500,13 @@ void deck(Monitor *m) {
return; return;
wl_list_for_each(fc, &clients, link) { wl_list_for_each(fc, &clients, link) {
if (VISIBLEON(fc, m) && ISFAKETILED(fc)) if (VISIBLEON(fc, m) && ISFAKETILED(fc))
break; break;
} }
// Calculate master width using mfact from pertag
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
: m->pertag->mfacts[m->pertag->curtag]; : m->pertag->mfacts[m->pertag->curtag];
// Calculate master width including outer gaps
if (n > nmasters) if (n > nmasters)
mw = nmasters ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0; mw = nmasters ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0;
else else
@ -521,16 +518,15 @@ void deck(Monitor *m) {
continue; continue;
if (i < nmasters) { if (i < nmasters) {
c->master_mfact_per = mfact; c->master_mfact_per = mfact;
// Master area clients int32_t h =
client_tile_resize( (m->w.height - 2 * cur_gappov - my) / (MIN(n, nmasters) - i);
c, client_tile_resize(c,
(struct wlr_box){.x = m->w.x + cur_gappoh, (struct wlr_box){.x = m->w.x + cur_gappoh,
.y = m->w.y + cur_gappov + my, .y = m->w.y + cur_gappov + my,
.width = mw, .width = mw,
.height = (m->w.height - 2 * cur_gappov - my) / .height = h},
(MIN(n, nmasters) - i)}, 0);
0); my += h;
my += c->geom.height;
} else { } else {
// Stack area clients // Stack area clients
c->master_mfact_per = mfact; c->master_mfact_per = mfact;
@ -588,6 +584,7 @@ void grid(Monitor *m) {
int32_t target_gappi = enablegaps ? config.gappih : 0; int32_t target_gappi = enablegaps ? config.gappih : 0;
float single_width_ratio = 0.9; float single_width_ratio = 0.9;
float single_height_ratio = 0.9; float single_height_ratio = 0.9;
struct wlr_box target_geom;
n = m->visible_fake_tiling_clients; n = m->visible_fake_tiling_clients;
@ -603,11 +600,11 @@ void grid(Monitor *m) {
ISFAKETILED(c))) { ISFAKETILED(c))) {
cw = (m->w.width - 2 * target_gappo) * single_width_ratio; cw = (m->w.width - 2 * target_gappo) * single_width_ratio;
ch = (m->w.height - 2 * target_gappo) * single_height_ratio; ch = (m->w.height - 2 * target_gappo) * single_height_ratio;
c->geom.x = m->w.x + (m->w.width - cw) / 2; target_geom.x = m->w.x + (m->w.width - cw) / 2;
c->geom.y = m->w.y + (m->w.height - ch) / 2; target_geom.y = m->w.y + (m->w.height - ch) / 2;
c->geom.width = cw; target_geom.width = cw;
c->geom.height = ch; target_geom.height = ch;
client_tile_resize(c, c->geom, 0); client_tile_resize(c, target_geom, 0);
return; return;
} }
} }
@ -651,16 +648,16 @@ void grid(Monitor *m) {
cw = avail_w * (col_pers[i] / sum_col); cw = avail_w * (col_pers[i] / sum_col);
if (i == 0) { if (i == 0) {
c->geom.x = m->w.x + target_gappo; target_geom.x = m->w.x + target_gappo;
} else if (i == 1) { } else if (i == 1) {
// 第二个窗口的 X 坐标紧跟第一个窗口后面 // 第二个窗口的 X 坐标紧跟第一个窗口后面
float cw0 = avail_w * (col_pers[0] / sum_col); float cw0 = avail_w * (col_pers[0] / sum_col);
c->geom.x = m->w.x + target_gappo + cw0 + target_gappi; target_geom.x = m->w.x + target_gappo + cw0 + target_gappi;
} }
c->geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo; target_geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
c->geom.width = cw; target_geom.width = cw;
c->geom.height = ch; target_geom.height = ch;
client_tile_resize(c, c->geom, 0); client_tile_resize(c, target_geom, 0);
i++; i++;
} }
} }
@ -757,11 +754,11 @@ void grid(Monitor *m) {
? (m->w.y + m->w.height - target_gappo - fl_cy) ? (m->w.y + m->w.height - target_gappo - fl_cy)
: avail_h * (row_pers[r_idx] / sum_row); : avail_h * (row_pers[r_idx] / sum_row);
c->geom.x = (int32_t)fl_cx; target_geom.x = (int32_t)fl_cx;
c->geom.y = (int32_t)fl_cy; target_geom.y = (int32_t)fl_cy;
c->geom.width = (int32_t)fl_cw; target_geom.width = (int32_t)fl_cw;
c->geom.height = (int32_t)fl_ch; target_geom.height = (int32_t)fl_ch;
client_tile_resize(c, c->geom, 0); client_tile_resize(c, target_geom, 0);
i++; i++;
} }
} }

View file

@ -137,12 +137,10 @@ void vertical_deck(Monitor *m) {
return; return;
wl_list_for_each(fc, &clients, link) { wl_list_for_each(fc, &clients, link) {
if (VISIBLEON(fc, m) && ISFAKETILED(fc)) if (VISIBLEON(fc, m) && ISFAKETILED(fc))
break; break;
} }
// Calculate master width using mfact from pertag
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
: m->pertag->mfacts[m->pertag->curtag]; : m->pertag->mfacts[m->pertag->curtag];
@ -156,16 +154,18 @@ void vertical_deck(Monitor *m) {
if (!VISIBLEON(c, m) || !ISFAKETILED(c)) if (!VISIBLEON(c, m) || !ISFAKETILED(c))
continue; continue;
if (i < nmasters) { if (i < nmasters) {
client_tile_resize( c->master_mfact_per = mfact;
c, int32_t w =
(struct wlr_box){.x = m->w.x + cur_gappoh + mx, (m->w.width - 2 * cur_gappoh - mx) / (MIN(n, nmasters) - i);
.y = m->w.y + cur_gappov, client_tile_resize(c,
.width = (m->w.width - 2 * cur_gappoh - mx) / (struct wlr_box){.x = m->w.x + cur_gappoh + mx,
(MIN(n, nmasters) - i), .y = m->w.y + cur_gappov,
.height = mh}, .width = w,
0); .height = mh},
mx += c->geom.width; 0);
mx += w;
} else { } else {
c->master_mfact_per = mfact;
client_tile_resize( client_tile_resize(
c, c,
(struct wlr_box){.x = m->w.x + cur_gappoh, (struct wlr_box){.x = m->w.x + cur_gappoh,
@ -186,14 +186,13 @@ void vertical_grid(Monitor *m) {
int32_t cw, ch; int32_t cw, ch;
int32_t rows, cols, overrows; int32_t rows, cols, overrows;
Client *c = NULL; Client *c = NULL;
int32_t target_gappo = int32_t target_gappo = enablegaps ? config.gappov : 0;
enablegaps ? m->isoverview ? config.overviewgappo : config.gappov : 0; int32_t target_gappi = enablegaps ? config.gappiv : 0;
int32_t target_gappi = float single_width_ratio = 0.9;
enablegaps ? m->isoverview ? config.overviewgappi : config.gappiv : 0; float single_height_ratio = 0.9;
float single_width_ratio = m->isoverview ? 0.7 : 0.9; struct wlr_box target_geom;
float single_height_ratio = m->isoverview ? 0.8 : 0.9;
n = m->isoverview ? m->visible_clients : m->visible_fake_tiling_clients; n = m->visible_fake_tiling_clients;
if (n == 0) if (n == 0)
return; return;
@ -202,15 +201,14 @@ void vertical_grid(Monitor *m) {
if (c->mon != m) if (c->mon != m)
continue; continue;
if (VISIBLEON(c, m) && !c->isunglobal && if (VISIBLEON(c, m) && !c->isunglobal &&
((m->isoverview && !client_is_x11_popup(c)) || (!client_is_x11_popup(c) || ISFAKETILED(c))) {
ISFAKETILED(c))) {
ch = (m->w.height - 2 * target_gappo) * single_height_ratio; ch = (m->w.height - 2 * target_gappo) * single_height_ratio;
cw = (m->w.width - 2 * target_gappo) * single_width_ratio; cw = (m->w.width - 2 * target_gappo) * single_width_ratio;
c->geom.x = m->w.x + (m->w.width - cw) / 2; target_geom.x = m->w.x + (m->w.width - cw) / 2;
c->geom.y = m->w.y + (m->w.height - ch) / 2; target_geom.y = m->w.y + (m->w.height - ch) / 2;
c->geom.width = cw; target_geom.width = cw;
c->geom.height = ch; target_geom.height = ch;
client_tile_resize(c, c->geom, 0); client_tile_resize(c, target_geom, 0);
return; return;
} }
} }
@ -224,8 +222,7 @@ void vertical_grid(Monitor *m) {
if (c->mon != m) if (c->mon != m)
continue; continue;
if (VISIBLEON(c, m) && !c->isunglobal && if (VISIBLEON(c, m) && !c->isunglobal &&
((m->isoverview && !client_is_x11_popup(c)) || (!client_is_x11_popup(c) || ISFAKETILED(c))) {
ISFAKETILED(c))) {
if (i < 2) if (i < 2)
row_pers[i] = row_pers[i] =
(c->grid_row_per > 0.0f) ? c->grid_row_per : 1.0f; (c->grid_row_per > 0.0f) ? c->grid_row_per : 1.0f;
@ -242,8 +239,7 @@ void vertical_grid(Monitor *m) {
if (c->mon != m) if (c->mon != m)
continue; continue;
if (VISIBLEON(c, m) && !c->isunglobal && if (VISIBLEON(c, m) && !c->isunglobal &&
((m->isoverview && !client_is_x11_popup(c)) || (!client_is_x11_popup(c) || ISFAKETILED(c))) {
ISFAKETILED(c))) {
c->grid_col_idx = 0; c->grid_col_idx = 0;
c->grid_row_idx = i; c->grid_row_idx = i;
c->grid_col_per = 1.0f; c->grid_col_per = 1.0f;
@ -252,17 +248,17 @@ void vertical_grid(Monitor *m) {
// 根据分配的权重动态计算当前窗口的高度 // 根据分配的权重动态计算当前窗口的高度
ch = avail_h * (row_pers[i] / sum_row); ch = avail_h * (row_pers[i] / sum_row);
c->geom.x = m->w.x + (m->w.width - cw) / 2 + target_gappo; target_geom.x = m->w.x + (m->w.width - cw) / 2 + target_gappo;
if (i == 0) { if (i == 0) {
c->geom.y = m->w.y + target_gappo; target_geom.y = m->w.y + target_gappo;
} else if (i == 1) { } else if (i == 1) {
// 第二个窗口的 Y 坐标紧跟第一个窗口下面 // 第二个窗口的 Y 坐标紧跟第一个窗口下面
float ch0 = avail_h * (row_pers[0] / sum_row); float ch0 = avail_h * (row_pers[0] / sum_row);
c->geom.y = m->w.y + target_gappo + ch0 + target_gappi; target_geom.y = m->w.y + target_gappo + ch0 + target_gappi;
} }
c->geom.width = cw; target_geom.width = cw;
c->geom.height = ch; target_geom.height = ch;
client_tile_resize(c, c->geom, 0); client_tile_resize(c, target_geom, 0);
i++; i++;
} }
} }
@ -287,7 +283,7 @@ void vertical_grid(Monitor *m) {
if (c->mon != m) if (c->mon != m)
continue; continue;
if (VISIBLEON(c, m) && !c->isunglobal && if (VISIBLEON(c, m) && !c->isunglobal &&
((m->isoverview && !client_is_x11_popup(c)) || ISFAKETILED(c))) { (!client_is_x11_popup(c) || ISFAKETILED(c))) {
int32_t c_idx = i / rows; int32_t c_idx = i / rows;
int32_t r_idx = i % rows; int32_t r_idx = i % rows;
if (r_idx == 0) if (r_idx == 0)
@ -314,7 +310,7 @@ void vertical_grid(Monitor *m) {
if (c->mon != m) if (c->mon != m)
continue; continue;
if (VISIBLEON(c, m) && !c->isunglobal && if (VISIBLEON(c, m) && !c->isunglobal &&
((m->isoverview && !client_is_x11_popup(c)) || ISFAKETILED(c))) { (!client_is_x11_popup(c) || ISFAKETILED(c))) {
int32_t c_idx = i / rows; int32_t c_idx = i / rows;
int32_t r_idx = i % rows; int32_t r_idx = i % rows;
@ -352,11 +348,11 @@ void vertical_grid(Monitor *m) {
? (m->w.x + m->w.width - target_gappo - fl_cx) ? (m->w.x + m->w.width - target_gappo - fl_cx)
: avail_w * (col_pers[c_idx] / sum_col); : avail_w * (col_pers[c_idx] / sum_col);
c->geom.x = (int32_t)fl_cx; target_geom.x = (int32_t)fl_cx;
c->geom.y = (int32_t)fl_cy; target_geom.y = (int32_t)fl_cy;
c->geom.width = (int32_t)fl_cw; target_geom.width = (int32_t)fl_cw;
c->geom.height = (int32_t)fl_ch; target_geom.height = (int32_t)fl_ch;
client_tile_resize(c, c->geom, 0); client_tile_resize(c, target_geom, 0);
i++; i++;
} }
} }

View file

@ -1073,7 +1073,7 @@ static struct wl_listener last_cursor_surface_destroy_listener = {
.notify = last_cursor_surface_destroy}; .notify = last_cursor_surface_destroy};
#ifdef XWAYLAND #ifdef XWAYLAND
static void fix_xwayland_unmanaged_coordinate(Client *c); static void fix_xwayland_coordinate(struct wlr_box *geom);
static int32_t synckeymap(void *data); static int32_t synckeymap(void *data);
static void activatex11(struct wl_listener *listener, void *data); static void activatex11(struct wl_listener *listener, void *data);
static void configurex11(struct wl_listener *listener, void *data); static void configurex11(struct wl_listener *listener, void *data);
@ -1615,7 +1615,7 @@ void applyrules(Client *c) {
#ifdef XWAYLAND #ifdef XWAYLAND
if (c->isfloating && client_is_x11(c)) { if (c->isfloating && client_is_x11(c)) {
fix_xwayland_unmanaged_coordinate(c); fix_xwayland_coordinate(&c->geom);
c->float_geom = c->geom; c->float_geom = c->geom;
} }
#endif #endif
@ -3140,7 +3140,6 @@ void createlayersurface(struct wl_listener *listener, void *data) {
LISTEN(&l->scene->node.events.destroy, &l->destroy, destroylayernodenotify); LISTEN(&l->scene->node.events.destroy, &l->destroy, destroylayernodenotify);
wl_list_insert(&l->mon->layers[layer_surface->pending.layer], &l->link); wl_list_insert(&l->mon->layers[layer_surface->pending.layer], &l->link);
wlr_surface_send_enter(surface, layer_surface->output);
} }
void createlocksurface(struct wl_listener *listener, void *data) { void createlocksurface(struct wl_listener *listener, void *data) {
@ -4206,6 +4205,11 @@ void keypress(struct wl_listener *listener, void *data) {
} }
} }
if (config.cursor_hide_on_keypress && !cursor_hidden &&
event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
hidecursor(NULL);
}
/* On _press_ if there is no active screen locker, /* On _press_ if there is no active screen locker,
* attempt to process a compositor keybinding. */ * attempt to process a compositor keybinding. */
for (i = 0; i < nsyms; i++) for (i = 0; i < nsyms; i++)
@ -4469,24 +4473,24 @@ mapnotify(struct wl_listener *listener, void *data) {
/* Handle unmanaged clients first so we can return prior create borders /* Handle unmanaged clients first so we can return prior create borders
*/ */
#ifdef XWAYLAND
if (client_is_unmanaged(c)) { if (client_is_unmanaged(c)) {
/* Unmanaged clients always are floating */ /* Unmanaged clients always are floating */
#ifdef XWAYLAND fix_xwayland_coordinate(&c->geom);
if (client_is_x11(c)) {
fix_xwayland_unmanaged_coordinate(c);
LISTEN(&c->surface.xwayland->events.set_geometry, &c->set_geometry,
setgeometrynotify);
}
#endif
wlr_scene_node_reparent(&c->scene->node, layers[LyrOverlay]);
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x,
c->geom.y, c->geom.width,
c->geom.height);
LISTEN(&c->surface.xwayland->events.set_geometry, &c->set_geometry,
setgeometrynotify);
wlr_scene_node_reparent(&c->scene->node, layers[LyrOverlay]);
if (client_wants_focus(c)) { if (client_wants_focus(c)) {
focusclient(c, 1); focusclient(c, 1);
exclusive_focus = c; exclusive_focus = c;
} }
return; return;
} }
#endif
// extra node // extra node
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
@ -4808,7 +4812,8 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
if (!surface && !seat->drag && !cursor_hidden) if (!surface && !seat->drag && !cursor_hidden)
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
if (c && c->mon && !c->animation.running && (INSIDEMON(c) || !ISTILED(c))) { if (c && c->mon && !c->animation.running &&
(INSIDEMON(c) || !ISSCROLLTILED(c))) {
scroller_focus_lock = 0; scroller_focus_lock = 0;
} }
@ -4820,13 +4825,15 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
} }
if (!scroller_focus_lock || !(c && c->mon && !INSIDEMON(c))) { if (!scroller_focus_lock || !(c && c->mon && !INSIDEMON(c))) {
if (c && c->mon && is_scroller_layout(c->mon) && !INSIDEMON(c)) { if (c && c->mon && ISSCROLLTILED(c) && is_scroller_layout(c->mon) &&
!INSIDEMON(c)) {
should_lock = true; should_lock = true;
} }
if (!((!config.edge_scroller_pointer_focus || if (!((!config.edge_scroller_pointer_focus ||
speed < config.edge_scroller_focus_allow_speed) && speed < config.edge_scroller_focus_allow_speed) &&
c && c->mon && is_scroller_layout(c->mon) && !INSIDEMON(c))) { c && c->mon && ISSCROLLTILED(c) && is_scroller_layout(c->mon) &&
!INSIDEMON(c))) {
pointerfocus(c, surface, sx, sy, time); pointerfocus(c, surface, sx, sy, time);
} }
@ -6825,16 +6832,17 @@ void virtualpointer(struct wl_listener *listener, void *data) {
} }
#ifdef XWAYLAND #ifdef XWAYLAND
void fix_xwayland_unmanaged_coordinate(Client *c) { void fix_xwayland_coordinate(struct wlr_box *geom) {
if (!selmon) if (!selmon)
return; return;
// 1. 如果窗口已经在当前活动显示器内,直接返回 // 1. 如果窗口已经在当前活动显示器内,直接返回
if (c->geom.x >= selmon->m.x && c->geom.x < selmon->m.x + selmon->m.width && if (geom->x >= selmon->m.x && geom->x <= selmon->m.x + selmon->m.width &&
c->geom.y >= selmon->m.y && c->geom.y < selmon->m.y + selmon->m.height) geom->y >= selmon->m.y && geom->y <= selmon->m.y + selmon->m.height)
return; return;
c->geom = setclient_coordinate_center(c, selmon, c->geom, 0, 0); geom->x = selmon->m.x + (selmon->m.width - geom->width) / 2;
geom->y = selmon->m.y + (selmon->m.height - geom->height) / 2;
} }
int32_t synckeymap(void *data) { int32_t synckeymap(void *data) {
@ -6889,24 +6897,41 @@ void activatex11(struct wl_listener *listener, void *data) {
void configurex11(struct wl_listener *listener, void *data) { void configurex11(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, configure); Client *c = wl_container_of(listener, c, configure);
struct wlr_xwayland_surface_configure_event *event = data; struct wlr_xwayland_surface_configure_event *event = data;
struct wlr_box new_geo;
new_geo.x = event->x;
new_geo.y = event->y;
new_geo.width = event->width;
new_geo.height = event->height;
fix_xwayland_coordinate(&new_geo);
if (!client_surface(c) || !client_surface(c)->mapped) { if (!client_surface(c) || !client_surface(c)->mapped) {
wlr_xwayland_surface_configure(c->surface.xwayland, event->x, event->y,
event->width, event->height); wlr_xwayland_surface_configure(c->surface.xwayland, new_geo.x,
new_geo.y, new_geo.width,
new_geo.height);
return; return;
} }
if (client_is_unmanaged(c)) { if (client_is_unmanaged(c)) {
wlr_scene_node_set_position(&c->scene->node, event->x, event->y); wlr_scene_node_set_position(&c->scene->node, new_geo.x, new_geo.y);
wlr_xwayland_surface_configure(c->surface.xwayland, event->x, event->y, wlr_xwayland_surface_configure(c->surface.xwayland, new_geo.x,
event->width, event->height); new_geo.y, new_geo.width,
new_geo.height);
return; return;
} }
if ((c->isfloating && c != grabc) ||
!c->mon->pertag->ltidxs[c->mon->pertag->curtag]->arrange) { if (c->isfloating && c != grabc) {
new_geo.x = new_geo.x - c->bw;
new_geo.y = new_geo.y - c->bw;
new_geo.width = new_geo.width + c->bw * 2;
new_geo.height = new_geo.height + c->bw * 2;
fix_xwayland_coordinate(&new_geo);
resize(c, resize(c,
(struct wlr_box){.x = event->x - c->bw, (struct wlr_box){.x = new_geo.x,
.y = event->y - c->bw, .y = new_geo.y,
.width = event->width + c->bw * 2, .width = new_geo.width,
.height = event->height + c->bw * 2}, .height = new_geo.height},
0); 0);
} else { } else {
arrange(c->mon, false, false); arrange(c->mon, false, false);