mirror of
https://github.com/yshui/picom.git
synced 2024-11-25 14:06:08 -05:00
core: recheck focus when client windows change
A toplevel is marked active if its client window is focused. So when a toplevel's client window changes, focus must be rechecked. Fix the problem that no window is marked active from the point when picom is just started, until the first focus change. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
5da5a93dcc
commit
c7fc8784d5
4 changed files with 36 additions and 17 deletions
|
@ -224,6 +224,8 @@ typedef struct session {
|
||||||
struct render_statistics render_stats;
|
struct render_statistics render_stats;
|
||||||
|
|
||||||
// === Operation related ===
|
// === Operation related ===
|
||||||
|
/// Whether there is a pending quest to get the focused window
|
||||||
|
bool pending_focus_check;
|
||||||
/// Flags related to the root window
|
/// Flags related to the root window
|
||||||
uint64_t root_flags;
|
uint64_t root_flags;
|
||||||
/// Program options.
|
/// Program options.
|
||||||
|
|
41
src/event.c
41
src/event.c
|
@ -205,6 +205,7 @@ update_ewmh_active_win(struct x_connection * /*c*/, struct x_async_request_base
|
||||||
auto ps = ((struct ev_ewmh_active_win_request *)req_base)->ps;
|
auto ps = ((struct ev_ewmh_active_win_request *)req_base)->ps;
|
||||||
free(req_base);
|
free(req_base);
|
||||||
|
|
||||||
|
ps->pending_focus_check = false;
|
||||||
if (reply_or_error->response_type == 0) {
|
if (reply_or_error->response_type == 0) {
|
||||||
log_error("Failed to get _NET_ACTIVE_WINDOW: %s",
|
log_error("Failed to get _NET_ACTIVE_WINDOW: %s",
|
||||||
x_strerror(((xcb_generic_error_t *)reply_or_error)));
|
x_strerror(((xcb_generic_error_t *)reply_or_error)));
|
||||||
|
@ -247,6 +248,8 @@ static void recheck_focus(struct x_connection * /*c*/, struct x_async_request_ba
|
||||||
auto ps = ((struct ev_ewmh_active_win_request *)req_base)->ps;
|
auto ps = ((struct ev_ewmh_active_win_request *)req_base)->ps;
|
||||||
free(req_base);
|
free(req_base);
|
||||||
|
|
||||||
|
ps->pending_focus_check = false;
|
||||||
|
|
||||||
// Determine the currently focused window so we can apply appropriate
|
// Determine the currently focused window so we can apply appropriate
|
||||||
// opacity on it
|
// opacity on it
|
||||||
if (reply_or_error->response_type == 0) {
|
if (reply_or_error->response_type == 0) {
|
||||||
|
@ -288,18 +291,39 @@ static void recheck_focus(struct x_connection * /*c*/, struct x_async_request_ba
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ev_focus_change(session_t *ps) {
|
void ev_update_focused(struct session *ps) {
|
||||||
if (ps->o.use_ewmh_active_win) {
|
if (ps->pending_focus_check) {
|
||||||
// Not using focus_in/focus_out events.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ps->o.use_ewmh_active_win) {
|
||||||
|
auto req = ccalloc(1, struct ev_ewmh_active_win_request);
|
||||||
|
req->base.sequence =
|
||||||
|
xcb_get_property(ps->c.c, 0, ps->c.screen_info->root,
|
||||||
|
ps->atoms->a_NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 0, 1)
|
||||||
|
.sequence;
|
||||||
|
req->base.callback = update_ewmh_active_win;
|
||||||
|
req->ps = ps;
|
||||||
|
x_await_request(&ps->c, &req->base);
|
||||||
|
log_debug("Started async request to get _NET_ACTIVE_WINDOW");
|
||||||
|
} else {
|
||||||
auto req = ccalloc(1, struct ev_recheck_focus_request);
|
auto req = ccalloc(1, struct ev_recheck_focus_request);
|
||||||
req->base.sequence = xcb_get_input_focus(ps->c.c).sequence;
|
req->base.sequence = xcb_get_input_focus(ps->c.c).sequence;
|
||||||
req->base.callback = recheck_focus;
|
req->base.callback = recheck_focus;
|
||||||
req->ps = ps;
|
req->ps = ps;
|
||||||
x_await_request(&ps->c, &req->base);
|
x_await_request(&ps->c, &req->base);
|
||||||
log_debug("Started async request to recheck focus");
|
log_debug("Started async request to recheck focus");
|
||||||
|
}
|
||||||
|
|
||||||
|
ps->pending_focus_check = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ev_focus_change(session_t *ps) {
|
||||||
|
if (ps->o.use_ewmh_active_win) {
|
||||||
|
// Not using focus_in/focus_out events.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ev_update_focused(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ev_focus_in(session_t *ps, xcb_focus_in_event_t *ev) {
|
static inline void ev_focus_in(session_t *ps, xcb_focus_in_event_t *ev) {
|
||||||
|
@ -556,16 +580,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
|
||||||
|
|
||||||
if (ps->c.screen_info->root == ev->window) {
|
if (ps->c.screen_info->root == ev->window) {
|
||||||
if (ps->o.use_ewmh_active_win && ps->atoms->a_NET_ACTIVE_WINDOW == ev->atom) {
|
if (ps->o.use_ewmh_active_win && ps->atoms->a_NET_ACTIVE_WINDOW == ev->atom) {
|
||||||
auto req = ccalloc(1, struct ev_ewmh_active_win_request);
|
ev_update_focused(ps);
|
||||||
req->base.sequence =
|
|
||||||
xcb_get_property(ps->c.c, 0, ps->c.screen_info->root,
|
|
||||||
ps->atoms->a_NET_ACTIVE_WINDOW,
|
|
||||||
XCB_ATOM_WINDOW, 0, 1)
|
|
||||||
.sequence;
|
|
||||||
req->base.callback = update_ewmh_active_win;
|
|
||||||
req->ps = ps;
|
|
||||||
x_await_request(&ps->c, &req->base);
|
|
||||||
log_debug("Started async request to get _NET_ACTIVE_WINDOW");
|
|
||||||
} else {
|
} else {
|
||||||
// Destroy the root "image" if the wallpaper probably changed
|
// Destroy the root "image" if the wallpaper probably changed
|
||||||
if (x_is_root_back_pixmap_atom(ps->atoms, ev->atom)) {
|
if (x_is_root_back_pixmap_atom(ps->atoms, ev->atom)) {
|
||||||
|
|
|
@ -7,3 +7,4 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
void ev_handle(session_t *ps, xcb_generic_event_t *ev);
|
void ev_handle(session_t *ps, xcb_generic_event_t *ev);
|
||||||
|
void ev_update_focused(struct session *ps);
|
||||||
|
|
|
@ -1590,6 +1590,7 @@ static void handle_new_windows(session_t *ps) {
|
||||||
wm_ref_win_id(wm_change.toplevel),
|
wm_ref_win_id(wm_change.toplevel),
|
||||||
wm_change.client.new_.x);
|
wm_change.client.new_.x);
|
||||||
}
|
}
|
||||||
|
ev_update_focused(ps);
|
||||||
break;
|
break;
|
||||||
case WM_TREE_CHANGE_TOPLEVEL_RESTACKED: invalidate_reg_ignore(ps); break;
|
case WM_TREE_CHANGE_TOPLEVEL_RESTACKED: invalidate_reg_ignore(ps); break;
|
||||||
default: unreachable();
|
default: unreachable();
|
||||||
|
|
Loading…
Reference in a new issue