diff --git a/src/compton.c b/src/compton.c index ce60fe4..717194b 100644 --- a/src/compton.c +++ b/src/compton.c @@ -118,6 +118,12 @@ update_ewmh_active_win(session_t *ps); static void draw_callback(EV_P_ ev_idle *w, int revents); +static void +render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, + 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); + typedef struct ev_session_timer { ev_timer w; session_t *ps; @@ -216,6 +222,103 @@ static const char *background_props_str[] = { /// have a pointer to current session passed in. session_t *ps_g = NULL; +/** + * Free Xinerama screen info. + * + * XXX consider moving to x.c + */ +static inline void +free_xinerama_info(session_t *ps) { +#ifdef CONFIG_XINERAMA + if (ps->xinerama_scr_regs) { + for (int i = 0; i < ps->xinerama_nscrs; ++i) + pixman_region32_fini(&ps->xinerama_scr_regs[i]); + free(ps->xinerama_scr_regs); + } + cxfree(ps->xinerama_scrs); + ps->xinerama_scrs = NULL; + ps->xinerama_nscrs = 0; +#endif +} + +/** + * Destroy all resources in a struct _win. + */ +static inline void +free_win_res(session_t *ps, win *w) { + free_win_res_glx(ps, w); + free_paint(ps, &w->paint); + pixman_region32_fini(&w->bounding_shape); + free_paint(ps, &w->shadow_paint); + // BadDamage may be thrown if the window is destroyed + set_ignore_cookie(ps, + xcb_damage_destroy(ps->c, w->damage)); + rc_region_unref(&w->reg_ignore); + free(w->name); + free(w->class_instance); + free(w->class_general); + free(w->role); +} + +/** + * Free root tile related things. + */ +static inline void +free_root_tile(session_t *ps) { + free_picture(ps, &ps->root_tile_paint.pict); + free_texture(ps, &ps->root_tile_paint.ptex); + if (ps->root_tile_fill) { + xcb_free_pixmap(ps->c, ps->root_tile_paint.pixmap); + ps->root_tile_paint.pixmap = XCB_NONE; + } + ps->root_tile_paint.pixmap = None; + ps->root_tile_fill = false; +} + +/** + * Get current system clock in milliseconds. + */ +static inline time_ms_t +get_time_ms(void) { + struct timeval tv; + + gettimeofday(&tv, NULL); + + return tv.tv_sec % SEC_WRAP * 1000 + tv.tv_usec / 1000; +} + +/** + * Resize a region. + */ +static inline void +resize_region(session_t *ps, region_t *region, short mod) { + if (!mod || !region) return; + // Loop through all rectangles + int nrects; + int nnewrects = 0; + pixman_box32_t *rects = pixman_region32_rectangles(region, &nrects); + pixman_box32_t *newrects = calloc(nrects, sizeof *newrects); + for (int i = 0; i < nrects; i++) { + int x1 = max_i(rects[i].x1 - mod, 0); + int y1 = max_i(rects[i].y1 - mod, 0); + int x2 = min_i(rects[i].x2 + mod, ps->root_width); + int y2 = min_i(rects[i].y2 + mod, ps->root_height); + int wid = x2 - x1; + int hei = y2 - y1; + if (wid <= 0 || hei <= 0) + continue; + newrects[nnewrects] = (pixman_box32_t) { + .x1 = x1, .x2 = x2, .y1 = y1, .y2 = y2 + }; + ++nnewrects; + } + + pixman_region32_fini(region); + pixman_region32_init_rects(region, newrects, nnewrects); + + free(newrects); +} + static inline int get_alpha_step(session_t *ps, opacity_t o) { double d = ((double) o) / OPAQUE; @@ -240,6 +343,86 @@ set_tgt_clip(session_t *ps, region_t *reg) { } } +/** + * Get the Xinerama screen a window is on. + * + * Return an index >= 0, or -1 if not found. + * + * XXX move to x.c + */ +static inline void +cxinerama_win_upd_scr(session_t *ps, win *w) { +#ifdef CONFIG_XINERAMA + w->xinerama_scr = -1; + + if (!ps->xinerama_scrs) + return; + + xcb_xinerama_screen_info_t *scrs = xcb_xinerama_query_screens_screen_info(ps->xinerama_scrs); + int length = xcb_xinerama_query_screens_screen_info_length(ps->xinerama_scrs); + for (int i = 0; i < length; i++) { + xcb_xinerama_screen_info_t *s = &scrs[i]; + if (s->x_org <= w->g.x && s->y_org <= w->g.y + && s->x_org + s->width >= w->g.x + w->widthb + && s->y_org + s->height >= w->g.y + w->heightb) { + w->xinerama_scr = i; + return; + } + } +#endif +} + +// XXX Move to x.c +static void +cxinerama_upd_scrs(session_t *ps) { +#ifdef CONFIG_XINERAMA + // XXX Consider deprecating Xinerama, switch to RandR when necessary + free_xinerama_info(ps); + + if (!ps->o.xinerama_shadow_crop || !ps->xinerama_exists) return; + + xcb_xinerama_is_active_reply_t *active = + xcb_xinerama_is_active_reply(ps->c, + xcb_xinerama_is_active(ps->c), NULL); + if (!active || !active->state) { + free(active); + return; + } + free(active); + + ps->xinerama_scrs = xcb_xinerama_query_screens_reply(ps->c, + xcb_xinerama_query_screens(ps->c), NULL); + if (!ps->xinerama_scrs) + return; + + xcb_xinerama_screen_info_t *scrs = xcb_xinerama_query_screens_screen_info(ps->xinerama_scrs); + ps->xinerama_nscrs = xcb_xinerama_query_screens_screen_info_length(ps->xinerama_scrs); + + ps->xinerama_scr_regs = allocchk(malloc(sizeof(region_t) + * ps->xinerama_nscrs)); + for (int i = 0; i < ps->xinerama_nscrs; ++i) { + const xcb_xinerama_screen_info_t * const s = &scrs[i]; + pixman_region32_init_rect(&ps->xinerama_scr_regs[i], s->x_org, s->y_org, s->width, s->height); + } +#endif +} + +/** + * Find matched window. + * + * XXX move to win.c + */ +static inline win * +find_win_all(session_t *ps, const Window wid) { + if (!wid || PointerRoot == wid || wid == ps->root || wid == ps->overlay) + return NULL; + + win *w = find_win(ps, wid); + if (!w) w = find_toplevel(ps, wid); + if (!w) w = find_toplevel2(ps, wid); + return w; +} + void queue_redraw(session_t *ps) { // If --benchmark is used, redraw is always queued if (!ps->redraw_needed && !ps->o.benchmark) @@ -1401,7 +1584,7 @@ win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer, } } -void +static void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, double opacity, bool argb, bool neg, xcb_render_picture_t pict, glx_texture_t *ptex, @@ -2065,7 +2248,7 @@ finish_unmap_win(session_t *ps, win **_w) { /* damage region */ add_damage_from_win(ps, w); - free_wpaint(ps, w); + free_paint(ps, &w->paint); free_paint(ps, &w->shadow_paint); } @@ -4607,7 +4790,7 @@ redir_stop(session_t *ps) { // If we don't destroy them here, looks like the resources are just // kept inaccessible somehow for (win *w = ps->list; w; w = w->next) - free_wpaint(ps, w); + free_paint(ps, &w->paint); xcb_composite_unredirect_subwindows(ps->c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); // Unmap overlay window @@ -4775,40 +4958,6 @@ x_event_callback(EV_P_ ev_io *w, int revents) { } } -static void -cxinerama_upd_scrs(session_t *ps) { -#ifdef CONFIG_XINERAMA - // XXX Consider deprecating Xinerama, switch to RandR when necessary - free_xinerama_info(ps); - - if (!ps->o.xinerama_shadow_crop || !ps->xinerama_exists) return; - - xcb_xinerama_is_active_reply_t *active = - xcb_xinerama_is_active_reply(ps->c, - xcb_xinerama_is_active(ps->c), NULL); - if (!active || !active->state) { - free(active); - return; - } - free(active); - - ps->xinerama_scrs = xcb_xinerama_query_screens_reply(ps->c, - xcb_xinerama_query_screens(ps->c), NULL); - if (!ps->xinerama_scrs) - return; - - xcb_xinerama_screen_info_t *scrs = xcb_xinerama_query_screens_screen_info(ps->xinerama_scrs); - ps->xinerama_nscrs = xcb_xinerama_query_screens_screen_info_length(ps->xinerama_scrs); - - ps->xinerama_scr_regs = allocchk(malloc(sizeof(region_t) - * ps->xinerama_nscrs)); - for (int i = 0; i < ps->xinerama_nscrs; ++i) { - const xcb_xinerama_screen_info_t * const s = &scrs[i]; - pixman_region32_init_rect(&ps->xinerama_scr_regs[i], s->x_org, s->y_org, s->width, s->height); - } -#endif -} - /** * Initialize a session. * diff --git a/src/compton.h b/src/compton.h index f89b543..951d171 100644 --- a/src/compton.h +++ b/src/compton.h @@ -52,12 +52,6 @@ win *find_toplevel2(session_t *ps, Window wid); void map_win(session_t *ps, Window id); -void -render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, - 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); - /** * Reset filter on a Picture. */ @@ -119,19 +113,6 @@ free_picture(session_t *ps, xcb_render_picture_t *p) { } } -/** - * Destroy a Damage. - */ -inline static void -free_damage(session_t *ps, xcb_damage_damage_t *p) { - if (*p) { - // BadDamage will be thrown if the window is destroyed - set_ignore_cookie(ps, - xcb_damage_destroy(ps->c, *p)); - *p = None; - } -} - /** * Destroy a condition list. */ @@ -141,23 +122,6 @@ free_wincondlst(c2_lptr_t **pcondlst) { continue; } -/** - * Free Xinerama screen info. - */ -static inline void -free_xinerama_info(session_t *ps) { -#ifdef CONFIG_XINERAMA - if (ps->xinerama_scr_regs) { - for (int i = 0; i < ps->xinerama_nscrs; ++i) - pixman_region32_fini(&ps->xinerama_scr_regs[i]); - free(ps->xinerama_scr_regs); - } - cxfree(ps->xinerama_scrs); - ps->xinerama_scrs = NULL; - ps->xinerama_nscrs = 0; -#endif -} - #ifdef CONFIG_OPENGL /** * Bind texture in paint_t if we are using GLX backend. @@ -203,69 +167,6 @@ free_paint(session_t *ps, paint_t *ppaint) { ppaint->pixmap = XCB_NONE; } -/** - * Free w->paint. - */ -static inline void -free_wpaint(session_t *ps, win *w) { - free_paint(ps, &w->paint); -} - -/** - * Destroy all resources in a struct _win. - */ -static inline void -free_win_res(session_t *ps, win *w) { - free_win_res_glx(ps, w); - free_paint(ps, &w->paint); - pixman_region32_fini(&w->bounding_shape); - free_paint(ps, &w->shadow_paint); - free_damage(ps, &w->damage); - rc_region_unref(&w->reg_ignore); - free(w->name); - free(w->class_instance); - free(w->class_general); - free(w->role); -} - -/** - * Free root tile related things. - */ -static inline void -free_root_tile(session_t *ps) { - free_picture(ps, &ps->root_tile_paint.pict); - free_texture(ps, &ps->root_tile_paint.ptex); - if (ps->root_tile_fill) { - xcb_free_pixmap(ps->c, ps->root_tile_paint.pixmap); - ps->root_tile_paint.pixmap = XCB_NONE; - } - ps->root_tile_paint.pixmap = None; - ps->root_tile_fill = false; -} - -/** - * Get current system clock in milliseconds. - */ -static inline time_ms_t -get_time_ms(void) { - struct timeval tv; - - gettimeofday(&tv, NULL); - - return tv.tv_sec % SEC_WRAP * 1000 + tv.tv_usec / 1000; -} - -/** - * Convert time from milliseconds to struct timeval. - */ -static inline struct timeval -ms_to_tv(int timeout) { - return (struct timeval) { - .tv_sec = timeout / MS_PER_SEC, - .tv_usec = timeout % MS_PER_SEC * (US_PER_SEC / MS_PER_SEC) - }; -} - /** * Create a XTextProperty of a single string. */ @@ -301,26 +202,6 @@ wid_set_text_prop(session_t *ps, Window wid, Atom prop_atom, char *str) { return true; } -/** - * Stop listening for events on a particular window. - */ -static inline void -win_ev_stop(session_t *ps, win *w) { - // Will get BadWindow if the window is destroyed - set_ignore_cookie(ps, - xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 })); - - if (w->client_win) { - set_ignore_cookie(ps, - xcb_change_window_attributes(ps->c, w->client_win, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 })); - } - - if (ps->shape_exists) { - set_ignore_cookie(ps, - xcb_shape_select_input(ps->c, w->id, 0)); - } -} - /** * Dump an drawable's info. */ @@ -366,20 +247,6 @@ win_validate_pixmap(session_t *ps, win *w) { free_paint(ps, &w->paint); } -/** - * Find matched window. - */ -static inline win * -find_win_all(session_t *ps, const Window wid) { - if (!wid || PointerRoot == wid || wid == ps->root || wid == ps->overlay) - return NULL; - - win *w = find_win(ps, wid); - if (!w) w = find_toplevel(ps, wid); - if (!w) w = find_toplevel2(ps, wid); - return w; -} - /** * Normalize a convolution kernel. */ @@ -393,38 +260,6 @@ normalize_conv_kern(int wid, int hei, xcb_render_fixed_t *kern) { kern[i] = DOUBLE_TO_XFIXED(XFIXED_TO_DOUBLE(kern[i]) * factor); } -/** - * Resize a region. - */ -static inline void -resize_region(session_t *ps, region_t *region, short mod) { - if (!mod || !region) return; - // Loop through all rectangles - int nrects; - int nnewrects = 0; - pixman_box32_t *rects = pixman_region32_rectangles(region, &nrects); - pixman_box32_t *newrects = calloc(nrects, sizeof *newrects); - for (int i = 0; i < nrects; i++) { - int x1 = max_i(rects[i].x1 - mod, 0); - int y1 = max_i(rects[i].y1 - mod, 0); - int x2 = min_i(rects[i].x2 + mod, ps->root_width); - int y2 = min_i(rects[i].y2 + mod, ps->root_height); - int wid = x2 - x1; - int hei = y2 - y1; - if (wid <= 0 || hei <= 0) - continue; - newrects[nnewrects] = (pixman_box32_t) { - .x1 = x1, .x2 = x2, .y1 = y1, .y2 = y2 - }; - ++nnewrects; - } - - pixman_region32_fini(region); - pixman_region32_init_rects(region, newrects, nnewrects); - - free(newrects); -} - #ifdef CONFIG_OPENGL /** * Ensure we have a GLX context. @@ -439,31 +274,4 @@ ensure_glx_context(session_t *ps) { } #endif -/** - * Get the Xinerama screen a window is on. - * - * Return an index >= 0, or -1 if not found. - */ -static inline void -cxinerama_win_upd_scr(session_t *ps, win *w) { -#ifdef CONFIG_XINERAMA - w->xinerama_scr = -1; - - if (!ps->xinerama_scrs) - return; - - xcb_xinerama_screen_info_t *scrs = xcb_xinerama_query_screens_screen_info(ps->xinerama_scrs); - int length = xcb_xinerama_query_screens_screen_info_length(ps->xinerama_scrs); - for (int i = 0; i < length; i++) { - xcb_xinerama_screen_info_t *s = &scrs[i]; - if (s->x_org <= w->g.x && s->y_org <= w->g.y - && s->x_org + s->width >= w->g.x + w->widthb - && s->y_org + s->height >= w->g.y + w->heightb) { - w->xinerama_scr = i; - return; - } - } -#endif -} - // vim: set et sw=2 : diff --git a/src/win.c b/src/win.c index b778b28..341eccc 100644 --- a/src/win.c +++ b/src/win.c @@ -1194,7 +1194,7 @@ void win_update_bounding_shape(session_t *ps, win *w) { win_rounded_corners(ps, w); // Window shape changed, we should free old wpaint and shadow pict - free_wpaint(ps, w); + free_paint(ps, &w->paint); free_paint(ps, &w->shadow_paint); //printf_errf("(): free out dated pict"); @@ -1265,3 +1265,22 @@ bool win_is_region_ignore_valid(session_t *ps, win *w) { } return true; } + +/** + * Stop listening for events on a particular window. + */ +void win_ev_stop(session_t *ps, win *w) { + // Will get BadWindow if the window is destroyed + set_ignore_cookie(ps, + xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 })); + + if (w->client_win) { + set_ignore_cookie(ps, + xcb_change_window_attributes(ps->c, w->client_win, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 })); + } + + if (ps->shape_exists) { + set_ignore_cookie(ps, + xcb_shape_select_input(ps->c, w->id, 0)); + } +} diff --git a/src/win.h b/src/win.h index 9b11b6b..4f0e674 100644 --- a/src/win.h +++ b/src/win.h @@ -332,6 +332,9 @@ void win_update_frame_extents(session_t *ps, win *w, Window client); bool add_win(session_t *ps, Window id, Window prev); +// Stop receiving events (except ConfigureNotify, XXX why?) from a window +void win_ev_stop(session_t *ps, win *w); + /** * Get the leader of a window. *