Merge branch 'mangowm:main' into main

This commit is contained in:
Ananya 2026-03-06 16:46:19 +01:00 committed by GitHub
commit 0931581e92
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 280 additions and 115 deletions

View file

@ -16,7 +16,7 @@ jobs:
days-before-issue-stale: -1
# 手动标记后14 天后关闭
days-before-issue-close: 7
# 使用的标签(必须和你手动添加的标签一致)
# 使用的标签
stale-issue-label: "stale"
# 自动关闭时自动加上的标签
close-issue-label: "automatic-closing"

View file

@ -78,7 +78,8 @@ typedef struct {
int32_t ignore_maximize;
int32_t ignore_minimize;
int32_t isnosizehint;
const char *monitor;
int32_t indleinhibit_when_focus;
char *monitor;
int32_t offsetx;
int32_t offsety;
int32_t width;
@ -111,6 +112,7 @@ typedef struct {
int32_t width, height; // Monitor resolution
float refresh; // Refresh rate
int32_t vrr; // variable refresh rate
int32_t custom; // enable custom mode
} ConfigMonitorRule;
// 修改后的宏定义
@ -1795,6 +1797,7 @@ bool parse_option(Config *config, char *key, char *value) {
rule->height = -1;
rule->refresh = 0.0f;
rule->vrr = 0;
rule->custom = 0;
bool parse_error = false;
char *token = strtok(value, ",");
@ -1832,6 +1835,8 @@ bool parse_option(Config *config, char *key, char *value) {
rule->refresh = CLAMP_FLOAT(atof(val), 0.001f, 1000.0f);
} else if (strcmp(key, "vrr") == 0) {
rule->vrr = CLAMP_INT(atoi(val), 0, 1);
} else if (strcmp(key, "custom") == 0) {
rule->custom = CLAMP_INT(atoi(val), 0, 1);
} else {
fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m Unknown "
@ -2022,6 +2027,7 @@ bool parse_option(Config *config, char *key, char *value) {
rule->ignore_maximize = -1;
rule->ignore_minimize = -1;
rule->isnosizehint = -1;
rule->indleinhibit_when_focus = -1;
rule->isterm = -1;
rule->allow_csd = -1;
rule->force_maximize = -1;
@ -2132,6 +2138,8 @@ bool parse_option(Config *config, char *key, char *value) {
rule->ignore_minimize = atoi(val);
} else if (strcmp(key, "isnosizehint") == 0) {
rule->isnosizehint = atoi(val);
} else if (strcmp(key, "indleinhibit_when_focus") == 0) {
rule->indleinhibit_when_focus = atoi(val);
} else if (strcmp(key, "isterm") == 0) {
rule->isterm = atoi(val);
} else if (strcmp(key, "allow_csd") == 0) {
@ -3551,7 +3559,7 @@ void reset_blur_params(void) {
void reapply_monitor_rules(void) {
ConfigMonitorRule *mr;
Monitor *m = NULL;
int32_t ji, vrr;
int32_t ji, vrr, custom;
int32_t mx, my;
struct wlr_output_state state;
struct wlr_output_mode *internal_mode = NULL;
@ -3605,13 +3613,15 @@ void reapply_monitor_rules(void) {
mx = mr->x == INT32_MAX ? m->m.x : mr->x;
my = mr->y == INT32_MAX ? m->m.y : mr->y;
vrr = mr->vrr >= 0 ? mr->vrr : 0;
custom = mr->custom >= 0 ? mr->custom : 0;
if (mr->width > 0 && mr->height > 0 && mr->refresh > 0) {
internal_mode = get_nearest_output_mode(
m->wlr_output, mr->width, mr->height, mr->refresh);
if (internal_mode) {
wlr_output_state_set_mode(&state, internal_mode);
} else if (wlr_output_is_headless(m->wlr_output)) {
} else if (custom ||
wlr_output_is_headless(m->wlr_output)) {
wlr_output_state_set_custom_mode(
&state, mr->width, mr->height,
(int32_t)roundf(mr->refresh * 1000));
@ -3637,10 +3647,10 @@ void reapply_monitor_rules(void) {
}
void reapply_cursor_style(void) {
if (hide_source) {
wl_event_source_timer_update(hide_source, 0);
wl_event_source_remove(hide_source);
hide_source = NULL;
if (hide_cursor_source) {
wl_event_source_timer_update(hide_cursor_source, 0);
wl_event_source_remove(hide_cursor_source);
hide_cursor_source = NULL;
}
wlr_cursor_unset_image(cursor);
@ -3671,12 +3681,13 @@ void reapply_cursor_style(void) {
wlr_cursor_set_xcursor(cursor, cursor_mgr, "left_ptr");
hide_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy),
hidecursor, cursor);
hide_cursor_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy),
hidecursor, cursor);
if (cursor_hidden) {
wlr_cursor_unset_image(cursor);
} else {
wl_event_source_timer_update(hide_source, cursor_hide_timeout * 1000);
wl_event_source_timer_update(hide_cursor_source,
cursor_hide_timeout * 1000);
}
}

View file

@ -110,7 +110,9 @@ int32_t exchange_client(const Arg *arg) {
if ((c->isfullscreen || c->ismaximizescreen) && !is_scroller_layout(c->mon))
return 0;
exchange_two_client(c, direction_select(arg));
Client *tc = direction_select(arg);
tc = get_focused_stack_client(tc);
exchange_two_client(c, tc);
return 0;
}

View file

@ -1,11 +1,41 @@
void save_old_size_per(Monitor *m) {
Client *c = NULL;
wl_list_for_each(c, &clients, link) {
if (VISIBLEON(c, m) && ISTILED(c)) {
c->old_master_inner_per = c->master_inner_per;
c->old_stack_inner_per = c->stack_inner_per;
} else {
if (c->old_master_inner_per <= 0.0f ||
c->old_master_inner_per > 1.0f) {
c->old_master_inner_per = 1.0f;
}
if (c->old_stack_inner_per <= 0.0f ||
c->old_stack_inner_per > 1.0f) {
c->old_stack_inner_per = 1.0f;
}
}
}
}
void restore_size_per(Monitor *m, Client *c) {
Client *fc = NULL;
double total_master_inner_per = 0;
double total_stack_inner_per = 0;
if (!m || !c)
return;
wl_list_for_each(fc, &clients, link) {
if (VISIBLEON(fc, m) && ISTILED(fc)) {
fc->old_ismaster = fc->ismaster;
}
}
c->old_master_inner_per = c->master_inner_per;
c->old_stack_inner_per = c->stack_inner_per;
pre_caculate_before_arrange(m, false, false, true);
const Layout *current_layout = m->pertag->ltidxs[m->pertag->curtag];
if (current_layout->id == SCROLLER ||
@ -15,7 +45,7 @@ void restore_size_per(Monitor *m, Client *c) {
return;
}
if (current_layout->id == CENTER_TILE || c->ismaster) {
if (current_layout->id == CENTER_TILE) {
wl_list_for_each(fc, &clients, link) {
if (VISIBLEON(fc, m) && ISTILED(fc) && !c->ismaster) {
set_size_per(m, fc);
@ -24,19 +54,32 @@ void restore_size_per(Monitor *m, Client *c) {
return;
}
wl_list_for_each(fc, &clients, link) {
if (VISIBLEON(fc, m) && ISTILED(fc) && fc != c) {
if (fc->ismaster) {
total_master_inner_per += fc->master_inner_per;
} else {
total_stack_inner_per += fc->stack_inner_per;
}
}
if (!c->ismaster && c->old_stack_inner_per < 1.0 &&
c->old_stack_inner_per > 0.0f && c->stack_inner_per < 1.0 &&
c->stack_inner_per > 0.0f) {
c->stack_inner_per = (1.0 - c->stack_inner_per) *
c->old_stack_inner_per /
(1.0 - c->old_stack_inner_per);
}
if (!c->ismaster && total_stack_inner_per) {
c->stack_inner_per = total_stack_inner_per * c->stack_inner_per /
(1 - c->stack_inner_per);
if (c->ismaster && c->old_master_inner_per < 1.0 &&
c->old_master_inner_per > 0.0f && c->master_inner_per < 1.0 &&
c->master_inner_per > 0.0f) {
c->master_inner_per = (1.0 - c->master_inner_per) *
c->old_master_inner_per /
(1.0 - c->old_master_inner_per);
}
wl_list_for_each(fc, &clients, link) {
if (VISIBLEON(fc, m) && ISTILED(fc) && fc != c && !fc->ismaster &&
fc->old_ismaster && fc->old_stack_inner_per < 1.0 &&
fc->old_stack_inner_per > 0.0f && fc->stack_inner_per < 1.0 &&
fc->stack_inner_per > 0.0f) {
fc->stack_inner_per = (1.0 - fc->stack_inner_per) *
fc->old_stack_inner_per /
(1.0 - fc->old_stack_inner_per);
fc->old_ismaster = false;
}
}
}
@ -90,8 +133,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
break;
}
if (!begin_find_nextnext && VISIBLEON(tc, grabc->mon) &&
ISTILED(tc)) { // 根据你的实际字段名调整
if (!begin_find_nextnext && VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
next = tc;
begin_find_nextnext = true;
continue;
@ -107,8 +149,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
break;
}
if (!begin_find_prevprev && VISIBLEON(tc, grabc->mon) &&
ISTILED(tc)) { // 根据你的实际字段名调整
if (!begin_find_prevprev && VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
prev = tc;
begin_find_prevprev = true;
continue;
@ -276,8 +317,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
for (node = grabc->link.next; node != &clients; node = node->next) {
tc = wl_container_of(node, tc, link);
if (VISIBLEON(tc, grabc->mon) &&
ISTILED(tc)) { // 根据你的实际字段名调整
if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
next = tc;
break;
}
@ -287,8 +327,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
for (node = grabc->link.prev; node != &clients; node = node->prev) {
tc = wl_container_of(node, tc, link);
if (VISIBLEON(tc, grabc->mon) &&
ISTILED(tc)) { // 根据你的实际字段名调整
if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) {
prev = tc;
break;
}
@ -705,8 +744,8 @@ void reset_size_per_mon(Monitor *m, int32_t tile_cilent_num,
}
}
void // 17
arrange(Monitor *m, bool want_animation, bool from_view) {
void pre_caculate_before_arrange(Monitor *m, bool want_animation,
bool from_view, bool only_caculate) {
Client *c = NULL;
double total_stack_inner_percent = 0;
double total_master_inner_percent = 0;
@ -795,14 +834,17 @@ arrange(Monitor *m, bool want_animation, bool from_view) {
i++;
}
set_arrange_visible(m, c, want_animation);
if (!only_caculate)
set_arrange_visible(m, c, want_animation);
} else {
set_arrange_hidden(m, c, want_animation);
if (!only_caculate)
set_arrange_hidden(m, c, want_animation);
}
}
if (c->mon == m && c->ismaximizescreen && !c->animation.tagouted &&
!c->animation.tagouting && VISIBLEON(c, m)) {
if (!only_caculate && c->mon == m && c->ismaximizescreen &&
!c->animation.tagouted && !c->animation.tagouting &&
VISIBLEON(c, m)) {
reset_maximizescreen_size(c);
}
}
@ -811,6 +853,12 @@ arrange(Monitor *m, bool want_animation, bool from_view) {
m, m->visible_tiling_clients, total_left_stack_hight_percent,
total_right_stack_hight_percent, total_stack_inner_percent,
total_master_inner_percent, master_num, stack_num);
}
void // 17
arrange(Monitor *m, bool want_animation, bool from_view) {
pre_caculate_before_arrange(m, want_animation, from_view, false);
if (m->isoverview) {
overviewlayout.arrange(m);

View file

@ -347,7 +347,7 @@ struct Client {
struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel;
int32_t isfloating, isurgent, isfullscreen, isfakefullscreen,
need_float_size_reduce, isminimized, isoverlay, isnosizehint,
ignore_maximize, ignore_minimize;
ignore_maximize, ignore_minimize, indleinhibit_when_focus;
int32_t ismaximizescreen;
int32_t overview_backup_bw;
int32_t fullscreen_backup_x, fullscreen_backup_y, fullscreen_backup_w,
@ -412,6 +412,7 @@ struct Client {
double old_master_mfact_per, old_master_inner_per, old_stack_inner_per;
double old_scroller_pproportion;
bool ismaster;
bool old_ismaster;
bool cursor_in_upper_half, cursor_in_left_half;
bool isleftstack;
int32_t tearing_hint;
@ -488,7 +489,6 @@ typedef struct {
typedef struct {
struct wlr_xdg_popup *wlr_popup;
uint32_t type;
struct wl_listener destroy;
struct wl_listener commit;
struct wl_listener reposition;
@ -800,6 +800,12 @@ static void monitor_stop_skip_frame_timer(Monitor *m);
static int monitor_skip_frame_timeout_callback(void *data);
static Monitor *get_monitor_nearest_to(int32_t lx, int32_t ly);
static bool match_monitor_spec(char *spec, Monitor *m);
static void last_cursor_surface_destroy(struct wl_listener *listener,
void *data);
static int32_t keep_idle_inhibit(void *data);
static void check_keep_idle_inhibit(Client *c);
static void pre_caculate_before_arrange(Monitor *m, bool want_animation,
bool from_view, bool only_caculate);
#include "data/static_keymap.h"
#include "dispatch/bind_declare.h"
@ -896,7 +902,8 @@ struct dvec2 *baked_points_focus;
struct dvec2 *baked_points_opafadein;
struct dvec2 *baked_points_opafadeout;
static struct wl_event_source *hide_source;
static struct wl_event_source *hide_cursor_source;
static struct wl_event_source *keep_idle_inhibit_source;
static bool cursor_hidden = false;
static bool tag_combo = false;
static const char *cli_config_path = NULL;
@ -964,6 +971,8 @@ static struct wl_listener new_session_lock = {.notify = locksession};
static struct wl_listener drm_lease_request = {.notify = requestdrmlease};
static struct wl_listener keyboard_shortcuts_inhibit_new_inhibitor = {
.notify = handle_keyboard_shortcuts_inhibit_new_inhibitor};
static struct wl_listener last_cursor_surface_destroy_listener = {
.notify = last_cursor_surface_destroy};
#ifdef XWAYLAND
static void fix_xwayland_unmanaged_coordinate(Client *c);
@ -1331,6 +1340,7 @@ static void apply_rule_properties(Client *c, const ConfigWinRule *r) {
APPLY_INT_PROP(c, r, ignore_maximize);
APPLY_INT_PROP(c, r, ignore_minimize);
APPLY_INT_PROP(c, r, isnosizehint);
APPLY_INT_PROP(c, r, indleinhibit_when_focus);
APPLY_INT_PROP(c, r, isunglobal);
APPLY_INT_PROP(c, r, noblur);
APPLY_INT_PROP(c, r, allow_shortcuts_inhibit);
@ -1435,7 +1445,7 @@ void applyrules(Client *c) {
// set monitor of client
wl_list_for_each(m, &mons, link) {
if (regex_match(r->monitor, m->wlr_output->name)) {
if (match_monitor_spec(r->monitor, m)) {
mon = m;
}
}
@ -1690,9 +1700,10 @@ void focuslayer(LayerSurface *l) {
client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat));
}
void reset_exclusive_layer(Monitor *m) {
void reset_exclusive_layers_focus(Monitor *m) {
LayerSurface *l = NULL;
int32_t i;
bool neet_change_focus_to_client = false;
uint32_t layers_above_shell[] = {
ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
ZWLR_LAYER_SHELL_V1_LAYER_TOP,
@ -1703,28 +1714,47 @@ void reset_exclusive_layer(Monitor *m) {
return;
for (i = 0; i < (int32_t)LENGTH(layers_above_shell); i++) {
wl_list_for_each_reverse(l, &m->layers[layers_above_shell[i]], link) {
wl_list_for_each(l, &m->layers[layers_above_shell[i]], link) {
if (l == exclusive_focus &&
l->layer_surface->current.keyboard_interactive !=
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) {
exclusive_focus = NULL;
neet_change_focus_to_client = true;
}
if (l->layer_surface->surface ==
seat->keyboard_state.focused_surface &&
l->being_unmapped) {
neet_change_focus_to_client = true;
}
if (l->layer_surface->current.keyboard_interactive ==
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
l->layer_surface->surface ==
seat->keyboard_state.focused_surface)
focusclient(focustop(selmon), 1);
seat->keyboard_state.focused_surface) {
neet_change_focus_to_client = true;
}
if (locked ||
l->layer_surface->current.keyboard_interactive !=
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE ||
!l->mapped || l == exclusive_focus)
l->being_unmapped)
continue;
/* Deactivate the focused client. */
exclusive_focus = l;
focuslayer(l);
neet_change_focus_to_client = false;
if (l->layer_surface->surface !=
seat->keyboard_state.focused_surface)
focuslayer(l);
return;
}
}
if (neet_change_focus_to_client) {
focusclient(focustop(selmon), 1);
}
}
void arrangelayers(Monitor *m) {
@ -1746,9 +1776,6 @@ void arrangelayers(Monitor *m) {
/* Arrange non-exlusive surfaces from top->bottom */
for (i = 3; i >= 0; i--)
arrangelayer(m, &m->layers[i], &usable_area, 0);
/* Find topmost keyboard interactive layer, if such a layer exists */
reset_exclusive_layer(m);
}
void // 鼠标滚轮事件
@ -2133,6 +2160,11 @@ void checkidleinhibitor(struct wlr_surface *exclude) {
wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited);
}
void last_cursor_surface_destroy(struct wl_listener *listener, void *data) {
last_cursor.surface = NULL;
wl_list_remove(&listener->link);
}
void setcursorshape(struct wl_listener *listener, void *data) {
struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
@ -2141,6 +2173,11 @@ void setcursorshape(struct wl_listener *listener, void *data) {
* actually has pointer focus first. If so, we can tell the cursor to
* use the provided cursor shape. */
if (event->seat_client == seat->pointer_state.focused_client) {
/* Remove surface destroy listener if active */
if (last_cursor.surface &&
last_cursor_surface_destroy_listener.link.prev != NULL)
wl_list_remove(&last_cursor_surface_destroy_listener.link);
last_cursor.shape = event->shape;
last_cursor.surface = NULL;
if (!cursor_hidden)
@ -2384,13 +2421,7 @@ void maplayersurfacenotify(struct wl_listener *listener, void *data) {
}
// 刷新布局让窗口能感应到exclude_zone变化以及设置独占表面
arrangelayers(l->mon);
// 按需交互layer需要像正常窗口一样抢占非独占layer的焦点
if (!exclusive_focus &&
l->layer_surface->current.keyboard_interactive ==
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) {
focuslayer(l);
}
reset_exclusive_layers_focus(l->mon);
}
void commitlayersurfacenotify(struct wl_listener *listener, void *data) {
@ -2410,7 +2441,12 @@ void commitlayersurfacenotify(struct wl_listener *listener, void *data) {
l->layer_surface->current = l->layer_surface->pending;
arrangelayers(l->mon);
l->layer_surface->current = old_state;
// 按需交互layer只在map之前设置焦点
if (!exclusive_focus &&
l->layer_surface->current.keyboard_interactive ==
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) {
focuslayer(l);
}
return;
}
@ -2455,28 +2491,31 @@ void commitlayersurfacenotify(struct wl_listener *listener, void *data) {
layer_flush_blur_background(l);
if (layer_surface == exclusive_focus &&
layer_surface->current.keyboard_interactive !=
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
exclusive_focus = NULL;
if (layer_surface->current.committed == 0 &&
l->mapped == layer_surface->surface->mapped)
return;
l->mapped = layer_surface->surface->mapped;
if (scene_layer != l->scene->node.parent) {
wlr_scene_node_reparent(&l->scene->node, scene_layer);
wl_list_remove(&l->link);
wl_list_insert(&l->mon->layers[layer_surface->current.layer], &l->link);
wlr_scene_node_reparent(
&l->popups->node,
(layer_surface->current.layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP
? layers[LyrTop]
: scene_layer));
if (layer_surface->current.committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
if (scene_layer != l->scene->node.parent) {
wlr_scene_node_reparent(&l->scene->node, scene_layer);
wl_list_remove(&l->link);
wl_list_insert(&l->mon->layers[layer_surface->current.layer],
&l->link);
wlr_scene_node_reparent(
&l->popups->node,
(layer_surface->current.layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP
? layers[LyrTop]
: scene_layer));
}
}
arrangelayers(l->mon);
if (layer_surface->current.committed &
WLR_LAYER_SURFACE_V1_STATE_KEYBOARD_INTERACTIVITY) {
reset_exclusive_layers_focus(l->mon);
}
}
void commitnotify(struct wl_listener *listener, void *data) {
@ -2554,6 +2593,9 @@ void destroydecoration(struct wl_listener *listener, void *data) {
static void popup_unconstrain(Popup *popup) {
struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
Client *c = NULL;
LayerSurface *l = NULL;
int32_t type = -1;
if (!wlr_popup || !wlr_popup->parent) {
return;
@ -2564,16 +2606,17 @@ static void popup_unconstrain(Popup *popup) {
wlr_log(WLR_ERROR, "Popup parent has no scene node");
return;
}
type = toplevel_from_wlr_surface(wlr_popup->base->surface, &c, &l);
if ((l && !l->mon) || (c && !c->mon)) {
wlr_xdg_popup_destroy(wlr_popup);
return;
}
int parent_lx, parent_ly;
wlr_scene_node_coords(parent_node, &parent_lx, &parent_ly);
struct wlr_box *scheduled = &wlr_popup->scheduled.geometry;
int popup_lx = parent_lx + scheduled->x;
int popup_ly = parent_ly + scheduled->y;
Monitor *mon = get_monitor_nearest_to(popup_lx, popup_ly);
struct wlr_box usable = popup->type == LayerShell ? mon->m : mon->w;
struct wlr_box usable = type == LayerShell ? l->mon->m : c->mon->w;
struct wlr_box constraint_box = {
.x = usable.x - parent_lx,
@ -2596,33 +2639,22 @@ static void commitpopup(struct wl_listener *listener, void *data) {
Popup *popup = wl_container_of(listener, popup, commit);
struct wlr_surface *surface = data;
struct wlr_xdg_popup *wkr_popup =
struct wlr_xdg_popup *wlr_popup =
wlr_xdg_popup_try_from_wlr_surface(surface);
Client *c = NULL;
LayerSurface *l = NULL;
int32_t type = -1;
if (!wkr_popup || !wkr_popup->base->initial_commit)
if (!wlr_popup || !wlr_popup->base->initial_commit)
goto commitpopup_listen_free;
type = toplevel_from_wlr_surface(wkr_popup->base->surface, &c, &l);
if (!wkr_popup->parent || !wkr_popup->parent->data || type < 0) {
wlr_xdg_popup_destroy(wkr_popup);
if (!wlr_popup->parent || !wlr_popup->parent->data) {
goto commitpopup_listen_free;
}
wlr_scene_node_raise_to_top(wkr_popup->parent->data);
wlr_scene_node_raise_to_top(wlr_popup->parent->data);
wkr_popup->base->surface->data =
wlr_scene_xdg_surface_create(wkr_popup->parent->data, wkr_popup->base);
if ((l && !l->mon) || (c && !c->mon)) {
wlr_xdg_popup_destroy(wkr_popup);
goto commitpopup_listen_free;
}
wlr_popup->base->surface->data =
wlr_scene_xdg_surface_create(wlr_popup->parent->data, wlr_popup->base);
popup->type = type;
popup->wlr_popup = wkr_popup;
popup->wlr_popup = wlr_popup;
popup_unconstrain(popup);
@ -2852,7 +2884,7 @@ void createmon(struct wl_listener *listener, void *data) {
struct wlr_output *wlr_output = data;
const ConfigMonitorRule *r;
uint32_t i;
int32_t ji, vrr;
int32_t ji, vrr, custom;
struct wlr_output_state state;
Monitor *m = NULL;
struct wlr_output_mode *internal_mode = NULL;
@ -2944,6 +2976,7 @@ void createmon(struct wl_listener *listener, void *data) {
m->m.x = r->x == INT32_MAX ? INT32_MAX : r->x;
m->m.y = r->y == INT32_MAX ? INT32_MAX : r->y;
vrr = r->vrr >= 0 ? r->vrr : 0;
custom = r->custom >= 0 ? r->custom : 0;
scale = r->scale;
rr = r->rr;
@ -2953,7 +2986,7 @@ void createmon(struct wl_listener *listener, void *data) {
if (internal_mode) {
custom_monitor_mode = true;
wlr_output_state_set_mode(&state, internal_mode);
} else if (wlr_output_is_headless(m->wlr_output)) {
} else if (custom || wlr_output_is_headless(m->wlr_output)) {
custom_monitor_mode = true;
wlr_output_state_set_custom_mode(
&state, r->width, r->height,
@ -3335,8 +3368,7 @@ void destroylocksurface(struct wl_listener *listener, void *data) {
if (lock_surface->surface != seat->keyboard_state.focused_surface) {
if (exclusive_focus && !locked) {
exclusive_focus = NULL;
reset_exclusive_layer(m);
reset_exclusive_layers_focus(m);
}
return;
}
@ -3345,9 +3377,7 @@ void destroylocksurface(struct wl_listener *listener, void *data) {
surface = wl_container_of(cur_lock->surfaces.next, surface, link);
client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat));
} else if (!locked) {
exclusive_focus = NULL;
reset_exclusive_layer(selmon);
focusclient(focustop(selmon), 1);
reset_exclusive_layers_focus(selmon);
} else {
wlr_seat_keyboard_clear_focus(seat);
}
@ -3452,6 +3482,8 @@ void focusclient(Client *c, int32_t lift) {
selmon->sel = c;
c->isfocusing = true;
check_keep_idle_inhibit(c);
if (last_focus_client && !last_focus_client->iskilling &&
last_focus_client != c) {
last_focus_client->isfocusing = false;
@ -3953,6 +3985,7 @@ void init_client_properties(Client *c) {
c->swallowing = NULL;
c->swallowedby = NULL;
c->ismaster = 0;
c->old_ismaster = 0;
c->isleftstack = 0;
c->ismaximizescreen = 0;
c->isfullscreen = 0;
@ -3993,12 +4026,16 @@ void init_client_properties(Client *c) {
c->master_mfact_per = 0.0f;
c->master_inner_per = 0.0f;
c->stack_inner_per = 0.0f;
c->old_stack_inner_per = 0.0f;
c->old_master_inner_per = 0.0f;
c->old_master_mfact_per = 0.0f;
c->isterm = 0;
c->allow_csd = 0;
c->force_maximize = 0;
c->force_tiled_state = 1;
c->force_tearing = 0;
c->allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
c->indleinhibit_when_focus = 0;
c->scroller_proportion_single = 0.0f;
c->float_geom.width = 0;
c->float_geom.height = 0;
@ -4794,6 +4831,11 @@ void exchange_two_client(Client *c1, Client *c2) {
} else {
arrange(c1->mon, false, false);
}
// In order to facilitate repeated exchanges for get_focused_stack_client
// set c2 focus order behind c1
wl_list_remove(&c2->flink);
wl_list_insert(&c1->flink, &c2->flink);
}
void set_activation_env() {
@ -4918,10 +4960,21 @@ void setcursor(struct wl_listener *listener, void *data) {
* hardware cursor on the output that it's currently on and continue to
* do so as the cursor moves between outputs. */
if (event->seat_client == seat->pointer_state.focused_client) {
/* Clear previous surface destroy listener if any */
if (last_cursor.surface &&
last_cursor_surface_destroy_listener.link.prev != NULL)
wl_list_remove(&last_cursor_surface_destroy_listener.link);
last_cursor.shape = 0;
last_cursor.surface = event->surface;
last_cursor.hotspot_x = event->hotspot_x;
last_cursor.hotspot_y = event->hotspot_y;
/* Track surface destruction to avoid dangling pointer */
if (event->surface)
wl_signal_add(&event->surface->events.destroy,
&last_cursor_surface_destroy_listener);
if (!cursor_hidden)
wlr_cursor_set_surface(cursor, event->surface, event->hotspot_x,
event->hotspot_y);
@ -5007,6 +5060,10 @@ setfloating(Client *c, int32_t floating) {
restore_size_per(c->mon, c);
}
if (c->isfloating && !old_floating_state) {
save_old_size_per(c->mon);
}
if (!c->force_maximize)
client_set_maximized(c, false);
@ -5093,6 +5150,10 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
restore_size_per(c->mon, c);
}
if (c->ismaximizescreen && !old_maximizescreen_state) {
save_old_size_per(c->mon);
}
if (!c->force_maximize && !c->ismaximizescreen) {
client_set_maximized(c, false);
} else if (!c->force_maximize && c->ismaximizescreen) {
@ -5164,6 +5225,10 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自
restore_size_per(c->mon, c);
}
if (c->isfullscreen && !old_fullscreen_state) {
save_old_size_per(c->mon);
}
arrange(c->mon, false, false);
}
@ -5523,6 +5588,9 @@ void setup(void) {
idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy);
wl_signal_add(&idle_inhibit_mgr->events.new_inhibitor, &new_idle_inhibitor);
keep_idle_inhibit_source = wl_event_loop_add_timer(
wl_display_get_event_loop(dpy), keep_idle_inhibit, NULL);
layer_shell = wlr_layer_shell_v1_create(dpy, 4);
wl_signal_add(&layer_shell->events.new_surface, &new_layer_surface);
@ -5590,8 +5658,8 @@ void setup(void) {
cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
wl_signal_add(&cursor_shape_mgr->events.request_set_shape,
&request_set_cursor_shape);
hide_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy),
hidecursor, cursor);
hide_cursor_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy),
hidecursor, cursor);
/*
* Configures a seat, which is a single "seat" at which a user sits and
* operates the computer. This conceptually includes up to one keyboard,
@ -5619,6 +5687,8 @@ void setup(void) {
LISTEN_STATIC(&cursor->events.hold_end, hold_end);
seat = wlr_seat_create(dpy, "seat0");
wl_list_init(&last_cursor_surface_destroy_listener.link);
wl_signal_add(&seat->events.request_set_cursor, &request_cursor);
wl_signal_add(&seat->events.request_set_selection, &request_set_sel);
wl_signal_add(&seat->events.request_set_primary_selection,
@ -5808,7 +5878,8 @@ void overview_restore(Client *c, const Arg *arg) {
}
void handlecursoractivity(void) {
wl_event_source_timer_update(hide_source, cursor_hide_timeout * 1000);
wl_event_source_timer_update(hide_cursor_source,
cursor_hide_timeout * 1000);
if (!cursor_hidden)
return;
@ -5818,7 +5889,7 @@ void handlecursoractivity(void) {
if (last_cursor.shape)
wlr_cursor_set_xcursor(cursor, cursor_mgr,
wlr_cursor_shape_v1_name(last_cursor.shape));
else
else if (last_cursor.surface)
wlr_cursor_set_surface(cursor, last_cursor.surface,
last_cursor.hotspot_x, last_cursor.hotspot_y);
}
@ -5829,6 +5900,36 @@ int32_t hidecursor(void *data) {
return 1;
}
void check_keep_idle_inhibit(Client *c) {
if (c && c->indleinhibit_when_focus && keep_idle_inhibit_source) {
wl_event_source_timer_update(keep_idle_inhibit_source, 1000);
}
}
int32_t keep_idle_inhibit(void *data) {
if (!idle_inhibit_mgr) {
wl_event_source_timer_update(keep_idle_inhibit_source, 0);
return 1;
}
if (session && !session->active) {
wl_event_source_timer_update(keep_idle_inhibit_source, 0);
return 1;
}
if (!selmon || !selmon->sel || !selmon->sel->indleinhibit_when_focus) {
wl_event_source_timer_update(keep_idle_inhibit_source, 0);
return 1;
}
if (seat && idle_notifier) {
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
wl_event_source_timer_update(keep_idle_inhibit_source, 1000);
}
return 1;
}
void unlocksession(struct wl_listener *listener, void *data) {
SessionLock *lock = wl_container_of(listener, lock, unlock);
destroylock(lock, 1);
@ -5843,17 +5944,20 @@ void unmaplayersurfacenotify(struct wl_listener *listener, void *data) {
init_fadeout_layers(l);
wlr_scene_node_set_enabled(&l->scene->node, false);
if (l == exclusive_focus)
exclusive_focus = NULL;
if (l->layer_surface->output && (l->mon = l->layer_surface->output->data))
arrangelayers(l->mon);
if (l->layer_surface->surface == seat->keyboard_state.focused_surface)
focusclient(focustop(selmon), 1);
reset_exclusive_layers_focus(l->mon);
motionnotify(0, NULL, 0, 0, 0, 0);
l->being_unmapped = false;
layer_flush_blur_background(l);
wlr_scene_node_destroy(&l->shadow->node);
l->shadow = NULL;
l->being_unmapped = false;
}
void unmapnotify(struct wl_listener *listener, void *data) {