mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-06-24 13:36:42 -04:00
feat: hdr support
This commit is contained in:
parent
085d65c219
commit
5fb6b230a0
8 changed files with 211 additions and 63 deletions
|
|
@ -12,6 +12,7 @@ description: Advanced settings for XWayland, focus behavior, and system integrat
|
|||
| `allow_lock_transparent` | `0` | Allow the lock screen to be transparent. |
|
||||
| `allow_shortcuts_inhibit` | `1` | Allow shortcuts to be inhibited by clients. |
|
||||
| `vrr` | - | Set via [monitor rule](/docs/configuration/monitors#monitor-rules). |
|
||||
| `hdr_hdr_depth` | `0`/`1`/`2` | Set the hdr depth for the current display. `0` is Default, `1` is HDR8, `2` is HDR10. |
|
||||
|
||||
## Focus & Input
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ monitorrule=name:Values,Parameter:Values,Parameter:Values
|
|||
| `y` | integer | 0-99999 | Y position |
|
||||
| `scale` | float | 0.01-100.0 | Monitor scale |
|
||||
| `vrr` | integer | 0, 1 | Enable variable refresh rate |
|
||||
| `hdr` | integer | 0, 1 | Enable hdr support |
|
||||
| `rr` | integer | 0-7 | Monitor transform |
|
||||
| `custom` | integer | 0, 1 | Enable custom mode (not supported on all displays — may cause black screen) |
|
||||
|
||||
|
|
|
|||
|
|
@ -265,4 +265,9 @@ void client_set_group_mon(Client *c, Monitor *m) {
|
|||
client_change_mon(cur, m);
|
||||
cur = cur->group_next;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_client_focus_change(Client *c) {
|
||||
check_keep_idle_inhibit(c);
|
||||
check_vrr_enable(c);
|
||||
}
|
||||
|
|
@ -22,6 +22,11 @@ enum { NUM_TYPE_MINUS, NUM_TYPE_PLUS, NUM_TYPE_DEFAULT };
|
|||
|
||||
enum { KEY_TYPE_CODE, KEY_TYPE_SYM };
|
||||
|
||||
enum render_bit_depth {
|
||||
MANGO_RENDER_BIT_DEPTH_DEFAULT = 0,
|
||||
MANGO_RENDER_BIT_DEPTH_8,
|
||||
MANGO_RENDER_BIT_DEPTH_10,
|
||||
};
|
||||
typedef struct {
|
||||
uint32_t keycode1;
|
||||
uint32_t keycode2;
|
||||
|
|
@ -112,6 +117,7 @@ typedef struct {
|
|||
float refresh; // Refresh rate
|
||||
int32_t vrr; // variable refresh rate
|
||||
int32_t custom; // enable custom mode
|
||||
int32_t hdr; // enable hdr mode
|
||||
} ConfigMonitorRule;
|
||||
|
||||
// 修改后的宏定义
|
||||
|
|
@ -391,6 +397,8 @@ typedef struct {
|
|||
struct xkb_keymap *keymap;
|
||||
DecorateDrawData jumplabeldata;
|
||||
DecorateDrawData tabdata;
|
||||
|
||||
int32_t hdr_depth;
|
||||
} Config;
|
||||
|
||||
typedef int32_t (*FuncType)(const Arg *);
|
||||
|
|
@ -1464,6 +1472,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
config->drag_floating_refresh_interval = atof(value);
|
||||
} else if (strcmp(key, "allow_tearing") == 0) {
|
||||
config->allow_tearing = atoi(value);
|
||||
} else if (strcmp(key, "hdr_depth") == 0) {
|
||||
config->hdr_depth = atoi(value);
|
||||
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
|
||||
config->allow_shortcuts_inhibit = atoi(value);
|
||||
} else if (strcmp(key, "allow_lock_transparent") == 0) {
|
||||
|
|
@ -2047,6 +2057,7 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
rule->height = -1;
|
||||
rule->refresh = 0.0f;
|
||||
rule->vrr = 0;
|
||||
rule->hdr = 0;
|
||||
rule->custom = 0;
|
||||
|
||||
bool parse_error = false;
|
||||
|
|
@ -2085,6 +2096,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, "hdr") == 0) {
|
||||
rule->hdr = CLAMP_INT(atoi(val), 0, 1);
|
||||
} else if (strcmp(key, "custom") == 0) {
|
||||
rule->custom = CLAMP_INT(atoi(val), 0, 1);
|
||||
} else {
|
||||
|
|
@ -3421,6 +3434,7 @@ void override_config(void) {
|
|||
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.hdr_depth = CLAMP_INT(config.hdr_depth, 0, 2);
|
||||
config.allow_shortcuts_inhibit =
|
||||
CLAMP_INT(config.allow_shortcuts_inhibit, 0, 1);
|
||||
config.allow_lock_transparent =
|
||||
|
|
@ -3588,6 +3602,7 @@ void set_value_default() {
|
|||
config.drag_tile_refresh_interval = 8.0f;
|
||||
config.drag_floating_refresh_interval = 8.0f;
|
||||
config.allow_tearing = TEARING_DISABLED;
|
||||
config.hdr_depth = MANGO_RENDER_BIT_DEPTH_DEFAULT;
|
||||
config.allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
|
||||
config.allow_lock_transparent = 0;
|
||||
config.no_border_when_single = 0;
|
||||
|
|
@ -3868,13 +3883,12 @@ void reapply_monitor_rules(void) {
|
|||
Monitor *m = NULL;
|
||||
int32_t ji, vrr, custom;
|
||||
int32_t mx, my;
|
||||
struct wlr_output_state state;
|
||||
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (!m->wlr_output->enabled)
|
||||
continue;
|
||||
|
||||
wlr_output_state_init(&state);
|
||||
wlr_output_state_init(&m->pending);
|
||||
|
||||
for (ji = 0; ji < config.monitor_rules_count; ji++) {
|
||||
if (config.monitor_rules_count < 1)
|
||||
|
|
@ -3887,16 +3901,31 @@ void reapply_monitor_rules(void) {
|
|||
my = mr->y == INT32_MAX ? m->m.y : mr->y;
|
||||
vrr = mr->vrr >= 0 ? mr->vrr : 0;
|
||||
custom = mr->custom >= 0 ? mr->custom : 0;
|
||||
m->hdr_enable = mr->hdr >= 0 ? mr->hdr : 0;
|
||||
|
||||
(void)apply_rule_to_state(m, mr, &state, vrr, custom);
|
||||
(void)apply_rule_to_state(m, mr, &m->pending, vrr, custom);
|
||||
wlr_output_layout_add(output_layout, m->wlr_output, mx, my);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wlr_output_state_finish(&state);
|
||||
wlr_output_state_set_enabled(&m->pending, true);
|
||||
|
||||
if (m->hdr_enable) {
|
||||
output_state_setup_hdr(m, false);
|
||||
bool success = wlr_output_commit_state(m->wlr_output, &m->pending);
|
||||
if (!success) { // 多尝试一次
|
||||
output_state_setup_hdr(m, true);
|
||||
}
|
||||
} else {
|
||||
wlr_output_commit_state(m->wlr_output, &m->pending);
|
||||
}
|
||||
|
||||
wlr_output_state_finish(&m->pending);
|
||||
wlr_output_effective_resolution(m->wlr_output, &m->m.width,
|
||||
&m->m.height);
|
||||
}
|
||||
|
||||
updatemons(NULL, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "dwl-ipc.h"
|
||||
#include "ext-workspace.h"
|
||||
#include "foreign-toplevel.h"
|
||||
#include "hdr.h"
|
||||
#include "tablet.h"
|
||||
#include "tearing.h"
|
||||
#include "text-input.h"
|
||||
|
|
|
|||
128
src/ext-protocol/hdr.h
Normal file
128
src/ext-protocol/hdr.h
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#include <drm_fourcc.h>
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
static uint32_t output_formats_8bit[] = {
|
||||
DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888, DRM_FORMAT_RGBX8888,
|
||||
DRM_FORMAT_BGRX8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
|
||||
DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_RGB888,
|
||||
DRM_FORMAT_BGR888,
|
||||
};
|
||||
|
||||
static uint32_t output_formats_10bit[] = {
|
||||
DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_RGBX1010102,
|
||||
DRM_FORMAT_BGRX1010102, DRM_FORMAT_ARGB2101010, DRM_FORMAT_ABGR2101010,
|
||||
DRM_FORMAT_RGBA1010102, DRM_FORMAT_BGRA1010102,
|
||||
};
|
||||
|
||||
static bool output_set_render_format(Monitor *m, uint32_t candidates[],
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
wlr_output_state_set_render_format(&m->pending, candidates[i]);
|
||||
if (wlr_output_test_state(m->wlr_output, &m->pending))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool output_format_in_candidates(uint32_t format, uint32_t candidates[],
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; i++)
|
||||
if (candidates[i] == format)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum render_bit_depth bit_depth_from_format(uint32_t render_format) {
|
||||
if (output_format_in_candidates(render_format, output_formats_10bit,
|
||||
ARRAY_SIZE(output_formats_10bit)))
|
||||
return MANGO_RENDER_BIT_DEPTH_10;
|
||||
if (output_format_in_candidates(render_format, output_formats_8bit,
|
||||
ARRAY_SIZE(output_formats_8bit)))
|
||||
return MANGO_RENDER_BIT_DEPTH_8;
|
||||
return MANGO_RENDER_BIT_DEPTH_DEFAULT;
|
||||
}
|
||||
|
||||
static bool output_supports_hdr(const struct wlr_output *output,
|
||||
const char **reason) {
|
||||
const char *r = NULL;
|
||||
if (!(output->supported_primaries & WLR_COLOR_NAMED_PRIMARIES_BT2020))
|
||||
r = "BT2020 primaries not supported";
|
||||
else if (!(output->supported_transfer_functions &
|
||||
WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ))
|
||||
r = "PQ transfer function not supported";
|
||||
else if (!drw->features.output_color_transform)
|
||||
r = "renderer doesn't support output color transforms";
|
||||
if (reason)
|
||||
*reason = r;
|
||||
return !r;
|
||||
}
|
||||
|
||||
void output_enable_hdr(Monitor *m, struct wlr_output_state *os, bool enabled,
|
||||
bool silent) {
|
||||
if (enabled && !output_supports_hdr(m->wlr_output, NULL))
|
||||
enabled = false;
|
||||
|
||||
if (!enabled) {
|
||||
if (m->wlr_output->supported_primaries ||
|
||||
m->wlr_output->supported_transfer_functions) {
|
||||
if (!silent)
|
||||
wlr_log(WLR_DEBUG, "Disabling HDR on output %s",
|
||||
m->wlr_output->name);
|
||||
wlr_output_state_set_image_description(os, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!silent)
|
||||
wlr_log(WLR_DEBUG, "Enabling HDR on output %s", m->wlr_output->name);
|
||||
struct wlr_output_image_description desc = {
|
||||
.primaries = WLR_COLOR_NAMED_PRIMARIES_BT2020,
|
||||
.transfer_function = WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ,
|
||||
};
|
||||
wlr_output_state_set_image_description(os, &desc);
|
||||
}
|
||||
|
||||
void output_state_setup_hdr(Monitor *m, bool silent) {
|
||||
uint32_t render_format = m->wlr_output->render_format;
|
||||
const char *unsupported_reason = NULL;
|
||||
bool hdr_supported =
|
||||
output_supports_hdr(m->wlr_output, &unsupported_reason);
|
||||
bool hdr_succeeded = false;
|
||||
|
||||
enum render_bit_depth depth = config.hdr_depth;
|
||||
if (depth == MANGO_RENDER_BIT_DEPTH_DEFAULT)
|
||||
depth = bit_depth_from_format(render_format);
|
||||
|
||||
if (!hdr_supported && depth == MANGO_RENDER_BIT_DEPTH_10) {
|
||||
if (!silent)
|
||||
wlr_log(WLR_INFO, "Cannot enable HDR on output %s: %s",
|
||||
m->wlr_output->name, unsupported_reason);
|
||||
depth = MANGO_RENDER_BIT_DEPTH_8;
|
||||
}
|
||||
|
||||
if (depth == MANGO_RENDER_BIT_DEPTH_10 &&
|
||||
bit_depth_from_format(render_format) == depth) {
|
||||
hdr_succeeded = true; // 上次已经成功设置10位,直接复用
|
||||
} else if (depth == MANGO_RENDER_BIT_DEPTH_10) {
|
||||
hdr_succeeded = output_set_render_format(
|
||||
m, output_formats_10bit, ARRAY_SIZE(output_formats_10bit));
|
||||
if (!hdr_succeeded) {
|
||||
if (!silent)
|
||||
wlr_log(WLR_INFO,
|
||||
"No 10 bit color formats supported, HDR disabled.");
|
||||
if (!output_set_render_format(m, output_formats_8bit,
|
||||
ARRAY_SIZE(output_formats_8bit)))
|
||||
if (!silent)
|
||||
wlr_log(WLR_ERROR, "No 8 bit color formats either!");
|
||||
}
|
||||
} else {
|
||||
// 明确要求8位或自动降级
|
||||
if (!output_set_render_format(m, output_formats_8bit,
|
||||
ARRAY_SIZE(output_formats_8bit)))
|
||||
if (!silent)
|
||||
wlr_log(WLR_ERROR, "No 8 bit color formats supported!");
|
||||
}
|
||||
|
||||
output_enable_hdr(m, &m->pending, hdr_succeeded, silent);
|
||||
}
|
||||
|
|
@ -100,73 +100,44 @@ bool custom_wlr_scene_output_commit(struct wlr_scene_output *scene_output,
|
|||
struct wlr_output *wlr_output = scene_output->output;
|
||||
Monitor *m = wlr_output->data;
|
||||
|
||||
// 检查是否需要帧
|
||||
if (!wlr_scene_output_needs_frame(scene_output)) {
|
||||
wlr_log(WLR_DEBUG, "No frame needed for output %s", wlr_output->name);
|
||||
if (!wlr_scene_output_needs_frame(scene_output))
|
||||
return true;
|
||||
}
|
||||
|
||||
// 构建输出状态
|
||||
if (!wlr_scene_output_build_state(scene_output, state, NULL)) {
|
||||
wlr_log(WLR_ERROR, "Failed to build output state for %s",
|
||||
wlr_output->name);
|
||||
// 构建状态,将场景的 Buffer 附着到 state 上
|
||||
if (!wlr_scene_output_build_state(scene_output, state, NULL))
|
||||
return false;
|
||||
|
||||
// 测试是否支持撕裂
|
||||
if (!wlr_output_test_state(wlr_output, state)) {
|
||||
// 如果 DRM 拒绝(例如当前输出/驱动不支持撕裂),降级关闭撕裂
|
||||
state->tearing_page_flip = false;
|
||||
}
|
||||
|
||||
// 测试撕裂翻页
|
||||
if (state->tearing_page_flip) {
|
||||
if (!wlr_output_test_state(wlr_output, state)) {
|
||||
state->tearing_page_flip = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试提交
|
||||
// 提交状态
|
||||
bool committed = wlr_output_commit_state(wlr_output, state);
|
||||
|
||||
// 如果启用撕裂翻页但提交失败,重试禁用撕裂翻页
|
||||
if (!committed && state->tearing_page_flip) {
|
||||
wlr_log(WLR_DEBUG, "Retrying commit without tearing for %s",
|
||||
wlr_output->name);
|
||||
// 重试一次
|
||||
state->tearing_page_flip = false;
|
||||
committed = wlr_output_commit_state(wlr_output, state);
|
||||
}
|
||||
|
||||
// 处理状态清理
|
||||
if (committed) {
|
||||
wlr_log(WLR_DEBUG, "Successfully committed output %s",
|
||||
wlr_output->name);
|
||||
if (state == &m->pending) {
|
||||
wlr_output_state_finish(&m->pending);
|
||||
wlr_output_state_init(&m->pending);
|
||||
}
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Failed to commit output %s", wlr_output->name);
|
||||
// 即使提交失败,也清理状态避免积累
|
||||
if (state == &m->pending) {
|
||||
wlr_output_state_finish(&m->pending);
|
||||
wlr_output_state_init(&m->pending);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return committed;
|
||||
}
|
||||
|
||||
void apply_tear_state(Monitor *m) {
|
||||
if (wlr_scene_output_needs_frame(m->scene_output)) {
|
||||
wlr_output_state_init(&m->pending);
|
||||
if (wlr_scene_output_build_state(m->scene_output, &m->pending, NULL)) {
|
||||
struct wlr_output_state *pending = &m->pending;
|
||||
pending->tearing_page_flip = true;
|
||||
if (!wlr_scene_output_needs_frame(m->scene_output))
|
||||
return;
|
||||
|
||||
if (!custom_wlr_scene_output_commit(m->scene_output, pending)) {
|
||||
wlr_log(WLR_ERROR, "Failed to commit output %s",
|
||||
m->scene_output->output->name);
|
||||
}
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Failed to build state for output %s",
|
||||
m->scene_output->output->name);
|
||||
wlr_output_state_finish(&m->pending);
|
||||
}
|
||||
wlr_output_state_init(&m->pending);
|
||||
m->pending.tearing_page_flip = true;
|
||||
if (!custom_wlr_scene_output_commit(m->scene_output, &m->pending)) {
|
||||
wlr_log(WLR_ERROR, "Failed to commit output %s",
|
||||
m->scene_output->output->name);
|
||||
}
|
||||
}
|
||||
34
src/mango.c
34
src/mango.c
|
|
@ -586,6 +586,7 @@ struct Monitor {
|
|||
int8_t carousel_anim_dir;
|
||||
bool vrr_global_enable;
|
||||
bool is_vrr_opening;
|
||||
bool hdr_enable;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -947,6 +948,9 @@ static void global_draw_group_bar(Client *c, int32_t x, int32_t y,
|
|||
static void client_reparent_group(Client *c);
|
||||
static void client_change_mon(Client *c, Monitor *m);
|
||||
static void check_vrr_enable(Client *c);
|
||||
static void output_state_setup_hdr(Monitor *m, bool silent);
|
||||
static void output_enable_hdr(Monitor *m, struct wlr_output_state *os,
|
||||
bool enabled, bool silent);
|
||||
|
||||
#include "data/static_keymap.h"
|
||||
#include "dispatch/bind_declare.h"
|
||||
|
|
@ -3346,7 +3350,6 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
const ConfigMonitorRule *r;
|
||||
uint32_t i;
|
||||
int32_t ji, vrr, custom;
|
||||
struct wlr_output_state state;
|
||||
Monitor *m = NULL;
|
||||
bool custom_monitor_mode = false;
|
||||
|
||||
|
|
@ -3374,6 +3377,8 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
m->vrr_global_enable = false;
|
||||
m->is_vrr_opening = false;
|
||||
|
||||
m->hdr_enable = false;
|
||||
|
||||
m->wlr_output = wlr_output;
|
||||
m->wlr_output->data = m;
|
||||
|
||||
|
|
@ -3394,9 +3399,9 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
float scale = 1;
|
||||
enum wl_output_transform rr = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
||||
wlr_output_state_init(&state);
|
||||
wlr_output_state_set_scale(&state, scale);
|
||||
wlr_output_state_set_transform(&state, rr);
|
||||
wlr_output_state_init(&m->pending);
|
||||
wlr_output_state_set_scale(&m->pending, scale);
|
||||
wlr_output_state_set_transform(&m->pending, rr);
|
||||
|
||||
for (ji = 0; ji < config.monitor_rules_count; ji++) {
|
||||
if (config.monitor_rules_count < 1)
|
||||
|
|
@ -3411,8 +3416,9 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
custom = r->custom >= 0 ? r->custom : 0;
|
||||
scale = r->scale;
|
||||
rr = r->rr;
|
||||
m->hdr_enable = r->hdr;
|
||||
|
||||
if (apply_rule_to_state(m, r, &state, vrr, custom)) {
|
||||
if (apply_rule_to_state(m, r, &m->pending, vrr, custom)) {
|
||||
custom_monitor_mode = true;
|
||||
}
|
||||
break; // 只应用第一个匹配规则
|
||||
|
|
@ -3420,7 +3426,7 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
if (!custom_monitor_mode)
|
||||
wlr_output_state_set_mode(&state,
|
||||
wlr_output_state_set_mode(&m->pending,
|
||||
wlr_output_preferred_mode(wlr_output));
|
||||
|
||||
/* Set up event listeners */
|
||||
|
|
@ -3429,9 +3435,16 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
LISTEN(&wlr_output->events.request_state, &m->request_state,
|
||||
requestmonstate);
|
||||
|
||||
wlr_output_state_set_enabled(&state, 1);
|
||||
wlr_output_commit_state(wlr_output, &state);
|
||||
wlr_output_state_finish(&state);
|
||||
wlr_output_state_set_enabled(&m->pending, 1);
|
||||
|
||||
if (m->hdr_enable) {
|
||||
output_state_setup_hdr(m, false);
|
||||
}
|
||||
|
||||
wlr_output_commit_state(wlr_output, &m->pending);
|
||||
wlr_output_state_finish(&m->pending);
|
||||
|
||||
wlr_output_effective_resolution(m->wlr_output, &m->m.width, &m->m.height);
|
||||
|
||||
wl_list_insert(&mons, &m->link);
|
||||
|
||||
|
|
@ -3908,8 +3921,7 @@ void focusclient(Client *c, int32_t lift) {
|
|||
selmon->sel = c;
|
||||
c->isfocusing = true;
|
||||
|
||||
check_keep_idle_inhibit(c);
|
||||
check_vrr_enable(c);
|
||||
handle_client_focus_change(c);
|
||||
|
||||
if (last_focus_client && !last_focus_client->iskilling &&
|
||||
last_focus_client != c) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue