diff --git a/src/backend/backend.c b/src/backend/backend.c
index ceba170..8399142 100644
--- a/src/backend/backend.c
+++ b/src/backend/backend.c
@@ -50,7 +50,7 @@ region_t get_damage(session_t *ps, bool all_damage) {
}
/// paint all windows
-void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
+void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
// All painting will be limited to the damage, if _some_ of
// the paints bleed out of the damage region, it will destroy
// part of the image we want to reuse
@@ -98,7 +98,7 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
// on top of that window. This is used to reduce the number of pixels painted.
//
// Whether this is beneficial is to be determined XXX
- for (win *w = t; w; w = w->prev_trans) {
+ for (auto w = t; w; w = w->prev_trans) {
pixman_region32_subtract(®_visible, &ps->screen_reg, w->reg_ignore);
assert(!(w->flags & WIN_FLAGS_IMAGE_ERROR));
diff --git a/src/backend/backend.h b/src/backend/backend.h
index 6c95678..fded6ff 100644
--- a/src/backend/backend.h
+++ b/src/backend/backend.h
@@ -11,7 +11,7 @@
#include "x.h"
typedef struct session session_t;
-typedef struct win win;
+struct managed_win;
struct backend_operations;
@@ -48,7 +48,7 @@ struct backend_operations {
/// 1) if ps->overlay is not XCB_NONE, use that
/// 2) use ps->root otherwise
/// TODO make the target window a parameter
- backend_t *(*init)(session_t *) attr_nonnull(1);
+ backend_t *(*init)(session_t *)attr_nonnull(1);
void (*deinit)(backend_t *backend_data) attr_nonnull(1);
/// Called when rendering will be stopped for an unknown amount of
@@ -92,7 +92,7 @@ struct backend_operations {
/// Fill rectangle of target, mostly for debug purposes, optional.
void (*fill)(backend_t *backend_data, double r, double g, double b, double a,
- const region_t *clip);
+ const region_t *clip);
/// Blur a given region of the target.
bool (*blur)(backend_t *backend_data, double opacity, const region_t *reg_blur,
@@ -129,8 +129,7 @@ struct backend_operations {
// want to break that assumption as for now. We need to reconsider this.
/// Free resources associated with an image data structure
- void (*release_image)(backend_t *backend_data, void *img_data)
- attr_nonnull(1, 2);
+ void (*release_image)(backend_t *backend_data, void *img_data) attr_nonnull(1, 2);
// =========== Query ===========
@@ -179,12 +178,11 @@ struct backend_operations {
/// Let the backend hook into the event handling queue
};
-typedef backend_t *(*backend_init_fn)(session_t *ps) attr_nonnull(1);
+typedef backend_t *(*backend_init_fn)(session_t *ps)attr_nonnull(1);
extern struct backend_operations *backend_list[];
-bool default_is_win_transparent(void *, win *, void *);
-bool default_is_frame_transparent(void *, win *, void *);
-void paint_all_new(session_t *ps, win *const t, bool ignore_damage) attr_nonnull(1);
+void paint_all_new(session_t *ps, struct managed_win *const t, bool ignore_damage)
+ attr_nonnull(1);
// vim: set noet sw=8 ts=8 :
diff --git a/src/backend/backend_common.c b/src/backend/backend_common.c
index 90ad52e..128fff4 100644
--- a/src/backend/backend_common.c
+++ b/src/backend/backend_common.c
@@ -279,11 +279,3 @@ default_backend_render_shadow(backend_t *backend_data, int width, int height,
xcb_render_free_picture(backend_data->c, pict);
return ret;
}
-
-bool default_is_win_transparent(void *backend_data, win *w, void *win_data) {
- return w->mode != WMODE_SOLID;
-}
-
-bool default_is_frame_transparent(void *backend_data, win *w, void *win_data) {
- return w->frame_opacity != 1;
-}
diff --git a/src/c2.c b/src/c2.c
index b51acf0..8ebbe41 100644
--- a/src/c2.c
+++ b/src/c2.c
@@ -310,7 +310,7 @@ static void attr_unused c2_dump(c2_ptr_t p);
static xcb_atom_t c2_get_atom_type(const c2_l_t *pleaf);
-static bool c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond);
+static bool c2_match_once(session_t *ps, const struct managed_win *w, const c2_ptr_t cond);
/**
* Parse a condition string.
@@ -1272,11 +1272,11 @@ static xcb_atom_t c2_get_atom_type(const c2_l_t *pleaf) {
*
* For internal use.
*/
-static inline void
-c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres, bool *perr) {
+static inline void c2_match_once_leaf(session_t *ps, const struct managed_win *w,
+ const c2_l_t *pleaf, bool *pres, bool *perr) {
assert(pleaf);
- const xcb_window_t wid = (pleaf->tgt_onframe ? w->client_win : w->id);
+ const xcb_window_t wid = (pleaf->tgt_onframe ? w->client_win : w->base.id);
// Return if wid is missing
if (pleaf->predef == C2_L_PUNDEFINED && !wid) {
@@ -1468,7 +1468,7 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
*
* @return true if matched, false otherwise.
*/
-static bool c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond) {
+static bool c2_match_once(session_t *ps, const struct managed_win *w, const c2_ptr_t cond) {
bool result = false;
bool error = true;
@@ -1542,7 +1542,7 @@ static bool c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond) {
* @param pdata a place to return the data
* @return true if matched, false otherwise.
*/
-bool c2_match(session_t *ps, const win *w, const c2_lptr_t *condlst, void **pdata) {
+bool c2_match(session_t *ps, const struct managed_win *w, const c2_lptr_t *condlst, void **pdata) {
// Then go through the whole linked list
for (; condlst; condlst = condlst->next) {
if (c2_match_once(ps, w, condlst->ptr)) {
diff --git a/src/c2.h b/src/c2.h
index 21eb112..d6b1d37 100644
--- a/src/c2.h
+++ b/src/c2.h
@@ -15,12 +15,12 @@
typedef struct _c2_lptr c2_lptr_t;
typedef struct session session_t;
-typedef struct win win;
+struct managed_win;
c2_lptr_t *c2_parse(c2_lptr_t **pcondlst, const char *pattern, void *data);
c2_lptr_t *c2_free_lptr(c2_lptr_t *lp);
-bool c2_match(session_t *ps, const win *w, const c2_lptr_t *condlst, void **pdata);
+bool c2_match(session_t *ps, const struct managed_win *w, const c2_lptr_t *condlst, void **pdata);
bool c2_list_postprocess(session_t *ps, c2_lptr_t *list);
diff --git a/src/common.h b/src/common.h
index fa3bc4b..93ab2a8 100644
--- a/src/common.h
+++ b/src/common.h
@@ -391,7 +391,7 @@ typedef struct session {
// === Window related ===
/// A hash table of all windows.
- win *windows;
+ struct win *windows;
/// Windows in their stacking order
struct list_node window_stack;
/// Pointer to win
of current active window. Used by
@@ -399,7 +399,7 @@ typedef struct session {
/// it's more reliable to store the window ID directly here, just in
/// case the WM does something extraordinary, but caching the pointer
/// means another layer of complexity.
- win *active_win;
+ struct managed_win *active_win;
/// Window ID of leader window of currently active window. Used for
/// subsidiary window detection.
xcb_window_t active_leader;
@@ -742,34 +742,22 @@ static inline bool bkend_use_glx(session_t *ps) {
return BKEND_GLX == ps->o.backend || BKEND_XR_GLX_HYBRID == ps->o.backend;
}
-/**
- * Check if a window is really focused.
- */
-static inline bool win_is_focused_real(session_t *ps, const win *w) {
- return w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->active_win == w;
-}
-
/**
* Find out the currently focused window.
*
* @return struct win object of the found window, NULL if not found
*/
-static inline win *find_focused(session_t *ps) {
- if (!ps->o.track_focus)
+static inline struct managed_win *find_focused(session_t *ps) {
+ if (!ps->o.track_focus) {
return NULL;
+ }
- if (ps->active_win && win_is_focused_real(ps, ps->active_win))
+ if (ps->active_win && win_is_focused_real(ps, ps->active_win)) {
return ps->active_win;
+ }
return NULL;
}
-/**
- * Check if a rectangle includes the whole screen.
- */
-static inline bool rect_is_fullscreen(session_t *ps, int x, int y, int wid, int hei) {
- return (x <= 0 && y <= 0 && (x + wid) >= ps->root_width && (y + hei) >= ps->root_height);
-}
-
static void set_ignore(session_t *ps, unsigned long sequence) {
if (ps->o.show_all_xerrors)
return;
@@ -791,23 +779,6 @@ static inline void set_ignore_cookie(session_t *ps, xcb_void_cookie_t cookie) {
set_ignore(ps, cookie.sequence);
}
-/**
- * Check if a window is a fullscreen window.
- *
- * It's not using w->border_size for performance measures.
- */
-static inline bool win_is_fullscreen(session_t *ps, const win *w) {
- return rect_is_fullscreen(ps, w->g.x, w->g.y, w->widthb, w->heightb) &&
- (!w->bounding_shaped || w->rounded_corners);
-}
-
-/**
- * Check if a window will be painted solid.
- */
-static inline bool win_is_solid(session_t *ps, const win *w) {
- return WMODE_SOLID == w->mode && !ps->o.force_win_blend;
-}
-
/**
* Determine if a window has a specific property.
*
@@ -864,13 +835,6 @@ void vsync_deinit(session_t *ps);
/** @name DBus hooks
*/
///@{
-void win_set_shadow_force(session_t *ps, win *w, switch_t val);
-
-void win_set_fade_force(session_t *ps, win *w, switch_t val);
-
-void win_set_focused_force(session_t *ps, win *w, switch_t val);
-
-void win_set_invert_color_force(session_t *ps, win *w, switch_t val);
void opts_init_track_focus(session_t *ps);
diff --git a/src/compton.c b/src/compton.c
index 17e17ac..8a41937 100644
--- a/src/compton.c
+++ b/src/compton.c
@@ -154,11 +154,11 @@ void cxinerama_upd_scrs(session_t *ps) {
*
* XXX move to win.c
*/
-static inline win *find_win_all(session_t *ps, const xcb_window_t wid) {
+static inline struct managed_win *find_win_all(session_t *ps, const xcb_window_t wid) {
if (!wid || PointerRoot == wid || wid == ps->root || wid == ps->overlay)
return NULL;
- win *w = find_win(ps, wid);
+ auto w = find_managed_win(ps, wid);
if (!w)
w = find_toplevel(ps, wid);
if (!w)
@@ -217,8 +217,8 @@ static double fade_timeout(session_t *ps) {
* @param steps steps of fading
* @return whether we are still in fading mode
*/
-static bool run_fade(session_t *ps, win **_w, long steps) {
- win *w = *_w;
+static bool run_fade(session_t *ps, struct managed_win **_w, long steps) {
+ auto w = *_w;
if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) {
// We are not fading
assert(w->opacity_tgt == w->opacity);
@@ -226,14 +226,14 @@ static bool run_fade(session_t *ps, win **_w, long steps) {
}
if (!win_should_fade(ps, w)) {
- log_debug("Window %#010x %s doesn't need fading", w->id, w->name);
+ log_debug("Window %#010x %s doesn't need fading", w->base.id, w->name);
w->opacity = w->opacity_tgt;
}
if (w->opacity == w->opacity_tgt) {
// We have reached target opacity.
// We don't call win_check_fade_finished here because that could destroy
// the window, but we still need the damage info from this window
- log_debug("Fading finished for window %#010x %s", w->id, w->name);
+ log_debug("Fading finished for window %#010x %s", w->base.id, w->name);
return false;
}
@@ -281,11 +281,11 @@ static int should_ignore(session_t *ps, unsigned long sequence) {
*/
uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) {
uint32_t evmask = 0;
- win *w = NULL;
+ struct managed_win *w = NULL;
// Check if it's a mapped frame window
if (WIN_EVMODE_FRAME == mode ||
- ((w = find_win(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) {
+ ((w = find_managed_win(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) {
evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE;
if (ps->o.track_focus && !ps->o.use_ewmh_active_win)
evmask |= XCB_EVENT_MASK_FOCUS_CHANGE;
@@ -302,38 +302,6 @@ uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) {
return evmask;
}
-/**
- * Find out the WM frame of a client window by querying X.
- *
- * @param ps current session
- * @param wid window ID
- * @return struct _win object of the found window, NULL if not found
- */
-win *find_toplevel2(session_t *ps, xcb_window_t wid) {
- // TODO this should probably be an "update tree", then find_toplevel.
- // current approach is a bit more "racy"
- win *w = NULL;
-
- // We traverse through its ancestors to find out the frame
- while (wid && wid != ps->root && !(w = find_win(ps, wid))) {
- xcb_query_tree_reply_t *reply;
-
- // xcb_query_tree probably fails if you run compton when X is somehow
- // initializing (like add it in .xinitrc). In this case
- // just leave it alone.
- reply = xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, wid), NULL);
- if (reply == NULL) {
- break;
- }
-
- wid = reply->parent;
-
- free(reply);
- }
-
- return w;
-}
-
/**
* Recheck currently focused window and set its w->focused
* to true.
@@ -341,7 +309,7 @@ win *find_toplevel2(session_t *ps, xcb_window_t wid) {
* @param ps current session
* @return struct _win of currently focused window, NULL if not found
*/
-win *recheck_focus(session_t *ps) {
+struct managed_win *recheck_focus(session_t *ps) {
// Use EWMH _NET_ACTIVE_WINDOW if enabled
if (ps->o.use_ewmh_active_win) {
update_ewmh_active_win(ps);
@@ -359,10 +327,10 @@ win *recheck_focus(session_t *ps) {
free(reply);
}
- win *w = find_win_all(ps, wid);
+ auto w = find_win_all(ps, wid);
log_trace("%#010" PRIx32 " (%#010lx \"%s\") focused.", wid,
- (w ? w->id : XCB_NONE), (w ? w->name : NULL));
+ (w ? w->base.id : XCB_NONE), (w ? w->name : NULL));
// And we set the focus state here
if (w) {
@@ -418,10 +386,10 @@ static void handle_root_flags(session_t *ps) {
}
}
-static win *paint_preprocess(session_t *ps, bool *fade_running) {
+static struct managed_win *paint_preprocess(session_t *ps, bool *fade_running) {
// XXX need better, more general name for `fade_running`. It really
// means if fade is still ongoing after the current frame is rendered
- win *t = NULL;
+ struct managed_win *bottom = NULL;
*fade_running = false;
// Fading step calculation
@@ -438,7 +406,7 @@ static win *paint_preprocess(session_t *ps, bool *fade_running) {
ps->fade_time += steps * ps->o.fade_delta;
// First, let's process fading
- list_foreach_safe(win, w, &ps->window_stack, stack_neighbour) {
+ win_stack_foreach_managed_safe(w, &ps->window_stack) {
const winmode_t mode_old = w->mode;
const bool was_painted = w->to_paint;
const double opacity_old = w->opacity;
@@ -491,7 +459,7 @@ static win *paint_preprocess(session_t *ps, bool *fade_running) {
// Track whether it's the highest window to paint
bool is_highest = true;
bool reg_ignore_valid = true;
- list_foreach(win, w, &ps->window_stack, stack_neighbour) {
+ win_stack_foreach_managed(w, &ps->window_stack) {
__label__ skip_window;
bool to_paint = true;
// w->to_paint remembers whether this window is painted last time
@@ -520,10 +488,10 @@ static win *paint_preprocess(session_t *ps, bool *fade_running) {
// log_trace("%s %d %d %d", w->name, to_paint, w->opacity,
// w->paint_excluded);
- if ((w->flags & WIN_FLAGS_STALE_IMAGE) != 0 &&
+ if ((w->flags & WIN_FLAGS_IMAGE_STALE) != 0 &&
(w->flags & WIN_FLAGS_IMAGE_ERROR) == 0 && to_paint) {
// Image needs to be updated, update it.
- w->flags &= ~WIN_FLAGS_STALE_IMAGE;
+ w->flags &= ~WIN_FLAGS_IMAGE_STALE;
if (w->state != WSTATE_UNMAPPING && w->state != WSTATE_DESTROYING) {
// Rebind image only when the window does have an image
// available
@@ -584,8 +552,8 @@ static win *paint_preprocess(session_t *ps, bool *fade_running) {
unredir_possible = true;
}
- w->prev_trans = t;
- t = w;
+ w->prev_trans = bottom;
+ bottom = w;
// If the screen is not redirected and the window has redir_ignore set,
// this window should not cause the screen to become redirected
@@ -633,7 +601,7 @@ static win *paint_preprocess(session_t *ps, bool *fade_running) {
}
}
- return t;
+ return bottom;
}
/**
@@ -652,7 +620,7 @@ static void rebuild_shadow_exclude_reg(session_t *ps) {
exit(1);
}
-static void restack_win(session_t *ps, win *w, xcb_window_t new_above) {
+static void restack_win(session_t *ps, struct win *w, xcb_window_t new_above) {
xcb_window_t old_above;
if (!list_node_is_last(&ps->window_stack, &w->stack_neighbour)) {
@@ -661,13 +629,21 @@ static void restack_win(session_t *ps, win *w, xcb_window_t new_above) {
old_above = XCB_NONE;
}
log_debug("Restack %#010x (%s), old_above: %#010x, new_above: %#010x", w->id,
- w->name, old_above, new_above);
+ win_get_name_if_managed(w), old_above, new_above);
+
+ struct managed_win *mw = NULL;
+ if (w->managed) {
+ mw = (struct managed_win *)w;
+ }
if (old_above != new_above) {
- w->reg_ignore_valid = false;
- rc_region_unref(&w->reg_ignore);
- if (!list_node_is_last(&ps->window_stack, &w->stack_neighbour)) {
- auto next_w = list_next_entry(w, stack_neighbour);
+ if (mw) {
+ mw->reg_ignore_valid = false;
+ rc_region_unref(&mw->reg_ignore);
+ }
+
+ auto next_w = win_stack_find_next_managed(ps, &w->stack_neighbour);
+ if (next_w) {
next_w->reg_ignore_valid = false;
rc_region_unref(&next_w->reg_ignore);
}
@@ -676,7 +652,7 @@ static void restack_win(session_t *ps, win *w, xcb_window_t new_above) {
if (!new_above) {
new_next = &ps->window_stack;
} else {
- win *tmp_w = NULL;
+ struct win *tmp_w = NULL;
HASH_FIND_INT(ps->windows, &new_above, tmp_w);
if (!tmp_w) {
@@ -692,11 +668,13 @@ static void restack_win(session_t *ps, win *w, xcb_window_t new_above) {
list_move_before(&w->stack_neighbour, new_next);
// add damage for this window
- add_damage_from_win(ps, w);
+ if (mw) {
+ add_damage_from_win(ps, mw);
+ }
#ifdef DEBUG_RESTACK
log_trace("Window stack modified. Current stack:");
- for (win *c = ps->list; c; c = c->next) {
+ for (auto c = ps->list; c; c = c->next) {
const char *desc = "";
if (c->state == WSTATE_DESTROYING) {
desc = "(D) ";
@@ -709,7 +687,7 @@ static void restack_win(session_t *ps, win *w, xcb_window_t new_above) {
/// Free up all the images and deinit the backend
static void destroy_backend(session_t *ps) {
- list_foreach_safe(win, w, &ps->window_stack, stack_neighbour) {
+ win_stack_foreach_managed_safe(w, &ps->window_stack) {
// Wrapping up fading in progress
win_skip_fading(ps, &w);
@@ -757,7 +735,11 @@ static bool initialize_backend(session_t *ps) {
// window_stack shouldn't include window that's not in the hash table at
// this point. Since there cannot be any fading windows.
- HASH_ITER2(ps->windows, w) {
+ HASH_ITER2(ps->windows, _w) {
+ if (!_w->managed) {
+ continue;
+ }
+ auto w = (struct managed_win *)_w;
if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) {
if (!win_bind_image(ps, w)) {
w->flags |= WIN_FLAGS_IMAGE_ERROR;
@@ -797,8 +779,8 @@ void configure_root(session_t *ps, int width, int height) {
ps->damage = ps->damage_ring + ps->ndamage - 1;
// Invalidate reg_ignore from the top
- if (!list_is_empty(&ps->window_stack)) {
- auto top_w = list_entry(ps->window_stack.next, win, stack_neighbour);
+ auto top_w = win_stack_find_next_managed(ps, &ps->window_stack);
+ if (top_w) {
rc_region_unref(&top_w->reg_ignore);
top_w->reg_ignore_valid = false;
}
@@ -831,7 +813,7 @@ void configure_root(session_t *ps, int width, int height) {
/// Handle configure event of a regular window
void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
- win *w = find_win(ps, ce->window);
+ auto w = find_managed_win(ps, ce->window);
region_t damage;
pixman_region32_init(&damage);
@@ -843,9 +825,9 @@ void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
w->state == WSTATE_DESTROYING) {
// Only restack the window to make sure we can handle future restack
// notification correctly
- restack_win(ps, w, ce->above_sibling);
+ restack_win(ps, &w->base, ce->above_sibling);
} else {
- restack_win(ps, w, ce->above_sibling);
+ restack_win(ps, &w->base, ce->above_sibling);
bool factor_change = false;
win_extents(w, &damage);
@@ -889,14 +871,14 @@ void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
}
void circulate_win(session_t *ps, xcb_circulate_notify_event_t *ce) {
- win *w = find_win(ps, ce->window);
+ auto w = find_win(ps, ce->window);
xcb_window_t new_above;
if (!w)
return;
if (ce->place == PlaceOnTop) {
- new_above = list_entry(ps->window_stack.next, win, stack_neighbour)->id;
+ new_above = list_entry(ps->window_stack.next, struct win, stack_neighbour)->id;
} else {
new_above = XCB_NONE;
}
@@ -962,48 +944,6 @@ void force_repaint(session_t *ps) {
*/
///@{
-/**
- * Set w->shadow_force of a window.
- */
-void win_set_shadow_force(session_t *ps, win *w, switch_t val) {
- if (val != w->shadow_force) {
- w->shadow_force = val;
- win_determine_shadow(ps, w);
- queue_redraw(ps);
- }
-}
-
-/**
- * Set w->fade_force of a window.
- *
- * Doesn't affect fading already in progress
- */
-void win_set_fade_force(session_t *ps, win *w, switch_t val) {
- w->fade_force = val;
-}
-
-/**
- * Set w->focused_force of a window.
- */
-void win_set_focused_force(session_t *ps, win *w, switch_t val) {
- if (val != w->focused_force) {
- w->focused_force = val;
- win_update_focused(ps, w);
- queue_redraw(ps);
- }
-}
-
-/**
- * Set w->invert_color_force of a window.
- */
-void win_set_invert_color_force(session_t *ps, win *w, switch_t val) {
- if (val != w->invert_color_force) {
- w->invert_color_force = val;
- win_determine_invert_color(ps, w);
- queue_redraw(ps);
- }
-}
-
/**
* Enable focus tracking.
*/
@@ -1017,7 +957,11 @@ void opts_init_track_focus(session_t *ps) {
if (!ps->o.use_ewmh_active_win) {
// Start listening to FocusChange events
HASH_ITER2(ps->windows, w) {
- if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) {
+ if (!w->managed) {
+ continue;
+ }
+ auto mw = (struct managed_win *)w;
+ if (mw->a.map_state == XCB_MAP_STATE_VIEWABLE) {
xcb_change_window_attributes(
ps->c, w->id, XCB_CW_EVENT_MASK,
(const uint32_t[]){
@@ -1053,11 +997,12 @@ void opts_set_no_fading_openclose(session_t *ps, bool newval) {
void update_ewmh_active_win(session_t *ps) {
// Search for the window
xcb_window_t wid = wid_get_prop_window(ps, ps->root, ps->atom_ewmh_active_win);
- win *w = find_win_all(ps, wid);
+ auto w = find_win_all(ps, wid);
// Mark the window focused. No need to unfocus the previous one.
- if (w)
+ if (w) {
win_set_focused(ps, w, true);
+ }
}
// === Main ===
@@ -1437,12 +1382,12 @@ static void fade_timer_callback(EV_P_ ev_timer *w, int revents) {
static void _draw_callback(EV_P_ session_t *ps, int revents) {
if (ps->o.benchmark) {
if (ps->o.benchmark_wid) {
- win *wi = find_win(ps, ps->o.benchmark_wid);
- if (!wi) {
+ auto w = find_managed_win(ps, ps->o.benchmark_wid);
+ if (!w) {
log_fatal("Couldn't find specified benchmark window.");
exit(1);
}
- add_damage_from_win(ps, wi);
+ add_damage_from_win(ps, w);
} else {
force_repaint(ps);
}
@@ -1458,7 +1403,7 @@ static void _draw_callback(EV_P_ session_t *ps, int revents) {
// should be redirected.
bool fade_running = false;
bool was_redirected = ps->redirected;
- win *t = paint_preprocess(ps, &fade_running);
+ auto bottom = paint_preprocess(ps, &fade_running);
ps->tmout_unredir_hit = false;
if (!was_redirected && ps->redirected) {
@@ -1467,7 +1412,7 @@ static void _draw_callback(EV_P_ session_t *ps, int revents) {
// window would be put into an error state). so we rerun paint_preprocess
// here to make sure the rendering decision we make is up-to-date
log_debug("Re-run paint_preprocess");
- t = paint_preprocess(ps, &fade_running);
+ bottom = paint_preprocess(ps, &fade_running);
}
// Start/stop fade timer depends on whether window are fading
@@ -1482,9 +1427,9 @@ static void _draw_callback(EV_P_ session_t *ps, int revents) {
if (ps->redirected && ps->o.stoppaint_force != ON) {
static int paint = 0;
if (ps->o.experimental_backends) {
- paint_all_new(ps, t, false);
+ paint_all_new(ps, bottom, false);
} else {
- paint_all(ps, t, false);
+ paint_all(ps, bottom, false);
}
paint++;
@@ -2122,21 +2067,29 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
children = NULL;
nchildren = 0;
}
+ free(reply);
for (int i = 0; i < nchildren; i++) {
- add_win(ps, children[i], i ? children[i - 1] : XCB_NONE);
+ auto w =
+ add_win_above(ps, children[i], i ? children[i - 1] : XCB_NONE);
+ fill_win(ps, w);
}
HASH_ITER2(ps->windows, w) {
- if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) {
- map_win(ps, w);
+ assert(!w->is_new);
+ if (!w->managed) {
+ continue;
+ }
+ auto mw = (struct managed_win *)w;
+ if (mw->a.map_state == XCB_MAP_STATE_VIEWABLE) {
+ map_win(ps, mw);
}
}
- free(reply);
log_trace("Initial stack:");
- list_foreach(win, w, &ps->window_stack, stack_neighbour) {
- log_trace("%#010x \"%s\"", w->id, w->name);
+ list_foreach(struct win, w, &ps->window_stack, stack_neighbour) {
+ log_trace("%#010x \"%s\"", w->id,
+ w->managed ? ((struct managed_win *)w)->name : "(null)");
}
}
@@ -2186,13 +2139,16 @@ static void session_destroy(session_t *ps) {
// Free window linked list
- list_foreach_safe(win, w, &ps->window_stack, stack_neighbour) {
- if (w->state != WSTATE_DESTROYING) {
+ list_foreach_safe(struct win, w, &ps->window_stack, stack_neighbour) {
+ if (!w->destroyed) {
win_ev_stop(ps, w);
HASH_DEL(ps->windows, w);
}
- free_win_res(ps, w);
+ if (w->managed) {
+ auto mw = (struct managed_win *)w;
+ free_win_res(ps, mw);
+ }
free(w);
}
list_init_head(&ps->window_stack);
diff --git a/src/compton.h b/src/compton.h
index a6c4759..8ab7fec 100644
--- a/src/compton.h
+++ b/src/compton.h
@@ -42,9 +42,7 @@ uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode);
xcb_window_t find_client_win(session_t *ps, xcb_window_t w);
-win *find_toplevel2(session_t *ps, xcb_window_t wid);
-
-win *recheck_focus(session_t *ps);
+struct managed_win *recheck_focus(session_t *ps);
/// Handle configure event of a root window
void configure_root(session_t *ps, int width, int height);
diff --git a/src/dbus.c b/src/dbus.c
index b60934f..cc11e79 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -21,13 +21,13 @@
#include "common.h"
#include "compiler.h"
#include "config.h"
+#include "list.h"
#include "log.h"
#include "string_utils.h"
#include "types.h"
#include "uthash_extra.h"
#include "utils.h"
#include "win.h"
-#include "list.h"
#include "dbus.h"
@@ -468,7 +468,7 @@ static bool cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data)
// Get the number of wids we are to include
unsigned count = 0;
HASH_ITER2(ps->windows, w) {
- assert(w->state != WSTATE_DESTROYING);
+ assert(!w->destroyed);
++count;
}
@@ -483,7 +483,7 @@ static bool cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data)
// Build the array
cdbus_window_t *pcur = arr;
HASH_ITER2(ps->windows, w) {
- assert(w->state != WSTATE_DESTROYING);
+ assert(!w->destroyed);
*pcur = w->id;
++pcur;
}
@@ -743,7 +743,7 @@ static bool cdbus_process_win_get(session_t *ps, DBusMessage *msg) {
return false;
}
- win *w = find_win(ps, wid);
+ auto w = find_managed_win(ps, wid);
if (!w) {
log_error("Window %#010x not found.", wid);
@@ -757,14 +757,16 @@ static bool cdbus_process_win_get(session_t *ps, DBusMessage *msg) {
return true; \
}
- cdbus_m_win_get_do(id, cdbus_reply_wid);
+ cdbus_m_win_get_do(base.id, cdbus_reply_wid);
// next
if (!strcmp("next", target)) {
- cdbus_reply_wid(ps, msg,
- (list_node_is_last(&ps->window_stack, &w->stack_neighbour)
- ? 0
- : list_next_entry(w, stack_neighbour)->id));
+ cdbus_reply_wid(
+ ps, msg,
+ (list_node_is_last(&ps->window_stack, &w->base.stack_neighbour)
+ ? 0
+ : list_entry(w->base.stack_neighbour.next, struct win, stack_neighbour)
+ ->id));
return true;
}
@@ -845,7 +847,7 @@ static bool cdbus_process_win_set(session_t *ps, DBusMessage *msg) {
return false;
}
- win *w = find_win(ps, wid);
+ auto w = find_managed_win(ps, wid);
if (!w) {
log_error("Window %#010x not found.", wid);
@@ -922,15 +924,17 @@ static bool cdbus_process_find_win(session_t *ps, DBusMessage *msg) {
cdbus_window_t client = XCB_NONE;
if (!cdbus_msg_get_arg(msg, 1, CDBUS_TYPE_WINDOW, &client))
return false;
- win *w = find_toplevel(ps, client);
- if (w)
- wid = w->id;
+ auto w = find_toplevel(ps, client);
+ if (w) {
+ wid = w->base.id;
+ }
}
// Find focused window
else if (!strcmp("focused", target)) {
- win *w = find_focused(ps);
- if (w)
- wid = w->id;
+ auto w = find_focused(ps);
+ if (w) {
+ wid = w->base.id;
+ }
} else {
log_error(CDBUS_ERROR_BADTGT_S, target);
cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, CDBUS_ERROR_BADTGT_S, target);
@@ -1301,37 +1305,37 @@ static DBusHandlerResult cdbus_process(DBusConnection *c, DBusMessage *msg, void
/** @name Core callbacks
*/
///@{
-void cdbus_ev_win_added(session_t *ps, win *w) {
+void cdbus_ev_win_added(session_t *ps, struct win *w) {
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_added", w->id);
}
-void cdbus_ev_win_destroyed(session_t *ps, win *w) {
+void cdbus_ev_win_destroyed(session_t *ps, struct win *w) {
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_destroyed", w->id);
}
-void cdbus_ev_win_mapped(session_t *ps, win *w) {
+void cdbus_ev_win_mapped(session_t *ps, struct win *w) {
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_mapped", w->id);
}
-void cdbus_ev_win_unmapped(session_t *ps, win *w) {
+void cdbus_ev_win_unmapped(session_t *ps, struct win *w) {
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_unmapped", w->id);
}
-void cdbus_ev_win_focusout(session_t *ps, win *w) {
+void cdbus_ev_win_focusout(session_t *ps, struct win *w) {
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_focusout", w->id);
}
-void cdbus_ev_win_focusin(session_t *ps, win *w) {
+void cdbus_ev_win_focusin(session_t *ps, struct win *w) {
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_focusin", w->id);
diff --git a/src/dbus.h b/src/dbus.h
index d60b47e..54a58af 100644
--- a/src/dbus.h
+++ b/src/dbus.h
@@ -14,7 +14,7 @@
#include
typedef struct session session_t;
-typedef struct win win;
+struct win;
/**
* Return a string representation of a D-Bus message type.
@@ -34,21 +34,21 @@ bool cdbus_init(session_t *ps, const char *uniq_name);
void cdbus_destroy(session_t *ps);
/// Generate dbus win_added signal
-void cdbus_ev_win_added(session_t *ps, win *w);
+void cdbus_ev_win_added(session_t *ps, struct win *w);
/// Generate dbus win_destroyed signal
-void cdbus_ev_win_destroyed(session_t *ps, win *w);
+void cdbus_ev_win_destroyed(session_t *ps, struct win *w);
/// Generate dbus win_mapped signal
-void cdbus_ev_win_mapped(session_t *ps, win *w);
+void cdbus_ev_win_mapped(session_t *ps, struct win *w);
/// Generate dbus win_unmapped signal
-void cdbus_ev_win_unmapped(session_t *ps, win *w);
+void cdbus_ev_win_unmapped(session_t *ps, struct win *w);
/// Generate dbus win_focusout signal
-void cdbus_ev_win_focusout(session_t *ps, win *w);
+void cdbus_ev_win_focusout(session_t *ps, struct win *w);
/// Generate dbus win_focusin signal
-void cdbus_ev_win_focusin(session_t *ps, win *w);
+void cdbus_ev_win_focusin(session_t *ps, struct win *w);
// vim: set noet sw=8 ts=8 :
diff --git a/src/event.c b/src/event.c
index 13b491c..1804c24 100644
--- a/src/event.c
+++ b/src/event.c
@@ -50,7 +50,7 @@ static inline const char *ev_window_name(session_t *ps, xcb_window_t wid) {
} else if (ps->overlay == wid) {
name = "(Overlay)";
} else {
- win *w = find_win(ps, wid);
+ auto w = find_managed_win(ps, wid);
if (!w) {
w = find_toplevel(ps, wid);
}
@@ -169,7 +169,8 @@ static inline void ev_focus_out(session_t *ps, xcb_focus_out_event_t *ev) {
static inline void ev_create_notify(session_t *ps, xcb_create_notify_event_t *ev) {
assert(ev->parent == ps->root);
- add_win(ps, ev->window, 0);
+ // TODO delay fill_win
+ fill_win(ps, add_win_top(ps, ev->window));
}
static inline void ev_configure_notify(session_t *ps, xcb_configure_notify_event_t *ev) {
@@ -183,7 +184,7 @@ static inline void ev_configure_notify(session_t *ps, xcb_configure_notify_event
}
static inline void ev_destroy_notify(session_t *ps, xcb_destroy_notify_event_t *ev) {
- win *w = find_win(ps, ev->window);
+ auto w = find_managed_win(ps, ev->window);
if (w) {
unmap_win(ps, &w, true);
}
@@ -199,7 +200,7 @@ static inline void ev_map_notify(session_t *ps, xcb_map_notify_event_t *ev) {
}
static inline void ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev) {
- win *w = find_win(ps, ev->window);
+ auto w = find_managed_win(ps, ev->window);
if (w) {
unmap_win(ps, &w, false);
}
@@ -211,12 +212,13 @@ static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t
if (ev->parent == ps->root) {
// new window
- add_win(ps, ev->window, 0);
+ // TODO delay fill_win
+ fill_win(ps, add_win_top(ps, ev->window));
} else {
// otherwise, find and destroy the window first
- win *w = find_win(ps, ev->window);
- if (w) {
- unmap_win(ps, &w, true);
+ auto w = find_win(ps, ev->window);
+ if (w && w->managed) {
+ unmap_win(ps, (struct managed_win **)&w, true);
}
// Reset event mask in case something wrong happens
@@ -228,10 +230,10 @@ static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t
// Firstly, check if it's a known client window
if (!find_toplevel(ps, ev->window)) {
// If not, look for its frame window
- win *w_top = find_toplevel2(ps, ev->parent);
+ auto w_top = find_toplevel2(ps, ev->parent);
// If found, and the client window has not been determined, or its
// frame may not have a correct client, continue
- if (w_top && (!w_top->client_win || w_top->client_win == w_top->id)) {
+ if (w_top && (!w_top->client_win || w_top->client_win == w_top->base.id)) {
// If it has WM_STATE, mark it the client window
if (wid_has_prop(ps, ev->window, ps->atom_client)) {
w_top->wmwin = false;
@@ -328,9 +330,9 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
(const uint32_t[]){determine_evmask(
ps, ev->window, WIN_EVMODE_UNKNOWN)});
- win *w_top = find_toplevel2(ps, ev->window);
+ auto w_top = find_toplevel2(ps, ev->window);
// Initialize client_win as early as possible
- if (w_top && (!w_top->client_win || w_top->client_win == w_top->id) &&
+ if (w_top && (!w_top->client_win || w_top->client_win == w_top->base.id) &&
wid_has_prop(ps, ev->window, ps->atom_client)) {
w_top->wmwin = false;
win_unmark_client(ps, w_top);
@@ -342,14 +344,14 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If _NET_WM_WINDOW_TYPE changes... God knows why this would happen, but
// there are always some stupid applications. (#144)
if (ev->atom == ps->atom_win_type) {
- win *w = NULL;
+ struct managed_win *w = NULL;
if ((w = find_toplevel(ps, ev->window)))
win_update_wintype(ps, w);
}
// If _NET_WM_OPACITY changes
if (ev->atom == ps->atom_opacity) {
- win *w = find_win(ps, ev->window) ?: find_toplevel(ps, ev->window);
+ auto w = find_managed_win(ps, ev->window) ?: find_toplevel(ps, ev->window);
if (w) {
win_update_opacity_prop(ps, w);
// we cannot receive OPACITY change when window is destroyed
@@ -364,7 +366,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If frame extents property changes
if (ps->o.frame_opacity > 0 && ev->atom == ps->atom_frame_extents) {
- win *w = find_toplevel(ps, ev->window);
+ auto w = find_toplevel(ps, ev->window);
if (w) {
win_update_frame_extents(ps, w, ev->window);
// If frame extents change, the window needs repaint
@@ -374,7 +376,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If name changes
if (ps->o.track_wdata && (ps->atom_name == ev->atom || ps->atom_name_ewmh == ev->atom)) {
- win *w = find_toplevel(ps, ev->window);
+ auto w = find_toplevel(ps, ev->window);
if (w && 1 == win_get_name(ps, w)) {
win_on_factor_change(ps, w);
}
@@ -382,7 +384,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If class changes
if (ps->o.track_wdata && ps->atom_class == ev->atom) {
- win *w = find_toplevel(ps, ev->window);
+ auto w = find_toplevel(ps, ev->window);
if (w) {
win_get_class(ps, w);
win_on_factor_change(ps, w);
@@ -391,7 +393,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If role changes
if (ps->o.track_wdata && ps->atom_role == ev->atom) {
- win *w = find_toplevel(ps, ev->window);
+ auto w = find_toplevel(ps, ev->window);
if (w && 1 == win_get_role(ps, w)) {
win_on_factor_change(ps, w);
}
@@ -399,15 +401,16 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If _COMPTON_SHADOW changes
if (ps->o.respect_prop_shadow && ps->atom_compton_shadow == ev->atom) {
- win *w = find_win(ps, ev->window);
- if (w)
+ auto w = find_managed_win(ps, ev->window);
+ if (w) {
win_update_prop_shadow(ps, w);
+ }
}
// If a leader property changes
if ((ps->o.detect_transient && ps->atom_transient == ev->atom) ||
(ps->o.detect_client_leader && ps->atom_client_leader == ev->atom)) {
- win *w = find_toplevel(ps, ev->window);
+ auto w = find_toplevel(ps, ev->window);
if (w) {
win_update_leader(ps, w);
}
@@ -416,7 +419,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// Check for other atoms we are tracking
for (latom_t *platom = ps->track_atom_lst; platom; platom = platom->next) {
if (platom->atom == ev->atom) {
- win *w = find_win(ps, ev->window);
+ auto w = find_managed_win(ps, ev->window);
if (!w)
w = find_toplevel(ps, ev->window);
if (w)
@@ -426,7 +429,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
}
}
-static inline void repair_win(session_t *ps, win *w) {
+static inline void repair_win(session_t *ps, struct managed_win *w) {
if (w->a.map_state != XCB_MAP_STATE_VIEWABLE)
return;
@@ -472,18 +475,20 @@ static inline void ev_damage_notify(session_t *ps, xcb_damage_notify_event_t *de
return;
} */
- win *w = find_win(ps, de->drawable);
+ auto w = find_managed_win(ps, de->drawable);
- if (!w)
+ if (!w) {
return;
+ }
repair_win(ps, w);
}
static inline void ev_shape_notify(session_t *ps, xcb_shape_notify_event_t *ev) {
- win *w = find_win(ps, ev->affected_window);
- if (!w || w->a.map_state == XCB_MAP_STATE_UNMAPPED)
+ auto w = find_managed_win(ps, ev->affected_window);
+ if (!w || w->a.map_state == XCB_MAP_STATE_UNMAPPED) {
return;
+ }
/*
* Empty bounding_shape may indicated an
diff --git a/src/opengl.c b/src/opengl.c
index 8683827..11e4030 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -221,7 +221,7 @@ void glx_destroy(session_t *ps) {
return;
// Free all GLX resources of windows
- list_foreach(win, w, &ps->window_stack, stack_neighbour) {
+ win_stack_foreach_managed(w, &ps->window_stack) {
free_win_res_glx(ps, w);
}
diff --git a/src/opengl.h b/src/opengl.h
index 8c746d3..863a84d 100644
--- a/src/opengl.h
+++ b/src/opengl.h
@@ -161,7 +161,7 @@ static inline void free_paint_glx(session_t *ps, paint_t *ppaint) {
/**
* Free GLX part of win.
*/
-static inline void free_win_res_glx(session_t *ps, win *w) {
+static inline void free_win_res_glx(session_t *ps, struct managed_win *w) {
free_paint_glx(ps, &w->paint);
free_paint_glx(ps, &w->shadow_paint);
#ifdef CONFIG_OPENGL
diff --git a/src/render.c b/src/render.c
index 2565824..96c9fa8 100644
--- a/src/render.c
+++ b/src/render.c
@@ -197,8 +197,8 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, doubl
}
static inline void
-paint_region(session_t *ps, win *w, int x, int y, int wid, int hei, double opacity,
- const region_t *reg_paint, xcb_render_picture_t pict) {
+paint_region(session_t *ps, const struct managed_win *w, int x, int y, int wid, int hei,
+ double opacity, const region_t *reg_paint, xcb_render_picture_t pict) {
const int dx = (w ? w->g.x : 0) + x;
const int dy = (w ? w->g.y : 0) + y;
const bool argb = (w && (win_has_alpha(w) || ps->o.force_win_blend));
@@ -237,19 +237,19 @@ static inline bool paint_isvalid(session_t *ps, const paint_t *ppaint) {
/**
* Paint a window itself and dim it if asked.
*/
-void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
+void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint) {
// Fetch Pixmap
if (!w->paint.pixmap) {
w->paint.pixmap = x_new_id(ps->c);
- set_ignore_cookie(
- ps, xcb_composite_name_window_pixmap(ps->c, w->id, w->paint.pixmap));
+ set_ignore_cookie(ps, xcb_composite_name_window_pixmap(ps->c, w->base.id,
+ w->paint.pixmap));
}
xcb_drawable_t draw = w->paint.pixmap;
if (!draw) {
log_error("Failed to get pixmap from window %#010x (%s), window won't be "
"visible",
- w->id, w->name);
+ w->base.id, w->name);
return;
}
@@ -269,12 +269,12 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
// causing the jittering issue M4he reported in #7.
if (!paint_bind_tex(ps, &w->paint, 0, 0, false, 0, w->a.visual,
(!ps->o.glx_no_rebind_pixmap && w->pixmap_damaged))) {
- log_error("Failed to bind texture for window %#010x.", w->id);
+ log_error("Failed to bind texture for window %#010x.", w->base.id);
}
w->pixmap_damaged = false;
if (!paint_isvalid(ps, &w->paint)) {
- log_error("Window %#010x is missing painting data.", w->id);
+ log_error("Window %#010x is missing painting data.", w->base.id);
return;
}
@@ -504,7 +504,7 @@ static void paint_root(session_t *ps, const region_t *reg_paint) {
/**
* Generate shadow Picture
for a window.
*/
-static bool win_build_shadow(session_t *ps, win *w, double opacity) {
+static bool win_build_shadow(session_t *ps, struct managed_win *w, double opacity) {
const int width = w->widthb;
const int height = w->heightb;
// log_trace("(): building shadow for %s %d %d", w->name, width, height);
@@ -577,12 +577,13 @@ shadow_picture_err:
/**
* Paint the shadow of a window.
*/
-static inline void win_paint_shadow(session_t *ps, win *w, region_t *reg_paint) {
+static inline void
+win_paint_shadow(session_t *ps, struct managed_win *w, region_t *reg_paint) {
// Bind shadow pixmap to GLX texture if needed
paint_bind_tex(ps, &w->shadow_paint, 0, 0, false, 32, 0, false);
if (!paint_isvalid(ps, &w->shadow_paint)) {
- log_error("Window %#010x is missing shadow data.", w->id);
+ log_error("Window %#010x is missing shadow data.", w->base.id);
return;
}
@@ -664,8 +665,9 @@ static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t
/**
* Blur the background of a window.
*/
-static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer,
- const region_t *reg_paint) {
+static inline void
+win_blur_background(session_t *ps, struct managed_win *w,
+ xcb_render_picture_t tgt_buffer, const region_t *reg_paint) {
const int16_t x = w->g.x;
const int16_t y = w->g.y;
const auto wid = to_u16_checked(w->widthb);
@@ -770,7 +772,7 @@ static inline void resize_region(region_t *region, short mod) {
/// paint all windows
/// region = ??
/// region_real = the damage region
-void paint_all(session_t *ps, win *const t, bool ignore_damage) {
+void paint_all(session_t *ps, struct managed_win *t, bool ignore_damage) {
if (ps->o.xrender_sync_fence) {
if (ps->xsync_exists && !x_fence_sync(ps->c, ps->sync_fence)) {
log_error("x_fence_sync failed, xrender-sync-fence will be "
@@ -857,7 +859,7 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
// pixels painted.
//
// Whether this is beneficial is to be determined XXX
- for (win *w = t; w; w = w->prev_trans) {
+ for (auto w = t; w; w = w->prev_trans) {
region_t bshape = win_get_bounding_shape_global_by_val(w);
// Painting shadow
if (w->shadow) {
diff --git a/src/render.h b/src/render.h
index 430e670..92b71c8 100644
--- a/src/render.h
+++ b/src/render.h
@@ -12,9 +12,10 @@
typedef struct _glx_texture glx_texture_t;
typedef struct glx_prog_main glx_prog_main_t;
-typedef struct win win;
typedef struct session session_t;
+struct managed_win;
+
typedef struct paint {
xcb_pixmap_t pixmap;
xcb_render_picture_t pict;
@@ -27,9 +28,9 @@ typedef struct paint {
void render(session_t *ps, int x, int y, int dx, int dy, int w, int h, double opacity,
bool argb, bool neg, xcb_render_picture_t pict, glx_texture_t *ptex,
const region_t *reg_paint, const glx_prog_main_t *pprogram);
-void paint_one(session_t *ps, win *w, const region_t *reg_paint);
+void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint);
-void paint_all(session_t *ps, win *const t, bool ignore_damage);
+void paint_all(session_t *ps, struct managed_win *const t, bool ignore_damage);
void free_picture(xcb_connection_t *c, xcb_render_picture_t *p);
diff --git a/src/win.c b/src/win.c
index ca001d4..b4daf32 100644
--- a/src/win.c
+++ b/src/win.c
@@ -20,6 +20,7 @@
#include "compiler.h"
#include "compton.h"
#include "config.h"
+#include "list.h"
#include "log.h"
#include "region.h"
#include "render.h"
@@ -28,7 +29,6 @@
#include "uthash_extra.h"
#include "utils.h"
#include "x.h"
-#include "list.h"
#ifdef CONFIG_DBUS
#include "dbus.h"
@@ -47,7 +47,7 @@
/// region via a region_t pointer argument.
/// Function signature has to be (win *, region_t *)
#define gen_by_val(fun) \
- region_t fun##_by_val(const win *w) { \
+ region_t fun##_by_val(const struct managed_win *w) { \
region_t ret; \
pixman_region32_init(&ret); \
fun(w, &ret); \
@@ -58,7 +58,7 @@
* Clear leader cache of all windows.
*/
static inline void clear_cache_win_leaders(session_t *ps) {
- list_foreach(win, w, &ps->window_stack, stack_neighbour) {
+ win_stack_foreach_managed(w, &ps->window_stack) {
w->cache_leader = XCB_NONE;
}
}
@@ -83,9 +83,13 @@ static inline void group_update_focused(session_t *ps, xcb_window_t leader) {
return;
HASH_ITER2(ps->windows, w) {
- assert(w->state != WSTATE_DESTROYING);
- if (win_get_leader(ps, w) == leader) {
- win_update_focused(ps, w);
+ assert(!w->destroyed);
+ if (!w->managed) {
+ continue;
+ }
+ auto mw = (struct managed_win *)w;
+ if (win_get_leader(ps, mw) == leader) {
+ win_update_focused(ps, mw);
}
}
@@ -99,12 +103,17 @@ static inline void group_update_focused(session_t *ps, xcb_window_t leader) {
* @return true if the window group is focused, false otherwise
*/
static inline bool group_is_focused(session_t *ps, xcb_window_t leader) {
- if (!leader)
+ if (!leader) {
return false;
+ }
HASH_ITER2(ps->windows, w) {
- assert(w->state != WSTATE_DESTROYING);
- if (win_get_leader(ps, w) == leader && win_is_focused_real(ps, w)) {
+ assert(!w->destroyed);
+ if (!w->managed) {
+ continue;
+ }
+ auto mw = (struct managed_win *)w;
+ if (win_get_leader(ps, mw) == leader && win_is_focused_real(ps, mw)) {
return true;
}
}
@@ -115,7 +124,7 @@ static inline bool group_is_focused(session_t *ps, xcb_window_t leader) {
/**
* Get a rectangular region a window occupies, excluding shadow.
*/
-static void win_get_region_local(const win *w, region_t *res) {
+static void win_get_region_local(const struct managed_win *w, region_t *res) {
assert(w->widthb >= 0 && w->heightb >= 0);
pixman_region32_fini(res);
pixman_region32_init_rect(res, 0, 0, (uint)w->widthb, (uint)w->heightb);
@@ -124,7 +133,7 @@ static void win_get_region_local(const win *w, region_t *res) {
/**
* Get a rectangular region a window occupies, excluding frame and shadow.
*/
-void win_get_region_noframe_local(const win *w, region_t *res) {
+void win_get_region_noframe_local(const struct managed_win *w, region_t *res) {
const margin_t extents = win_calc_frame_extents(w);
int x = extents.left;
@@ -140,7 +149,7 @@ void win_get_region_noframe_local(const win *w, region_t *res) {
gen_by_val(win_get_region_noframe_local);
-void win_get_region_frame_local(const win *w, region_t *res) {
+void win_get_region_frame_local(const struct managed_win *w, region_t *res) {
const margin_t extents = win_calc_frame_extents(w);
pixman_region32_fini(res);
pixman_region32_init_rects(
@@ -172,7 +181,7 @@ gen_by_val(win_get_region_frame_local);
* @param ps current session
* @param w struct _win element representing the window
*/
-void add_damage_from_win(session_t *ps, win *w) {
+void add_damage_from_win(session_t *ps, const struct managed_win *w) {
// XXX there was a cached extents region, investigate
// if that's better
region_t extents;
@@ -183,7 +192,7 @@ void add_damage_from_win(session_t *ps, win *w) {
}
/// Release the images attached to this window
-void win_release_image(backend_t *base, win *w) {
+void win_release_image(backend_t *base, struct managed_win *w) {
assert(w->win_image || (w->flags & WIN_FLAGS_IMAGE_ERROR));
if (w->win_image) {
base->ops->release_image(base, w->win_image);
@@ -199,12 +208,12 @@ void win_release_image(backend_t *base, win *w) {
}
static inline bool
-_win_bind_image(session_t *ps, win *w, void **win_image, void **shadow_image) {
+_win_bind_image(session_t *ps, struct managed_win *w, void **win_image, void **shadow_image) {
auto pixmap = x_new_id(ps->c);
auto e = xcb_request_check(
- ps->c, xcb_composite_name_window_pixmap_checked(ps->c, w->id, pixmap));
+ ps->c, xcb_composite_name_window_pixmap_checked(ps->c, w->base.id, pixmap));
if (e) {
- log_error("Failed to get named pixmap for window %#010x(%s)", w->id, w->name);
+ log_error("Failed to get named pixmap for window %#010x(%s)", w->base.id, w->name);
free(e);
return false;
}
@@ -228,12 +237,12 @@ _win_bind_image(session_t *ps, win *w, void **win_image, void **shadow_image) {
return true;
}
-bool win_bind_image(session_t *ps, win *w) {
+bool win_bind_image(session_t *ps, struct managed_win *w) {
assert(!w->win_image && !w->shadow_image);
return _win_bind_image(ps, w, &w->win_image, &w->shadow_image);
}
-bool win_try_rebind_image(session_t *ps, win *w) {
+bool win_try_rebind_image(session_t *ps, struct managed_win *w) {
log_trace("Freeing old window image");
// Must release first, otherwise breaks NVIDIA driver
win_release_image(ps->backend_data, w);
@@ -245,7 +254,7 @@ bool win_try_rebind_image(session_t *ps, win *w) {
* Check if a window has rounded corners.
* XXX This is really dumb
*/
-static bool attr_pure win_has_rounded_corners(const win *w) {
+static bool attr_pure win_has_rounded_corners(const struct managed_win *w) {
if (!w->bounding_shaped) {
return false;
}
@@ -278,7 +287,7 @@ static bool attr_pure win_has_rounded_corners(const win *w) {
return false;
}
-int win_get_name(session_t *ps, win *w) {
+int win_get_name(session_t *ps, struct managed_win *w) {
XTextProperty text_prop = {NULL, XCB_NONE, 0, 0};
char **strlst = NULL;
int nstr = 0;
@@ -314,11 +323,11 @@ int win_get_name(session_t *ps, win *w) {
log_trace("(%#010x): client = %#010x, name = \"%s\", "
"ret = %d",
- w->id, w->client_win, w->name, ret);
+ w->base.id, w->client_win, w->name, ret);
return ret;
}
-int win_get_role(session_t *ps, win *w) {
+int win_get_role(session_t *ps, struct managed_win *w) {
char **strlst = NULL;
int nstr = 0;
@@ -336,7 +345,7 @@ int win_get_role(session_t *ps, win *w) {
log_trace("(%#010x): client = %#010x, role = \"%s\", "
"ret = %d",
- w->id, w->client_win, w->role, ret);
+ w->base.id, w->client_win, w->role, ret);
return ret;
}
@@ -394,12 +403,12 @@ wid_get_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t def, opacity_t *
}
// XXX should distinguish between frame has alpha and window body has alpha
-bool win_has_alpha(const win *w) {
+bool win_has_alpha(const struct managed_win *w) {
return w->pictfmt && w->pictfmt->type == XCB_RENDER_PICT_TYPE_DIRECT &&
w->pictfmt->direct.alpha_mask;
}
-winmode_t win_calc_mode(const win *w) {
+winmode_t win_calc_mode(const struct managed_win *w) {
if (win_has_alpha(w) || w->opacity < 1.0) {
return WMODE_TRANS;
}
@@ -429,7 +438,7 @@ winmode_t win_calc_mode(const win *w) {
*
* @return target opacity
*/
-double win_calc_opacity_target(session_t *ps, const win *w) {
+double win_calc_opacity_target(session_t *ps, const struct managed_win *w) {
double opacity = 1;
if (w->state == WSTATE_UNMAPPED) {
@@ -463,7 +472,7 @@ double win_calc_opacity_target(session_t *ps, const win *w) {
/**
* Determine whether a window is to be dimmed.
*/
-bool win_should_dim(session_t *ps, const win *w) {
+bool win_should_dim(session_t *ps, const struct managed_win *w) {
// Make sure we do nothing if the window is unmapped / being destroyed
if (w->state == WSTATE_UNMAPPED) {
return false;
@@ -479,7 +488,7 @@ bool win_should_dim(session_t *ps, const win *w) {
/**
* Determine if a window should fade on opacity change.
*/
-bool win_should_fade(session_t *ps, const win *w) {
+bool win_should_fade(session_t *ps, const struct managed_win *w) {
// To prevent it from being overwritten by last-paint value if the window is
if (w->fade_force != UNSET) {
return w->fade_force;
@@ -488,7 +497,7 @@ bool win_should_fade(session_t *ps, const win *w) {
return false;
}
if (ps->o.no_fading_destroyed_argb && w->state == WSTATE_DESTROYING &&
- win_has_alpha(w) && w->client_win && w->client_win != w->id) {
+ win_has_alpha(w) && w->client_win && w->client_win != w->base.id) {
// deprecated
return false;
}
@@ -507,9 +516,9 @@ bool win_should_fade(session_t *ps, const win *w) {
*
* The property must be set on the outermost window, usually the WM frame.
*/
-void win_update_prop_shadow_raw(session_t *ps, win *w) {
+void win_update_prop_shadow_raw(session_t *ps, struct managed_win *w) {
winprop_t prop =
- wid_get_prop(ps, w->id, ps->atom_compton_shadow, 1, XCB_ATOM_CARDINAL, 32);
+ wid_get_prop(ps, w->base.id, ps->atom_compton_shadow, 1, XCB_ATOM_CARDINAL, 32);
if (!prop.nitems) {
w->prop_shadow = -1;
@@ -524,7 +533,7 @@ void win_update_prop_shadow_raw(session_t *ps, win *w) {
* Reread _COMPTON_SHADOW property from a window and update related
* things.
*/
-void win_update_prop_shadow(session_t *ps, win *w) {
+void win_update_prop_shadow(session_t *ps, struct managed_win *w) {
long attr_shadow_old = w->prop_shadow;
win_update_prop_shadow_raw(ps, w);
@@ -533,12 +542,12 @@ void win_update_prop_shadow(session_t *ps, win *w) {
win_determine_shadow(ps, w);
}
-void win_set_shadow(session_t *ps, win *w, bool shadow_new) {
+void win_set_shadow(session_t *ps, struct managed_win *w, bool shadow_new) {
if (w->shadow == shadow_new) {
return;
}
- log_debug("Updating shadow property of window %#010x (%s) to %d", w->id, w->name,
+ log_debug("Updating shadow property of window %#010x (%s) to %d", w->base.id, w->name,
shadow_new);
if (ps->o.experimental_backends && ps->redirected &&
w->state != WSTATE_UNMAPPED && !(w->flags & WIN_FLAGS_IMAGE_ERROR)) {
@@ -580,8 +589,8 @@ void win_set_shadow(session_t *ps, win *w, bool shadow_new) {
* Determine if a window should have shadow, and update things depending
* on shadow state.
*/
-void win_determine_shadow(session_t *ps, win *w) {
- log_debug("Determining shadow of window %#010x (%s)", w->id, w->name);
+void win_determine_shadow(session_t *ps, struct managed_win *w) {
+ log_debug("Determining shadow of window %#010x (%s)", w->base.id, w->name);
bool shadow_new = w->shadow;
if (w->shadow_force != UNSET) {
@@ -607,7 +616,7 @@ void win_determine_shadow(session_t *ps, win *w) {
win_set_shadow(ps, w, shadow_new);
}
-void win_set_invert_color(session_t *ps, win *w, bool invert_color_new) {
+void win_set_invert_color(session_t *ps, struct managed_win *w, bool invert_color_new) {
if (w->invert_color == invert_color_new)
return;
@@ -616,10 +625,52 @@ void win_set_invert_color(session_t *ps, win *w, bool invert_color_new) {
add_damage_from_win(ps, w);
}
+/**
+ * Set w->invert_color_force of a window.
+ */
+void win_set_invert_color_force(session_t *ps, struct managed_win *w, switch_t val) {
+ if (val != w->invert_color_force) {
+ w->invert_color_force = val;
+ win_determine_invert_color(ps, w);
+ queue_redraw(ps);
+ }
+}
+
+/**
+ * Set w->fade_force of a window.
+ *
+ * Doesn't affect fading already in progress
+ */
+void win_set_fade_force(session_t *ps, struct managed_win *w, switch_t val) {
+ w->fade_force = val;
+}
+
+/**
+ * Set w->focused_force of a window.
+ */
+void win_set_focused_force(session_t *ps, struct managed_win *w, switch_t val) {
+ if (val != w->focused_force) {
+ w->focused_force = val;
+ win_update_focused(ps, w);
+ queue_redraw(ps);
+ }
+}
+
+/**
+ * Set w->shadow_force of a window.
+ */
+void win_set_shadow_force(session_t *ps, struct managed_win *w, switch_t val) {
+ if (val != w->shadow_force) {
+ w->shadow_force = val;
+ win_determine_shadow(ps, w);
+ queue_redraw(ps);
+ }
+}
+
/**
* Determine if a window should have color inverted.
*/
-void win_determine_invert_color(session_t *ps, win *w) {
+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)
@@ -630,7 +681,7 @@ void win_determine_invert_color(session_t *ps, win *w) {
win_set_invert_color(ps, w, invert_color_new);
}
-void win_set_blur_background(session_t *ps, win *w, bool blur_background_new) {
+void win_set_blur_background(session_t *ps, struct managed_win *w, bool blur_background_new) {
if (w->blur_background == blur_background_new)
return;
@@ -645,7 +696,7 @@ void win_set_blur_background(session_t *ps, win *w, bool blur_background_new) {
/**
* Determine if a window should have background blurred.
*/
-void win_determine_blur_background(session_t *ps, win *w) {
+void win_determine_blur_background(session_t *ps, struct managed_win *w) {
if (w->a.map_state != XCB_MAP_STATE_VIEWABLE)
return;
@@ -661,7 +712,7 @@ void win_determine_blur_background(session_t *ps, win *w) {
* TODO This override the window's opacity property, may not be
* a good idea.
*/
-void win_update_opacity_rule(session_t *ps, win *w) {
+void win_update_opacity_rule(session_t *ps, struct managed_win *w) {
if (w->a.map_state != XCB_MAP_STATE_VIEWABLE)
return;
@@ -678,16 +729,17 @@ void win_update_opacity_rule(session_t *ps, win *w) {
w->opacity_set = opacity;
w->opacity_is_set = is_set;
- if (!is_set)
- wid_rm_opacity_prop(ps, w->id);
- else
- wid_set_opacity_prop(ps, w->id, (opacity_t)(opacity * OPAQUE));
+ if (!is_set) {
+ wid_rm_opacity_prop(ps, w->base.id);
+ } else {
+ wid_set_opacity_prop(ps, w->base.id, (opacity_t)(opacity * OPAQUE));
+ }
}
/**
* Function to be called on window type changes.
*/
-void win_on_wtype_change(session_t *ps, win *w) {
+void win_on_wtype_change(session_t *ps, struct managed_win *w) {
win_determine_shadow(ps, w);
win_update_focused(ps, w);
if (ps->o.invert_color_list)
@@ -701,7 +753,7 @@ void win_on_wtype_change(session_t *ps, win *w) {
*
* TODO need better name
*/
-void win_on_factor_change(session_t *ps, win *w) {
+void win_on_factor_change(session_t *ps, struct managed_win *w) {
if (ps->o.shadow_blacklist)
win_determine_shadow(ps, w);
if (ps->o.invert_color_list)
@@ -723,7 +775,7 @@ void win_on_factor_change(session_t *ps, win *w) {
/**
* Update cache data in struct _win that depends on window size.
*/
-void win_on_win_size_change(session_t *ps, win *w) {
+void win_on_win_size_change(session_t *ps, struct managed_win *w) {
w->widthb = w->g.width + w->g.border_width * 2;
w->heightb = w->g.height + w->g.border_width * 2;
w->shadow_dx = ps->o.shadow_offset_x;
@@ -734,7 +786,7 @@ void win_on_win_size_change(session_t *ps, win *w) {
if (ps->o.experimental_backends && ps->redirected) {
if (w->state == WSTATE_MAPPED || w->state == WSTATE_MAPPING ||
w->state == WSTATE_FADING) {
- w->flags |= WIN_FLAGS_STALE_IMAGE;
+ w->flags |= WIN_FLAGS_IMAGE_STALE;
} else {
assert(w->state == WSTATE_UNMAPPED);
}
@@ -746,7 +798,7 @@ void win_on_win_size_change(session_t *ps, win *w) {
/**
* Update window type.
*/
-void win_update_wintype(session_t *ps, win *w) {
+void win_update_wintype(session_t *ps, struct managed_win *w) {
const wintype_t wtype_old = w->window_type;
// Detect window type here
@@ -774,7 +826,7 @@ void win_update_wintype(session_t *ps, win *w) {
* @param w struct _win of the parent window
* @param client window ID of the client window
*/
-void win_mark_client(session_t *ps, win *w, xcb_window_t client) {
+void win_mark_client(session_t *ps, struct managed_win *w, xcb_window_t client) {
w->client_win = client;
// If the window isn't mapped yet, stop here, as the function will be
@@ -821,7 +873,7 @@ void win_mark_client(session_t *ps, win *w, xcb_window_t client) {
* @param ps current session
* @param w struct _win of the parent window
*/
-void win_unmark_client(session_t *ps, win *w) {
+void win_unmark_client(session_t *ps, struct managed_win *w) {
xcb_window_t client = w->client_win;
w->client_win = XCB_NONE;
@@ -838,7 +890,7 @@ void win_unmark_client(session_t *ps, win *w) {
* @param ps current session
* @param w struct _win of the parent window
*/
-void win_recheck_client(session_t *ps, win *w) {
+void win_recheck_client(session_t *ps, struct managed_win *w) {
// Initialize wmwin to false
w->wmwin = false;
@@ -846,15 +898,16 @@ void win_recheck_client(session_t *ps, win *w) {
// Always recursively look for a window with WM_STATE, as Fluxbox
// sets override-redirect flags on all frame windows.
- xcb_window_t cw = find_client_win(ps, w->id);
- if (cw)
- log_trace("(%#010x): client %#010x", w->id, cw);
+ xcb_window_t cw = find_client_win(ps, w->base.id);
+ if (cw) {
+ log_trace("(%#010x): client %#010x", w->base.id, cw);
+ }
// Set a window's client window to itself if we couldn't find a
// client window
if (!cw) {
- cw = w->id;
+ cw = w->base.id;
w->wmwin = !w->a.override_redirect;
- log_trace("(%#010x): client self (%s)", w->id,
+ log_trace("(%#010x): client self (%s)", w->base.id,
(w->wmwin ? "wmwin" : "override-redirected"));
}
@@ -869,7 +922,7 @@ void win_recheck_client(session_t *ps, win *w) {
/**
* Free all resources in a struct _win
.
*/
-void free_win_res(session_t *ps, win *w) {
+void free_win_res(session_t *ps, struct managed_win *w) {
// No need to call backend release_image here because
// finish_unmap_win should've done that for us.
// XXX unless we are called by session_destroy
@@ -890,9 +943,46 @@ void free_win_res(session_t *ps, win *w) {
free(w->role);
}
-// TODO: probably split into win_new (in win.c) and add_win (in compton.c)
-void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) {
- static const win win_def = {
+/// Insert a new window above window with id `below`, if there is no window, add to top
+/// New window will be in unmapped state
+struct win *add_win_above(session_t *ps, xcb_window_t id, xcb_window_t below) {
+ struct win *w = NULL;
+ HASH_FIND_INT(ps->windows, &below, w);
+ if (!w && !list_is_empty(&ps->window_stack)) {
+ // `below` window is not found even if the window stack is not empty
+ return NULL;
+ }
+
+ auto new_w = cmalloc(struct win);
+ if (list_is_empty(&ps->window_stack)) {
+ assert(w == NULL);
+ list_insert_after(&ps->window_stack, &new_w->stack_neighbour);
+ } else {
+ list_insert_before(&w->stack_neighbour, &new_w->stack_neighbour);
+ }
+ new_w->id = id;
+ new_w->managed = false;
+ new_w->is_new = true;
+ new_w->destroyed = false;
+
+ HASH_ADD_INT(ps->windows, id, new_w);
+ return new_w;
+}
+
+/// Insert a new win entry at the top of the stack
+struct win *add_win_top(session_t *ps, xcb_window_t id) {
+ if (!list_is_empty(&ps->window_stack)) {
+ auto first = list_entry(ps->window_stack.next, struct win, stack_neighbour);
+ return add_win_above(ps, id, first->id);
+ } else {
+ return add_win_above(ps, id, 0);
+ }
+}
+
+/// Query the Xorg for information about window `win`
+/// `win` pointer might become invalid after this function returns
+void fill_win(session_t *ps, struct win *w) {
+ static const struct managed_win win_def = {
// No need to initialize. (or, you can think that
// they are initialized right here).
// The following ones are updated during paint or paint preprocess
@@ -919,7 +1009,6 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) {
.invert_color_force = UNSET,
// Initialized in this function
- .id = XCB_NONE,
.a = {0},
.pictfmt = NULL,
.widthb = 0,
@@ -970,20 +1059,24 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) {
.shadow_paint = PAINT_INIT,
};
+ assert(!w->destroyed);
+ assert(w->is_new);
+
// Reject overlay window and already added windows
- if (id == ps->overlay) {
+ if (w->id == ps->overlay) {
return;
}
- auto duplicated_win = find_win(ps, id);
+ auto duplicated_win = find_managed_win(ps, w->id);
if (duplicated_win) {
- log_debug("Window %#010x (recorded name: %s) added multiple times", id,
+ log_debug("Window %#010x (recorded name: %s) added multiple times", w->id,
duplicated_win->name);
return;
}
- log_debug("Adding window %#010x, prev %#010x", id, prev);
- xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(ps->c, id);
+ log_debug("Adding window %#010x", w->id);
+ xcb_get_window_attributes_cookie_t acookie =
+ xcb_get_window_attributes(ps->c, w->id);
xcb_get_window_attributes_reply_t *a =
xcb_get_window_attributes_reply(ps->c, acookie, NULL);
if (!a || a->map_state == XCB_MAP_STATE_UNVIEWABLE) {
@@ -996,51 +1089,51 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) {
return;
}
+ if (a->_class == XCB_WINDOW_CLASS_INPUT_ONLY) {
+ // No need to manage this window, but we still keep it on the window stack
+ w->managed = false;
+ w->is_new = false;
+ return;
+ }
+
// Allocate and initialize the new win structure
- auto new = cmalloc(win);
+ auto new = cmalloc(struct managed_win);
// Fill structure
// We only need to initialize the part that are not initialized
// by map_win
*new = win_def;
- new->id = id;
+ new->base = *w;
+ new->base.is_new = false;
+ new->base.managed = true;
new->a = *a;
pixman_region32_init(&new->bounding_shape);
free(a);
// Create Damage for window (if not Input Only)
- if (new->a._class != XCB_WINDOW_CLASS_INPUT_ONLY) {
- new->damage = x_new_id(ps->c);
- xcb_generic_error_t *e = xcb_request_check(
- ps->c, xcb_damage_create_checked(ps->c, new->damage, id,
- XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY));
- if (e) {
- free(e);
- free(new);
- return;
- }
-
- new->pictfmt = x_get_pictform_for_visual(ps->c, new->a.visual);
+ new->damage = x_new_id(ps->c);
+ xcb_generic_error_t *e = xcb_request_check(
+ ps->c, xcb_damage_create_checked(ps->c, new->damage, w->id,
+ XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY));
+ if (e) {
+ free(e);
+ free(new);
+ return;
}
- // Find window insertion point
- struct list_node *p = NULL;
- if (prev) {
- win *w = NULL;
- HASH_FIND_INT(ps->windows, &prev, w);
- assert(w);
- p = w->stack_neighbour.prev;
- } else {
- p = &ps->window_stack;
- }
- list_insert_after(p, &new->stack_neighbour);
- HASH_ADD_INT(ps->windows, id, new);
+ new->pictfmt = x_get_pictform_for_visual(ps->c, new->a.visual);
+
+ list_replace(&w->stack_neighbour, &new->base.stack_neighbour);
+ struct win *replaced = NULL;
+ HASH_REPLACE_INT(ps->windows, id, &new->base, replaced);
+ assert(replaced == w);
+ free(w);
#ifdef CONFIG_DBUS
// Send D-Bus signal
if (ps->o.dbus) {
- cdbus_ev_win_added(ps, new);
+ cdbus_ev_win_added(ps, &new->base);
}
#endif
return;
@@ -1049,7 +1142,7 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) {
/**
* Update focused state of a window.
*/
-void win_update_focused(session_t *ps, win *w) {
+void win_update_focused(session_t *ps, struct managed_win *w) {
if (UNSET != w->focused_force) {
w->focused = w->focused_force;
} else {
@@ -1059,7 +1152,7 @@ void win_update_focused(session_t *ps, win *w) {
// windows specially
if (ps->o.wintype_option[w->window_type].focus ||
(ps->o.mark_wmwin_focused && w->wmwin) ||
- (ps->o.mark_ovredir_focused && w->id == w->client_win && !w->wmwin) ||
+ (ps->o.mark_ovredir_focused && w->base.id == w->client_win && !w->wmwin) ||
(w->a.map_state == XCB_MAP_STATE_VIEWABLE &&
c2_match(ps, w, ps->o.focus_blacklist, NULL)))
w->focused = true;
@@ -1088,7 +1181,7 @@ void win_update_focused(session_t *ps, win *w) {
/**
* Set leader of a window.
*/
-static inline void win_set_leader(session_t *ps, win *w, xcb_window_t nleader) {
+static inline void win_set_leader(session_t *ps, struct managed_win *w, xcb_window_t nleader) {
// If the leader changes
if (w->leader != nleader) {
xcb_window_t cache_leader_old = win_get_leader(ps, w);
@@ -1121,7 +1214,7 @@ static inline void win_set_leader(session_t *ps, win *w, xcb_window_t nleader) {
/**
* Update leader of a window.
*/
-void win_update_leader(session_t *ps, win *w) {
+void win_update_leader(session_t *ps, struct managed_win *w) {
xcb_window_t leader = XCB_NONE;
// Read the leader properties
@@ -1133,14 +1226,14 @@ void win_update_leader(session_t *ps, win *w) {
win_set_leader(ps, w, leader);
- log_trace("(%#010x): client %#010x, leader %#010x, cache %#010x", w->id,
+ log_trace("(%#010x): client %#010x, leader %#010x, cache %#010x", w->base.id,
w->client_win, w->leader, win_get_leader(ps, w));
}
/**
* Internal function of win_get_leader().
*/
-xcb_window_t win_get_leader_raw(session_t *ps, win *w, int recursions) {
+xcb_window_t win_get_leader_raw(session_t *ps, struct managed_win *w, int recursions) {
// Rebuild the cache if needed
if (!w->cache_leader && (w->client_win || w->leader)) {
// Leader defaults to client window
@@ -1149,7 +1242,7 @@ xcb_window_t win_get_leader_raw(session_t *ps, win *w, int recursions) {
// If the leader of this window isn't itself, look for its ancestors
if (w->cache_leader && w->cache_leader != w->client_win) {
- win *wp = find_toplevel(ps, w->cache_leader);
+ auto wp = find_toplevel(ps, w->cache_leader);
if (wp) {
// Dead loop?
if (recursions > WIN_GET_LEADER_MAX_RECURSION)
@@ -1167,7 +1260,7 @@ xcb_window_t win_get_leader_raw(session_t *ps, win *w, int recursions) {
* Retrieve the WM_CLASS
of a window and update its
* win
structure.
*/
-bool win_get_class(session_t *ps, win *w) {
+bool win_get_class(session_t *ps, struct managed_win *w) {
char **strlst = NULL;
int nstr = 0;
@@ -1195,7 +1288,7 @@ bool win_get_class(session_t *ps, win *w) {
log_trace("(%#010x): client = %#010x, "
"instance = \"%s\", general = \"%s\"",
- w->id, w->client_win, w->class_instance, w->class_general);
+ w->base.id, w->client_win, w->class_instance, w->class_general);
return true;
}
@@ -1203,7 +1296,7 @@ bool win_get_class(session_t *ps, win *w) {
/**
* Handle window focus change.
*/
-static void win_on_focus_change(session_t *ps, win *w) {
+static void win_on_focus_change(session_t *ps, struct managed_win *w) {
// If window grouping detection is enabled
if (ps->o.track_leader) {
xcb_window_t leader = win_get_leader(ps, w);
@@ -1239,9 +1332,9 @@ static void win_on_focus_change(session_t *ps, win *w) {
// Send D-Bus signal
if (ps->o.dbus) {
if (win_is_focused_real(ps, w))
- cdbus_ev_win_focusin(ps, w);
+ cdbus_ev_win_focusin(ps, &w->base);
else
- cdbus_ev_win_focusout(ps, w);
+ cdbus_ev_win_focusout(ps, &w->base);
}
#endif
}
@@ -1249,7 +1342,7 @@ static void win_on_focus_change(session_t *ps, win *w) {
/**
* Set real focused state of a window.
*/
-void win_set_focused(session_t *ps, win *w, bool focused) {
+void win_set_focused(session_t *ps, struct managed_win *w, bool focused) {
// Unmapped windows will have their focused state reset on map
if (w->a.map_state == XCB_MAP_STATE_UNMAPPED)
return;
@@ -1275,7 +1368,7 @@ void win_set_focused(session_t *ps, win *w, bool focused) {
* Note w->shadow and shadow geometry must be correct before calling this
* function.
*/
-void win_extents(const win *w, region_t *res) {
+void win_extents(const struct managed_win *w, region_t *res) {
pixman_region32_clear(res);
pixman_region32_union_rect(res, res, w->g.x, w->g.y, (uint)w->widthb, (uint)w->heightb);
@@ -1294,9 +1387,9 @@ gen_by_val(win_extents);
*
* Mark the window shape as updated
*/
-void win_update_bounding_shape(session_t *ps, win *w) {
+void win_update_bounding_shape(session_t *ps, struct managed_win *w) {
if (ps->shape_exists)
- w->bounding_shaped = win_bounding_shaped(ps, w->id);
+ w->bounding_shaped = win_bounding_shaped(ps, w->base.id);
pixman_region32_clear(&w->bounding_shape);
// Start with the window rectangular region
@@ -1311,7 +1404,8 @@ void win_update_bounding_shape(session_t *ps, win *w) {
*/
xcb_shape_get_rectangles_reply_t *r = xcb_shape_get_rectangles_reply(
- ps->c, xcb_shape_get_rectangles(ps->c, w->id, XCB_SHAPE_SK_BOUNDING), NULL);
+ ps->c,
+ xcb_shape_get_rectangles(ps->c, w->base.id, XCB_SHAPE_SK_BOUNDING), NULL);
if (!r)
break;
@@ -1353,7 +1447,7 @@ void win_update_bounding_shape(session_t *ps, win *w) {
// Note we only do this when screen is redirected, because
// otherwise win_data is not valid
assert(w->state != WSTATE_UNMAPPING && w->state != WSTATE_DESTROYING);
- w->flags |= WIN_FLAGS_STALE_IMAGE;
+ w->flags |= WIN_FLAGS_IMAGE_STALE;
}
} else {
free_paint(ps, &w->paint);
@@ -1366,15 +1460,15 @@ void win_update_bounding_shape(session_t *ps, win *w) {
/**
* Reread opacity property of a window.
*/
-void win_update_opacity_prop(session_t *ps, win *w) {
+void win_update_opacity_prop(session_t *ps, struct managed_win *w) {
// get frame opacity first
- w->has_opacity_prop = wid_get_opacity_prop(ps, w->id, OPAQUE, &w->opacity_prop);
+ w->has_opacity_prop = wid_get_opacity_prop(ps, w->base.id, OPAQUE, &w->opacity_prop);
if (w->has_opacity_prop)
// opacity found
return;
- if (ps->o.detect_client_opacity && w->client_win && w->id == w->client_win)
+ if (ps->o.detect_client_opacity && w->client_win && w->base.id == w->client_win)
// checking client opacity not allowed
return;
@@ -1386,7 +1480,7 @@ void win_update_opacity_prop(session_t *ps, win *w) {
/**
* Retrieve frame extents from a window.
*/
-void win_update_frame_extents(session_t *ps, win *w, xcb_window_t client) {
+void win_update_frame_extents(session_t *ps, struct managed_win *w, xcb_window_t client) {
winprop_t prop =
wid_get_prop(ps, client, ps->atom_frame_extents, 4L, XCB_ATOM_CARDINAL, 32);
@@ -1412,14 +1506,14 @@ void win_update_frame_extents(session_t *ps, win *w, xcb_window_t client) {
w->reg_ignore_valid = false;
}
- log_trace("(%#010x): %d, %d, %d, %d", w->id, w->frame_extents.left,
+ log_trace("(%#010x): %d, %d, %d, %d", w->base.id, w->frame_extents.left,
w->frame_extents.right, w->frame_extents.top, w->frame_extents.bottom);
free_winprop(&prop);
}
-bool win_is_region_ignore_valid(session_t *ps, const win *w) {
- list_foreach(win, i, &ps->window_stack, stack_neighbour) {
+bool win_is_region_ignore_valid(session_t *ps, const struct managed_win *w) {
+ win_stack_foreach_managed(i, &ps->window_stack) {
if (i == w)
break;
if (!i->reg_ignore_valid)
@@ -1431,11 +1525,16 @@ bool win_is_region_ignore_valid(session_t *ps, const win *w) {
/**
* Stop listening for events on a particular window.
*/
-void win_ev_stop(session_t *ps, const win *w) {
+void win_ev_stop(session_t *ps, const struct win *w) {
xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]){0});
- if (w->client_win) {
- xcb_change_window_attributes(ps->c, w->client_win, XCB_CW_EVENT_MASK,
+ if (!w->managed) {
+ return;
+ }
+
+ auto mw = (struct managed_win *)w;
+ if (mw->client_win) {
+ xcb_change_window_attributes(ps->c, mw->client_win, XCB_CW_EVENT_MASK,
(const uint32_t[]){0});
}
@@ -1444,8 +1543,8 @@ void win_ev_stop(session_t *ps, const win *w) {
}
}
-static void finish_unmap_win(session_t *ps, win **_w) {
- win *w = *_w;
+static void finish_unmap_win(session_t *ps, struct managed_win **_w) {
+ auto w = *_w;
w->ever_damaged = false;
w->reg_ignore_valid = false;
w->state = WSTATE_UNMAPPED;
@@ -1463,8 +1562,8 @@ static void finish_unmap_win(session_t *ps, win **_w) {
w->flags = 0;
}
-static void finish_destroy_win(session_t *ps, win **_w) {
- win *w = *_w;
+static void finish_destroy_win(session_t *ps, struct managed_win **_w) {
+ auto w = *_w;
if (w->state != WSTATE_UNMAPPED) {
// Only UNMAPPED state has window resources freed, otherwise
@@ -1479,14 +1578,14 @@ static void finish_destroy_win(session_t *ps, win **_w) {
// paint happened at least once, w->reg_ignore_valid would
// be true, and there is no need to invalid w->next->reg_ignore
// when w is destroyed.
- if (!list_node_is_last(&ps->window_stack, &w->stack_neighbour)) {
- auto next_w = list_next_entry(w, stack_neighbour);
+ if (!list_node_is_last(&ps->window_stack, &w->base.stack_neighbour)) {
+ auto next_w = list_next_entry(w, base.stack_neighbour); // XXX
rc_region_unref(&next_w->reg_ignore);
next_w->reg_ignore_valid = false;
}
- log_trace("Trying to destroy (%#010x)", w->id);
- list_remove(&w->stack_neighbour);
+ log_trace("Trying to destroy (%#010x)", w->base.id);
+ list_remove(&w->base.stack_neighbour);
if (w == ps->active_win) {
ps->active_win = NULL;
@@ -1497,7 +1596,7 @@ static void finish_destroy_win(session_t *ps, win **_w) {
// Drop w from all prev_trans to avoid accessing freed memory in
// repair_win()
// TODO there can only be one prev_trans pointing to w
- list_foreach(win, w2, &ps->window_stack, stack_neighbour) {
+ win_stack_foreach_managed(w2, &ps->window_stack) {
if (w == w2->prev_trans) {
w2->prev_trans = NULL;
}
@@ -1509,14 +1608,14 @@ static void finish_destroy_win(session_t *ps, win **_w) {
assert(false);
}
-static void finish_map_win(session_t *ps, win **_w) {
- win *w = *_w;
+static void finish_map_win(session_t *ps, struct managed_win **_w) {
+ auto w = *_w;
w->in_openclose = false;
w->state = WSTATE_MAPPED;
}
-void unmap_win(session_t *ps, win **_w, bool destroy) {
- win *w = *_w;
+void unmap_win(session_t *ps, struct managed_win **_w, bool destroy) {
+ auto w = *_w;
winstate_t target_state = destroy ? WSTATE_DESTROYING : WSTATE_UNMAPPING;
@@ -1532,7 +1631,7 @@ void unmap_win(session_t *ps, win **_w, bool destroy) {
return;
}
- log_trace("Unmapping %#010x \"%s\", destroy = %d", w->id, (w ? w->name : NULL), destroy);
+ log_trace("Unmapping %#010x \"%s\", destroy = %d", w->base.id, (w ? w->name : NULL), destroy);
if (unlikely(w->state == WSTATE_DESTROYING && !destroy)) {
log_warn("Trying to undestroy a window?");
@@ -1551,13 +1650,13 @@ void unmap_win(session_t *ps, win **_w, bool destroy) {
// Keep the window in the window stack, since we might still need to
// render it (fading out). Window will be removed from the stack when
// fading finishes.
- HASH_DEL(ps->windows, w);
+ HASH_DEL(ps->windows, &w->base);
}
if (unlikely(w->state == WSTATE_UNMAPPED) || w->a._class == XCB_WINDOW_CLASS_INPUT_ONLY) {
if (unlikely(!destroy)) {
log_warn("Unmapping an already unmapped window %#010x %s twice",
- w->id, w->name);
+ w->base.id, w->name);
return;
}
// Window is already unmapped, or is an Input Only window, just destroy it
@@ -1576,16 +1675,16 @@ void unmap_win(session_t *ps, win **_w, bool destroy) {
// don't care about properties anymore
if (!destroy) {
- win_ev_stop(ps, w);
+ win_ev_stop(ps, &w->base);
}
#ifdef CONFIG_DBUS
// Send D-Bus signal
if (ps->o.dbus) {
if (destroy) {
- cdbus_ev_win_destroyed(ps, w);
+ cdbus_ev_win_destroyed(ps, &w->base);
} else {
- cdbus_ev_win_unmapped(ps, w);
+ cdbus_ev_win_unmapped(ps, &w->base);
}
}
#endif
@@ -1598,8 +1697,8 @@ void unmap_win(session_t *ps, win **_w, bool destroy) {
/**
* Execute fade callback of a window if fading finished.
*/
-void win_check_fade_finished(session_t *ps, win **_w) {
- win *w = *_w;
+void win_check_fade_finished(session_t *ps, struct managed_win **_w) {
+ auto w = *_w;
if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) {
// No fading in progress
assert(w->opacity_tgt == w->opacity);
@@ -1618,13 +1717,13 @@ void win_check_fade_finished(session_t *ps, win **_w) {
/// Skip the current in progress fading of window,
/// transition the window straight to its end state
-void win_skip_fading(session_t *ps, win **_w) {
- win *w = *_w;
+void win_skip_fading(session_t *ps, struct managed_win **_w) {
+ auto w = *_w;
if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) {
assert(w->opacity_tgt == w->opacity);
return;
}
- log_trace("Skipping fading process of window %#010x (%s)", w->id, w->name);
+ log_trace("Skipping fading process of window %#010x (%s)", w->base.id, w->name);
w->opacity = w->opacity_tgt;
win_check_fade_finished(ps, _w);
}
@@ -1637,7 +1736,7 @@ void win_skip_fading(session_t *ps, win **_w) {
* TODO move to x.c
* TODO use xrandr
*/
-void win_update_screen(session_t *ps, win *w) {
+void win_update_screen(session_t *ps, struct managed_win *w) {
w->xinerama_scr = -1;
if (!ps->xinerama_scrs)
@@ -1661,7 +1760,7 @@ void win_update_screen(session_t *ps, win *w) {
void configure_win(session_t *, xcb_configure_notify_event_t *);
/// Map an already registered window
-void map_win(session_t *ps, win *w) {
+void map_win(session_t *ps, struct managed_win *w) {
assert(w);
// Don't care about window mapping if it's an InputOnly window
@@ -1670,7 +1769,7 @@ void map_win(session_t *ps, win *w) {
return;
}
- log_debug("Mapping (%#010x \"%s\")", w->id, w->name);
+ log_debug("Mapping (%#010x \"%s\")", w->base.id, w->name);
assert(w->state != WSTATE_DESTROYING);
if (w->state != WSTATE_UNMAPPED && w->state != WSTATE_UNMAPPING) {
@@ -1688,11 +1787,11 @@ void map_win(session_t *ps, win *w) {
// We stopped processing window size change when we were unmapped, refresh the
// size of the window
- xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(ps->c, w->id);
+ xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(ps->c, w->base.id);
xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(ps->c, gcookie, NULL);
if (!g) {
- log_error("Failed to get the geometry of window %#010x", w->id);
+ log_error("Failed to get the geometry of window %#010x", w->base.id);
return;
}
@@ -1717,12 +1816,12 @@ void map_win(session_t *ps, win *w) {
// Set window event mask before reading properties so that no property
// changes are lost
xcb_change_window_attributes(
- ps->c, w->id, XCB_CW_EVENT_MASK,
- (const uint32_t[]){determine_evmask(ps, w->id, WIN_EVMODE_FRAME)});
+ ps->c, w->base.id, XCB_CW_EVENT_MASK,
+ (const uint32_t[]){determine_evmask(ps, w->base.id, WIN_EVMODE_FRAME)});
// Notify compton when the shape of a window changes
if (ps->shape_exists) {
- xcb_shape_select_input(ps->c, w->id, 1);
+ xcb_shape_select_input(ps->c, w->base.id, 1);
}
// Update window mode here to check for ARGB windows
@@ -1738,7 +1837,7 @@ void map_win(session_t *ps, win *w) {
}
assert(w->client_win);
- log_debug("Window (%#010x) has type %s", w->id, WINTYPES[w->window_type]);
+ log_debug("Window (%#010x) has type %s", w->base.id, WINTYPES[w->window_type]);
// Update window focus state
win_update_focused(ps, w);
@@ -1759,7 +1858,7 @@ void map_win(session_t *ps, win *w) {
w->state = WSTATE_MAPPING;
w->opacity_tgt = win_calc_opacity_target(ps, w);
- log_debug("Window %#010x has opacity %f, opacity target is %f", w->id, w->opacity,
+ log_debug("Window %#010x has opacity %f, opacity target is %f", w->base.id, w->opacity,
w->opacity_tgt);
win_determine_blur_background(ps, w);
@@ -1777,7 +1876,7 @@ void map_win(session_t *ps, win *w) {
//
// Also because NVIDIA driver doesn't like seeing the same pixmap under different
// ids, so avoid naming the pixmap again when it didn't actually change.
- w->flags &= ~WIN_FLAGS_STALE_IMAGE;
+ w->flags &= ~WIN_FLAGS_IMAGE_STALE;
// Bind image after update_bounding_shape, so the shadow has the correct size.
if (ps->redirected && ps->o.experimental_backends) {
@@ -1789,7 +1888,7 @@ void map_win(session_t *ps, win *w) {
#ifdef CONFIG_DBUS
// Send D-Bus signal
if (ps->o.dbus) {
- cdbus_ev_win_mapped(ps, w);
+ cdbus_ev_win_mapped(ps, &w->base);
}
#endif
@@ -1813,7 +1912,7 @@ void map_win_by_id(session_t *ps, xcb_window_t id) {
return;
}
- win *w = find_win(ps, id);
+ auto w = find_managed_win(ps, id);
if (!w) {
return;
}
@@ -1822,36 +1921,134 @@ void map_win_by_id(session_t *ps, xcb_window_t id) {
}
/**
- * Find a window from window id in window linked list of the session.
+ * Find a managed window from window id in window linked list of the session.
*/
-win *find_win(session_t *ps, xcb_window_t id) {
+struct win *find_win(session_t *ps, xcb_window_t id) {
if (!id) {
return NULL;
}
- win *w = NULL;
+ struct win *w = NULL;
HASH_FIND_INT(ps->windows, &id, w);
- assert(w == NULL || w->state != WSTATE_DESTROYING);
+ assert(w == NULL || !w->destroyed);
return w;
}
+/**
+ * Find a managed window from window id in window linked list of the session.
+ */
+struct managed_win *find_managed_win(session_t *ps, xcb_window_t id) {
+ struct win *w = find_win(ps, id);
+ if (!w || !w->managed) {
+ return NULL;
+ }
+
+ auto mw = (struct managed_win *)w;
+ assert(mw->state != WSTATE_DESTROYING);
+ return mw;
+}
+
/**
* Find out the WM frame of a client window using existing data.
*
* @param id window ID
* @return struct win object of the found window, NULL if not found
*/
-win *find_toplevel(session_t *ps, xcb_window_t id) {
+struct managed_win *find_toplevel(session_t *ps, xcb_window_t id) {
if (!id) {
return NULL;
}
HASH_ITER2(ps->windows, w) {
- assert(w->state != WSTATE_DESTROYING);
- if (w->client_win == id) {
- return w;
+ assert(!w->destroyed);
+ if (!w->managed) {
+ continue;
+ }
+
+ auto mw = (struct managed_win *)w;
+ if (mw->client_win == id) {
+ return mw;
}
}
return NULL;
}
+
+/**
+ * Find out the WM frame of a client window by querying X.
+ *
+ * @param ps current session
+ * @param wid window ID
+ * @return struct _win object of the found window, NULL if not found
+ */
+struct managed_win *find_toplevel2(session_t *ps, xcb_window_t wid) {
+ // TODO this should probably be an "update tree", then find_toplevel.
+ // current approach is a bit more "racy"
+ struct win *w = NULL;
+
+ // We traverse through its ancestors to find out the frame
+ // Using find_win here because if we found a unmanaged window we know about, we
+ // can stop early.
+ while (wid && wid != ps->root && !(w = find_win(ps, wid))) {
+ // xcb_query_tree probably fails if you run compton when X is somehow
+ // initializing (like add it in .xinitrc). In this case
+ // just leave it alone.
+ auto reply = xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, wid), NULL);
+ if (reply == NULL) {
+ break;
+ }
+
+ wid = reply->parent;
+ free(reply);
+ }
+
+ if (w == NULL || !w->managed) {
+ return NULL;
+ }
+
+ return (struct managed_win *)w;
+}
+
+/**
+ * Check if a rectangle includes the whole screen.
+ */
+static inline bool rect_is_fullscreen(const session_t *ps, int x, int y, int wid, int hei) {
+ return (x <= 0 && y <= 0 && (x + wid) >= ps->root_width && (y + hei) >= ps->root_height);
+}
+
+/**
+ * Check if a window is a fullscreen window.
+ *
+ * It's not using w->border_size for performance measures.
+ */
+bool win_is_fullscreen(const session_t *ps, const struct managed_win *w) {
+ return rect_is_fullscreen(ps, w->g.x, w->g.y, w->widthb, w->heightb) &&
+ (!w->bounding_shaped || w->rounded_corners);
+}
+
+/**
+ * Check if a window will be painted solid.
+ */
+bool win_is_solid(const session_t *ps, const struct managed_win *w) {
+ return WMODE_SOLID == w->mode && !ps->o.force_win_blend;
+}
+
+/**
+ * Check if a window is really focused.
+ */
+bool win_is_focused_real(const session_t *ps, const struct managed_win *w) {
+ return w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->active_win == w;
+}
+
+// Find the managed window immediately below `i` in the window stack
+struct managed_win *
+win_stack_find_next_managed(const session_t *ps, const struct list_node *i) {
+ while (!list_node_is_last(&ps->window_stack, i)) {
+ auto next = list_entry(i->next, struct win, stack_neighbour);
+ if (next->managed) {
+ return (struct managed_win *)next;
+ }
+ i = &next->stack_neighbour;
+ }
+ return NULL;
+}
diff --git a/src/win.h b/src/win.h
index d258975..43fdde3 100644
--- a/src/win.h
+++ b/src/win.h
@@ -17,16 +17,23 @@
#include "backend/backend.h"
#include "c2.h"
#include "compiler.h"
+#include "list.h"
#include "region.h"
#include "render.h"
#include "types.h"
#include "utils.h"
#include "x.h"
-#include "list.h"
typedef struct session session_t;
typedef struct _glx_texture glx_texture_t;
+#define win_stack_foreach_managed(w, win_stack) \
+ list_foreach(struct managed_win, w, win_stack, base.stack_neighbour) if (w->base.managed)
+
+#define win_stack_foreach_managed_safe(w, win_stack) \
+ list_foreach_safe(struct managed_win, w, win_stack, \
+ base.stack_neighbour) if (w->base.managed)
+
#ifdef CONFIG_OPENGL
// FIXME this type should be in opengl.h
// it is very unideal for it to be here
@@ -108,15 +115,16 @@ typedef enum {
WSTATE_UNMAPPED,
} winstate_t;
-typedef enum win_flags {
+enum win_flags {
/// win_image/shadow_image is out of date
- WIN_FLAGS_STALE_IMAGE = 1,
+ WIN_FLAGS_IMAGE_STALE = 1,
/// there was an error trying to bind the images
WIN_FLAGS_IMAGE_ERROR = 2,
-} win_flags_t;
+};
/// An entry in the window stack. May or may not correspond to a window we know about.
struct window_stack_entry {
+ struct list_node stack_neighbour;
/// The actual window correspond to this stack entry. NULL if we didn't know about
/// this window (e.g. an InputOnly window, or we haven't handled the window
/// creation yet)
@@ -124,7 +132,6 @@ struct window_stack_entry {
/// The window id. Might not be unique in the stack, because there might be
/// destroyed window still fading out in the stack.
xcb_window_t id;
- struct list_node stack_neighbour;
};
/**
@@ -141,18 +148,30 @@ struct window_stack_entry {
/// Structure representing a top-level window compton manages.
typedef struct win win;
struct win {
+ UT_hash_handle hh;
struct list_node stack_neighbour;
+ /// ID of the top-level frame window.
+ xcb_window_t id;
+ /// Whether the window is destroyed from Xorg's perspective
+ bool destroyed : 1;
+ /// True if we just received CreateNotify, and haven't queried X for any info
+ /// about the window
+ bool is_new : 1;
+ /// True if this window is managed, i.e. this struct is actually a `managed_win`.
+ /// Always false if `is_new` is true.
+ bool managed : 1;
+};
+struct managed_win {
+ struct win base;
/// backend data attached to this window. Only available when
/// `state` is not UNMAPPED
void *win_image;
void *shadow_image;
/// Pointer to the next higher window to paint.
- win *prev_trans;
+ struct managed_win *prev_trans;
// TODO rethink reg_ignore
// Core members
- /// ID of the top-level frame window.
- xcb_window_t id;
/// The "mapped state" of this window, doesn't necessary
/// match X mapped state, because of fading.
winstate_t state;
@@ -299,64 +318,67 @@ struct win {
/// Textures and FBO background blur use.
glx_blur_cache_t glx_blur_cache;
#endif
- UT_hash_handle hh;
};
-void win_release_image(backend_t *base, win *w);
-bool must_use win_bind_image(session_t *ps, win *w);
+void win_release_image(backend_t *base, struct managed_win *w);
+bool must_use win_bind_image(session_t *ps, struct managed_win *w);
/// Attempt a rebind of window's images. If that failed, the original images are kept.
-bool must_use win_try_rebind_image(session_t *ps, win *w);
-int win_get_name(session_t *ps, win *w);
-int win_get_role(session_t *ps, win *w);
-winmode_t attr_pure win_calc_mode(const win *w);
+bool must_use win_try_rebind_image(session_t *ps, struct managed_win *w);
+int win_get_name(session_t *ps, struct managed_win *w);
+int win_get_role(session_t *ps, struct managed_win *w);
+winmode_t attr_pure win_calc_mode(const struct managed_win *w);
+void win_set_shadow_force(session_t *ps, struct managed_win *w, switch_t val);
+void win_set_fade_force(session_t *ps, struct managed_win *w, switch_t val);
+void win_set_focused_force(session_t *ps, struct managed_win *w, switch_t val);
+void win_set_invert_color_force(session_t *ps, struct managed_win *w, switch_t val);
/**
* Set real focused state of a window.
*/
-void win_set_focused(session_t *ps, win *w, bool focused);
-bool attr_pure win_should_fade(session_t *ps, const win *w);
-void win_update_prop_shadow_raw(session_t *ps, win *w);
-void win_update_prop_shadow(session_t *ps, win *w);
-void win_set_shadow(session_t *ps, win *w, bool shadow_new);
-void win_determine_shadow(session_t *ps, win *w);
-void win_set_invert_color(session_t *ps, win *w, bool invert_color_new);
-void win_determine_invert_color(session_t *ps, win *w);
-void win_set_blur_background(session_t *ps, win *w, bool blur_background_new);
-void win_determine_blur_background(session_t *ps, win *w);
-void win_on_wtype_change(session_t *ps, win *w);
-void win_on_factor_change(session_t *ps, win *w);
+void win_set_focused(session_t *ps, struct managed_win *w, bool focused);
+bool attr_pure win_should_fade(session_t *ps, const struct managed_win *w);
+void win_update_prop_shadow_raw(session_t *ps, struct managed_win *w);
+void win_update_prop_shadow(session_t *ps, struct managed_win *w);
+void win_set_shadow(session_t *ps, struct managed_win *w, bool shadow_new);
+void win_determine_shadow(session_t *ps, struct managed_win *w);
+void win_set_invert_color(session_t *ps, struct managed_win *w, bool invert_color_new);
+void win_determine_invert_color(session_t *ps, struct managed_win *w);
+void win_set_blur_background(session_t *ps, struct managed_win *w, bool blur_background_new);
+void win_determine_blur_background(session_t *ps, struct managed_win *w);
+void win_on_wtype_change(session_t *ps, struct managed_win *w);
+void win_on_factor_change(session_t *ps, struct managed_win *w);
/**
* Update cache data in struct _win that depends on window size.
*/
-void win_on_win_size_change(session_t *ps, win *w);
-void win_update_wintype(session_t *ps, win *w);
-void win_mark_client(session_t *ps, win *w, xcb_window_t client);
-void win_unmark_client(session_t *ps, win *w);
-void win_recheck_client(session_t *ps, win *w);
-xcb_window_t win_get_leader_raw(session_t *ps, win *w, int recursions);
-bool win_get_class(session_t *ps, win *w);
-double attr_pure win_calc_opacity_target(session_t *ps, const win *w);
-bool attr_pure win_should_dim(session_t *ps, const win *w);
-void win_update_screen(session_t *, win *);
+void win_on_win_size_change(session_t *ps, struct managed_win *w);
+void win_update_wintype(session_t *ps, struct managed_win *w);
+void win_mark_client(session_t *ps, struct managed_win *w, xcb_window_t client);
+void win_unmark_client(session_t *ps, struct managed_win *w);
+void win_recheck_client(session_t *ps, struct managed_win *w);
+xcb_window_t win_get_leader_raw(session_t *ps, struct managed_win *w, int recursions);
+bool win_get_class(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 *);
/// Prepare window for fading because opacity target changed
-void win_start_fade(session_t *, win **);
+void win_start_fade(session_t *, struct managed_win **);
/**
* Reread opacity property of a window.
*/
-void win_update_opacity_prop(session_t *ps, win *w);
+void win_update_opacity_prop(session_t *ps, struct managed_win *w);
/**
* Update leader of a window.
*/
-void win_update_leader(session_t *ps, win *w);
+void win_update_leader(session_t *ps, struct managed_win *w);
/**
* Update focused state of a window.
*/
-void win_update_focused(session_t *ps, win *w);
+void win_update_focused(session_t *ps, struct managed_win *w);
/**
* Retrieve the bounding shape of a window.
*/
// XXX was win_border_size
-void win_update_bounding_shape(session_t *ps, win *w);
+void win_update_bounding_shape(session_t *ps, struct managed_win *w);
/**
* Get a rectangular region in global coordinates a window (and possibly
* its shadow) occupies.
@@ -364,71 +386,109 @@ void win_update_bounding_shape(session_t *ps, win *w);
* Note w->shadow and shadow geometry must be correct before calling this
* function.
*/
-void win_extents(const win *w, region_t *res);
-region_t win_extents_by_val(const win *w);
+void win_extents(const struct managed_win *w, region_t *res);
+region_t win_extents_by_val(const struct managed_win *w);
/**
* Add a window to damaged area.
*
* @param ps current session
* @param w struct _win element representing the window
*/
-void add_damage_from_win(session_t *ps, win *w);
+void add_damage_from_win(session_t *ps, const struct managed_win *w);
/**
* Get a rectangular region a window occupies, excluding frame and shadow.
*
* Return region in global coordinates.
*/
-void win_get_region_noframe_local(const win *w, region_t *);
-region_t win_get_region_noframe_local_by_val(const win *w);
+void win_get_region_noframe_local(const struct managed_win *w, region_t *);
+region_t win_get_region_noframe_local_by_val(const struct managed_win *w);
/// Get the region for the frame of the window
-void win_get_region_frame_local(const win *w, region_t *res);
+void win_get_region_frame_local(const struct managed_win *w, region_t *res);
/// Get the region for the frame of the window, by value
-region_t win_get_region_frame_local_by_val(const win *w);
+region_t win_get_region_frame_local_by_val(const struct managed_win *w);
/**
* Retrieve frame extents from a window.
*/
-void win_update_frame_extents(session_t *ps, win *w, xcb_window_t client);
-void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev);
+void win_update_frame_extents(session_t *ps, struct managed_win *w, xcb_window_t client);
+/// Insert a new window above window with id `below`, if there is no window, add to top
+/// New window will be in unmapped state
+struct win *add_win_above(session_t *ps, xcb_window_t id, xcb_window_t below);
+/// Insert a new win entry at the top of the stack
+struct win *add_win_top(session_t *ps, xcb_window_t id);
+/// Query the Xorg for information about window `win`
+/// `win` pointer might become invalid after this function returns
+void fill_win(session_t *ps, struct win *win);
/// Unmap or destroy a window
-void unmap_win(session_t *ps, win **, bool destroy);
+void unmap_win(session_t *ps, struct managed_win **, bool destroy);
-void map_win(session_t *ps, win *w);
+void map_win(session_t *ps, struct managed_win *w);
void map_win_by_id(session_t *ps, xcb_window_t id);
/**
* Execute fade callback of a window if fading finished.
*/
-void win_check_fade_finished(session_t *ps, win **_w);
+void win_check_fade_finished(session_t *ps, struct managed_win **_w);
// Stop receiving events (except ConfigureNotify, XXX why?) from a window
-void win_ev_stop(session_t *ps, const win *w);
+void win_ev_stop(session_t *ps, const struct win *w);
/// Skip the current in progress fading of window,
/// transition the window straight to its end state
-void win_skip_fading(session_t *ps, win **_w);
-win *find_win(session_t *ps, xcb_window_t id);
-win *find_toplevel(session_t *ps, xcb_window_t id);
+void win_skip_fading(session_t *ps, struct managed_win **_w);
+/**
+ * Find a managed window from window id in window linked list of the session.
+ */
+struct managed_win *find_managed_win(session_t *ps, xcb_window_t id);
+struct win *find_win(session_t *ps, xcb_window_t id);
+struct managed_win *find_toplevel(session_t *ps, xcb_window_t id);
+/**
+ * Find out the WM frame of a client window by querying X.
+ *
+ * @param ps current session
+ * @param wid window ID
+ * @return struct _win object of the found window, NULL if not found
+ */
+struct managed_win *find_toplevel2(session_t *ps, xcb_window_t wid);
+/**
+ * Check if a window is a fullscreen window.
+ *
+ * It's not using w->border_size for performance measures.
+ */
+bool attr_pure win_is_fullscreen(const session_t *ps, const struct managed_win *w);
+
+/**
+ * Check if a window will be painted solid.
+ */
+bool attr_pure win_is_solid(const session_t *ps, const struct managed_win *w);
+/**
+ * Check if a window is really focused.
+ */
+bool attr_pure win_is_focused_real(const session_t *ps, const struct managed_win *w);
/**
* Get the leader of a window.
*
* This function updates w->cache_leader if necessary.
*/
-static inline xcb_window_t win_get_leader(session_t *ps, win *w) {
+static inline xcb_window_t win_get_leader(session_t *ps, struct managed_win *w) {
return win_get_leader_raw(ps, w, 0);
}
/// check if window has ARGB visual
-bool attr_pure win_has_alpha(const win *w);
+bool attr_pure win_has_alpha(const struct managed_win *w);
/// check if reg_ignore_valid is true for all windows above us
-bool attr_pure win_is_region_ignore_valid(session_t *ps, const win *w);
+bool attr_pure win_is_region_ignore_valid(session_t *ps, const struct managed_win *w);
+
+// Find the managed window immediately below `w` in the window stack
+struct managed_win *attr_pure win_stack_find_next_managed(const session_t *ps,
+ const struct list_node *w);
/// Free all resources in a struct win
-void free_win_res(session_t *ps, win *w);
+void free_win_res(session_t *ps, struct managed_win *w);
-static inline region_t win_get_bounding_shape_global_by_val(win *w) {
+static inline region_t win_get_bounding_shape_global_by_val(struct managed_win *w) {
region_t ret;
pixman_region32_init(&ret);
pixman_region32_copy(&ret, &w->bounding_shape);
@@ -440,7 +500,7 @@ static inline region_t win_get_bounding_shape_global_by_val(win *w) {
* Calculate the extents of the frame of the given window based on EWMH
* _NET_FRAME_EXTENTS and the X window border width.
*/
-static inline margin_t attr_pure win_calc_frame_extents(const win *w) {
+static inline margin_t attr_pure win_calc_frame_extents(const struct managed_win *w) {
margin_t result = w->frame_extents;
result.top = max2(result.top, w->g.border_width);
result.left = max2(result.left, w->g.border_width);
@@ -452,7 +512,15 @@ static inline margin_t attr_pure win_calc_frame_extents(const win *w) {
/**
* Check whether a window has WM frames.
*/
-static inline bool attr_pure win_has_frame(const win *w) {
+static inline bool attr_pure win_has_frame(const struct managed_win *w) {
return w->g.border_width || w->frame_extents.top || w->frame_extents.left ||
w->frame_extents.right || w->frame_extents.bottom;
}
+
+static inline const char *win_get_name_if_managed(const struct win *w) {
+ if (!w->managed) {
+ return "(unmanaged)";
+ }
+ auto mw = (struct managed_win *)w;
+ return mw->name;
+}