summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--[-rwxr-xr-x]compton.c1058
-rw-r--r--compton.h198
2 files changed, 222 insertions, 1034 deletions
diff --git a/compton.c b/compton.c
index 576052886..bb9d7bb8f 100755..100644
--- a/compton.c
+++ b/compton.c
@@ -35,7 +35,7 @@ const char *WINTYPES[NUM_WINTYPES] = {
struct timeval time_start = { 0, 0 };
win *list;
-Display *dpy = NULL;
+Display *dpy;
int scr;
Window root;
@@ -47,67 +47,25 @@ Picture cshadow_picture;
Picture dim_picture = 0;
Picture root_tile;
XserverRegion all_damage;
+#if HAS_NAME_WINDOW_PIXMAP
Bool has_name_pixmap;
+#endif
int root_height, root_width;
-
-/// Pregenerated alpha pictures.
-Picture *alpha_picts = NULL;
/// Whether the program is idling. I.e. no fading, no potential window
/// changes.
Bool idling;
-/// Whether all reg_ignore of windows should expire in this paint.
-Bool reg_ignore_expire = False;
-/// Window ID of the window we register as a symbol.
-Window reg_win = 0;
-
-/// Currently used refresh rate. Used for Software VSync.
-short refresh_rate = 0;
-/// Interval between refresh in nanoseconds. Used for Software VSync.
-unsigned long refresh_intv = 0;
-/// Nanosecond-level offset of the first painting.
-/// Used for Software VSync.
-long paint_tm_offset = 0;
-
-#ifdef CONFIG_VSYNC_DRM
-/// File descriptor of DRI device file. Used for DRM VSync.
-int drm_fd = 0;
-#endif
-
-#ifdef CONFIG_VSYNC_OPENGL
-/// GLX context.
-GLXContext glx_context;
-
-/// Pointer to glXGetVideoSyncSGI function. Used by OpenGL VSync.
-f_GetVideoSync glx_get_video_sync = NULL;
-
-/// Pointer to glXWaitVideoSyncSGI function. Used by OpenGL VSync.
-f_WaitVideoSync glx_wait_video_sync = NULL;
-#endif
/* errors */
ignore *ignore_head = NULL, **ignore_tail = &ignore_head;
int xfixes_event, xfixes_error;
int damage_event, damage_error;
int composite_event, composite_error;
-int render_event, render_error;
-int composite_opcode;
-
/// Whether X Shape extension exists.
-Bool shape_exists = False;
+Bool shape_exists = True;
/// Event base number and error base number for X Shape extension.
int shape_event, shape_error;
-
-/// Whether X RandR extension exists.
-Bool randr_exists = False;
-/// Event base number and error base number for X RandR extension.
-int randr_event, randr_error;
-
-#ifdef CONFIG_VSYNC_OPENGL
-/// Whether X GLX extension exists.
-Bool glx_exists = False;
-/// Event base number and error base number for X GLX extension.
-int glx_event, glx_error;
-#endif
+int render_event, render_error;
+int composite_opcode;
/* shadows */
conv *gaussian_map;
@@ -137,7 +95,6 @@ Atom client_atom;
Atom name_atom;
Atom name_ewmh_atom;
Atom class_atom;
-Atom transient_atom;
Atom win_type_atom;
Atom win_type[NUM_WINTYPES];
@@ -161,9 +118,6 @@ static options_t opts = {
.synchronize = False,
.detect_rounded_corners = False,
- .refresh_rate = 0,
- .vsync = VSYNC_NONE,
-
.wintype_shadow = { False },
.shadow_red = 0.0,
.shadow_green = 0.0,
@@ -187,9 +141,7 @@ static options_t opts = {
.inactive_opacity = 0,
.inactive_opacity_override = False,
.frame_opacity = 0.0,
- .detect_client_opacity = False,
.inactive_dim = 0.0,
- .alpha_step = 0.03,
.track_focus = False,
.track_wdata = False,
@@ -208,7 +160,7 @@ unsigned long fade_time = 0;
* passed since the epoch.
*/
static unsigned long
-get_time_ms() {
+get_time_in_milliseconds() {
struct timeval tv;
gettimeofday(&tv, NULL);
@@ -223,7 +175,7 @@ get_time_ms() {
*/
static int
fade_timeout(void) {
- int diff = opts.fade_delta - get_time_ms() + fade_time;
+ int diff = opts.fade_delta - get_time_in_milliseconds() + fade_time;
if (diff < 0)
diff = 0;
@@ -989,8 +941,7 @@ determine_evmask(Display *dpy, Window wid, win_evmode_t mode) {
}
if (WIN_EVMODE_CLIENT == mode || find_toplevel(dpy, wid)) {
- if (opts.frame_opacity || opts.track_wdata
- || opts.detect_client_opacity)
+ if (opts.frame_opacity || opts.track_wdata)
evmask |= PropertyChangeMask;
}
@@ -1161,36 +1112,6 @@ paint_root(Display *dpy) {
}
/**
- * Get a rectangular region a window occupies, excluding shadow.
- */
-static XserverRegion
-win_get_region(Display *dpy, win *w) {
- XRectangle r;
-
- r.x = w->a.x;
- r.y = w->a.y;
- r.width = w->widthb;
- r.height = w->heightb;
-
- return XFixesCreateRegion(dpy, &r, 1);
-}
-
-/**
- * Get a rectangular region a window occupies, excluding frame and shadow.
- */
-static XserverRegion
-win_get_region_noframe(Display *dpy, win *w) {
- XRectangle r;
-
- r.x = w->a.x + w->left_width;
- r.y = w->a.y + w->top_width;
- r.width = w->a.width;
- r.height = w->a.height;
-
- return XFixesCreateRegion(dpy, &r, 1);
-}
-
-/**
* Get a rectangular region a window (and possibly its shadow) occupies.
*
* Note w->shadow and shadow geometry must be correct before calling this
@@ -1315,38 +1236,23 @@ get_frame_extents(Display *dpy, win *w, Window client) {
}
}
-static inline Picture
-get_alpha_pict_d(double o) {
- assert((lround(normalize_d(o) / opts.alpha_step)) <= lround(1.0 / opts.alpha_step));
- return alpha_picts[lround(normalize_d(o) / opts.alpha_step)];
-}
-
-static inline Picture
-get_alpha_pict_o(opacity_t o) {
- return get_alpha_pict_d((double) o / OPAQUE);
-}
-
static win *
paint_preprocess(Display *dpy, win *list) {
win *w;
win *t = NULL, *next = NULL;
+ // Sounds like the timeout in poll() frequently does not work
+ // accurately, asking it to wait to 20ms, and often it would wait for
+ // 19ms, so the step value has to be rounded.
+ unsigned steps = roundl((double) (get_time_in_milliseconds() - fade_time) / opts.fade_delta);
- // Fading step calculation
- unsigned steps = (sub_unslong(get_time_ms(), fade_time)
- + FADE_DELTA_TOLERANCE * opts.fade_delta) / opts.fade_delta;
- fade_time += steps * opts.fade_delta;
-
- XserverRegion last_reg_ignore = None;
+ // Reset fade_time
+ fade_time = get_time_in_milliseconds();
for (w = list; w; w = next) {
// In case calling the fade callback function destroys this window
next = w->next;
opacity_t opacity_old = w->opacity;
- // Destroy reg_ignore on all windows if they should expire
- if (reg_ignore_expire)
- free_region(dpy, &w->reg_ignore);
-
#if CAN_DO_USABLE
if (!w->usable) continue;
#endif
@@ -1368,10 +1274,7 @@ paint_preprocess(Display *dpy, win *list) {
add_damage_win(dpy, w);
}
- w->alpha_pict = get_alpha_pict_o(w->opacity);
-
- // End the game if we are using the 0 opacity alpha_pict
- if (w->alpha_pict == alpha_picts[0]) {
+ if (!w->opacity) {
check_fade_fin(dpy, w);
continue;
}
@@ -1382,11 +1285,13 @@ paint_preprocess(Display *dpy, win *list) {
XRenderPictFormat *format;
Drawable draw = w->id;
+#if HAS_NAME_WINDOW_PIXMAP
if (has_name_pixmap && !w->pixmap) {
set_ignore(dpy, NextRequest(dpy));
w->pixmap = XCompositeNameWindowPixmap(dpy, w->id);
}
if (w->pixmap) draw = w->pixmap;
+#endif
format = XRenderFindVisualFormat(dpy, w->a.visual);
pa.subwindow_mode = IncludeInferiors;
@@ -1407,23 +1312,31 @@ paint_preprocess(Display *dpy, win *list) {
add_damage_win(dpy, w);
}
- // Calculate frame_opacity
- {
- double frame_opacity_old = w->frame_opacity;
+ // Rebuild alpha_pict only if necessary
+ if (OPAQUE != w->opacity
+ && (!w->alpha_pict || w->opacity != w->opacity_cur)) {
+ free_picture(dpy, &w->alpha_pict);
+ w->alpha_pict = solid_picture(
+ dpy, False, get_opacity_percent(dpy, w), 0, 0, 0);
+ w->opacity_cur = w->opacity;
+ }
- if (opts.frame_opacity && 1.0 != opts.frame_opacity
- && w->top_width)
- w->frame_opacity = get_opacity_percent(dpy, w) *
- opts.frame_opacity;
- else
- w->frame_opacity = 0.0;
+ // Calculate frame_opacity
+ if (opts.frame_opacity && 1.0 != opts.frame_opacity && w->top_width)
+ w->frame_opacity = get_opacity_percent(dpy, w) * opts.frame_opacity;
+ else
+ w->frame_opacity = 0.0;
- if ((0.0 == frame_opacity_old) != (0.0 == w->frame_opacity))
- reg_ignore_expire = True;
+ // Rebuild frame_alpha_pict only if necessary
+ if (w->frame_opacity
+ && (!w->frame_alpha_pict
+ || w->frame_opacity != w->frame_opacity_cur)) {
+ free_picture(dpy, &w->frame_alpha_pict);
+ w->frame_alpha_pict = solid_picture(
+ dpy, False, w->frame_opacity, 0, 0, 0);
+ w->frame_opacity_cur = w->frame_opacity;
}
- w->frame_alpha_pict = get_alpha_pict_d(w->frame_opacity);
-
// Calculate shadow opacity
if (w->frame_opacity)
w->shadow_opacity = opts.shadow_opacity * w->frame_opacity;
@@ -1439,36 +1352,16 @@ paint_preprocess(Display *dpy, win *list) {
w->widthb, w->heightb);
}
- w->shadow_alpha_pict = get_alpha_pict_d(w->shadow_opacity);
-
- // Generate ignore region for painting to reduce GPU load
- if (reg_ignore_expire) {
- free_region(dpy, &w->reg_ignore);
-
- // If the window is solid, we add the window region to the
- // ignored region
- if (WINDOW_SOLID == w->mode) {
- if (!w->frame_opacity)
- w->reg_ignore = win_get_region(dpy, w);
- else
- w->reg_ignore = win_get_region_noframe(dpy, w);
-
- XFixesIntersectRegion(dpy, w->reg_ignore, w->reg_ignore,
- w->border_size);
-
- if (last_reg_ignore)
- XFixesUnionRegion(dpy, w->reg_ignore, w->reg_ignore,
- last_reg_ignore);
- }
- // Otherwise we copy the last region over
- else if (last_reg_ignore)
- w->reg_ignore = copy_region(dpy, last_reg_ignore);
- else
- w->reg_ignore = None;
+ // Rebuild shadow_alpha_pict if necessary
+ if (w->shadow
+ && (!w->shadow_alpha_pict
+ || w->shadow_opacity != w->shadow_opacity_cur)) {
+ free_picture(dpy, &w->shadow_alpha_pict);
+ w->shadow_alpha_pict = solid_picture(
+ dpy, False, w->shadow_opacity, 0, 0, 0);
+ w->shadow_opacity_cur = w->shadow_opacity;
}
- last_reg_ignore = w->reg_ignore;
-
// Reset flags
w->flags = 0;
@@ -1479,82 +1372,13 @@ paint_preprocess(Display *dpy, win *list) {
return t;
}
-/**
- * Paint the shadow of a window.
- */
-static inline void
-win_paint_shadow(Display *dpy, win *w, Picture root_buffer) {
- XRenderComposite(
- dpy, PictOpOver, w->shadow_pict, w->shadow_alpha_pict,
- root_buffer, 0, 0, 0, 0,
- w->a.x + w->shadow_dx, w->a.y + w->shadow_dy,
- w->shadow_width, w->shadow_height);
-}
-
-/**
- * Paint a window itself and dim it if asked.
- */
-static inline void
-win_paint_win(Display *dpy, win *w, Picture root_buffer) {
- int x = w->a.x;
- int y = w->a.y;
- int wid = w->widthb;
- int hei = w->heightb;
-
- Picture alpha_mask = (OPAQUE == w->opacity ? None: w->alpha_pict);
- int op = (w->mode == WINDOW_SOLID ? PictOpSrc: PictOpOver);
-
- if (!w->frame_opacity) {
- XRenderComposite(dpy, op, w->picture, alpha_mask,
- root_buffer, 0, 0, 0, 0, x, y, wid, hei);
- }
- else {
- unsigned int t = w->top_width;
- unsigned int l = w->left_width;
- unsigned int b = w->bottom_width;
- unsigned int r = w->right_width;
-
- // top
- XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
- root_buffer, 0, 0, 0, 0, x, y, wid, t);
-
- // left
- XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
- root_buffer, 0, t, 0, t, x, y + t, l, hei - t);
-
- // bottom
- XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
- root_buffer, l, hei - b, l, hei - b, x + l, y + hei - b, wid - l - r, b);
-
- // right
- XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
- root_buffer, wid - r, t, wid - r, t, x + wid - r, y + t, r, hei - t);
-
- // body
- XRenderComposite(dpy, op, w->picture, alpha_mask, root_buffer,
- l, t, l, t, x + l, y + t, wid - l - r, hei - t - b);
-
- }
-
- // Dimming the window if needed
- if (w->dim) {
- XRenderComposite(dpy, PictOpOver, dim_picture, None,
- root_buffer, 0, 0, 0, 0, x, y, wid, hei);
- }
-}
-
static void
paint_all(Display *dpy, XserverRegion region, win *t) {
win *w;
- XserverRegion reg_paint = None, reg_tmp = None, reg_tmp2 = None;
if (!region) {
region = get_screen_region(dpy);
}
- else {
- // Remove the damaged area out of screen
- XFixesIntersectRegion(dpy, region, region, get_screen_region(dpy));
- }
#ifdef MONITOR_REPAINT
root_buffer = root_picture;
@@ -1581,86 +1405,97 @@ paint_all(Display *dpy, XserverRegion region, win *t) {
root_width, root_height);
#endif
+ paint_root(dpy);
+
#ifdef DEBUG_REPAINT
- print_timestamp();
printf("paint:");
#endif
- if (t && t->reg_ignore) {
- // Calculate the region upon which the root window is to be painted
- // based on the ignore region of the lowest window, if available
- reg_paint = reg_tmp = XFixesCreateRegion(dpy, NULL, 0);
- XFixesSubtractRegion(dpy, reg_paint, region, t->reg_ignore);
- }
- else {
- reg_paint = region;
- }
-
- XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, reg_paint);
-
- paint_root(dpy);
+ for (w = t; w; w = w->prev_trans) {
+ int x, y, wid, hei;
- // Create temporary regions for use during painting
- if (!reg_tmp)
- reg_tmp = XFixesCreateRegion(dpy, NULL, 0);
- reg_tmp2 = XFixesCreateRegion(dpy, NULL, 0);
+#if HAS_NAME_WINDOW_PIXMAP
+ x = w->a.x;
+ y = w->a.y;
+ wid = w->widthb;
+ hei = w->heightb;
+#else
+ x = w->a.x + w->a.border_width;
+ y = w->a.y + w->a.border_width;
+ wid = w->a.width;
+ hei = w->a.height;
+#endif
- for (w = t; w; w = w->prev_trans) {
#ifdef DEBUG_REPAINT
printf(" %#010lx", w->id);
#endif
+ // Allow shadow to be painted anywhere in the damaged region
+ XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, region);
+
// Painting shadow
if (w->shadow) {
- // Shadow is to be painted based on the ignore region of current
- // window
- if (w->reg_ignore) {
- if (w == t) {
- // If it's the first cycle and reg_tmp2 is not ready, calculate
- // the paint region here
- reg_paint = reg_tmp;
- XFixesSubtractRegion(dpy, reg_paint, region, w->reg_ignore);
- }
- else {
- // Otherwise, used the cached region during last cycle
- reg_paint = reg_tmp2;
- }
- XFixesIntersectRegion(dpy, reg_paint, reg_paint, w->extents);
- }
- else {
- reg_paint = region;
- }
+ XRenderComposite(
+ dpy, PictOpOver, w->shadow_pict, w->shadow_alpha_pict,
+ root_buffer, 0, 0, 0, 0,
+ w->a.x + w->shadow_dx, w->a.y + w->shadow_dy,
+ w->shadow_width, w->shadow_height);
+ }
- // Detect if the region is empty before painting
- if (region == reg_paint || !is_region_empty(dpy, reg_paint)) {
- XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, reg_paint);
+ // The window only could be painted in its bounding region
+ XserverRegion paint_reg = XFixesCreateRegion(dpy, NULL, 0);
+ XFixesIntersectRegion(dpy, paint_reg, region, w->border_size);
+ XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, paint_reg);
- win_paint_shadow(dpy, w, root_buffer);
- }
- }
+ Picture alpha_mask = (OPAQUE == w->opacity ? None: w->alpha_pict);
+ int op = (w->mode == WINDOW_SOLID ? PictOpSrc: PictOpOver);
- // Calculate the region based on the reg_ignore of the next (higher)
- // window and the bounding region
- reg_paint = reg_tmp;
- if (w->prev_trans && w->prev_trans->reg_ignore) {
- XFixesSubtractRegion(dpy, reg_paint, region,
- w->prev_trans->reg_ignore);
- // Copy the subtracted region to be used for shadow painting in next
- // cycle
- XFixesCopyRegion(dpy, reg_tmp2, reg_paint);
- XFixesIntersectRegion(dpy, reg_paint, reg_paint, w->border_size);
+ // Painting the window
+ if (!w->frame_opacity) {
+ XRenderComposite(dpy, op, w->picture, alpha_mask,
+ root_buffer, 0, 0, 0, 0, x, y, wid, hei);
}
else {
- XFixesIntersectRegion(dpy, reg_paint, region, w->border_size);
- }
+ unsigned int t = w->top_width;
+ unsigned int l = w->left_width;
+ unsigned int b = w->bottom_width;
+ unsigned int r = w->right_width;
+
+ /* top */
+ XRenderComposite(
+ dpy, PictOpOver, w->picture, w->frame_alpha_pict, root_buffer,
+ 0, 0, 0, 0, x, y, wid, t);
+
+ /* left */
+ XRenderComposite(
+ dpy, PictOpOver, w->picture, w->frame_alpha_pict, root_buffer,
+ 0, t, 0, t, x, y + t, l, hei - t);
+
+ /* bottom */
+ XRenderComposite(
+ dpy, PictOpOver, w->picture, w->frame_alpha_pict, root_buffer,
+ l, hei - b, l, hei - b, x + l, y + hei - b, wid - l - r, b);
+
+ /* right */
+ XRenderComposite(
+ dpy, PictOpOver, w->picture, w->frame_alpha_pict, root_buffer,
+ wid - r, t, wid - r, t, x + wid - r, y + t, r, hei - t);
+
+ /* body */
+ XRenderComposite(
+ dpy, op, w->picture, alpha_mask, root_buffer,
+ l, t, l, t, x + l, y + t, wid - l - r, hei - t - b);
- if (!is_region_empty(dpy, reg_paint)) {
- XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, reg_paint);
+ }
- // Painting the window
- win_paint_win(dpy, w, root_buffer);
+ // Dimming the window if needed
+ if (w->dim) {
+ XRenderComposite(dpy, PictOpOver, dim_picture, None,
+ root_buffer, 0, 0, 0, 0, x, y, wid, hei);
}
+ XFixesDestroyRegion(dpy, paint_reg);
+
check_fade_fin(dpy, w);
}
@@ -1669,10 +1504,7 @@ paint_all(Display *dpy, XserverRegion region, win *t) {
fflush(stdout);
#endif
- // Free up all temporary regions
XFixesDestroyRegion(dpy, region);
- XFixesDestroyRegion(dpy, reg_tmp);
- XFixesDestroyRegion(dpy, reg_tmp2);
if (root_buffer != root_picture) {
XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, None);
@@ -1710,10 +1542,6 @@ repair_win(Display *dpy, win *w) {
w->a.y + w->a.border_width);
}
- // Remove the part in the damage area that could be ignored
- if (!reg_ignore_expire && w->prev_trans && w->prev_trans->reg_ignore)
- XFixesSubtractRegion(dpy, parts, parts, w->prev_trans->reg_ignore);
-
add_damage(dpy, parts);
w->damaged = 1;
}
@@ -1750,6 +1578,30 @@ get_wintype_prop(Display *dpy, Window wid) {
return WINTYPE_UNKNOWN;
}
+static wintype
+determine_wintype(Display *dpy, Window w) {
+ Window *children = NULL;
+ unsigned int nchildren, i;
+ wintype type;
+
+ type = get_wintype_prop(dpy, w);
+ if (type != WINTYPE_UNKNOWN) return type;
+
+ if (!wid_get_children(dpy, w, &children, &nchildren))
+ return WINTYPE_UNKNOWN;
+
+ for (i = 0; i < nchildren; i++) {
+ type = determine_wintype(dpy, children[i]);
+ if (type != WINTYPE_UNKNOWN) return type;
+ }
+
+ if (children) {
+ XFree((void *)children);
+ }
+
+ return WINTYPE_UNKNOWN;
+}
+
static void
map_win(Display *dpy, Window id,
unsigned long sequence, Bool fade,
@@ -1758,8 +1610,6 @@ map_win(Display *dpy, Window id,
if (!w) return;
- reg_ignore_expire = True;
-
w->focused = False;
w->a.map_state = IsViewable;
@@ -1775,21 +1625,10 @@ map_win(Display *dpy, Window id,
// Detect client window here instead of in add_win() as the client
// window should have been prepared at this point
if (!w->client_win) {
- Window cw = 0;
- // Always recursively look for a window with WM_STATE, as Fluxbox
- // sets override-redirect flags on all frame windows.
- cw = find_client_win(dpy, w->id);
+ Window cw = find_client_win(dpy, w->id);
#ifdef DEBUG_CLIENTWIN
printf("find_client_win(%#010lx): client %#010lx\n", w->id, cw);
#endif
- // Set a window's client window to itself only if we didn't find a
- // client window and the window has override-redirect flag
- if (!cw && w->a.override_redirect) {
- cw = w->id;
-#ifdef DEBUG_CLIENTWIN
- printf("find_client_win(%#010lx): client self (override-redirected)\n", w->id);
-#endif
- }
if (cw) {
mark_client_win(dpy, w, cw);
}
@@ -1800,10 +1639,8 @@ map_win(Display *dpy, Window id,
get_frame_extents(dpy, w, w->client_win);
}
- // Workaround for _NET_WM_WINDOW_TYPE for Openbox menus, which is
- // set on a non-override-redirect window with no WM_STATE either
- if (!w->client_win && WINTYPE_UNKNOWN == w->window_type)
- w->window_type = get_wintype_prop(dpy, w->id);
+ if (WINTYPE_UNKNOWN == w->window_type)
+ w->window_type = determine_wintype(dpy, w->id);
#ifdef DEBUG_WINTYPE
printf("map_win(%#010lx): type %s\n",
@@ -1897,7 +1734,9 @@ finish_unmap_win(Display *dpy, win *w) {
w->extents = None;
}
+#if HAS_NAME_WINDOW_PIXMAP
free_pixmap(dpy, &w->pixmap);
+#endif
free_picture(dpy, &w->picture);
free_region(dpy, &w->border_size);
@@ -1915,8 +1754,6 @@ unmap_win(Display *dpy, Window id, Bool fade) {
if (!w) return;
- reg_ignore_expire = True;
-
w->a.map_state = IsUnmapped;
// Fading out
@@ -1937,14 +1774,14 @@ unmap_win(Display *dpy, Window id, Bool fade) {
}
static opacity_t
-wid_get_opacity_prop(Display *dpy, Window wid, opacity_t def) {
+get_opacity_prop(Display *dpy, win *w, opacity_t def) {
Atom actual;
int format;
unsigned long n, left;
unsigned char *data;
int result = XGetWindowProperty(
- dpy, wid, opacity_atom, 0L, 1L, False,
+ dpy, w->id, opacity_atom, 0L, 1L, False,
XA_CARDINAL, &actual, &format, &n, &left, &data);
if (result == Success && data != NULL) {
@@ -1983,11 +1820,6 @@ determine_mode(Display *dpy, win *w) {
mode = WINDOW_SOLID;
}
- // Expire reg_ignore if the window mode changes from solid to not, or
- // vice versa
- if ((WINDOW_SOLID == mode) != (WINDOW_SOLID == w->mode))
- reg_ignore_expire = True;
-
w->mode = mode;
}
@@ -2023,18 +1855,13 @@ calc_opacity(Display *dpy, win *w, Bool refetch_prop) {
// Do not refetch the opacity window attribute unless necessary, this
// is probably an expensive operation in some cases
if (refetch_prop) {
- w->opacity_prop = wid_get_opacity_prop(dpy, w->id, OPAQUE);
- if (!opts.detect_client_opacity || !w->client_win
- || w->id == w->client_win)
- w->opacity_prop_client = OPAQUE;
- else
- w->opacity_prop_client = wid_get_opacity_prop(dpy, w->client_win,
- OPAQUE);
+ w->opacity_prop = get_opacity_prop(dpy, w, OPAQUE);
}
- if (OPAQUE == (opacity = w->opacity_prop)
- && OPAQUE == (opacity = w->opacity_prop_client)) {
- opacity = opts.wintype_opacity[w->window_type] * OPAQUE;
+ if (OPAQUE == (opacity = w->opacity_prop)) {
+ if (1.0 != opts.wintype_opacity[w->window_type]) {
+ opacity = opts.wintype_opacity[w->window_type] * OPAQUE;
+ }
}
// Respect inactive_opacity in some cases
@@ -2135,28 +1962,14 @@ static void
mark_client_win(Display *dpy, win *w, Window client) {
w->client_win = client;
- XSelectInput(dpy, client, determine_evmask(dpy, client, WIN_EVMODE_CLIENT));
-
// Get the frame width and monitor further frame width changes on client
// window if necessary
if (opts.frame_opacity) {
get_frame_extents(dpy, w, client);
}
-
- // Detect window type here
+ XSelectInput(dpy, client, determine_evmask(dpy, client, WIN_EVMODE_CLIENT));
if (WINTYPE_UNKNOWN == w->window_type)
w->window_type = get_wintype_prop(dpy, w->client_win);
-
- // Conform to EWMH standard, if _NET_WM_WINDOW_TYPE is not present, take
- // override-redirect windows or windows without WM_TRANSIENT_FOR as
- // _NET_WM_WINDOW_TYPE_NORMAL, otherwise as _NET_WM_WINDOW_TYPE_DIALOG.
- if (WINTYPE_UNKNOWN == w->window_type) {
- if (w->a.override_redirect
- || !wid_has_attr(dpy, client, transient_atom))
- w->window_type = WINTYPE_NORMAL;
- else
- w->window_type = WINTYPE_DIALOG;
- }
}
static void
@@ -2191,7 +2004,9 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
#if CAN_DO_USABLE
new->usable = False;
#endif
+#if HAS_NAME_WINDOW_PIXMAP
new->pixmap = None;
+#endif
new->picture = None;
if (new->a.class == InputOnly) {
@@ -2212,10 +2027,10 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
new->rounded_corners = False;
new->border_size = None;
- new->reg_ignore = None;
new->extents = None;
new->shadow = False;
new->shadow_opacity = 0.0;
+ new->shadow_opacity_cur = 0.0;
new->shadow_pict = None;
new->shadow_alpha_pict = None;
new->shadow_dx = 0;
@@ -2224,13 +2039,14 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
new->shadow_height = 0;
new->opacity = 0;
new->opacity_tgt = 0;
+ new->opacity_cur = OPAQUE;
new->opacity_prop = OPAQUE;
- new->opacity_prop_client = OPAQUE;
new->fade = False;
new->fade_callback = NULL;
new->fade_fin = False;
new->alpha_pict = None;
new->frame_opacity = 1.0;
+ new->frame_opacity_cur = 1.0;
new->frame_alpha_pict = None;
new->dim = False;
new->focused = False;
@@ -2238,7 +2054,7 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
new->need_configure = False;
new->window_type = WINTYPE_UNKNOWN;
- new->prev_trans = NULL;
+ new->prev_trans = 0;
new->left_width = 0;
new->right_width = 0;
@@ -2349,8 +2165,6 @@ configure_win(Display *dpy, XConfigureEvent *ce) {
restack_win(dpy, w, ce->above);
}
- reg_ignore_expire = True;
-
w->need_configure = False;
#if CAN_DO_USABLE
@@ -2367,8 +2181,10 @@ configure_win(Display *dpy, XConfigureEvent *ce) {
w->a.y = ce->y;
if (w->a.width != ce->width || w->a.height != ce->height) {
+#if HAS_NAME_WINDOW_PIXMAP
free_pixmap(dpy, &w->pixmap);
free_picture(dpy, &w->picture);
+#endif
}
if (w->a.width != ce->width || w->a.height != ce->height
@@ -2419,9 +2235,10 @@ finish_destroy_win(Display *dpy, Window id) {
finish_unmap_win(dpy, w);
*prev = w->next;
+ free_picture(dpy, &w->alpha_pict);
+ free_picture(dpy, &w->frame_alpha_pict);
free_picture(dpy, &w->shadow_pict);
free_damage(dpy, &w->damage);
- free_region(dpy, &w->reg_ignore);
free(w->name);
free(w->class_instance);
free(w->class_general);
@@ -2432,10 +2249,12 @@ finish_destroy_win(Display *dpy, Window id) {
}
}
+#if HAS_NAME_WINDOW_PIXMAP
static void
destroy_callback(Display *dpy, win *w) {
finish_destroy_win(dpy, w->id);
}
+#endif
static void
destroy_win(Display *dpy, Window id, Bool fade) {
@@ -2962,17 +2781,12 @@ ev_property_notify(XPropertyEvent *ev) {
}
}
- // If _NET_WM_OPACITY changes
+ /* check if Trans property was changed */
if (ev->atom == opacity_atom) {
- win *w = NULL;
- if ((w = find_win(dpy, ev->window)))
- w->opacity_prop = wid_get_opacity_prop(dpy, w->id, OPAQUE);
- else if (opts.detect_client_opacity
- && (w = find_toplevel(dpy, ev->window)))
- w->opacity_prop_client = wid_get_opacity_prop(dpy, w->client_win,
- OPAQUE);
+ /* reset mode and redraw window */
+ win *w = find_win(dpy, ev->window);
if (w) {
- calc_opacity(dpy, w, False);
+ calc_opacity(dpy, w, True);
}
}
@@ -3041,22 +2855,7 @@ ev_shape_notify(XShapeEvent *ev) {
}
}
-/**
- * Handle ScreenChangeNotify events from X RandR extension.
- */
-static void
-ev_screen_change_notify(XRRScreenChangeNotifyEvent *ev) {
- if (!opts.refresh_rate) {
- update_refresh_rate(dpy);
- if (!refresh_rate) {
- fprintf(stderr, "ev_screen_change_notify(): Refresh rate detection "
- "failed, software VSync disabled.");
- opts.vsync = VSYNC_NONE;
- }
- }
-}
-
-static void
+inline static void
ev_handle(XEvent *ev) {
if ((ev->type & 0x7f) != KeymapNotify) {
discard_ignore(dpy, ev->xany.serial);
@@ -3130,10 +2929,6 @@ ev_handle(XEvent *ev) {
ev_shape_notify((XShapeEvent *) ev);
break;
}
- if (randr_exists && ev->type == (randr_event + RRScreenChangeNotify)) {
- ev_screen_change_notify((XRRScreenChangeNotifyEvent *) ev);
- break;
- }
if (ev->type == damage_event + XDamageNotify) {
ev_damage_notify((XDamageNotifyEvent *)ev);
}
@@ -3145,14 +2940,11 @@ ev_handle(XEvent *ev) {
* Main
*/
-/**
- * Print usage text and exit.
- */
static void
usage(void) {
- fputs(
- "compton (v0.0.1)\n"
- "usage: compton [options]\n"
+ fprintf(stderr, "compton (development version)\n");
+ fprintf(stderr, "usage: compton [options]\n");
+ fprintf(stderr,
"Options:\n"
"\n"
"-d display\n"
@@ -3219,27 +3011,6 @@ usage(void) {
"--detect-rounded-corners\n"
" Try to detect windows with rounded corners and don't consider\n"
" them shaped windows.\n"
- "--detect-client-opacity\n"
- " Detect _NET_WM_OPACITY on client windows, useful for window\n"
- " managers not passing _NET_WM_OPACITY of client windows to frame\n"
- " windows.\n"
- "\n"
- "--refresh-rate val\n"
- " Specify refresh rate of the screen. If not specified or 0, compton\n"
- " will try detecting this with X RandR extension.\n"
- "--vsync vsync-method\n"
- " Set VSync method. There are 4 VSync methods currently available:\n"
- " none = No VSync\n"
- " sw = software VSync, basically limits compton to send a request\n"
- " every 1 / refresh_rate second. Experimental.\n"
- " drm = VSync with DRM_IOCTL_WAIT_VBLANK. May only work on some\n"
- " drivers. Experimental.\n"
- " opengl = Try to VSync with SGI_swap_control OpenGL extension. Only\n"
- " work on some drivers. Experimental.\n"
- " (Note some VSync methods may not be enabled at compile time.)\n"
- "--alpha-step val\n"
- " Step for pregenerating alpha pictures. 0.01 - 1.0. Defaults to\n"
- " 0.03.\n"
"\n"
"Format of a condition:\n"
"\n"
@@ -3256,77 +3027,26 @@ usage(void) {
" flag is \"i\" (ignore case).\n"
"\n"
" <pattern> is the actual pattern string.\n"
- , stderr);
+ );
exit(1);
}
-/**
- * Register a window as symbol, and initialize GLX context if wanted.
- */
static void
-register_cm(Bool want_glxct) {
+register_cm(int scr) {
+ Window w;
Atom a;
char *buf;
int len, s;
-#ifdef CONFIG_VSYNC_OPENGL
- // Create a window with the wanted GLX visual
- if (want_glxct) {
- XVisualInfo *pvi = NULL;
- Bool ret = False;
- // Get visual for the window
- int attribs[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None };
- pvi = glXChooseVisual(dpy, scr, attribs);
-
- if (!pvi) {
- fprintf(stderr, "register_cm(): Failed to choose visual required "
- "by fake OpenGL VSync window. OpenGL VSync turned off.\n");
- }
- else {
- // Create the window
- XSetWindowAttributes swa = {
- .colormap = XCreateColormap(dpy, root, pvi->visual, AllocNone),
- .border_pixel = 0,
- };
-
- pvi->screen = scr;
- reg_win = XCreateWindow(dpy, root, 0, 0, 1, 1, 0, pvi->depth,
- InputOutput, pvi->visual, CWBorderPixel | CWColormap, &swa);
-
- if (!reg_win)
- fprintf(stderr, "register_cm(): Failed to create window required "
- "by fake OpenGL VSync. OpenGL VSync turned off.\n");
- else {
- // Get GLX context
- glx_context = glXCreateContext(dpy, pvi, None, GL_TRUE);
- if (!glx_context) {
- fprintf(stderr, "register_cm(): Failed to get GLX context. "
- "OpenGL VSync turned off.\n");
- opts.vsync = VSYNC_NONE;
- }
- else {
- // Attach GLX context
- if (!(ret = glXMakeCurrent(dpy, reg_win, glx_context)))
- fprintf(stderr, "register_cm(): Failed to attach GLX context."
- " OpenGL VSync turned off.\n");
- }
- }
- }
- if (pvi)
- XFree(pvi);
+ if (scr < 0) return;
- if (!ret)
- opts.vsync = VSYNC_NONE;
- }
-#endif
-
- if (!reg_win)
- reg_win = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0,
- None, None);
+ w = XCreateSimpleWindow(
+ dpy, RootWindow(dpy, 0),
+ 0, 0, 1, 1, 0, None, None);
Xutf8SetWMProperties(
- dpy, reg_win, "xcompmgr", "xcompmgr",
+ dpy, w, "xcompmgr", "xcompmgr",
NULL, 0, NULL, NULL, NULL);
len = strlen(REGISTER_PROP) + 2;
@@ -3343,7 +3063,7 @@ register_cm(Bool want_glxct) {
a = XInternAtom(dpy, buf, False);
free(buf);
- XSetSelectionOwner(dpy, a, reg_win, 0);
+ XSetSelectionOwner(dpy, a, w, 0);
}
static void
@@ -3551,13 +3271,6 @@ parse_config(char *cpath, struct options_tmp *pcfgtmp) {
// --detect-rounded-corners
lcfg_lookup_bool(&cfg, "detect-rounded-corners",
&opts.detect_rounded_corners);
- // --detect-client-opacity
- lcfg_lookup_bool(&cfg, "detect-client-opacity",
- &opts.detect_client_opacity);
- // --refresh-rate
- lcfg_lookup_int(&cfg, "refresh-rate", &opts.refresh_rate);
- // --alpha-step
- config_lookup_float(&cfg, "alpha-step", &opts.alpha_step);
// --shadow-exclude
{
config_setting_t *setting =
@@ -3620,19 +3333,9 @@ get_cfg(int argc, char *const *argv) {
{ "no-fading-openclose", no_argument, NULL, 265 },
{ "shadow-ignore-shaped", no_argument, NULL, 266 },
{ "detect-rounded-corners", no_argument, NULL, 267 },
- { "detect-client-opacity", no_argument, NULL, 268 },
- { "refresh-rate", required_argument, NULL, 269 },
- { "vsync", required_argument, NULL, 270 },
- { "alpha-step", required_argument, NULL, 271 },
// Must terminate with a NULL entry
{ NULL, 0, NULL, 0 },
};
- const static char * const vsync_str[] = {
- "none", // VSYNC_NONE
- "sw", // VSYNC_SW
- "drm", // VSYNC_DRM
- "opengl", // VSYNC_OPENGL
- };
struct options_tmp cfgtmp = {
.no_dock_shadow = False,
@@ -3784,32 +3487,6 @@ get_cfg(int argc, char *const *argv) {
// --detect-rounded-corners
opts.detect_rounded_corners = True;
break;
- case 268:
- // --detect-client-opacity
- opts.detect_client_opacity = True;
- break;
- case 269:
- // --refresh-rate
- opts.refresh_rate = atoi(optarg);
- break;
- case 270:
- // --vsync
- {
- vsync_t i;
- for (i = 0; i < (sizeof(vsync_str) / sizeof(vsync_str[0])); ++i)
- if (!strcasecmp(optarg, vsync_str[i])) {
- opts.vsync = i;
- break;
- }
- if ((sizeof(vsync_str) / sizeof(vsync_str[0])) == i) {
- fputs("Invalid --vsync argument. Ignored.\n", stderr);
- }
- }
- break;
- case 271:
- // --alpha-step
- opts.alpha_step = atof(optarg);
- break;
default:
usage();
break;
@@ -3830,8 +3507,6 @@ get_cfg(int argc, char *const *argv) {
opts.frame_opacity = normalize_d(opts.frame_opacity);
opts.shadow_opacity = normalize_d(opts.shadow_opacity);
cfgtmp.menu_opacity = normalize_d(cfgtmp.menu_opacity);
- opts.refresh_rate = normalize_i_range(opts.refresh_rate, 0, 300);
- opts.alpha_step = normalize_d_range(opts.alpha_step, 0.01, 1.0);
if (OPAQUE == opts.inactive_opacity) {
opts.inactive_opacity = 0;
}
@@ -3866,11 +3541,10 @@ get_atoms(void) {
extents_atom = XInternAtom(dpy, "_NET_FRAME_EXTENTS", False);
opacity_atom = XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", False);
frame_extents_atom = XInternAtom(dpy, "_NET_FRAME_EXTENTS", False);
- client_atom = XInternAtom(dpy, "WM_STATE", False);
+ client_atom = XA_WM_CLASS;
name_atom = XA_WM_NAME;
name_ewmh_atom = XInternAtom(dpy, "_NET_WM_NAME", False);
class_atom = XA_WM_CLASS;
- transient_atom = XA_WM_TRANSIENT_FOR;
win_type_atom = XInternAtom(dpy,
"_NET_WM_WINDOW_TYPE", False);
@@ -3905,291 +3579,6 @@ get_atoms(void) {
"_NET_WM_WINDOW_TYPE_DND", False);
}
-/**
- * Update refresh rate info with X Randr extension.
- */
-static void
-update_refresh_rate(Display *dpy) {
- XRRScreenConfiguration* randr_info;
-
- if (!(randr_info = XRRGetScreenInfo(dpy, root)))
- return;
- refresh_rate = XRRConfigCurrentRate(randr_info);
-
- XRRFreeScreenConfigInfo(randr_info);
-
- if (refresh_rate)
- refresh_intv = NS_PER_SEC / refresh_rate;
- else
- refresh_intv = 0;
-}
-
-/**
- * Initialize software VSync.
- *
- * @return True for success, False otherwise
- */
-static Bool
-vsync_sw_init(void) {
- // Prepare refresh rate
- // Check if user provides one
- refresh_rate = opts.refresh_rate;
- if (refresh_rate)
- refresh_intv = NS_PER_SEC / refresh_rate;
-
- // Auto-detect refresh rate otherwise
- if (!refresh_rate && randr_exists) {
- update_refresh_rate(dpy);
- }
-
- // Turn off vsync_sw if we can't get the refresh rate
- if (!refresh_rate)
- return False;
-
- // Monitor screen changes only if vsync_sw is enabled and we are using
- // an auto-detected refresh rate
- if (randr_exists && !opts.refresh_rate)
- XRRSelectInput(dpy, root, RRScreenChangeNotify);
-
- return True;
-}
-
-/**
- * Get current time in struct timespec.
- *
- * Note its starting time is unspecified.
- */
-static inline struct timespec
-get_time_timespec(void) {
- struct timespec tm = { 0 };
-
- clock_gettime(CLOCK_MONOTONIC, &tm);
-
- // Return a time of all 0 if the call fails
- return tm;
-}
-
-/**
- * Get the smaller number that is bigger than <code>dividend</code> and is
- * N times of <code>divisor</code>.
- */
-static inline long
-lceil_ntimes(long dividend, long divisor) {
- // It's possible to use the more beautiful expression here:
- // ret = ((dividend - 1) / divisor + 1) * divisor;
- // But it does not work well for negative values.
- long ret = dividend / divisor * divisor;
- if (ret < dividend)
- ret += divisor;
-
- return ret;
-}
-
-/**
- * Calculate time for which the program should wait for events if vsync_sw is
- * enabled.
- *
- * @param timeout old timeout value, never negative!
- * @return time to wait, in struct timespec
- */
-static struct timespec
-vsync_sw_ntimeout(int timeout) {
- // Convert the old timeout to struct timespec
- struct timespec next_paint_tmout = {
- .tv_sec = timeout / MS_PER_SEC,
- .tv_nsec = timeout % MS_PER_SEC * (NS_PER_SEC / MS_PER_SEC)
- };
- // Get the nanosecond offset of the time when the we reach the timeout
- // I don't think a 32-bit long could overflow here.
- long target_relative_offset = (next_paint_tmout.tv_nsec + get_time_timespec().tv_nsec - paint_tm_offset) % NS_PER_SEC;
- if (target_relative_offset < 0)
- target_relative_offset += NS_PER_SEC;
-
- assert(target_relative_offset >= 0);
-
- // If the target time is sufficiently close to a VSync time, don't add
- // an offset, to avoid certain blocking conditions.
- if ((target_relative_offset % NS_PER_SEC) < VSYNC_SW_TOLERANCE)
- return next_paint_tmout;
-
- // Add an offset so we wait until the next VSync after timeout
- next_paint_tmout.tv_nsec += lceil_ntimes(target_relative_offset, refresh_intv) - target_relative_offset;
- if (next_paint_tmout.tv_nsec > NS_PER_SEC) {
- next_paint_tmout.tv_nsec -= NS_PER_SEC;
- ++next_paint_tmout.tv_sec;
- }
-
- return next_paint_tmout;
-}
-
-/**
- * Initialize DRM VSync.
- *
- * @return True for success, False otherwise
- */
-static Bool
-vsync_drm_init(void) {
-#ifdef CONFIG_VSYNC_DRM
- // Should we always open card0?
- if ((drm_fd = open("/dev/dri/card0", O_RDWR)) < 0) {
- fprintf(stderr, "vsync_drm_init(): Failed to open device.\n");
- return False;
- }
-
- if (vsync_drm_wait())
- return False;
-
- return True;
-#else
- fprintf(stderr, "Program not compiled with DRM VSync support.\n");
- return False;
-#endif
-}
-
-#ifdef CONFIG_VSYNC_DRM
-/**
- * Wait for next VSync, DRM method.
- *
- * Stolen from: https://github.com/MythTV/mythtv/blob/master/mythtv/libs/libmythtv/vsync.cpp
- */
-static int
-vsync_drm_wait(void) {
- int ret = -1;
- drm_wait_vblank_t vbl;
-
- vbl.request.type = _DRM_VBLANK_RELATIVE,
- vbl.request.sequence = 1;
-
- do {
- ret = ioctl(drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
- vbl.request.type &= ~_DRM_VBLANK_RELATIVE;
- } while (ret && errno == EINTR);
-
- if (ret)
- fprintf(stderr, "vsync_drm_wait(): VBlank ioctl did not work, "
- "unimplemented in this drmver?\n");
-
- return ret;
-
-}
-#endif
-
-/**
- * Initialize OpenGL VSync.
- *
- * Stolen from: http://git.tuxfamily.org/?p=ccm/cairocompmgr.git;a=commitdiff;h=efa4ceb97da501e8630ca7f12c99b1dce853c73e
- * Possible original source: http://www.inb.uni-luebeck.de/~boehme/xvideo_sync.html
- *
- * @return True for success, False otherwise
- */
-static Bool
-vsync_opengl_init(void) {
-#ifdef CONFIG_VSYNC_OPENGL
- // Get video sync functions
- glx_get_video_sync = (f_GetVideoSync)
- glXGetProcAddress ((const GLubyte *) "glXGetVideoSyncSGI");
- glx_wait_video_sync = (f_WaitVideoSync)
- glXGetProcAddress ((const GLubyte *) "glXWaitVideoSyncSGI");
- if (!glx_wait_video_sync || !glx_get_video_sync) {
- fprintf(stderr, "vsync_opengl_init(): "
- "Failed to get glXWait/GetVideoSyncSGI function.\n");
- return False;
- }
-
- return True;
-#else
- fprintf(stderr, "Program not compiled with OpenGL VSync support.\n");
- return False;
-#endif
-}
-
-#ifdef CONFIG_VSYNC_OPENGL
-/**
- * Wait for next VSync, OpenGL method.
- */
-static void
-vsync_opengl_wait(void) {
- unsigned vblank_count;
-
- glx_get_video_sync(&vblank_count);
- glx_wait_video_sync(2, (vblank_count + 1) % 2, &vblank_count);
- // I see some code calling glXSwapIntervalSGI(1) afterwards, is it required?
-}
-#endif
-
-/**
- * Wait for next vsync and timeout unless new events appear.
- *
- * @param fd struct pollfd used for poll()
- * @param timeout second timeout (fading timeout)
- * @return > 0 if we get some events, 0 if timeout is reached, < 0 on
- * problems
- */
-static Bool
-vsync_wait(Display *dpy, struct pollfd *fd, int timeout) {
- // Always wait infinitely if asked so, to minimize CPU usage
- if (timeout < 0) {
- int ret = poll(fd, 1, timeout);
- // Reset fade_time so the fading steps during idling are not counted
- fade_time = get_time_ms();
- return ret;
- }
-
- if (VSYNC_NONE == opts.vsync)
- return poll(fd, 1, timeout);
-
- // vsync_sw: Wait until the next sync right after next fading timeout
- if (VSYNC_SW == opts.vsync) {
- struct timespec new_tmout = vsync_sw_ntimeout(timeout);
- // printf("ppoll(): %3ld:%09ld\n", new_tmout.tv_sec, new_tmout.tv_nsec);
- return ppoll(fd, 1, &new_tmout, NULL);
- }
-
-#ifdef CONFIG_VSYNC_DRM
- // vsync_drm: We are not accepting events when waiting for next sync,
- // so I guess this would generate a latency of at most one frame. I'm
- // not sure if it's possible to add some smart logic in vsync_drm_wait()
- // to avoid this problem, unless I could find more documentation...
- if (VSYNC_DRM == opts.vsync) {
- vsync_drm_wait();
- return 0;
- }
-#endif
-
-#ifdef CONFIG_VSYNC_OPENGL
- // vsync_opengl: Same one-frame-latency issue, well, not sure how to deal it
- // here.
- if (VSYNC_OPENGL == opts.vsync) {
- vsync_opengl_wait();
- return 0;
- }
-#endif
-
- // This place should not reached!
- assert(0);
-
- return 0;
-}
-
-/**
- * Pregenerate alpha pictures.
- */
-static void
-init_alpha_picts(Display *dpy) {
- int i;
- int num = lround(1.0 / opts.alpha_step) + 1;
-
- alpha_picts = malloc(sizeof(Picture) * num);
-
- for (i = 0; i < num; ++i) {
- double o = i * opts.alpha_step;
- if ((1.0 - o) > opts.alpha_step)
- alpha_picts[i] = solid_picture(dpy, False, o, 0, 0, 0);
- else
- alpha_picts[i] = None;
- }
-}
-
int
main(int argc, char **argv) {
XEvent ev;
@@ -4210,7 +3599,7 @@ main(int argc, char **argv) {
get_cfg(argc, argv);
- fade_time = get_time_ms();
+ fade_time = get_time_in_milliseconds();
dpy = XOpenDisplay(opts.display);
if (!dpy) {
@@ -4239,9 +3628,11 @@ main(int argc, char **argv) {
XCompositeQueryVersion(dpy, &composite_major, &composite_minor);
+#if HAS_NAME_WINDOW_PIXMAP
if (composite_major > 0 || composite_minor >= 2) {
has_name_pixmap = True;
}
+#endif
if (!XDamageQueryExtension(dpy, &damage_event, &damage_error)) {
fprintf(stderr, "No damage extension\n");
@@ -4253,44 +3644,15 @@ main(int argc, char **argv) {
exit(1);
}
- // Query X Shape
- if (XShapeQueryExtension(dpy, &shape_event, &shape_error)) {
- shape_exists = True;
- }
-
- // Query X RandR
- if (VSYNC_SW == opts.vsync && !opts.refresh_rate) {
- if (XRRQueryExtension(dpy, &randr_event, &randr_error))
- randr_exists = True;
- else
- fprintf(stderr, "No XRandR extension, automatic refresh rate "
- "detection impossible.\n");
- }
-
-#ifdef CONFIG_VSYNC_OPENGL
- // Query X GLX extension
- if (VSYNC_OPENGL == opts.vsync) {
- if (glXQueryExtension(dpy, &glx_event, &glx_error))
- glx_exists = True;
- else {
- fprintf(stderr, "No GLX extension, OpenGL VSync impossible.\n");
- opts.vsync = VSYNC_NONE;
- }
+ if (!XShapeQueryExtension(dpy, &shape_event, &shape_error)) {
+ shape_exists = False;
}
-#endif
-
- register_cm((VSYNC_OPENGL == opts.vsync));
- // Initialize software/DRM/OpenGL VSync
- if ((VSYNC_SW == opts.vsync && !vsync_sw_init())
- || (VSYNC_DRM == opts.vsync && !vsync_drm_init())
- || (VSYNC_OPENGL == opts.vsync && !vsync_opengl_init()))
- opts.vsync = VSYNC_NONE;
+ register_cm(scr);
if (opts.fork_after_register) fork_after();
get_atoms();
- init_alpha_picts(dpy);
pa.subwindow_mode = IncludeInferiors;
@@ -4350,51 +3712,31 @@ main(int argc, char **argv) {
ufd.fd = ConnectionNumber(dpy);
ufd.events = POLLIN;
-#ifdef DEBUG_REPAINT
- struct timespec last_paint = get_time_timespec();
-#endif
-
- if (VSYNC_SW == opts.vsync)
- paint_tm_offset = get_time_timespec().tv_nsec;
-
- reg_ignore_expire = True;
-
t = paint_preprocess(dpy, list);
-
paint_all(dpy, None, t);
// Initialize idling
idling = False;
- // Main loop
- while (1) {
- Bool ev_received = False;
+ for (;;) {
+ do {
+ if (!QLength(dpy)) {
+ if (poll(&ufd, 1, (idling ? -1: fade_timeout())) == 0) {
+ break;
+ }
+ }
- while (QLength(dpy)
- || (vsync_wait(dpy, &ufd,
- (ev_received ? 0: (idling ? -1: fade_timeout()))) > 0)) {
XNextEvent(dpy, &ev);
- ev_handle((XEvent *) &ev);
- ev_received = True;
- }
+ ev_handle((XEvent *)&ev);
+ } while (QLength(dpy));
// idling will be turned off during paint_preprocess() if needed
idling = True;
t = paint_preprocess(dpy, list);
-
- if (all_damage && !is_region_empty(dpy, all_damage)) {
-#ifdef DEBUG_REPAINT
- struct timespec now = get_time_timespec();
- struct timespec diff = { 0 };
- timespec_subtract(&diff, &now, &last_paint);
- printf("[ %5ld:%09ld ] ", diff.tv_sec, diff.tv_nsec);
- last_paint = now;
-#endif
-
+ if (all_damage) {
static int paint;
paint_all(dpy, all_damage, t);
- reg_ignore_expire = False;
paint++;
XSync(dpy, False);
all_damage = None;
diff --git a/compton.h b/compton.h
index 6aac338e9..83b78769e 100644
--- a/compton.h
+++ b/compton.h
@@ -26,10 +26,6 @@
// #define CONFIG_REGEX_PCRE_JIT 1
// Whether to enable parsing of configuration files using libconfig
// #define CONFIG_LIBCONFIG 1
-// Whether to enable DRM VSync support
-// #define CONFIG_VSYNC_DRM 1
-// Whether to enable OpenGL VSync support
-// #define CONFIG_VSYNC_OPENGL 1
// === Includes ===
@@ -48,7 +44,6 @@
#include <getopt.h>
#include <stdbool.h>
#include <locale.h>
-#include <assert.h>
#include <fnmatch.h>
@@ -74,25 +69,10 @@
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/shape.h>
-#include <X11/extensions/Xrandr.h>
-
-#ifdef CONFIG_VSYNC_DRM
-#include <fcntl.h>
-// We references some definitions in drm.h, which could also be found in
-// /usr/src/linux/include/drm/drm.h, but that path is probably even less
-// reliable than libdrm
-#include <libdrm/drm.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#endif
-
-#ifdef CONFIG_VSYNC_OPENGL
-#include <GL/glx.h>
-#endif
// === Constants ===
-#if !(COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2)
-#error libXcomposite version unsupported
+#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2
+#define HAS_NAME_WINDOW_PIXMAP 1
#endif
#define ROUNDED_PERCENT 0.05
@@ -109,13 +89,6 @@ extern struct timeval time_start;
#define WINDOW_TRANS 1
#define WINDOW_ARGB 2
-#define FADE_DELTA_TOLERANCE 0.2
-#define VSYNC_SW_TOLERANCE 1000
-
-#define NS_PER_SEC 1000000000L
-#define US_PER_SEC 1000000L
-#define MS_PER_SEC 1000
-
// Window flags
// Window size is changed
@@ -183,7 +156,9 @@ typedef struct _win {
struct _win *next;
Window id;
Window client_win;
+#if HAS_NAME_WINDOW_PIXMAP
Pixmap pixmap;
+#endif
XWindowAttributes a;
#if CAN_DO_USABLE
Bool usable; /* mapped and all damaged at one point */
@@ -219,12 +194,10 @@ typedef struct _win {
opacity_t opacity;
/// Target window opacity.
opacity_t opacity_tgt;
+ /// Opacity of current alpha_pict.
+ opacity_t opacity_cur;
/// Cached value of opacity window attribute.
opacity_t opacity_prop;
- /// Cached value of opacity window attribute on client window. For
- /// broken window managers not transferring client window's
- /// _NET_WM_OPACITY value
- opacity_t opacity_prop_client;
/// Alpha mask Picture to render window with opacity.
Picture alpha_pict;
@@ -240,6 +213,8 @@ typedef struct _win {
// Frame-opacity-related members
/// Current window frame opacity. Affected by window opacity.
double frame_opacity;
+ /// Opacity of current frame_alpha_pict.
+ opacity_t frame_opacity_cur;
/// Alpha mask Picture to render window frame with opacity.
Picture frame_alpha_pict;
/// Frame widths. Determined by client window attributes.
@@ -250,6 +225,8 @@ typedef struct _win {
Bool shadow;
/// Opacity of the shadow. Affected by window opacity and frame opacity.
double shadow_opacity;
+ /// Opacity of current shadow_pict.
+ double shadow_opacity_cur;
/// X offset of shadow. Affected by commandline argument.
int shadow_dx;
/// Y offset of shadow. Affected by commandline argument.
@@ -274,27 +251,10 @@ typedef struct _win {
Bool need_configure;
XConfigureEvent queue_configure;
- /// Region to be ignored when painting. Basically the region where
- /// higher opaque windows will paint upon. Depends on window frame
- /// opacity state, window geometry, window mapped/unmapped state,
- /// window mode, of this and all higher windows.
- XserverRegion reg_ignore;
struct _win *prev_trans;
} win;
-typedef enum _vsync_t {
- VSYNC_NONE,
- VSYNC_SW,
- VSYNC_DRM,
- VSYNC_OPENGL,
-} vsync_t;
-
-#ifdef CONFIG_VSYNC_OPENGL
-typedef int (*f_WaitVideoSync) (int, int, unsigned *);
-typedef int (*f_GetVideoSync) (unsigned *);
-#endif
-
typedef struct _options {
// General
char *display;
@@ -309,12 +269,6 @@ typedef struct _options {
/// Whether to work under synchronized mode for debugging.
Bool synchronize;
- // VSync
- /// User-specified refresh rate.
- int refresh_rate;
- /// VSync method to use;
- vsync_t vsync;
-
// Shadow
Bool wintype_shadow[NUM_WINTYPES];
/// Red, green and blue tone of the shadow.
@@ -348,16 +302,9 @@ typedef struct _options {
/// Whether inactive_opacity overrides the opacity set by window
/// attributes.
Bool inactive_opacity_override;
- /// Frame opacity. Relative to window opacity, also affects shadow
- /// opacity.
double frame_opacity;
- /// Whether to detect _NET_WM_OPACITY on client windows. Used on window
- /// managers that don't pass _NET_WM_OPACITY to frame windows.
- Bool detect_client_opacity;
/// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
double inactive_dim;
- /// Step for pregenerating alpha pictures. 0.01 - 1.0.
- double alpha_step;
// Calculated
/// Whether compton needs to track focus changes.
@@ -408,16 +355,6 @@ static int
should_ignore(Display *dpy, unsigned long sequence);
/**
- * Subtract two unsigned long values.
- *
- * Truncate to 0 if the result is negative.
- */
-static inline unsigned long
-sub_unslong(unsigned long a, unsigned long b) {
- return (a > b) ? a - b : 0;
-}
-
-/**
* Set a Bool array of all wintypes to true.
*/
static void
@@ -578,41 +515,6 @@ timeval_subtract(struct timeval *result,
return x->tv_sec < y->tv_sec;
}
-/*
- * Subtracting two struct timespec values.
- *
- * Taken from glibc manual.
- *
- * Subtract the `struct timespec' values X and Y,
- * storing the result in RESULT.
- * Return 1 if the difference is negative, otherwise 0.
- */
-static inline int
-timespec_subtract(struct timespec *result,
- struct timespec *x,
- struct timespec *y) {
- /* Perform the carry for the later subtraction by updating y. */
- if (x->tv_nsec < y->tv_nsec) {
- int nsec = (y->tv_nsec - x->tv_nsec) / NS_PER_SEC + 1;
- y->tv_nsec -= NS_PER_SEC * nsec;
- y->tv_sec += nsec;
- }
-
- if (x->tv_nsec - y->tv_nsec > NS_PER_SEC) {
- int nsec = (x->tv_nsec - y->tv_nsec) / NS_PER_SEC;
- y->tv_nsec += NS_PER_SEC * nsec;
- y->tv_sec -= nsec;
- }
-
- /* Compute the time remaining to wait.
- tv_nsec is certainly positive. */
- result->tv_sec = x->tv_sec - y->tv_sec;
- result->tv_nsec = x->tv_nsec - y->tv_nsec;
-
- /* Return 1 if result is negative. */
- return x->tv_sec < y->tv_sec;
-}
-
/**
* Print time passed since program starts execution.
*
@@ -675,7 +577,7 @@ free_damage(Display *dpy, Damage *p) {
}
static unsigned long
-get_time_ms(void);
+get_time_in_milliseconds(void);
static int
fade_timeout(void);
@@ -729,7 +631,8 @@ solid_picture(Display *dpy, Bool argb, double a,
static inline bool is_normal_win(const win *w) {
return (WINTYPE_NORMAL == w->window_type
- || WINTYPE_UTILITY == w->window_type);
+ || WINTYPE_UTILITY == w->window_type
+ || WINTYPE_UNKNOWN == w->window_type);
}
/**
@@ -858,6 +761,9 @@ repair_win(Display *dpy, win *w);
static wintype
get_wintype_prop(Display * dpy, Window w);
+static wintype
+determine_wintype(Display *dpy, Window w);
+
static void
map_win(Display *dpy, Window id,
unsigned long sequence, Bool fade,
@@ -869,14 +775,16 @@ finish_map_win(Display *dpy, win *w);
static void
finish_unmap_win(Display *dpy, win *w);
+#if HAS_NAME_WINDOW_PIXMAP
static void
unmap_callback(Display *dpy, win *w);
+#endif
static void
unmap_win(Display *dpy, Window id, Bool fade);
static opacity_t
-wid_get_opacity_prop(Display *dpy, Window wid, opacity_t def);
+get_opacity_prop(Display *dpy, win *w, opacity_t def);
static double
get_opacity_percent(Display *dpy, win *w);
@@ -927,8 +835,10 @@ circulate_win(Display *dpy, XCirculateEvent *ce);
static void
finish_destroy_win(Display *dpy, Window id);
+#if HAS_NAME_WINDOW_PIXMAP
static void
destroy_callback(Display *dpy, win *w);
+#endif
static void
destroy_win(Display *dpy, Window id, Bool fade);
@@ -970,7 +880,7 @@ static void
usage(void);
static void
-register_cm(Bool want_glxct);
+register_cm(int scr);
inline static void
ev_focus_in(XFocusChangeEvent *ev);
@@ -1038,39 +948,6 @@ copy_region(Display *dpy, XserverRegion oldregion) {
}
/**
- * Dump a region.
- */
-static inline void
-dump_region(Display *dpy, XserverRegion region) {
- int nrects = 0, i;
- XRectangle *rects = XFixesFetchRegion(dpy, region, &nrects);
- if (!rects)
- return;
-
- for (i = 0; i < nrects; ++i)
- printf("Rect #%d: %8d, %8d, %8d, %8d\n", i, rects[i].x, rects[i].y,
- rects[i].width, rects[i].height);
-
- XFree(rects);
-}
-
-/**
- * Check if a region is empty.
- *
- * Keith Packard said this is slow:
- * http://lists.freedesktop.org/archives/xorg/2007-November/030467.html
- */
-static inline Bool
-is_region_empty(Display *dpy, XserverRegion region) {
- int nrects = 0;
- XRectangle *rects = XFixesFetchRegion(dpy, region, &nrects);
-
- XFree(rects);
-
- return !nrects;
-}
-
-/**
* Add a window to damaged area.
*
* @param dpy display in use
@@ -1125,34 +1002,3 @@ get_cfg(int argc, char *const *argv);
static void
get_atoms(void);
-
-static void
-update_refresh_rate(Display *dpy);
-
-static Bool
-vsync_sw_init(void);
-
-static struct timespec
-vsync_sw_ntimeout(int timeout);
-
-static Bool
-vsync_drm_init(void);
-
-#ifdef CONFIG_VSYNC_DRM
-static int
-vsync_drm_wait(void);
-#endif
-
-static Bool
-vsync_opengl_init(void);
-
-#ifdef CONFIG_VSYNC_OPENGL
-static void
-vsync_opengl_wait(void);
-#endif
-
-static Bool
-vsync_wait(Display *dpy, struct pollfd *fd, int timeout);
-
-static void
-init_alpha_picts(Display *dpy);