diff --git a/README.md b/README.md index cb67951..01c01d1 100644 --- a/README.md +++ b/README.md @@ -62,23 +62,23 @@ $ compton -cC -fF -I 0.065 -O 0.065 -D 6 -m 0.8 -i 0.6 -e 0.6 compton [-d display] [-r radius] [-o opacity] [-l left-offset] [-t top-offset] - [-i opacity] [-e opacity] [-cCfFS] + [-i opacity] [-e opacity] [-cCfFSdG] -* `-d` display +* `-d` __display__ Specifies the display to manage. -* `-r` radius +* `-r` __radius__ Specifies the blur radius for client-side shadows. -* `-o` opacity +* `-o` __opacity__ Specifies the opacity for client-side shadows. -* `-l` left-offset +* `-l` __left-offset__ Specifies the left offset for client-side shadows. -* `-t` top-offset +* `-t` __top-offset__ Specifies the top offset for client-side shadows. -* `-I` fade-in-step +* `-I` __fade-in-step__ Specifies the opacity change between steps while fading in. -* `-O` fade-out-step +* `-O` __fade-out-step__ Specifies the opacity change between steps while fading out. -* `-D` fade-delta +* `-D` __fade-delta__ Specifies the time (in milliseconds) between steps in a fade. * `-c` Enable client-side shadows on windows. @@ -90,10 +90,14 @@ $ compton -cC -fF -I 0.065 -O 0.065 -D 6 -m 0.8 -i 0.6 -e 0.6 * `-F` When -f is specified, also enables the fade effect when windows change their opacity, as with transset(1). -* `-i` opacity +* `-i` __opacity__ Specifies inactive window transparency. (0.1 - 1.0) -* `-e` opacity +* `-e` __opacity__ Specifies window frame transparency. (0.1 - 1.0) +* `-G` + Avoid painting shadows on DND windows. +* `-b` __daemonize__ + Attempt to daemonize process. * `-S` Enables synchronous operation. Useful for debugging. diff --git a/compton.1 b/compton.1 index abdfbbd..176a6ec 100644 --- a/compton.1 +++ b/compton.1 @@ -4,7 +4,7 @@ compton \- a compositor for X11 .SH SYNOPSIS .nf -.B compton [\-d display] [\-r radius] [\-o opacity] [\-l left-offset] [\-t top-offset] [\-i opacity] [\-e opacity] [\-cCfFS] +.B compton [\-d display] [\-r radius] [\-o opacity] [\-l left-offset] [\-t top-offset] [\-i opacity] [\-e opacity] [\-cCfFSdG] .fi .SH DESCRIPTION .B compton @@ -57,11 +57,7 @@ When \-f is specified, also enables the fade effect when windows change their opacity, as with transset(1). .TP .BI \-b -Attempts to fork to background after registered composition -manager. Still sits in foreground if fork failed. Maybe useful -if you computer is too fast, in which case some programs -requiring a composite manager may have started before composite -manager is ready. +Attempt to fork to background after registering compositor. .TP .BI \-i\ opacity Specifies inactive window transparency. (0.1 - 1.0) diff --git a/compton.c b/compton.c index 64ef3c9..2b33575 100644 --- a/compton.c +++ b/compton.c @@ -1,15 +1,19 @@ /* - * compton - a compositor for X11 + * Compton - a compositor for X11 * - * based on xcompmgr - copyright (c) 2003, keith packard + * Based on `xcompmgr` - Copyright (c) 2003, Keith Packard * - * copyright (c) 2011, christopher jeffrey + * Copyright (c) 2011, Christopher Jeffrey * See LICENSE for more information. * */ #include "compton.h" +/** + * Shared + */ + win *list; fade *fades; Display *dpy; @@ -74,7 +78,6 @@ Bool win_type_fade[NUM_WINTYPES]; #define IS_NORMAL_WIN(w) \ ((w) && ((w)->window_type == WINTYPE_NORMAL \ || (w)->window_type == WINTYPE_UTILITY)) -// || (w)->window_type == WINTYPE_UNKNOWN)) #define HAS_FRAME_OPACITY(w) (frame_opacity && (w)->top_width) @@ -104,7 +107,7 @@ Bool synchronize = False; * Fades */ -int +static int get_time_in_milliseconds() { struct timeval tv; @@ -113,7 +116,7 @@ get_time_in_milliseconds() { return tv.tv_sec * 1000 + tv.tv_usec / 1000; } -fade * +static fade * find_fade(win *w) { fade *f; @@ -124,7 +127,7 @@ find_fade(win *w) { return 0; } -void +static void dequeue_fade(Display *dpy, fade *f) { fade **prev; @@ -140,7 +143,7 @@ dequeue_fade(Display *dpy, fade *f) { } } -void +static void cleanup_fade(Display *dpy, win *w) { fade *f = find_fade (w); if (f) { @@ -148,7 +151,7 @@ cleanup_fade(Display *dpy, win *w) { } } -void +static void enqueue_fade(Display *dpy, fade *f) { if (!fades) { fade_time = get_time_in_milliseconds() + fade_delta; @@ -192,10 +195,6 @@ set_fade(Display *dpy, win *w, double start, f->callback = callback; w->opacity = f->cur * OPAQUE; -#if 0 - printf("set_fade start %g step %g\n", f->cur, f->step); -#endif - determine_mode(dpy, w); if (w->shadow) { @@ -219,7 +218,7 @@ set_fade(Display *dpy, win *w, double start, w->damaged = 1; } -int +static int fade_timeout(void) { int now; int delta; @@ -230,22 +229,17 @@ fade_timeout(void) { delta = fade_time - now; if (delta < 0) delta = 0; -/* printf("timeout %d\n", delta); */ return delta; } -void +static void run_fades(Display *dpy) { int now = get_time_in_milliseconds(); fade *next = fades; int steps; Bool need_dequeue; -#if 0 - printf("run fades\n"); -#endif - if (fade_time - now > 0) return; steps = 1 + (now - fade_time) / fade_delta; @@ -261,10 +255,6 @@ run_fades(Display *dpy) { f->cur = 0; } -#if 0 - printf("opacity now %g\n", f->cur); -#endif - w->opacity = f->cur * OPAQUE; need_dequeue = False; if (f->step > 0) { @@ -333,8 +323,6 @@ make_gaussian_map(Display *dpy, double r) { } } -/* printf("gaussian total %f\n", t); */ - for (y = 0; y < size; y++) { for (x = 0; x < size; x++) { c->data[y * size + x] /= t; @@ -489,19 +477,19 @@ make_shadow(Display *dpy, double opacity, * center (fill the complete data array) */ -if (!clear_shadow) { - if (Gsize > 0) { - d = shadow_top[opacity_int * (Gsize + 1) + Gsize]; - } else { - d = sum_gaussian(gaussian_map, - opacity, center, center, width, height); - } + if (!clear_shadow) { + if (Gsize > 0) { + d = shadow_top[opacity_int * (Gsize + 1) + Gsize]; + } else { + d = sum_gaussian(gaussian_map, + opacity, center, center, width, height); + } - memset(data, d, sheight * swidth); -} else { - // zero the pixmap - memset(data, 0, sheight * swidth); -} + memset(data, d, sheight * swidth); + } else { + // zero the pixmap + memset(data, 0, sheight * swidth); + } /* * corners @@ -513,7 +501,7 @@ if (!clear_shadow) { xlimit = gsize; if (xlimit > swidth / 2) xlimit = (swidth + 1) / 2; - for (y = 0; y < ylimit; y++) + for (y = 0; y < ylimit; y++) { for (x = 0; x < xlimit; x++) { if (xlimit == Gsize && ylimit == Gsize) { d = shadow_corner[opacity_int * (Gsize + 1) * (Gsize + 1) @@ -527,6 +515,7 @@ if (!clear_shadow) { data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d; data[y * swidth + (swidth - x - 1)] = d; } + } /* * top/bottom @@ -564,8 +553,7 @@ if (!clear_shadow) { } // zero extra pixels - if (clear_shadow) - if (width > gsize && height > gsize) { + if (clear_shadow && width > gsize && height > gsize) { int r = gsize / 2; int sr = r - 2; int er = r + 4; @@ -600,6 +588,7 @@ shadow_picture(Display *dpy, double opacity, Picture alpha_pict, shadow_picture = XRenderCreatePicture(dpy, shadowPixmap, XRenderFindStandardFormat(dpy, PictStandardA8), 0, 0); + if (!shadow_picture) { XDestroyImage(shadowImage); XFreePixmap(dpy, shadowPixmap); @@ -627,7 +616,7 @@ shadow_picture(Display *dpy, double opacity, Picture alpha_pict, return shadow_picture; } -Picture +static Picture solid_picture(Display *dpy, Bool argb, double a, double r, double g, double b) { Pixmap pixmap; @@ -666,7 +655,7 @@ solid_picture(Display *dpy, Bool argb, double a, * Errors */ -void +static void discard_ignore(Display *dpy, unsigned long sequence) { while (ignore_head) { if ((long) (sequence - ignore_head->sequence) > 0) { @@ -682,7 +671,7 @@ discard_ignore(Display *dpy, unsigned long sequence) { } } -void +static void set_ignore(Display *dpy, unsigned long sequence) { ignore *i = malloc(sizeof(ignore)); if (!i) return; @@ -693,7 +682,7 @@ set_ignore(Display *dpy, unsigned long sequence) { ignore_tail = &i->next; } -int +static int should_ignore(Display *dpy, unsigned long sequence) { discard_ignore(dpy, sequence); return ignore_head && ignore_head->sequence == sequence; @@ -809,15 +798,15 @@ win_extents(Display *dpy, win *w) { if (!w->shadow) { double opacity = shadow_opacity; -if (!clear_shadow) { - if (w->mode != WINDOW_SOLID) { - opacity = opacity * ((double)w->opacity) / ((double)OPAQUE); - } + if (!clear_shadow) { + if (w->mode != WINDOW_SOLID) { + opacity = opacity * ((double)w->opacity) / ((double)OPAQUE); + } - if (HAS_FRAME_OPACITY(w)) { - opacity = opacity * frame_opacity; + if (HAS_FRAME_OPACITY(w)) { + opacity = opacity * frame_opacity; + } } -} w->shadow = shadow_picture( dpy, opacity, w->alpha_pict, @@ -927,10 +916,10 @@ get_frame_extents(Display *dpy, Window w, unsigned char *data = NULL; int result; - // *left = 0; - // *right = 0; - // *top = 0; - // *bottom = 0; + *left = 0; + *right = 0; + *top = 0; + *bottom = 0; // w = find_client_win(dpy, w); if (!w) return; @@ -1150,7 +1139,6 @@ paint_all(Display *dpy, XserverRegion region) { dpy, PictOpOver, w->picture, w->alpha_pict, root_buffer, 0, 0, 0, 0, x, y, wid, hei); } else { - /* TODO - clean me */ unsigned int t = w->top_width; unsigned int l = w->left_width; unsigned int b = w->bottom_width; @@ -1229,7 +1217,7 @@ repair_win(Display *dpy, win *w) { w->damaged = 1; } -#if 0 +#if DEBUG_WINTYPE static const char* wintype_name(wintype type) { const char *t; @@ -1373,15 +1361,16 @@ map_win(Display *dpy, Window id, w->a.map_state = IsViewable; w->window_type = determine_wintype(dpy, w->id, w->id); -#if 0 +#if DEBUG_WINTYPE printf("window 0x%x type %s\n", w->id, wintype_name(w->window_type)); #endif /* select before reading the property so that no property changes are lost */ - if (!override_redirect) - XSelectInput(dpy, id, PropertyChangeMask | FocusChangeMask); + if (!override_redirect) { + XSelectInput(dpy, id, PropertyChangeMask | FocusChangeMask); + } // this causes problems for inactive transparency //w->opacity = get_opacity_prop(dpy, w, OPAQUE); @@ -1416,7 +1405,8 @@ finish_unmap_win(Display *dpy, win *w) { #endif if (w->extents != None) { - add_damage(dpy, w->extents); /* destroys region */ + /* destroys region */ + add_damage(dpy, w->extents); w->extents = None; } @@ -1480,10 +1470,6 @@ unmap_win(Display *dpy, Window id, Bool fade) { finish_unmap_win(dpy, w); } -/* Get the opacity prop from window - not found: default - otherwise the value - */ static unsigned int get_opacity_prop(Display *dpy, win *w, unsigned int def) { Atom actual; @@ -1505,12 +1491,6 @@ get_opacity_prop(Display *dpy, win *w, unsigned int def) { return def; } -/* - * Get the opacity property from the window in a percent format - * not found: default - * otherwise: the value -*/ - static double get_opacity_percent(Display *dpy, win *w) { double def = win_type_opacity[w->window_type]; @@ -1569,16 +1549,6 @@ determine_mode(Display *dpy, win *w) { static void set_opacity(Display *dpy, win *w, unsigned long opacity) { -#if 0 - if (fade_trans) { - double old_opacity = (double)w->opacity / OPAQUE; - w->opacity = opacity; - set_fade(dpy, w, old_opacity, - (double)w->opacity / OPAQUE, - fade_out_step, 0, True, False); - return; - } -#endif w->opacity = opacity; determine_mode(dpy, w); if (w->shadow) { @@ -1683,7 +1653,7 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) { } } -void +static void restack_win(Display *dpy, win *w, Window new_above) { Window old_above; @@ -1871,26 +1841,6 @@ destroy_win(Display *dpy, Window id, Bool fade) { } } -#if 0 -static void -dump_win(win *w) { - printf("\t%08lx: %d x %d + %d + %d(%d)\n", w->id, - w->a.width, w->a.height, - w->a.x, w->a.y, w->a.border_width); -} - - -static void -dump_wins(void) { - win *w; - - printf("windows:\n"); - for (w = list; w; w = w->next) { - dump_win(w); - } -} -#endif - static void damage_win(Display *dpy, XDamageNotifyEvent *de) { win *w = find_win(dpy, de->drawable); @@ -1922,18 +1872,6 @@ damage_win(Display *dpy, XDamageNotifyEvent *de) { } } -#if 0 - printf("unusable damage %d, %d: %d x %d bounds %d, %d: %d x %d\n", - de->area.x, - de->area.y, - de->area.width, - de->area.height, - w->damage_bounds.x, - w->damage_bounds.y, - w->damage_bounds.width, - w->damage_bounds.height); -#endif - if (w->damage_bounds.x <= 0 && w->damage_bounds.y <= 0 && w->a.width <= w->damage_bounds.x + w->damage_bounds.width @@ -1988,36 +1926,34 @@ error(Display *dpy, XErrorEvent *ev) { o = ev->error_code - render_error; switch (o) { case BadPictFormat: - name ="BadPictFormat"; + name = "BadPictFormat"; break; case BadPicture: - name ="BadPicture"; + name = "BadPicture"; break; case BadPictOp: - name ="BadPictOp"; + name = "BadPictOp"; break; case BadGlyphSet: - name ="BadGlyphSet"; + name = "BadGlyphSet"; break; case BadGlyph: - name ="BadGlyph"; + name = "BadGlyph"; break; default: break; } printf("error %d (%s) request %d minor %d serial %lu\n", - ev->error_code, name, ev->request_code, - ev->minor_code, ev->serial); + ev->error_code, name, ev->request_code, + ev->minor_code, ev->serial); -/* abort(); this is just annoying to most people */ return 0; } static void expose_root(Display *dpy, Window root, XRectangle *rects, int nrects) { XserverRegion region = XFixesCreateRegion(dpy, rects, nrects); - add_damage(dpy, region); } @@ -2083,9 +2019,9 @@ inline static void ev_focus_in(XFocusChangeEvent *ev) { if (!inactive_opacity) return; - win *fw = find_win(dpy, ev->window); - if (IS_NORMAL_WIN(fw)) { - set_opacity(dpy, fw, OPAQUE); + win *w = find_win(dpy, ev->window); + if (IS_NORMAL_WIN(w)) { + set_opacity(dpy, w, OPAQUE); } } @@ -2102,9 +2038,9 @@ ev_focus_out(XFocusChangeEvent *ev) { return; } - win *fw = find_win(dpy, ev->window); - if (IS_NORMAL_WIN(fw)) { - set_opacity(dpy, fw, INACTIVE_OPACITY); + win *w = find_win(dpy, ev->window); + if (IS_NORMAL_WIN(w)) { + set_opacity(dpy, w, INACTIVE_OPACITY); } } @@ -2216,7 +2152,7 @@ ev_damage_notify(XDamageNotifyEvent *ev) { } inline static void -handle_event(XEvent *ev) { +ev_handle(XEvent *ev) { if ((ev->type & 0x7f) != KeymapNotify) { discard_ignore(dpy, ev->xany.serial); } @@ -2224,7 +2160,7 @@ handle_event(XEvent *ev) { #if DEBUG_EVENTS if (ev->type != damage_event + XDamageNotify) { printf("event %10.10s serial 0x%08x window 0x%08x\n", - ev_name(ev), ev_serial(ev), ev_window(ev)); + ev_name(ev), ev_serial(ev), ev_window(ev)); } #endif @@ -2274,10 +2210,10 @@ handle_event(XEvent *ev) { * Main */ -void -usage(char *program) { - fprintf(stderr, "%s v0.0.1\n", program); - fprintf(stderr, "usage: %s [options]\n", program); +static void +usage() { + fprintf(stderr, "compton v0.0.1\n"); + fprintf(stderr, "usage: compton [options]\n"); fprintf(stderr, "Options\n"); fprintf(stderr, @@ -2328,6 +2264,12 @@ usage(char *program) { fprintf(stderr, " -e opacity\n " "Opacity of window titlebars and borders. (0.1 - 1.0)\n"); + fprintf(stderr, + " -G\n " + "Don't draw shadows on DND windows\n"); + fprintf(stderr, + " -b daemonize\n " + "Daemonize process.\n"); fprintf(stderr, " -S\n " "Enable synchronous operation (for debugging).\n"); @@ -2369,6 +2311,26 @@ register_cm(int scr) { XSetSelectionOwner(dpy, a, w, 0); } +static void +fork_after() { + if (getppid() == 1) return; + + int pid = fork(); + + if (pid == -1) { + fprintf(stderr, "Fork failed\n"); + return; + } + + if (pid > 0) _exit(0); + + setsid(); + + freopen("/dev/null", "r", stdin); + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); +} + static void get_atoms() { extents_atom = XInternAtom(dpy, @@ -2512,7 +2474,7 @@ main(int argc, char **argv) { fork_after_register = True; break; default: - usage(argv[0]); + usage(); break; } } @@ -2521,8 +2483,9 @@ main(int argc, char **argv) { win_type_shadow[WINTYPE_DOCK] = False; } - if (no_dnd_shadow) + if (no_dnd_shadow) { win_type_shadow[WINTYPE_DND] = False; + } dpy = XOpenDisplay(display); if (!dpy) { @@ -2568,13 +2531,9 @@ main(int argc, char **argv) { } register_cm(scr); - if (fork_after_register) { - int pid = fork(); - if (pid < 0) - fprintf(stderr, "Fork failed\n"); - else if (pid > 0) - exit(0); - } + + if (fork_after_register) fork_after(); + get_atoms(); pa.subwindow_mode = IncludeInferiors; @@ -2588,6 +2547,7 @@ main(int argc, char **argv) { root_picture = XRenderCreatePicture(dpy, root, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, scr)), CPSubwindowMode, &pa); + black_picture = solid_picture(dpy, True, 1, 0, 0, 0); all_damage = None; @@ -2620,7 +2580,6 @@ main(int argc, char **argv) { paint_all(dpy, None); for (;;) { - /* dump_wins(); */ do { if (!QLength(dpy)) { if (poll(&ufd, 1, fade_timeout()) == 0) { @@ -2630,9 +2589,7 @@ main(int argc, char **argv) { } XNextEvent(dpy, &ev); - - handle_event((XEvent *)&ev); - + ev_handle((XEvent *)&ev); } while (QLength(dpy)); if (all_damage) { @@ -2645,4 +2602,3 @@ main(int argc, char **argv) { } } } - diff --git a/compton.h b/compton.h index 51a2646..18e3859 100644 --- a/compton.h +++ b/compton.h @@ -1,3 +1,9 @@ +/** + * compton.h + */ + +// Throw everything in here. + #include #include #include @@ -22,6 +28,7 @@ #define CAN_DO_USABLE 0 #define DEBUG_REPAINT 0 #define DEBUG_EVENTS 0 +#define DEBUG_WINTYPE 0 #define MONITOR_REPAINT 0 #define OPAQUE 0xffffffff @@ -31,6 +38,10 @@ #define WINDOW_TRANS 1 #define WINDOW_ARGB 2 +/** + * Types + */ + typedef enum { WINTYPE_UNKNOWN, WINTYPE_DESKTOP, @@ -113,19 +124,23 @@ typedef struct _fade { Display *dpy; } fade; -int +/** + * Functions + */ + +static int get_time_in_milliseconds(); -fade * +static fade * find_fade(win *w); -void +static void dequeue_fade(Display *dpy, fade *f); -void +static void cleanup_fade(Display *dpy, win *w); -void +static void enqueue_fade(Display *dpy, fade *f); static void @@ -134,10 +149,10 @@ set_fade(Display *dpy, win *w, double start, void(*callback) (Display *dpy, win *w), Bool exec_callback, Bool override); -int +static int fade_timeout(void); -void +static void run_fades(Display *dpy); static double @@ -161,17 +176,17 @@ static Picture shadow_picture(Display *dpy, double opacity, Picture alpha_pict, int width, int height, int *wp, int *hp); -Picture +static Picture solid_picture(Display *dpy, Bool argb, double a, double r, double g, double b); -void +static void discard_ignore(Display *dpy, unsigned long sequence); -void +static void set_ignore(Display *dpy, unsigned long sequence); -int +static int should_ignore(Display *dpy, unsigned long sequence); static win * @@ -211,11 +226,6 @@ add_damage(Display *dpy, XserverRegion damage); static void repair_win(Display *dpy, win *w); -#if 0 -static const char* -wintype_name(wintype type); -#endif - static wintype get_wintype_prop(Display * dpy, Window w); @@ -253,7 +263,7 @@ set_opacity(Display *dpy, win *w, unsigned long opacity); static void add_win(Display *dpy, Window id, Window prev, Bool override_redirect); -void +static void restack_win(Display *dpy, win *w, Window new_above); static void @@ -273,11 +283,6 @@ destroy_callback(Display *dpy, win *w); static void destroy_win(Display *dpy, Window id, Bool fade); -#if 0 -static void -dump_win(win *w); -#endif - static void damage_win(Display *dpy, XDamageNotifyEvent *de); @@ -298,8 +303,8 @@ static Window ev_window(XEvent *ev); #endif -void -usage(char *program); +static void +usage(); static void register_cm(int scr); @@ -341,7 +346,10 @@ inline static void ev_damage_notify(XDamageNotifyEvent *ev); inline static void -handle_event(XEvent *ev); +ev_handle(XEvent *ev); + +static void +fork_after(); static void get_atoms();