This commit is contained in:
Yuxuan Shui 2019-04-14 22:36:23 +01:00
parent fb53ff50a1
commit 53fd3a2f7a
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
17 changed files with 699 additions and 514 deletions

View File

@ -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(&reg_visible, &ps->screen_reg, w->reg_ignore);
assert(!(w->flags & WIN_FLAGS_IMAGE_ERROR));

View File

@ -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 :

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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);

View File

@ -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 <code>win</code> 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);

View File

@ -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 <code>w->focused</code>
* 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);

View File

@ -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);

View File

@ -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);

View File

@ -14,7 +14,7 @@
#include <dbus/dbus.h>
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 :

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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 <code>Picture</code> 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) {

View File

@ -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);

535
src/win.c

File diff suppressed because it is too large Load Diff

198
src/win.h
View File

@ -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;
}