mirror of https://github.com/yshui/picom.git
win: delayed handling of configure notify
Part of the configure notify handling which requires querying the X server, has been moved into the X critical section. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
f447e51380
commit
a099678664
57
src/event.c
57
src/event.c
|
@ -189,8 +189,6 @@ static inline void ev_create_notify(session_t *ps, xcb_create_notify_event_t *ev
|
|||
/// Handle configure event of a regular window
|
||||
static void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
|
||||
auto w = find_win(ps, ce->window);
|
||||
region_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
|
||||
if (!w) {
|
||||
return;
|
||||
|
@ -210,44 +208,47 @@ static void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
|
|||
restack_above(ps, w, ce->above_sibling);
|
||||
} else {
|
||||
restack_above(ps, w, ce->above_sibling);
|
||||
bool factor_change = false;
|
||||
win_extents(mw, &damage);
|
||||
|
||||
// If window geometry change, free old extents
|
||||
if (mw->g.x != ce->x || mw->g.y != ce->y || mw->g.width != ce->width ||
|
||||
mw->g.height != ce->height || mw->g.border_width != ce->border_width) {
|
||||
factor_change = true;
|
||||
}
|
||||
region_t damage, new_extents;
|
||||
pixman_region32_init(&damage);
|
||||
pixman_region32_init(&new_extents);
|
||||
|
||||
mw->g.x = ce->x;
|
||||
mw->g.y = ce->y;
|
||||
// Get the old window extents
|
||||
win_extents(mw, &damage);
|
||||
|
||||
if (mw->g.width != ce->width || mw->g.height != ce->height ||
|
||||
mw->g.border_width != ce->border_width) {
|
||||
log_trace("Window size changed, %dx%d -> %dx%d", mw->g.width,
|
||||
mw->g.height, ce->width, ce->height);
|
||||
mw->g.width = ce->width;
|
||||
mw->g.height = ce->height;
|
||||
mw->g.border_width = ce->border_width;
|
||||
win_on_win_size_change(ps, mw);
|
||||
win_update_bounding_shape(ps, mw);
|
||||
}
|
||||
// Queue pending updates
|
||||
win_set_flags(mw, WIN_FLAGS_FACTOR_CHANGED);
|
||||
ps->pending_updates = true;
|
||||
|
||||
region_t new_extents;
|
||||
pixman_region32_init(&new_extents);
|
||||
win_extents(mw, &new_extents);
|
||||
pixman_region32_union(&damage, &damage, &new_extents);
|
||||
pixman_region32_fini(&new_extents);
|
||||
mw->g.x = ce->x;
|
||||
mw->g.y = ce->y;
|
||||
|
||||
if (factor_change) {
|
||||
win_on_factor_change(ps, mw);
|
||||
if (mw->g.width != ce->width || mw->g.height != ce->height ||
|
||||
mw->g.border_width != ce->border_width) {
|
||||
log_trace("Window size changed, %dx%d -> %dx%d",
|
||||
mw->g.width, mw->g.height, ce->width, ce->height);
|
||||
mw->g.width = ce->width;
|
||||
mw->g.height = ce->height;
|
||||
mw->g.border_width = ce->border_width;
|
||||
win_set_flags(mw, WIN_FLAGS_SIZE_STALE);
|
||||
}
|
||||
|
||||
win_extents(mw, &new_extents);
|
||||
// Mark the union of the old and new extents as damaged
|
||||
pixman_region32_union(&damage, &damage, &new_extents);
|
||||
add_damage(ps, &damage);
|
||||
win_update_screen(ps, mw);
|
||||
|
||||
pixman_region32_fini(&damage);
|
||||
pixman_region32_fini(&new_extents);
|
||||
|
||||
// Recalculate which screen this window is on
|
||||
win_update_screen(ps->xinerama_nscrs, ps->xinerama_scr_regs, mw);
|
||||
}
|
||||
}
|
||||
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
// override_redirect flag cannot be changed after window creation, as far
|
||||
// as I know, so there's no point to re-match windows here.
|
||||
mw->a.override_redirect = ce->override_redirect;
|
||||
|
|
137
src/win.c
137
src/win.c
|
@ -350,6 +350,60 @@ static bool win_fetch_and_unset_property_stale(struct managed_win *w, xcb_atom_t
|
|||
/// Returns true if any of the properties are stale, as well as clear all the stale flags.
|
||||
static bool win_check_and_clear_all_properties_stale(struct managed_win *w);
|
||||
|
||||
/// Fetch new window properties from the X server, and run appropriate updates. Might set
|
||||
/// WIN_FLAGS_FACTOR_CHANGED
|
||||
static void win_update_properties(session_t *ps, struct managed_win *w) {
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->a_NET_WM_WINDOW_TYPE)) {
|
||||
win_update_wintype(ps, w);
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->a_NET_WM_WINDOW_OPACITY)) {
|
||||
win_update_opacity_prop(ps, w);
|
||||
// we cannot receive OPACITY change when window has been destroyed
|
||||
assert(w->state != WSTATE_DESTROYING);
|
||||
win_update_opacity_target(ps, w);
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->a_NET_FRAME_EXTENTS)) {
|
||||
win_update_frame_extents(ps, w, w->client_win);
|
||||
add_damage_from_win(ps, w);
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->aWM_NAME) ||
|
||||
win_fetch_and_unset_property_stale(w, ps->atoms->a_NET_WM_NAME)) {
|
||||
if (win_update_name(ps, w) == 1) {
|
||||
win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->aWM_CLASS)) {
|
||||
if (win_update_class(ps, w)) {
|
||||
win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->aWM_WINDOW_ROLE)) {
|
||||
if (win_update_role(ps, w) == 1) {
|
||||
win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->a_COMPTON_SHADOW)) {
|
||||
win_update_prop_shadow(ps, w);
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->aWM_CLIENT_LEADER) ||
|
||||
win_fetch_and_unset_property_stale(w, ps->atoms->aWM_TRANSIENT_FOR)) {
|
||||
win_update_leader(ps, w);
|
||||
}
|
||||
|
||||
if (win_check_and_clear_all_properties_stale(w)) {
|
||||
// Some other flags we didn't explicitly check has changed, must
|
||||
// have been a tracked atom for the custom rules
|
||||
win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
void win_process_update_flags(session_t *ps, struct managed_win *w) {
|
||||
if (win_check_flags_all(w, WIN_FLAGS_MAPPED)) {
|
||||
map_win_start(ps, w);
|
||||
|
@ -363,62 +417,21 @@ void win_process_update_flags(session_t *ps, struct managed_win *w) {
|
|||
win_clear_flags(w, WIN_FLAGS_CLIENT_STALE);
|
||||
}
|
||||
|
||||
if (win_check_flags_all(w, WIN_FLAGS_SIZE_STALE)) {
|
||||
win_on_win_size_change(ps, w);
|
||||
win_update_bounding_shape(ps, w);
|
||||
win_clear_flags(w, WIN_FLAGS_SIZE_STALE);
|
||||
}
|
||||
|
||||
if (win_check_flags_all(w, WIN_FLAGS_PROPERTY_STALE)) {
|
||||
bool factor_change = false;
|
||||
win_update_properties(ps, w);
|
||||
win_clear_flags(w, WIN_FLAGS_PROPERTY_STALE);
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->a_NET_WM_WINDOW_TYPE)) {
|
||||
win_update_wintype(ps, w);
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->a_NET_WM_WINDOW_OPACITY)) {
|
||||
win_update_opacity_prop(ps, w);
|
||||
// we cannot receive OPACITY change when window has been destroyed
|
||||
assert(w->state != WSTATE_DESTROYING);
|
||||
win_update_opacity_target(ps, w);
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->a_NET_FRAME_EXTENTS)) {
|
||||
win_update_frame_extents(ps, w, w->client_win);
|
||||
add_damage_from_win(ps, w);
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->aWM_NAME) ||
|
||||
win_fetch_and_unset_property_stale(w, ps->atoms->a_NET_WM_NAME)) {
|
||||
if (win_update_name(ps, w) == 1) {
|
||||
factor_change = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->aWM_CLASS)) {
|
||||
if (win_update_class(ps, w)) {
|
||||
factor_change = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->aWM_WINDOW_ROLE)) {
|
||||
if (win_update_role(ps, w) == 1) {
|
||||
factor_change = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->a_COMPTON_SHADOW)) {
|
||||
win_update_prop_shadow(ps, w);
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->aWM_CLIENT_LEADER) ||
|
||||
win_fetch_and_unset_property_stale(w, ps->atoms->aWM_TRANSIENT_FOR)) {
|
||||
win_update_leader(ps, w);
|
||||
}
|
||||
|
||||
if (win_check_and_clear_all_properties_stale(w)) {
|
||||
// Some other flags we didn't explicitly check has changed, must
|
||||
// have been a tracked atom for the custom rules
|
||||
factor_change = true;
|
||||
}
|
||||
|
||||
if (factor_change) {
|
||||
win_on_factor_change(ps, w);
|
||||
}
|
||||
// Factor change flags could be set by previous stages, so must be handled last
|
||||
if (win_check_flags_all(w, WIN_FLAGS_FACTOR_CHANGED)) {
|
||||
win_on_factor_change(ps, w);
|
||||
win_clear_flags(w, WIN_FLAGS_FACTOR_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -884,8 +897,9 @@ void win_update_prop_shadow(session_t *ps, struct managed_win *w) {
|
|||
}
|
||||
|
||||
static void win_set_invert_color(session_t *ps, struct managed_win *w, bool invert_color_new) {
|
||||
if (w->invert_color == invert_color_new)
|
||||
if (w->invert_color == invert_color_new) {
|
||||
return;
|
||||
}
|
||||
|
||||
w->invert_color = invert_color_new;
|
||||
|
||||
|
@ -898,10 +912,11 @@ static void win_set_invert_color(session_t *ps, struct managed_win *w, bool inve
|
|||
static void win_determine_invert_color(session_t *ps, struct managed_win *w) {
|
||||
bool invert_color_new = w->invert_color;
|
||||
|
||||
if (UNSET != w->invert_color_force)
|
||||
if (UNSET != w->invert_color_force) {
|
||||
invert_color_new = w->invert_color_force;
|
||||
else if (w->a.map_state == XCB_MAP_STATE_VIEWABLE)
|
||||
} else if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) {
|
||||
invert_color_new = c2_match(ps, w, ps->o.invert_color_list, NULL);
|
||||
}
|
||||
|
||||
win_set_invert_color(ps, w, invert_color_new);
|
||||
}
|
||||
|
@ -2118,11 +2133,11 @@ bool win_skip_fading(session_t *ps, struct managed_win *w) {
|
|||
* TODO(yshui) move to x.c
|
||||
* TODO(yshui) use xrandr
|
||||
*/
|
||||
void win_update_screen(session_t *ps, struct managed_win *w) {
|
||||
void win_update_screen(int nscreens, region_t *screens, struct managed_win *w) {
|
||||
w->xinerama_scr = -1;
|
||||
|
||||
for (int i = 0; i < ps->xinerama_nscrs; i++) {
|
||||
auto e = pixman_region32_extents(&ps->xinerama_scr_regs[i]);
|
||||
for (int i = 0; i < nscreens; i++) {
|
||||
auto e = pixman_region32_extents(&screens[i]);
|
||||
if (e->x1 <= w->g.x && e->y1 <= w->g.y && e->x2 >= w->g.x + w->widthb &&
|
||||
e->y2 >= w->g.y + w->heightb) {
|
||||
w->xinerama_scr = i;
|
||||
|
@ -2190,7 +2205,7 @@ void map_win_start(session_t *ps, struct managed_win *w) {
|
|||
// XXX Can we assume map_state is always viewable?
|
||||
w->a.map_state = XCB_MAP_STATE_VIEWABLE;
|
||||
|
||||
win_update_screen(ps, w);
|
||||
win_update_screen(ps->xinerama_nscrs, ps->xinerama_scr_regs, w);
|
||||
|
||||
// Set window event mask before reading properties so that no property
|
||||
// changes are lost
|
||||
|
|
|
@ -314,7 +314,7 @@ void win_recheck_client(session_t *ps, struct managed_win *w);
|
|||
*/
|
||||
double attr_pure win_calc_opacity_target(session_t *ps, const struct managed_win *w);
|
||||
bool attr_pure win_should_dim(session_t *ps, const struct managed_win *w);
|
||||
void win_update_screen(session_t *, struct managed_win *);
|
||||
void win_update_screen(int nscreens, region_t *screens, struct managed_win *w);
|
||||
/**
|
||||
* Retrieve the bounding shape of a window.
|
||||
*/
|
||||
|
|
|
@ -87,6 +87,10 @@ enum win_flags {
|
|||
WIN_FLAGS_MAPPED = 64,
|
||||
/// this window has properties which needs to be updated
|
||||
WIN_FLAGS_PROPERTY_STALE = 128,
|
||||
/// this window has an unhandled size/shape change
|
||||
WIN_FLAGS_SIZE_STALE = 256,
|
||||
/// need better name for this, is set when some aspects of the window changed
|
||||
WIN_FLAGS_FACTOR_CHANGED = 512,
|
||||
};
|
||||
|
||||
static const uint64_t WIN_FLAGS_IMAGES_STALE =
|
||||
|
|
Loading…
Reference in New Issue