diff options
Diffstat (limited to 'twin/kompmgr/kompmgr.c')
-rw-r--r-- | twin/kompmgr/kompmgr.c | 3960 |
1 files changed, 0 insertions, 3960 deletions
diff --git a/twin/kompmgr/kompmgr.c b/twin/kompmgr/kompmgr.c deleted file mode 100644 index 150c06bb8..000000000 --- a/twin/kompmgr/kompmgr.c +++ /dev/null @@ -1,3960 +0,0 @@ -/* - * $Id$ - * - * Copyright © 2003 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - - -/* Modified by Matthew Hawn. I don't know what to say here so follow what it - says above. Not that I can really do anything about it -*/ - -/* Modified by Dan Doel*/ - -/* Modified by Timothy Pearson - * - * CHANGELOG: - * http://patchwork.freedesktop.org/patch/1049/ [Add default background color option] 08/11/2011 - * http://patchwork.freedesktop.org/patch/1052/ [Prevent flicker on root pixmap change] 08/11/2011 - * Added SIGUSR1 handler to change process UID [Prevent flicker on login] 08/12/2011 - * Added ability to write PID of process to home directory 08/14/2011 - * Added SIGUSR2 handler to reload settings [Prevent flicker on settings change] 08/14/2011 - * Added SIGTERM handler to clean up stale PID files on exit 08/14/2011 - * Added hack to work around ATI fglrx XDamage event generation bugs [WORK_AROUND_FGLRX] 09/01/2011 - * Redraw root window automatically when X damage events are detected (this fixes xsetroot) 10/23/2011 - * - * TODO: - * http://patchwork.freedesktop.org/patch/1053/ [Fix window mapping with re-used window ids] -*/ - -/* -Version 2.x of xcompmgr, kompmgr changes by Thomas L�bking and Heiko Przybyl -check baghira.sf.net for more infos -*/ - -#define _VERSION_ 2.02 -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <math.h> -#include <sys/poll.h> -#include <sys/time.h> -#include <sys/types.h> -#include <signal.h> -#include <time.h> -#include <unistd.h> -#include <libgen.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/extensions/Xcomposite.h> -#include <X11/extensions/Xdamage.h> -#include <X11/extensions/Xrender.h> -#include <X11/extensions/shape.h> - -#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2 -#define HAS_NAME_WINDOW_PIXMAP 1 -#endif - -#define CAN_DO_USABLE 1 - -#define WORK_AROUND_FGLRX 1 - -#define _TOPHEIGHT_(x) ((x >> 24) & 0xff) -#define _RIGHTWIDTH_(x) ((x >> 16) & 0xff) -#define _BOTTOMHEIGHT_(x) ((x >> 8) & 0xff) -#define _LEFTWIDTH_(x) (x & 0xff) - -/* #define USE_ENV_HOME 1 */ -#define WRITE_PID_FILE 1 - -#ifndef USE_ENV_HOME -#include <pwd.h> -#endif - -typedef enum { - WINTYPE_DESKTOP, - WINTYPE_DOCK, - WINTYPE_TOOLBAR, - WINTYPE_MENU, - WINTYPE_UTILITY, - WINTYPE_SPLASH, - WINTYPE_DIALOG, - WINTYPE_NORMAL, - WINTYPE_DROPDOWN_MENU, - WINTYPE_POPUP_MENU, - WINTYPE_TOOLTIP, - WINTYPE_NOTIFY, - WINTYPE_COMBO, - WINTYPE_DND, - NUM_WINTYPES -} wintype; - -typedef struct _ignore { - struct _ignore *next; - unsigned long sequence; -} ignore; - -typedef struct _win { - struct _win *next; - Window id; -#if HAS_NAME_WINDOW_PIXMAP - Pixmap pixmap; -#endif - XWindowAttributes a; - XWindowAttributes a_prev; -#if CAN_DO_USABLE - Bool usable; /* mapped and all damaged at one point */ - XRectangle damage_bounds; /* bounds of damage */ -#endif - Bool isInFade; - int mode; - int damaged; - Damage damage; - Picture picture; - Picture alphaPict; - Picture shadowPict; - XserverRegion borderSize; - XserverRegion decoRegion; - XserverRegion contentRegion; - XserverRegion extents; - unsigned int preShadeOpacity; - Picture shadow; - /*Picture alpha;*/ - int shadow_dx; - int shadow_dy; - int shadow_width; - int shadow_height; - unsigned int opacity; - unsigned int shadowSize; - wintype windowType; - unsigned long damage_sequence; /* sequence when damage was created */ - int destroyed; - Bool destruct_queued; - Bool destruct_requested; - int destruct_request_time; - Bool shapable; /* this will allow window managers to exclude windows if just the deco is shaped*/ - Bool shaped; - XRectangle shape_bounds; - XRectangle shape_bounds_prev; - unsigned int decoHash; - Picture dimPicture; - - /* for drawing translucent windows */ - XserverRegion borderClip; - struct _win *prev_trans; - - /* setting whether a window will be transparent to the desktop or the windows below it */ - Bool show_root_tile; - - /* setting whether a window will be transparent to a black background or something else */ - Bool show_black_background; -} win; - -typedef struct _conv { - int size; - double *data; -} conv; - -typedef struct _fade { - struct _fade *next; - win *w; - double cur; - double finish; - double step; - void (*callback) (Display *dpy, win *w, Bool gone); - Display *dpy; - unsigned int decoHash; - Bool gone; -} fade; - -struct sigaction usr_action; -sigset_t block_mask; - -int my_exit_code = 3; - -win *list; -fade *fades; -Display *dpy; -char *display = 0; -int scr; -Window root; -Picture rootPicture; -Picture rootBuffer; -Picture blackPicture; -Picture transBlackPicture; -Picture rootTile; -XserverRegion allDamage; -Bool clipChanged; -#if HAS_NAME_WINDOW_PIXMAP -Bool hasNamePixmap; -#endif -XRenderColor fill_color; -int root_height, root_width; -ignore *ignore_head, **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 xshape_event, xshape_error; -Bool synchronize; -int composite_opcode; -Bool screen_damaged = False; -Bool disable_argb = False; - -int shapeEvent; - -/* find these once and be done with it */ -Atom opacityAtom; -Atom shadowAtom; -Atom shadeAtom; -Atom shapableAtom; -Atom decoHashAtom; -Atom dimAtom; -Atom deskChangeAtom; -Atom winTypeAtom; -Atom winTDETTDAtom; -Atom winTDETTBAtom; -Atom winType[NUM_WINTYPES]; -double winTypeOpacity[NUM_WINTYPES]; -Bool winTypeShadow[NUM_WINTYPES]; -Bool winTypeFade[NUM_WINTYPES]; - -/* opacity property name; sometime soon I'll write up an EWMH spec for it */ -#define OPACITY_PROP "_TDE_WM_WINDOW_OPACITY" -#define SHADOW_PROP "_TDE_WM_WINDOW_SHADOW" -#define SHADE_PROP "_TDE_WM_WINDOW_SHADE" -#define SHAPABLE_PROP "_TDE_WM_WINDOW_SHAPABLE" -#define DECOHASH_PROP "_TDE_WM_WINDOW_DECOHASH" -#define DIM_PROP "_TDE_WM_WINDOW_DIM" -#define DESKCHANGE_PROP "_TDE_WM_DESKTOP_CHANGE" - -#define TRANSLUCENT 0xe0000000 -#define OPAQUE 0xffffffff - -conv *gaussianMap; - -#define WINDOW_SOLID 0 -#define WINDOW_TRANS 1 -#define WINDOW_ARGB 2 - -#define TRANS_OPACITY 0.75 - -#define NDEBUG 1 -#define DEBUG_REPAINT 0 -#define DEBUG_WINDOWS 0 -#define DEBUG_EVENTS 0 -#define MONITOR_REPAINT 0 - -#define SHADOWS 1 -#define SHARP_SHADOW 0 - -typedef enum _compMode { - CompSimple, /* looks like a regular X server */ - CompServerShadows, /* use window alpha for shadow; sharp, but precise */ - CompClientShadows /* use window extents for shadow, blurred */ -} CompMode; - -static void -determine_mode(Display *dpy, win *w); - -static double -get_opacity_percent(Display *dpy, win *w); - -static XserverRegion -win_extents (Display *dpy, win *w); - -static void -presum_gaussian (conv *map); - -static conv * -make_gaussian_map (Display *dpy, double r); - -Picture -solid_picture (Display *dpy, Bool argb, double a, double r, double g, double b); - -CompMode compMode = CompSimple; - -int shadowRadius = 12; -int shadowOffsetX = 0; -int shadowOffsetY = 0; -double shadowOpacity = .75; -XRenderColor shadowColor; - -double fade_in_step = 0.028; -double fade_out_step = 0.03; -int fade_delta = 10; -int fade_time = 0; -Bool fadeTrans = False; - -Bool autoRedirect = False; - -#if WORK_AROUND_FGLRX -Bool restartOnSigterm = True; -#endif - -/* For shadow precomputation */ -int Gsize = -1; -unsigned char *shadowCorner = NULL; -unsigned char *shadowTop = NULL; - -XRenderPictFormat* sXRenderFindVisualFormat(Display *dpy, _Xconst Visual *visual) -{ - XRenderPictFormat* format = XRenderFindVisualFormat(dpy,visual); - if (format) - return format; - else - return XRenderFindStandardFormat (dpy, PictStandardRGB24); -} - -int -get_time_in_milliseconds () -{ - struct timeval tv; - - gettimeofday (&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -void write_pid_file(pid_t pid) -{ -#ifdef WRITE_PID_FILE -#ifdef USE_ENV_HOME - const char *home = getenv("HOME"); -#else - const char *home; - struct passwd *p; - p = getpwuid(getuid()); - if (p) - home = p->pw_dir; - else - home = getenv("HOME"); -#endif - const char *filename; - const char *configfile = "/.kompmgr.pid"; - int n = strlen(home)+strlen(configfile)+1; - filename = (char*)malloc(n*sizeof(char)); - memset(filename,0,n); - strcat(filename, home); - strcat(filename, configfile); - - printf("writing '%s' as pidfile\n\n", filename); - - /* now that we did all that by way of introduction...write the file! */ - FILE *pFile; - char buffer[255]; - sprintf(buffer, "%d", pid); - pFile = fopen(filename, "w"); - if (pFile) { - fwrite(buffer,1,strlen(buffer), pFile); - fclose(pFile); - } - - free(filename); - filename = NULL; -#endif -} - -void delete_pid_file() -{ -#ifdef WRITE_PID_FILE -#ifdef USE_ENV_HOME - const char *home = getenv("HOME"); -#else - const char *home; - struct passwd *p; - p = getpwuid(getuid()); - if (p) - home = p->pw_dir; - else - home = getenv("HOME"); -#endif - const char *filename; - const char *configfile = "/.kompmgr.pid"; - int n = strlen(home)+strlen(configfile)+1; - filename = (char*)malloc(n*sizeof(char)); - memset(filename,0,n); - strcat(filename, home); - strcat(filename, configfile); - - printf("deleting '%s' as pidfile\n\n", filename); - - /* now that we did all that by way of introduction...delete the file! */ - unlink(filename); - - free(filename); - filename = NULL; -#endif - -#if WORK_AROUND_FGLRX - if ((my_exit_code == 3) && (restartOnSigterm)) { - printf("kompmgr lost connection to X server, restarting...\n"); fflush(stdout); - sleep(1); - char me[2048]; - int chars = readlink("/proc/self/exe", me, sizeof(me)); - me[chars] = 0; - me[2047] = 0; - execl(me, basename(me), (char*)NULL); - } -#endif -} - -void clear_shadow_cache() -{ - win *w; - - for (w = list; w; w = w->next) { - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - if (w->opacity != OPAQUE && !w->alphaPict) - w->alphaPict = solid_picture (dpy, False, - (double) w->opacity / OPAQUE, shadowColor.red, shadowColor.green, shadowColor.blue); - if( w->extents != None ) { - XFixesDestroyRegion( dpy, w->extents ); - } - w->extents = win_extents (dpy, w); - w->damaged = 1; /* redraw */ - } - } -} - -void handle_siguser (int sig) -{ - int uidnum; - if (sig == SIGTERM) { - my_exit_code=0; - delete_pid_file(); - exit(0); - } - if (sig == SIGUSR1) { - char newuid[1024]; -#ifndef NDEBUG - printf("Enter the new user ID:\n"); fflush(stdout); -#endif - char *eof; - newuid[0] = '\0'; - newuid[sizeof(newuid)-1] = '\0'; - eof = fgets(newuid, sizeof(newuid), stdin); - uidnum = atoi(newuid); -#ifndef NDEBUG - printf("Setting kompmgr process uid to %d...\n", uidnum); fflush(stdout); -#endif - - my_exit_code=4; - delete_pid_file(); - my_exit_code=3; - setuid(uidnum); - write_pid_file(getpid()); - - } - else { - uidnum = getuid(); - } - if ((sig == SIGUSR1) || (sig == SIGUSR2)) { -#ifdef USE_ENV_HOME - const char *home = getenv("HOME"); -#else - const char *home; - struct passwd *p; - p = getpwuid(uidnum); - if (p) - home = p->pw_dir; - else - home = getenv("HOME"); -#endif - const char *filename; - const char *configfile = "/.xcompmgrrc"; - int n = strlen(home)+strlen(configfile)+1; - filename = (char*)malloc(n*sizeof(char)); - memset(filename,0,n); - strcat(filename, home); - strcat(filename, configfile); - - loadConfig(filename); /* reload the configuration file */ - - /* set background/shadow picture using the new settings */ - blackPicture = solid_picture (dpy, True, 1, (double)(shadowColor.red)/0xff, (double)(shadowColor.green)/0xff, (double)(shadowColor.blue)/0xff); - if (compMode == CompServerShadows) - transBlackPicture = solid_picture (dpy, True, 0.3, 0, 0, 0); - - /* regenerate shadows using the new settings */ - if (compMode == CompClientShadows) - { - gaussianMap = make_gaussian_map(dpy, shadowRadius); - presum_gaussian (gaussianMap); - } - clear_shadow_cache(); - - free(filename); - filename = NULL; - } -} - -fade * -find_fade (win *w) -{ - fade *f; - - for (f = fades; f; f = f->next) - { - if (f->w == w) - return f; - } - return 0; -} - -void dequeue_fade (Display *dpy, fade *f) -{ - fade **prev; - f->w->isInFade = False; - f->w->decoHash = f->decoHash; - - for (prev = &fades; *prev; prev = &(*prev)->next) - if (*prev == f) - { - *prev = f->next; - if (f->callback) - { - (*f->callback) (dpy, f->w, f->gone); - } - free (f); - break; - } -} - -void -cleanup_fade (Display *dpy, win *w) -{ - fade *f = find_fade (w); - if (f) - dequeue_fade (dpy, f); -} - -void -enqueue_fade (Display *dpy, fade *f) -{ - f->w->isInFade = True; - if (!fades) - fade_time = get_time_in_milliseconds () + fade_delta; - f->next = fades; - fades = f; -} - -static void unmap_callback (Display *dpy, win *w, Bool gone); - -static void -set_fade (Display *dpy, win *w, double start, double finish, double step, - void (*callback) (Display *dpy, win *w, Bool gone), - Bool gone, Bool exec_callback, Bool override, Bool wholeWin) -{ - fade *f; - - f = find_fade (w); - if (!f) - { - if (start == finish) - return; - f = malloc (sizeof (fade)); - f->next = 0; - f->w = w; - f->decoHash = w->decoHash; - f->cur = start; - enqueue_fade (dpy, f); - } - else if(!override) - return; - else - { - if (exec_callback && f->callback) - (*f->callback)(dpy, f->w, f->gone); - } - if (finish < 0) - finish = 0; - if (finish > 1) - finish = 1; - f->finish = finish; - if (f->cur < finish) - f->step = step; - else if (f->cur > finish) - f->step = -step; - f->gone = gone && (exec_callback || f->callback != unmap_callback); - f->callback = callback; - w->opacity = f->cur * OPAQUE; - if (wholeWin) - w->decoHash = 0; -#if 0 - printf ("set_fade start %g step %g\n", f->cur, f->step); -#endif - determine_mode (dpy, w); - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - if( w->extents != None ) - XFixesDestroyRegion( dpy, w->extents ); - w->extents = win_extents (dpy, w); - } - - /* fading windows need to be drawn, mark them as damaged. - when a window maps, if it tries to fade in but it already at the right - opacity (map/unmap/map fast) then it will never get drawn without this - until it repaints */ - w->damaged = 1; -} - - int -fade_timeout (void) -{ - int now; - int delta; - if (!fades) - return -1; - now = get_time_in_milliseconds(); - delta = fade_time - now; - if (delta < 0) - delta = 0; - /* printf ("timeout %d\n", delta); */ - return delta; -} - - void -run_fades (Display *dpy) -{ - int now = get_time_in_milliseconds(); - fade *f, *next; - 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; - for (next = fades; (f = next); ) - { - win *w = f->w; - next = f->next; - f->cur += f->step * steps; - if (f->cur >= 1) - f->cur = 1; - else if (f->cur < 0) - f->cur = 0; -#if 0 - printf ("opacity now %g -> %g\n", f->cur, f->finish); -#endif - w->opacity = f->cur * OPAQUE; - need_dequeue = False; - if (f->step > 0) - { - if (f->cur >= f->finish) - { - w->opacity = f->finish*OPAQUE; - need_dequeue = True; - } - } - else - { - if (f->cur <= f->finish) - { - w->opacity = f->finish*OPAQUE; - need_dequeue = True; - } - } - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - if( w->extents != None ) - XFixesDestroyRegion( dpy, w->extents ); - w->extents = win_extents(dpy, w); - } - determine_mode (dpy, w); - /* Must do this last as it might destroy f->w in callbacks */ - if (need_dequeue) - dequeue_fade (dpy, f); - } - fade_time = now + fade_delta; -} - -#define SHADOW_OFFSET_X ((-shadowRadius * 7 / 5) - shadowOffsetX * shadowRadius / 100) * w->shadowSize -#define SHADOW_OFFSET_Y ((-shadowRadius * 7 / 5) - shadowOffsetY * shadowRadius / 100) * w->shadowSize -/*#define SHADOW_OFFSET_X (w->shadowSize * -shadowRadius * 7 / 500) - w->shadowSize * shadowOffsetX * shadowRadius / 10000 -#define SHADOW_OFFSET_Y (w->shadowSize * -shadowRadius * 7 / 500) - w->shadowSize * shadowOffsetY * shadowRadius / 10000*/ - - static double -gaussian (double r, double x, double y) -{ - return ((1 / (sqrt (2 * M_PI * r))) * - exp ((- (x * x + y * y)) / (2 * r * r))); -} - - - static conv * -make_gaussian_map (Display *dpy, double r) -{ - conv *c; - int size = ((int) ceil ((r * 3)) + 1) & ~1; - int center = size / 2; - int x, y; - double t; - double g; - - c = malloc (sizeof (conv) + size * size * sizeof (double)); - c->size = size; - c->data = (double *) (c + 1); - t = 0.0; - for (y = 0; y < size; y++) - for (x = 0; x < size; x++) - { - g = gaussian (r, (double) (x - center), (double) (y - center)); - t += g; - c->data[y * size + x] = g; - } - /* printf ("gaussian total %f\n", t); */ - for (y = 0; y < size; y++) - for (x = 0; x < size; x++) - { - c->data[y*size + x] /= t; - } - return c; -} - -/* - * A picture will help - * - * -center 0 width width+center - * -center +-----+-------------------+-----+ - * | | | | - * | | | | - * 0 +-----+-------------------+-----+ - * | | | | - * | | | | - * | | | | - * height +-----+-------------------+-----+ - * | | | | - * height+ | | | | - * center +-----+-------------------+-----+ - */ - - static unsigned char -sum_gaussian (conv *map, double opacity, int x, int y, int width, int height) -{ - int fx, fy; - double *g_data; - double *g_line = map->data; - int g_size = map->size; - int center = g_size / 2; - int fx_start, fx_end; - int fy_start, fy_end; - double v; - - /* - * Compute set of filter values which are "in range", - * that's the set with: - * 0 <= x + (fx-center) && x + (fx-center) < width && - * 0 <= y + (fy-center) && y + (fy-center) < height - * - * 0 <= x + (fx - center) x + fx - center < width - * center - x <= fx fx < width + center - x - */ - - fx_start = center - x; - if (fx_start < 0) - fx_start = 0; - fx_end = width + center - x; - if (fx_end > g_size) - fx_end = g_size; - - fy_start = center - y; - if (fy_start < 0) - fy_start = 0; - fy_end = height + center - y; - if (fy_end > g_size) - fy_end = g_size; - - g_line = g_line + fy_start * g_size + fx_start; - - v = 0; - for (fy = fy_start; fy < fy_end; fy++) - { - g_data = g_line; - g_line += g_size; - - for (fx = fx_start; fx < fx_end; fx++) - v += *g_data++; - } - if (v > 1) - v = 1; - - return ((unsigned char) (v * opacity * 255.0)); -} - -/* precompute shadow corners and sides to save time for large windows */ - static void -presum_gaussian (conv *map) -{ - int center = map->size/2; - int opacity, x, y; - - Gsize = map->size; - - if (shadowCorner) - free ((void *)shadowCorner); - if (shadowTop) - free ((void *)shadowTop); - - shadowCorner = (unsigned char *)(malloc ((Gsize + 1) * (Gsize + 1) * 26)); - shadowTop = (unsigned char *)(malloc ((Gsize + 1) * 26)); - - for (x = 0; x <= Gsize; x++) - { - shadowTop[25 * (Gsize + 1) + x] = sum_gaussian (map, 1, x - center, center, Gsize * 2, Gsize * 2); - for(opacity = 0; opacity < 25; opacity++) - shadowTop[opacity * (Gsize + 1) + x] = shadowTop[25 * (Gsize + 1) + x] * opacity / 25; - for(y = 0; y <= x; y++) - { - shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x] - = sum_gaussian (map, 1, x - center, y - center, Gsize * 2, Gsize * 2); - shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + x * (Gsize + 1) + y] - = shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x]; - for(opacity = 0; opacity < 25; opacity++) - shadowCorner[opacity * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x] - = shadowCorner[opacity * (Gsize + 1) * (Gsize + 1) + x * (Gsize + 1) + y] - = shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x] * opacity / 25; - } - } -} - - static XImage * -make_shadow (Display *dpy, double opacity, int width, int height) -{ - XImage *ximage; - unsigned char *data; - int gsize = gaussianMap->size; - int ylimit, xlimit; - int swidth = width + gsize; - int sheight = height + gsize; - int center = gsize / 2; - int x, y; - unsigned char d; - int x_diff; - int opacity_int = (int)(opacity * 25); - data = malloc (swidth * sheight * sizeof (unsigned char)); - if (!data) - return 0; - ximage = XCreateImage (dpy, - DefaultVisual(dpy, DefaultScreen(dpy)), - 8, - ZPixmap, - 0, - (char *) data, - swidth, sheight, 8, swidth * sizeof (unsigned char)); - if (!ximage) - { - free (data); - return 0; - } - /* - * Build the gaussian in sections - */ - - /* - * center (fill the complete data array) - */ - if (Gsize > 0) - d = shadowTop[opacity_int * (Gsize + 1) + Gsize]; - else - d = sum_gaussian (gaussianMap, opacity, center, center, width, height); - memset(data, d, sheight * swidth); - - /* - * corners - */ - ylimit = gsize; - if (ylimit > sheight / 2) - ylimit = (sheight + 1) / 2; - xlimit = gsize; - if (xlimit > swidth / 2) - xlimit = (swidth + 1) / 2; - - for (y = 0; y < ylimit; y++) - for (x = 0; x < xlimit; x++) - { - if (xlimit == Gsize && ylimit == Gsize) - d = shadowCorner[opacity_int * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x]; - else - d = sum_gaussian (gaussianMap, opacity, x - center, y - center, width, height); - data[y * swidth + x] = d; - data[(sheight - y - 1) * swidth + x] = d; - data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d; - data[y * swidth + (swidth - x - 1)] = d; - } - - /* - * top/bottom - */ - x_diff = swidth - (gsize * 2); - if (x_diff > 0 && ylimit > 0) - { - for (y = 0; y < ylimit; y++) - { - if (ylimit == Gsize) - d = shadowTop[opacity_int * (Gsize + 1) + y]; - else - d = sum_gaussian (gaussianMap, opacity, center, y - center, width, height); - memset (&data[y * swidth + gsize], d, x_diff); - memset (&data[(sheight - y - 1) * swidth + gsize], d, x_diff); - } - } - - /* - * sides - */ - - for (x = 0; x < xlimit; x++) - { - if (xlimit == Gsize) - d = shadowTop[opacity_int * (Gsize + 1) + x]; - else - d = sum_gaussian (gaussianMap, opacity, x - center, center, width, height); - for (y = gsize; y < sheight - gsize; y++) - { - data[y * swidth + x] = d; - data[y * swidth + (swidth - x - 1)] = d; - } - } - - return ximage; -} - - static Picture -shadow_picture (Display *dpy, double opacity, Picture alpha_pict, int width, int height, int *wp, int *hp) -{ - XImage *shadowImage; - Pixmap shadowPixmap; - Pixmap finalPixmap; - Picture shadowPicture; - Picture finalPicture; - GC gc; - - shadowImage = make_shadow (dpy, opacity, width, height); - if (!shadowImage) - return None; - shadowPixmap = XCreatePixmap (dpy, root, - shadowImage->width, - shadowImage->height, - 8); - if (!shadowPixmap) - { - XDestroyImage (shadowImage); - return None; - } - - shadowPicture = XRenderCreatePicture (dpy, shadowPixmap, - XRenderFindStandardFormat (dpy, PictStandardA8), - 0, 0); - if (!shadowPicture) - { - XDestroyImage (shadowImage); - XFreePixmap (dpy, shadowPixmap); - return None; - } - - gc = XCreateGC (dpy, shadowPixmap, 0, 0); - if (!gc) - { - XDestroyImage (shadowImage); - XFreePixmap (dpy, shadowPixmap); - XRenderFreePicture (dpy, shadowPicture); - return None; - } - - XPutImage (dpy, shadowPixmap, gc, shadowImage, 0, 0, 0, 0, - shadowImage->width, - shadowImage->height); - *wp = shadowImage->width; - *hp = shadowImage->height; - XFreeGC (dpy, gc); - XDestroyImage (shadowImage); - XFreePixmap (dpy, shadowPixmap); - return shadowPicture; -} - - Picture -solid_picture (Display *dpy, Bool argb, double a, double r, double g, double b) -{ - Pixmap pixmap; - Picture picture; - XRenderPictureAttributes pa; - XRenderColor c; - - pixmap = XCreatePixmap (dpy, root, 1, 1, argb ? 32 : 8); - if (!pixmap) - return None; - - pa.repeat = True; - picture = XRenderCreatePicture (dpy, pixmap, - XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8), - CPRepeat, - &pa); - if (!picture) - { - XFreePixmap (dpy, pixmap); - return None; - } - - c.alpha = a * 0xffff; - c.red = r * 0xffff; - c.green = g * 0xffff; - c.blue = b * 0xffff; - XRenderFillRectangle (dpy, PictOpSrc, picture, &c, 0, 0, 1, 1); - XFreePixmap (dpy, pixmap); - return picture; -} - - void -discard_ignore (Display *dpy, unsigned long sequence) -{ - while (ignore_head) - { - if ((long) (sequence - ignore_head->sequence) > 0) - { - ignore *next = ignore_head->next; - free (ignore_head); - ignore_head = next; - if (!ignore_head) - ignore_tail = &ignore_head; - } - else - break; - } -} - - void -set_ignore (Display *dpy, unsigned long sequence) -{ - ignore *i = malloc (sizeof (ignore)); - if (!i) { - return; - } - i->sequence = sequence; - i->next = 0; - *ignore_tail = i; - ignore_tail = &i->next; -} - - int -should_ignore (Display *dpy, unsigned long sequence) -{ - discard_ignore (dpy, sequence); - return ignore_head && ignore_head->sequence == sequence; -} - - static win * -find_win (Display *dpy, Window id) -{ - win *w; - - for (w = list; w; w = w->next) { - if ((!w->destroyed) && (w->id == id)) { - return w; - } - } - return 0; -} - -static char *backgroundProps[] = { - "_XROOTPMAP_ID", - "_XSETROOT_ID", - 0, -}; - -static Bool -determine_window_transparent_to_black(Display *dpy, Window w); - -static Bool -determine_window_transparent_to_desktop(Display *dpy, Window w); - -static Picture -root_tile (Display *dpy) -{ - Picture picture; - Atom actual_type; - Pixmap pixmap; - int actual_format; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *prop; - Bool fill; - XRenderPictureAttributes pa; - int p; - - pixmap = None; - for (p = 0; backgroundProps[p]; p++) - { - if (XGetWindowProperty (dpy, root, XInternAtom (dpy, backgroundProps[p], False), - 0, 4, False, AnyPropertyType, - &actual_type, &actual_format, &nitems, &bytes_after, &prop) == Success && - actual_type == XInternAtom (dpy, "PIXMAP", False) && actual_format == 32 && nitems == 1) - { - pixmap = *(long*)prop; - XFree (prop); - fill = False; - break; - } - } - if (!pixmap) - { - pixmap = XCreatePixmap (dpy, root, 1, 1, DefaultDepth (dpy, scr)); - fill = True; - } - pa.repeat = True; - picture = XRenderCreatePicture (dpy, pixmap, - sXRenderFindVisualFormat (dpy, - DefaultVisual (dpy, scr)), - CPRepeat, &pa); - if (fill) - { - XRenderFillRectangle (dpy, PictOpSrc, picture, &fill_color, - 0, 0, 1, 1); - } - return picture; -} - -static void -paint_root (Display *dpy) -{ - if (!rootTile) - rootTile = root_tile (dpy); - - XRenderComposite (dpy, PictOpSrc, - rootTile, None, rootBuffer, - 0, 0, 0, 0, 0, 0, root_width, root_height); -} - -static XserverRegion -win_extents (Display *dpy, win *w) -{ - XRectangle r; - - r.x = w->a.x; - r.y = w->a.y; - r.width = w->a.width + w->a.border_width * 2; - r.height = w->a.height + w->a.border_width * 2; - if (winTypeShadow[w->windowType]) - { - if (compMode == CompServerShadows || w->mode != WINDOW_ARGB) - { - XRectangle sr; - - if (compMode == CompServerShadows) - { - w->shadow_dx = 2; - w->shadow_dy = 7; - w->shadow_width = w->a.width; - w->shadow_height = w->a.height; - } - else - { - w->shadow_dx = SHADOW_OFFSET_X; - w->shadow_dx = w->shadow_dx / 100; - w->shadow_dy = SHADOW_OFFSET_Y; - w->shadow_dy = w->shadow_dy / 100; - if (!w->shadow) - { - double opacity = shadowOpacity; - if (w->shadowSize > 100) - opacity = opacity/(w->shadowSize*0.015); - if (w->mode == WINDOW_TRANS) - opacity = opacity * ((double)w->opacity)/((double)OPAQUE); - w->shadow = shadow_picture (dpy, opacity, w->alphaPict, - w->a.width + w->a.border_width * 2 - 2*(shadowRadius - (w->shadowSize*shadowRadius/100)) , - w->a.height + w->a.border_width * 2 - 2*(shadowRadius - (w->shadowSize*shadowRadius/100)), - &w->shadow_width, &w->shadow_height); - /*int kill; - w->alpha = shadow_picture (dpy, 0.9, w->alphaPict, - w->a.width + w->a.border_width * 2, - w->a.height + w->a.border_width * 2, - &kill, &kill);*/ - } - } - sr.x = w->a.x + w->shadow_dx; - sr.y = w->a.y + w->shadow_dy; - sr.width = w->shadow_width; - sr.height = w->shadow_height; - if (sr.x < r.x) - { - r.width = (r.x + r.width) - sr.x; - r.x = sr.x; - } - if (sr.y < r.y) - { - r.height = (r.y + r.height) - sr.y; - r.y = sr.y; - } - if (sr.x + sr.width > r.x + r.width) - r.width = sr.x + sr.width - r.x; - if (sr.y + sr.height > r.y + r.height) - r.height = sr.y + sr.height - r.y; - } - } - return XFixesCreateRegion (dpy, &r, 1); -} - - static XserverRegion -border_size (Display *dpy, win *w) -{ - XserverRegion border; - /* - * if window doesn't exist anymore, this will generate an error - * as well as not generate a region. Perhaps a better XFixes - * architecture would be to have a request that copies instead - * of creates, that way you'd just end up with an empty region - * instead of an invalid XID. - */ - set_ignore (dpy, NextRequest (dpy)); - border = XFixesCreateRegionFromWindow (dpy, w->id, WindowRegionBounding); - /* translate this */ - set_ignore (dpy, NextRequest (dpy)); - XFixesTranslateRegion (dpy, border, - w->a.x + w->a.border_width, - w->a.y + w->a.border_width); - return border; -} - - static XserverRegion -deco_region (Display *dpy, win *w) -{ - XserverRegion title; - XRectangle r; /*titlebounding rect*/ - /* - * if window doesn't exist anymore, this will generate an error - * as well as not generate a region. Perhaps a better XFixes - * architecture would be to have a request that copies instead - * of creates, that way you'd just end up with an empty region - * instead of an invalid XID. - */ - r.x = w->a.x - w->a.border_width + _LEFTWIDTH_(w->decoHash); - r.y = w->a.y - w->a.border_width + _TOPHEIGHT_(w->decoHash); - r.width = w->a.width + w->a.border_width * 2 - _LEFTWIDTH_(w->decoHash) - _RIGHTWIDTH_(w->decoHash); - r.height = w->a.height + w->a.border_width - _TOPHEIGHT_(w->decoHash) - _BOTTOMHEIGHT_(w->decoHash); - set_ignore (dpy, NextRequest (dpy)); - title = XFixesCreateRegion (dpy, &r, 1); - if (!w->borderSize) - w->borderSize = border_size (dpy, w); - set_ignore (dpy, NextRequest (dpy)); - XFixesSubtractRegion(dpy, title, w->borderSize, title); - return title; -} - -static void finish_destroy_win (Display *dpy, Window id, Bool gone); - - static XserverRegion -content_region (Display *dpy, win *w) -{ - XserverRegion content; - XRectangle r; /*contentbounding rect*/ - /* - * if window doesn't exist anymore, this will generate an error - * as well as not generate a region. Perhaps a better XFixes - * architecture would be to have a request that copies instead - * of creates, that way you'd just end up with an empty region - * instead of an invalid XID. - */ - r.x = w->a.x - w->a.border_width + _LEFTWIDTH_(w->decoHash); - r.y = w->a.y - w->a.border_width + _TOPHEIGHT_(w->decoHash); - r.width = w->a.width + w->a.border_width * 2 - _LEFTWIDTH_(w->decoHash) - _RIGHTWIDTH_(w->decoHash); - r.height = w->a.height + w->a.border_width - _TOPHEIGHT_(w->decoHash) - _BOTTOMHEIGHT_(w->decoHash); - set_ignore (dpy, NextRequest (dpy)); - content = XFixesCreateRegion (dpy, &r, 1); - if (!w->borderSize) - w->borderSize = border_size (dpy, w); - set_ignore (dpy, NextRequest (dpy)); - XFixesIntersectRegion(dpy, content, w->borderSize, content); - return content; -} - - static void -paint_all (Display *dpy, XserverRegion region) -{ - win *w; - win *t = 0; - -#if DEBUG_WINDOWS - int window_count = 0; -#endif - - if (!region) - { - XRectangle r; - r.x = 0; - r.y = 0; - r.width = root_width; - r.height = root_height; - region = XFixesCreateRegion (dpy, &r, 1); - } -#if MONITOR_REPAINT - rootBuffer = rootPicture; -#else - if (!rootBuffer) - { - Pixmap rootPixmap = XCreatePixmap (dpy, root, root_width, root_height, - DefaultDepth (dpy, scr)); - rootBuffer = XRenderCreatePicture (dpy, rootPixmap, - sXRenderFindVisualFormat (dpy, - DefaultVisual (dpy, scr)), - 0, 0); - XFreePixmap (dpy, rootPixmap); - } -#endif - XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region); -#if MONITOR_REPAINT - XRenderComposite (dpy, PictOpSrc, blackPicture, None, rootPicture, - 0, 0, 0, 0, 0, 0, root_width, root_height); -#endif -#if DEBUG_REPAINT - printf ("paint:"); -#endif - - // Time delayed garbage collect - // It waits 10 seconds before destroying window data - // This allows the fade out to perform smoothly under all conditions - // Yes, this code is somewhat inefficient! - // But it shouldn't matter unless someone has tens of thousands of windows open... - // If the user can set a fade out that is longer than 10 seconds, - // then the value must be increased. I am assuming that 10 seconds - // is far too long for any normal human being to wait... ;-) - for (w = list; w; w = w->next) - { - if (w->destruct_requested) { - int curtime = get_time_in_milliseconds(); - if ((curtime - w->destruct_request_time) > 10000) { - finish_destroy_win (dpy, w->id, True); - w = list; - } - } - } - - for (w = list; w; w = w->next) - { -#if DEBUG_WINDOWS - window_count++; -#endif -#if CAN_DO_USABLE - if (!w->usable) - continue; -#endif - - /* never painted, ignore it */ - if ((!screen_damaged) && (!w->damaged)) { -#if DEBUG_REPAINT - printf(" [not damaged: 0x%x]", w->id); -#endif - continue; - } - - /* skip invisible windows */ - if (w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1 || w->a.x >= root_width || w->a.y >= root_height) { -#if DEBUG_REPAINT - printf(" [invisible: 0x%x]", w->id); -#endif - continue; - } - - if (!w->picture) - { - XRenderPictureAttributes pa; - XRenderPictFormat *format; - Drawable draw = w->id; - -#if HAS_NAME_WINDOW_PIXMAP - if (hasNamePixmap && !w->pixmap) - w->pixmap = XCompositeNameWindowPixmap (dpy, w->id); - if (w->pixmap) - draw = w->pixmap; -#endif - format = sXRenderFindVisualFormat (dpy, w->a.visual); - pa.subwindow_mode = IncludeInferiors; - w->picture = XRenderCreatePicture (dpy, draw, - format, - CPSubwindowMode, - &pa); - } -#if DEBUG_REPAINT - printf (" [painting 0x%x]", w->id); -#endif - if (clipChanged) - { - if (w->borderSize) - { - set_ignore (dpy, NextRequest (dpy)); - XFixesDestroyRegion (dpy, w->borderSize); - w->borderSize = None; - } - if (w->decoRegion) - { - set_ignore (dpy, NextRequest (dpy)); - XFixesDestroyRegion (dpy, w->decoRegion); - w->decoRegion = None; - } - if (w->contentRegion) - { - set_ignore (dpy, NextRequest (dpy)); - XFixesDestroyRegion (dpy, w->contentRegion); - w->contentRegion = None; - } - if (w->extents) - { - XFixesDestroyRegion (dpy, w->extents); - w->extents = None; - } - if (w->borderClip) - { - XFixesDestroyRegion (dpy, w->borderClip); - w->borderClip = None; - } - } - if (!w->borderSize) - w->borderSize = border_size (dpy, w); - if (!w->extents) - w->extents = win_extents (dpy, w); - if ((w->mode == WINDOW_SOLID) || ((w->mode == WINDOW_TRANS) && w->decoHash)) - { - int x, y, wid, hei; -#if HAS_NAME_WINDOW_PIXMAP - x = w->a.x; - y = w->a.y; - wid = w->a.width + w->a.border_width * 2; - hei = w->a.height + w->a.border_width * 2; -#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 - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region); - set_ignore (dpy, NextRequest (dpy)); - /*XFixesSubtractRegion (dpy, region, region, w->borderSize); - set_ignore (dpy, NextRequest (dpy));*/ - if (w->mode == WINDOW_SOLID) - { - XFixesSubtractRegion (dpy, region, region, w->borderSize); - set_ignore (dpy, NextRequest (dpy)); - XRenderComposite (dpy, PictOpSrc, w->picture, None, rootBuffer, - 0, 0, 0, 0, x, y, wid, hei); - if (w->dimPicture) - XRenderComposite (dpy, PictOpOver, w->dimPicture, None, rootBuffer, 0, 0, 0, 0, x, y, wid, hei); - } - else - { - if (!w->contentRegion) - w->contentRegion = content_region (dpy, w); - XFixesSubtractRegion (dpy, region, region, w->contentRegion); - set_ignore (dpy, NextRequest (dpy)); - /*solid part*/ - XRenderComposite (dpy, PictOpSrc, w->picture, None, rootBuffer, - _LEFTWIDTH_(w->decoHash), _TOPHEIGHT_(w->decoHash), 0, 0, - x + _LEFTWIDTH_(w->decoHash), - y + _TOPHEIGHT_(w->decoHash), - wid - _LEFTWIDTH_(w->decoHash) - _RIGHTWIDTH_(w->decoHash), - hei - _TOPHEIGHT_(w->decoHash) - _BOTTOMHEIGHT_(w->decoHash)); - } - } - if (!w->borderClip) - { - w->borderClip = XFixesCreateRegion (dpy, 0, 0); - XFixesCopyRegion (dpy, w->borderClip, region); - } - w->prev_trans = t; - t = w; - } -#if DEBUG_WINDOWS - printf("window count: %d\n", window_count); -#endif -#if DEBUG_REPAINT - printf ("\n"); - fflush (stdout); -#endif - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region); - paint_root (dpy); - for (w = t; w; w = w->prev_trans) - { - if (w->shadowSize > 0){ - if (winTypeShadow[w->windowType]) { - switch (compMode) { - case CompSimple: - break; - case CompServerShadows: - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip); - set_ignore (dpy, NextRequest (dpy)); - if (w->opacity != OPAQUE && !w->shadowPict) - w->shadowPict = solid_picture (dpy, True, - (double) w->opacity / OPAQUE * 0.3, - 0, 0, 0); - XRenderComposite (dpy, PictOpOver, - w->shadowPict ? w->shadowPict : transBlackPicture, - w->picture, rootBuffer, - 0, 0, 0, 0, - w->a.x + w->shadow_dx, - w->a.y + w->shadow_dy, - w->shadow_width, w->shadow_height); - break; - case CompClientShadows: - if (w->shadow) - { - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip); - XRenderComposite (dpy, PictOpOver, blackPicture, w->shadow, rootBuffer, - 0, 0, 0, 0, - w->a.x + w->shadow_dx, - w->a.y + w->shadow_dy, - w->shadow_width, w->shadow_height); - } - break; - } - } - } - if (w->opacity != OPAQUE && !w->alphaPict) - w->alphaPict = solid_picture (dpy, False, - (double) w->opacity / OPAQUE, shadowColor.red, shadowColor.green, shadowColor.blue); - if (w->mode == WINDOW_TRANS) - { - int x, y, wid, hei; - XFixesIntersectRegion (dpy, w->borderClip, w->borderClip, w->borderSize); - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip); -#if HAS_NAME_WINDOW_PIXMAP - x = w->a.x; - y = w->a.y; - wid = w->a.width + w->a.border_width * 2; - hei = w->a.height + w->a.border_width * 2; -#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 - set_ignore (dpy, NextRequest (dpy)); - if (!w->decoHash) - { - XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer, - 0, 0, 0, 0, x, y, wid, hei); - } - else - { - /*trans part*/ - /* PICTURE ;) - |-----------------------------| - | top | - |-----------------------------| - |l | | r| - |e | | i| - |f | | g| - |t | | h| - |--------------------------| t| - | bottom | | - |--------------------------|--|*/ - /*top*/ - XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer, - 0, 0, 0, 0, x, y, wid, _TOPHEIGHT_(w->decoHash)); - /*right*/ - XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer, - wid - _RIGHTWIDTH_(w->decoHash), _TOPHEIGHT_(w->decoHash), - 0, 0, - x + wid - _RIGHTWIDTH_(w->decoHash), - y + _TOPHEIGHT_(w->decoHash), _RIGHTWIDTH_(w->decoHash), - hei - _TOPHEIGHT_(w->decoHash)); - /*bottom*/ - XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer, - 0, hei - _BOTTOMHEIGHT_(w->decoHash), 0, 0, - x, y + hei - _BOTTOMHEIGHT_(w->decoHash), - wid - _RIGHTWIDTH_(w->decoHash), _BOTTOMHEIGHT_(w->decoHash)); - /*left*/ - XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer, - 0, _TOPHEIGHT_(w->decoHash), 0, 0, - x, y + _TOPHEIGHT_(w->decoHash), - _LEFTWIDTH_(w->decoHash), hei - _TOPHEIGHT_(w->decoHash) - _BOTTOMHEIGHT_(w->decoHash)); - } - } - else if (w->mode == WINDOW_ARGB) - { - int x, y, wid, hei; - XFixesIntersectRegion (dpy, w->borderClip, w->borderClip, w->borderSize); - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip); -#if HAS_NAME_WINDOW_PIXMAP - x = w->a.x; - y = w->a.y; - wid = w->a.width + w->a.border_width * 2; - hei = w->a.height + w->a.border_width * 2; -#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 - set_ignore (dpy, NextRequest (dpy)); - /* Here we redraw the background of the transparent window if we want - to do anything special (i.e. anything other than showing the - windows and desktop prestacked behind of the window). - For example, if you want to blur the background or show another - background pixmap entirely here is the place to do it; simply - draw the new background onto rootBuffer before continuing! */ - if (w->isInFade == False) { - if (w->show_black_background == True) { - XRenderComposite (dpy, PictOpSrc, blackPicture, None, rootBuffer, - x, y, x, y, - x, y, wid, hei); - } - else if (w->show_root_tile == True) { - XRenderComposite (dpy, PictOpSrc, rootTile, None, rootBuffer, - x, y, x, y, - x, y, wid, hei); - } - } - XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer, - 0, 0, 0, 0, - x, y, wid, hei); - } - XFixesDestroyRegion (dpy, w->borderClip); - w->borderClip = None; - } - XFixesDestroyRegion (dpy, region); - if (rootBuffer != rootPicture) - { -#if 0 - XTransform t; - t.matrix[0][0] = XDoubleToFixed (3.0 /*/ scale*/); - t.matrix[0][1] = 0.0; - t.matrix[0][2] = 0.0; - - t.matrix[1][0] = 0.0; - t.matrix[1][1] = XDoubleToFixed (1.0 /*/ scale*/); - t.matrix[1][2] = 0.0; - - t.matrix[2][0] = 0.0; - t.matrix[2][1] = 0.0; - t.matrix[2][2] = XDoubleToFixed (1.0); - - XRenderSetPictureTransform (dpy, rootBuffer, &t); -#endif - XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, None); - XRenderComposite (dpy, PictOpSrc, rootBuffer, None, rootPicture, - 0, 0, 0, 0, 0, 0, root_width, root_height); - } - screen_damaged = False; -} - -static void -add_damage (Display *dpy, XserverRegion damage) -{ - if (allDamage) - { - XFixesUnionRegion (dpy, allDamage, allDamage, damage); - XFixesDestroyRegion (dpy, damage); - } - else - allDamage = damage; -} - -static void damage_win (Display *dpy, XDamageNotifyEvent *de); - -static void -repair_win (Display *dpy, win *w) -{ - XserverRegion parts; - - if (!w->damaged) - { - parts = win_extents (dpy, w); - set_ignore (dpy, NextRequest (dpy)); - XDamageSubtract (dpy, w->damage, None, None); - } - else - { - XserverRegion o; - parts = XFixesCreateRegion (dpy, 0, 0); - set_ignore (dpy, NextRequest (dpy)); - XDamageSubtract (dpy, w->damage, None, parts); - XFixesTranslateRegion (dpy, parts, - w->a.x + w->a.border_width, - w->a.y + w->a.border_width); - if (compMode == CompServerShadows) - { - o = XFixesCreateRegion (dpy, 0, 0); - XFixesCopyRegion (dpy, o, parts); - XFixesTranslateRegion (dpy, o, w->shadow_dx, w->shadow_dy); - XFixesUnionRegion (dpy, parts, parts, o); - XFixesDestroyRegion (dpy, o); - } - } - add_damage (dpy, parts); - w->damaged = 1; -} - -static const char* -wintype_name(wintype type) -{ - const char *t; - switch (type) { - case WINTYPE_DESKTOP: t = "desktop"; break; - case WINTYPE_DOCK: t = "dock"; break; - case WINTYPE_TOOLBAR: t = "toolbar"; break; - case WINTYPE_MENU: t = "menu"; break; - case WINTYPE_UTILITY: t = "utility"; break; - case WINTYPE_SPLASH: t = "slash"; break; - case WINTYPE_DIALOG: t = "dialog"; break; - case WINTYPE_NORMAL: t = "normal"; break; - case WINTYPE_DROPDOWN_MENU: t = "dropdown"; break; - case WINTYPE_POPUP_MENU: t = "popup"; break; - case WINTYPE_TOOLTIP: t = "tooltip"; break; - case WINTYPE_NOTIFY: t = "notification"; break; - case WINTYPE_COMBO: t = "combo"; break; - case WINTYPE_DND: t = "dnd"; break; - default: t = "unknown"; break; - } - return t; -} - -void repaint_root_overlay_window () -{ - XRectangle r; - r.x = 0; - r.y = 0; - r.width = root_width; - r.height = root_height; - XserverRegion region = XFixesCreateRegion (dpy, &r, 1); - add_damage (dpy, region); -} - -static wintype -get_wintype_prop(Display * dpy, Window w) -{ - Atom actual; - wintype ret; - int format; - unsigned long n, left, off; - unsigned char *data; - - ret = (wintype)-1; - off = 0; - - do { - set_ignore (dpy, NextRequest (dpy)); - int result = XGetWindowProperty (dpy, w, winTypeAtom, off, 1L, False, - XA_ATOM, &actual, &format, - &n, &left, &data); - - if (result != Success) - break; - if (data != None) - { - int i; - - for (i = 0; i < NUM_WINTYPES; ++i) { - Atom a; - memcpy (&a, data, sizeof (Atom)); - if (a == winType[i]) { - /* known type */ - ret = i; - break; - } - } - - XFree ( (void *) data); - } - - ++off; - } while (left >= 4 && ret == (wintype)-1); - - return ret; -} - -static wintype -determine_wintype (Display *dpy, Window w, Window top) -{ - Window root_return, parent_return; - Window *children = NULL; - unsigned int nchildren, i; - wintype type; - - type = get_wintype_prop (dpy, w); - if (type != (wintype)-1) - return type; - - set_ignore (dpy, NextRequest (dpy)); - if (!XQueryTree (dpy, w, &root_return, &parent_return, &children, - &nchildren)) - { - /* XQueryTree failed. */ - if (children) - XFree ((void *)children); - return (wintype)-1; - } - - for (i = 0;i < nchildren;i++) - { - type = determine_wintype (dpy, children[i], top); - if (type != (wintype)-1) - return type; - } - - if (children) - XFree ((void *)children); - - if (w != top) - return (wintype)-1; - else - return WINTYPE_NORMAL; -} - -static unsigned int -get_opacity_prop(Display *dpy, win *w, unsigned int def); - -static void -map_win (Display *dpy, Window id, unsigned long sequence, Bool fade) -{ - win *w = find_win (dpy, id); - Drawable back; - -#if DEBUG_WINDOWS - printf("map_win: 0x%x 0x%x\n", w, id); -#endif - - if (!w) { - return; - } - - w->a.map_state = IsViewable; - - /* This needs to be here or else we lose transparency messages */ - XSelectInput (dpy, id, PropertyChangeMask); - - /* This needs to be here since we don't get PropertyNotify when unmapped */ - w->opacity = get_opacity_prop (dpy, w, OPAQUE); - w->show_root_tile = determine_window_transparent_to_desktop(dpy, id); - w->show_black_background = determine_window_transparent_to_black(dpy, id); - determine_mode (dpy, w); - - w->windowType = determine_wintype (dpy, w->id, w->id); - if ((w->windowType < 0) || (w->windowType > NUM_WINTYPES)) w->windowType = WINTYPE_NORMAL; -#if 0 - printf("window 0x%x type %s\n", w->id, wintype_name(w->windowType)); -#endif - -#if CAN_DO_USABLE - w->damage_bounds.x = w->damage_bounds.y = 0; - w->damage_bounds.width = w->damage_bounds.height = 0; -#endif - w->damaged = 0; - -#if WORK_AROUND_FGLRX - if (w->a.x != 0) { - XserverRegion extents = win_extents (dpy, w); - XDamageNotifyEvent de; - de.drawable = w->id; - de.area.x = 0; - de.area.y = 0; - de.area.width = w->a.width + w->a.border_width * 2; - de.area.height = w->a.height + w->a.border_width * 2; - damage_win(dpy, &de); - XFixesDestroyRegion (dpy, extents); - } -#endif - w->a_prev = w->a; - - if (fade && winTypeFade[w->windowType]) { - set_fade (dpy, w, 0, get_opacity_prop(dpy, w, OPAQUE)*1.0/OPAQUE, fade_in_step, 0, False, True, True, True); - } -} - -static void -finish_unmap_win (Display *dpy, win *w) -{ -#if DEBUG_WINDOWS - printf("finish_unmap_win: 0x%x\n", w->id); -#endif - w->damaged = 0; -#if CAN_DO_USABLE - w->usable = False; -#endif - if (w->extents != None) - { - add_damage (dpy, w->extents); /* destroys region */ - w->extents = None; - } - -#if HAS_NAME_WINDOW_PIXMAP - if (w->pixmap) - { - XFreePixmap (dpy, w->pixmap); - w->pixmap = None; - } -#endif - - if (w->picture) - { - set_ignore (dpy, NextRequest (dpy)); - XRenderFreePicture (dpy, w->picture); - w->picture = None; - } - - /* don't care about properties anymore */ - set_ignore (dpy, NextRequest (dpy)); - XSelectInput(dpy, w->id, 0); - - if (w->borderSize) - { - set_ignore (dpy, NextRequest (dpy)); - XFixesDestroyRegion (dpy, w->borderSize); - w->borderSize = None; - } - - if (w->decoRegion) - { - set_ignore (dpy, NextRequest (dpy)); - XFixesDestroyRegion (dpy, w->decoRegion); - w->decoRegion = None; - } - - if (w->contentRegion) - { - set_ignore (dpy, NextRequest (dpy)); - XFixesDestroyRegion (dpy, w->contentRegion); - w->contentRegion = None; - } - - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - } - if (w->borderClip) - { - XFixesDestroyRegion (dpy, w->borderClip); - w->borderClip = None; - } - - clipChanged = True; -} - -#if HAS_NAME_WINDOW_PIXMAP -static void -unmap_callback (Display *dpy, win *w, Bool gone) -{ - finish_unmap_win (dpy, w); -} -#endif - -static void -unmap_win (Display *dpy, Window id, Bool fade) -{ - win *w = find_win (dpy, id); - -#if DEBUG_WINDOWS - printf("unmap_win: 0x%x 0x%x\n", w, id); -#endif - - if (!w) - return; - - if (w->a.map_state != IsUnmapped) { - w->a.map_state = IsUnmapped; -#if HAS_NAME_WINDOW_PIXMAP - if (w->pixmap && fade && winTypeFade[w->windowType]) { - set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, unmap_callback, False, False, True, True); - } - else -#endif - 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; - int format; - unsigned long n, left; - - unsigned char *data; - int result = XGetWindowProperty(dpy, w->id, opacityAtom, 0L, 1L, False, - XA_CARDINAL, &actual, &format, - &n, &left, &data); - if (result == Success && data != NULL && format == 32 ) - { - unsigned int i; - i = *(long*)data; - XFree( (void *) data); - return i; - } - return def; -} - - static unsigned int -get_shadow_prop(Display *dpy, win *w) -{ - Atom actual; - int format; - unsigned long n, left; - - unsigned char *data = NULL; - int result = XGetWindowProperty(dpy, w->id, shadowAtom, 0L, 1L, False, - XA_CARDINAL, &actual, &format, - &n, &left, &data); - if (result == Success && data != NULL && format == 32 ) - { - unsigned int i; - i = *(long*)data; - XFree( (void *) data); - /*i added this for security reaons but limiting a value to 200% is somewhat indiscriminate - if (i > 200) - return 200; - else*/ - return i; - } - return 100; -} - - static unsigned int -get_shade_prop(Display *dpy, win *w) -{ - Atom actual; - int format; - unsigned long n, left; - - unsigned char *data = NULL; - int result = XGetWindowProperty(dpy, w->id, shadeAtom, 0L, 1L, False, - XA_CARDINAL, &actual, &format, - &n, &left, &data); - if (result == Success && data != NULL && format == 32 ) - { - unsigned int i; - i = *(long*)data; - XFree( (void *) data); - return i; - } - return 0; -} - - static Bool -get_shapable_prop(Display *dpy, win *w) -{ - Atom actual; - int format; - unsigned long n, left; - - unsigned char *data = NULL; - int result = XGetWindowProperty(dpy, w->id, shapableAtom, 0L, 1L, False, - XA_CARDINAL, &actual, &format, - &n, &left, &data); - if (result == Success && data != NULL && format == 32 ) - { - unsigned int i; - i = *(long*)data; - XFree( (void *) data); - return i==1; - } - return True; /*in general, the window should be shapable*/ -} - -static unsigned int -get_decoHash_prop(Display *dpy, win *w) -{ - Atom actual; - int format; - unsigned long n, left; - - unsigned char *data = NULL; - int result = XGetWindowProperty(dpy, w->id, decoHashAtom, 0L, 1L, False, - XA_CARDINAL, &actual, &format, - &n, &left, &data); - if (result == Success && data != NULL && format == 32 ) - { - unsigned int i; - i = *(long*)data; - XFree( (void *) data); - return i; - } - return 0; /*no titlebar*/ -} - -static unsigned int -get_dim_prop(Display *dpy, win *w) -{ - Atom actual; - int format; - unsigned long n, left; - - unsigned char *data = NULL; - int result = XGetWindowProperty(dpy, w->id, dimAtom, 0L, 1L, False, - XA_CARDINAL, &actual, &format, - &n, &left, &data); - if (result == Success && data != NULL) - { - unsigned int i; - memcpy (&i, data, sizeof (unsigned int)); - XFree( (void *) data); - if (i == 0) i = 1; - return i; - } - return OPAQUE; /*in general, the window is not dimmed*/ -} - -static unsigned int -get_deskchange_prop(Display *dpy, Window id) -{ - Atom actual; - int format; - unsigned long n, left; - - unsigned char *data = NULL; - int result = XGetWindowProperty(dpy, id, deskChangeAtom, 0L, 1L, False, - XA_CARDINAL, &actual, &format, - &n, &left, &data); - if (result == Success && data != NULL) - { - unsigned int i; - memcpy (&i, data, sizeof (unsigned int)); - XFree( (void *) data); - if (i < 3) - return i; - } - return 0; /*no valid change state*/ -} - -/* 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) -{ - if (w && w->isInFade) - { - fade *f = find_fade(w); - return f->finish; - } - else - { - double def = winTypeOpacity[w->windowType]; - unsigned int opacity = get_opacity_prop (dpy, w, (unsigned int)(OPAQUE*def)); - return opacity*1.0/OPAQUE; - } -} -#if 0 -static void -damage_shape(Display *dpy, win *w, XRectangle *shape_damage) -{ - set_ignore (dpy, NextRequest (dpy)); - XserverRegion region = XFixesCreateRegion (dpy, shape_damage, 1); - set_ignore (dpy, NextRequest (dpy)); - XserverRegion tmpRegion; - add_damage(dpy, region); - win *i; - XRectangle *rect; - int n; - for (i = w; i; i = i->next) - { - XFixesIntersectRegion (dpy, tmpRegion, region, w->extents); - rect = XFixesFetchRegion (dpy, region, &n); - free(rect); - printf("%d\n",n); - if (n != 1) - { - w->damage = True; - XFixesSubtractRegion (dpy, region, region, w->extents); - } - else - break; - } - set_ignore (dpy, NextRequest (dpy)); - XFixesDestroyRegion (dpy, tmpRegion); - set_ignore (dpy, NextRequest (dpy)); - XFixesDestroyRegion (dpy, region); -} -#endif - -static Bool -get_window_transparent_to_desktop(Display * dpy, Window w) -{ - Atom actual; - int format; - unsigned long n, left; - - unsigned char *data; - int result = XGetWindowProperty (dpy, w, winTDETTDAtom, 0L, 1L, False, - XA_ATOM, &actual, &format, - &n, &left, &data); - - if (result == Success && data != None && format == 32 ) - { - Atom a; - a = *(long*)data; - XFree ( (void *) data); - return True; - } - return False; -} - -static Bool -get_window_transparent_to_black(Display * dpy, Window w) -{ - Atom actual; - int format; - unsigned long n, left; - - unsigned char *data; - int result = XGetWindowProperty (dpy, w, winTDETTBAtom, 0L, 1L, False, - XA_ATOM, &actual, &format, - &n, &left, &data); - - if (result == Success && data != None && format == 32 ) - { - Atom a; - a = *(long*)data; - XFree ( (void *) data); - return True; - } - return False; -} - - static void -determine_mode(Display *dpy, win *w) -{ - int mode; - XRenderPictFormat *format; - unsigned int default_opacity; - - /* if trans prop == -1 fall back on previous tests*/ - - if (w->alphaPict) - { - XRenderFreePicture (dpy, w->alphaPict); - w->alphaPict = None; - } - if (w->shadowPict) - { - XRenderFreePicture (dpy, w->shadowPict); - w->shadowPict = None; - } - - if (w->a.class == InputOnly) - { - format = 0; - } - else - { - format = XRenderFindVisualFormat (dpy, w->a.visual); - } - - if (!disable_argb && format && format->type == PictTypeDirect && format->direct.alphaMask) - { - mode = WINDOW_ARGB; - } - else if (w->opacity != OPAQUE) - { - mode = WINDOW_TRANS; - } - else - { - mode = WINDOW_SOLID; - } - w->mode = mode; - if (w->extents) - { - XserverRegion damage; - damage = XFixesCreateRegion (dpy, 0, 0); - XFixesCopyRegion (dpy, damage, w->extents); - add_damage (dpy, damage); - } -} - -static Bool -determine_window_transparent_to_desktop (Display *dpy, Window w) -{ - Window root_return, parent_return; - Window *children = NULL; - unsigned int nchildren, i; - Bool type; - - type = get_window_transparent_to_desktop (dpy, w); - if (type == True) { - return True; - } - - if (!XQueryTree (dpy, w, &root_return, &parent_return, &children, - &nchildren)) - { - /* XQueryTree failed. */ - if (children) - XFree ((void *)children); - return False; - } - - for (i = 0;i < nchildren;i++) - { - type = determine_window_transparent_to_desktop (dpy, children[i]); - if (type == True) - return True; - } - - if (children) - XFree ((void *)children); - - return False; -} - -static Bool -determine_window_transparent_to_black (Display *dpy, Window w) -{ - Window root_return, parent_return; - Window *children = NULL; - unsigned int nchildren, i; - Bool type; - Bool ret = False; - - type = get_window_transparent_to_black (dpy, w); - if (type == True) { - return True; - } - - if (!XQueryTree (dpy, w, &root_return, &parent_return, &children, - &nchildren)) - { - /* XQueryTree failed. */ - if (children) { - XFree ((void *)children); - } - return False; - } - - for (i = 0;i < nchildren;i++) - { - type = determine_window_transparent_to_black (dpy, children[i]); - if (type == True) { - ret = True; - break; - } - } - - if (children) { - XFree ((void *)children); - } - - return ret; -} - - static void -add_win (Display *dpy, Window id, Window prev) -{ - win *new = malloc (sizeof (win)); - win **p; - unsigned int tmp; - -#if DEBUG_WINDOWS - printf("add_win: 0x%x\n", id); -#endif - - if (!new) { -#if DEBUG_WINDOWS - printf("add_win: malloc() failed!\n", id); -#endif - return; - } - if (prev) { - for (p = &list; *p; p = &(*p)->next) { - if (((*p)->id == prev) && (!(*p)->destroyed)) { - break; - } - } - } - else { - p = &list; - } - new->id = id; - set_ignore (dpy, NextRequest (dpy)); - if (!XGetWindowAttributes (dpy, id, &new->a)) - { -#if DEBUG_WINDOWS - printf("not adding 0x%x: failed to get attributes\n", new->id); -#endif - free (new); - return; - } - new->shaped = False; - new->shape_bounds.x = new->a.x; - new->shape_bounds.y = new->a.y; - new->shape_bounds_prev = new->shape_bounds; - new->shape_bounds.width = new->a.width; - new->shape_bounds.height = new->a.height; - new->a_prev = new->a; - new->damaged = 0; -#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) - { - new->damage_sequence = 0; - new->damage = None; - } - else - { - new->damage_sequence = NextRequest (dpy); - new->damage = XDamageCreate (dpy, id, XDamageReportNonEmpty); - XShapeSelectInput (dpy, id, ShapeNotifyMask); - } - new->isInFade = False; - new->alphaPict = None; - new->shadowPict = None; - new->borderSize = None; - new->decoRegion = None; - new->contentRegion = None; - new->extents = None; - new->shadow = None; - new->shadow_dx = 0; - new->shadow_dy = 0; - new->shadow_width = 0; - new->shadow_height = 0; - new->opacity = OPAQUE; - new->destroyed = False; - new->destruct_queued = False; - new->destruct_requested = False; - new->destruct_request_time = 0; - new->shadowSize = 100; - new->decoHash = 0; - new->show_root_tile = determine_window_transparent_to_desktop(dpy, id); - new->show_black_background = determine_window_transparent_to_black(dpy, id); - - new->windowType = determine_wintype (dpy, new->id, new->id); - if ((new->windowType < 0) || (new->windowType > NUM_WINTYPES)) new->windowType = WINTYPE_NORMAL; - - new->borderClip = None; - new->prev_trans = 0; - - XShapeSelectInput( dpy, id, ShapeNotifyMask ); - - new->shadowSize = get_shadow_prop (dpy, new); - new->shapable = get_shapable_prop(dpy, new); - new->decoHash = get_decoHash_prop(dpy, new); - tmp = get_dim_prop(dpy, new); - new->dimPicture = (tmp < OPAQUE) ? solid_picture (dpy, True, (double)tmp/OPAQUE, 0.1, 0.1, 0.1) : None; - - new->next = *p; - *p = new; -#if DEBUG_WINDOWS - printf("adding 0x%x\n", new->id); -#endif - if (new->a.map_state == IsViewable) { - map_win (dpy, id, new->damage_sequence - 1, True); -#if DEBUG_WINDOWS - printf("mapped 0x%x\n", new->id); -#endif - } -} - - void -restack_win (Display *dpy, win *w, Window new_above) -{ - Window old_above; - -#if DEBUG_WINDOWS - printf("restack_win: 0x%x\n", w->id); -#endif - - if (w->next) { - old_above = w->next->id; - } - else { - old_above = None; - } - if (old_above != new_above) { - win **prev; - - /* unhook */ - for (prev = &list; *prev; prev = &(*prev)->next) { - if ((*prev) == w) { - break; - } - } - *prev = w->next; - - /* rehook */ - for (prev = &list; *prev; prev = &(*prev)->next) { - if ((!(*prev)->destroyed) && ((*prev)->id == new_above)) { - break; - } - } - w->next = *prev; - *prev = w; - } -} - - static void -configure_win (Display *dpy, XConfigureEvent *ce) -{ - win *w = find_win (dpy, ce->window); - Window above; - XserverRegion damage = None; - - if (!w) - { - if (ce->window == root) - { - if (rootBuffer) - { - XRenderFreePicture (dpy, rootBuffer); - rootBuffer = None; - } - root_width = ce->width; - root_height = ce->height; - } - return; - } - -#if CAN_DO_USABLE - if (w->usable) -#endif - { - damage = XFixesCreateRegion (dpy, 0, 0); - if (w->extents != None) - XFixesCopyRegion (dpy, damage, w->extents); - } - w->shape_bounds.x -= w->a.x; - w->shape_bounds.y -= w->a.y; - w->a.x = ce->x; - w->a.y = ce->y; - /* Only destroy the pixmap if the window is mapped */ - if (w->a.map_state != IsUnmapped && - (w->a.width != ce->width || w->a.height != ce->height)) - { -#if HAS_NAME_WINDOW_PIXMAP - if (w->pixmap) - { - XFreePixmap (dpy, w->pixmap); - w->pixmap = None; - if (w->picture) - { - XRenderFreePicture (dpy, w->picture); - w->picture = None; - } - } -#endif - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - } - } - w->a.width = ce->width; - w->a.height = ce->height; - w->a.border_width = ce->border_width; - w->a.override_redirect = ce->override_redirect; - restack_win (dpy, w, ce->above); - if (w->a.map_state != IsUnmapped && damage) - { - XserverRegion extents = win_extents (dpy, w); - XFixesUnionRegion (dpy, damage, damage, extents); - XFixesDestroyRegion (dpy, extents); - add_damage (dpy, damage); - } - w->shape_bounds.x += w->a.x; - w->shape_bounds.y += w->a.y; - if (!w->shaped) - { - w->shape_bounds.width = w->a.width; - w->shape_bounds.height = w->a.height; - } - - if (w->a.map_state != IsUnmapped) - clipChanged = True; -} - - static void -circulate_win (Display *dpy, XCirculateEvent *ce) -{ - win *w = find_win (dpy, ce->window); - Window new_above; - - if (!w) - return; - - if (ce->place == PlaceOnTop) - new_above = list->id; - else - new_above = None; - restack_win (dpy, w, new_above); - clipChanged = True; -} - - static void -finish_destroy_win (Display *dpy, Window id, Bool gone) -{ - win **prev, *w; - -#if DEBUG_WINDOWS - printf("finish_destroy_win: 0x%x\n", id); -#endif - - for (prev = &list; (w = *prev); prev = &w->next) { - if (w->id == id && w->destroyed) { - if (gone) { - finish_unmap_win (dpy, w); - } - *prev = w->next; - if (w->picture) - { - set_ignore (dpy, NextRequest (dpy)); - XRenderFreePicture (dpy, w->picture); - w->picture = None; - } - if (w->alphaPict) - { - XRenderFreePicture (dpy, w->alphaPict); - w->alphaPict = None; - } - if (w->shadowPict) - { - XRenderFreePicture (dpy, w->shadowPict); - w->shadowPict = None; - } - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - } - if (w->damage != None) - { - set_ignore (dpy, NextRequest (dpy)); - XDamageDestroy (dpy, w->damage); - w->damage = None; - } - cleanup_fade (dpy, w); - free (w); - break; - } - } -} - -#if HAS_NAME_WINDOW_PIXMAP -static void -destroy_callback (Display *dpy, win *w, Bool gone) -{ - finish_destroy_win (dpy, w->id, gone); -} -#endif - -static void -destroy_win (Display *dpy, Window id, Bool gone, Bool fadeout) -{ - fade *f; - win *w = find_win (dpy, id); - -#if DEBUG_WINDOWS - printf("destroy_win: 0x%x 0x%x\n", w, id); -#endif - - if (w) { - w->destroyed = True; - } - - if (w && w->destruct_queued == False) { - f = find_fade (w); - if (f) { - w->destruct_queued = True; - f->callback = destroy_callback; - } - else { -#if HAS_NAME_WINDOW_PIXMAP - if (w->pixmap && fadeout && winTypeFade[w->windowType]) { - set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, destroy_callback, gone, False, True, True); - } - else -#endif - { - if (!gone) { - finish_destroy_win (dpy, id, gone); - } - else { - w->destruct_queued = True; - w->destruct_requested = True; - w->destruct_request_time = get_time_in_milliseconds(); - } - } - } - } -} - -#if DEBUG_WINDOWS - 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); - - if (!w) - return; - -#if WORK_AROUND_FGLRX - if (w->a.map_state != IsViewable) - return; -#endif - -#if CAN_DO_USABLE - if (!w->usable) - { - if (w->damage_bounds.width == 0 || w->damage_bounds.height == 0) - { - w->damage_bounds = de->area; - } - else - { - if (de->area.x < w->damage_bounds.x) - { - w->damage_bounds.width += (w->damage_bounds.x - de->area.x); - w->damage_bounds.x = de->area.x; - } - if (de->area.y < w->damage_bounds.y) - { - w->damage_bounds.height += (w->damage_bounds.y - de->area.y); - w->damage_bounds.y = de->area.y; - } - if (de->area.x + de->area.width > w->damage_bounds.x + w->damage_bounds.width) - w->damage_bounds.width = de->area.x + de->area.width - w->damage_bounds.x; - if (de->area.y + de->area.height > w->damage_bounds.y + w->damage_bounds.height) - w->damage_bounds.height = de->area.y + de->area.height - w->damage_bounds.y; - } -#if 0 - printf ("unusable damage [%d] %d, %d: %d x %d bounds %d, %d: %d x %d\n", - de->drawable, - 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 && - w->a.height <= w->damage_bounds.y + w->damage_bounds.height) - { - clipChanged = True; - if (winTypeFade[w->windowType]) { - set_fade (dpy, w, 0, get_opacity_percent (dpy, w), fade_in_step, 0, False, True, True, False); - } - w->usable = True; - } - } - if (w->usable) -#endif - repair_win (dpy, w); -} - -static const char * -shape_kind(int kind) -{ - static char buf[128]; - - switch(kind){ - case ShapeBounding: - return "ShapeBounding"; - case ShapeClip: - return "ShapeClip"; - case ShapeInput: - return "ShapeInput"; - default: - sprintf (buf, "Shape %d", kind); - return buf; - } -} - -static void -shape_win (Display *dpy, XShapeEvent *se) -{ - win *w = find_win (dpy, se->window); - - if (!w) - return; - - if (w->a.map_state == IsUnmapped) - return; - - if (w->isInFade) - return; - - if (se->kind == ShapeClip || se->kind == ShapeBounding) - { - XserverRegion region0; - XserverRegion region1; - -#if 0 - printf("win 0x%lx %s:%s %ux%u+%d+%d (@%d+%d)\n", - (unsigned long) se->window, - shape_kind(se->kind), - (se->shaped == True) ? "true" : "false", - se->width, se->height, - se->x, se->y, - w->a.x, w->a.y); - printf("\told %s %d+%d (@%d+%d)\n", - (w->shaped == True) ? "true" : "false", - w->shape_bounds_prev.width, w->shape_bounds_prev.height, - w->shape_bounds_prev.x, w->shape_bounds_prev.y); -#endif - - clipChanged = True; - - region0 = XFixesCreateRegion (dpy, &w->shape_bounds_prev, 1); - - if (se->shaped == True) - { - w->shaped = True; - w->shape_bounds.x = w->a.x + se->x; - w->shape_bounds.y = w->a.y + se->y; - w->shape_bounds.width = se->width; - w->shape_bounds.height = se->height; - } - else - { - w->shaped = False; - w->shape_bounds.x = w->a.x; - w->shape_bounds.y = w->a.y; - w->shape_bounds.width = w->a.width; - w->shape_bounds.height = w->a.height; - } - - region1 = XFixesCreateRegion (dpy, &w->shape_bounds, 1); - XFixesUnionRegion (dpy, region0, region0, region1); - XFixesDestroyRegion (dpy, region1); - - /* ask for repaint of the old and new region */ - paint_all (dpy, region0); - } - - w->shape_bounds_prev = w->shape_bounds; -} - -static void -damage_screen (Display *dpy) -{ - XserverRegion region; - XRectangle r; - - r.x = 0; - r.y = 0; - r.width = root_width; - r.height = root_height; - - region = XFixesCreateRegion (dpy, &r, 1); - add_damage (dpy, region); - screen_damaged = True; -} - -static int -error (Display *dpy, XErrorEvent *ev) -{ - int o; - char *name = 0; - - if (should_ignore (dpy, ev->serial)) - return 0; - - if (ev->request_code == composite_opcode && - ev->minor_code == X_CompositeRedirectSubwindows) - { - fprintf (stderr, "Another composite manager is already running\n"); - my_exit_code=2; - exit (2); - } - - o = ev->error_code - xfixes_error; - switch (o) { - case BadRegion: name = "BadRegion"; break; - default: break; - } - o = ev->error_code - damage_error; - switch (o) { - case BadDamage: name = "BadDamage"; break; - default: break; - } - o = ev->error_code - render_error; - switch (o) { - case BadPictFormat: name ="BadPictFormat"; break; - case BadPicture: name ="BadPicture"; break; - case BadPictOp: name ="BadPictOp"; break; - case BadGlyphSet: name ="BadGlyphSet"; break; - case BadGlyph: name ="BadGlyph"; break; - default: break; - } - -#ifndef NDEBUG - fprintf (stderr,"error %d request %d minor %d serial %d\n", - ev->error_code, ev->request_code, ev->minor_code, ev->serial); -#endif - - /* 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); -} - - - static int -ev_serial (XEvent *ev) -{ - if ((ev->type & 0x7f) != KeymapNotify) - return ev->xany.serial; - return NextRequest (ev->xany.display); -} - - - static char * -ev_name (XEvent *ev) -{ - static char buf[128]; - switch (ev->type & 0x7f) { - case Expose: - return "Expose"; - case MapNotify: - return "Map"; - case UnmapNotify: - return "Unmap"; - case ReparentNotify: - return "Reparent"; - case CirculateNotify: - return "Circulate"; - default: - if (ev->type == damage_event + XDamageNotify) { - return "Damage"; - } - else if (ev->type == xshape_event + ShapeNotify) - { - return "Shape"; - } - sprintf (buf, "Event %d", ev->type); - return buf; - } -} - - static Window -ev_window (XEvent *ev) -{ - switch (ev->type) { - case Expose: - return ev->xexpose.window; - case MapNotify: - return ev->xmap.window; - case UnmapNotify: - return ev->xunmap.window; - case ReparentNotify: - return ev->xreparent.window; - case CirculateNotify: - return ev->xcirculate.window; - default: - if (ev->type == damage_event + XDamageNotify) { -// fprintf(stderr, "%d", ev->type); - return ((XDamageNotifyEvent *) ev)->drawable; - } - else if (ev->type == xshape_event + ShapeNotify) - { -// fprintf(stderr, "%d", ev->type); - return ((XShapeEvent *) ev)->window; - } - return 0; - } -} - -void -setShadowColor(char *value){ /*format nach #xxxxxx (html) �ndern?*/ - unsigned int tmp; - char **res = NULL; - tmp = strtoul(value, res, 16); - if( !value || strlen(value) < 6 || strlen(value) > 8 || (*(value+1) == 'x' && strlen(value) < 8) || res != NULL ){ - shadowColor.red = 0; - shadowColor.green = 0; - shadowColor.blue = 0; - printf("wrong hexadecimal (use 0xXXXXXX or XXXXXX)! defaulting to black...\n"); - return; - } - shadowColor.blue = tmp&0xff; - tmp >>= 8; - shadowColor.green = tmp&0xff; - tmp >>= 8; - shadowColor.red = tmp&0xff; -} - -typedef enum _option{ - Display_=0, - Compmode, - ExcludeDockShadows, - FadeWindows, - FadeTrans, - AutoRedirect, - Synchronize, - ShadowColor, - ShadowRadius, - ShadowOpacity, - ShadowOffsetX, - ShadowOffsetY, - FadeOutStep, - FadeInStep, - FadeDelta, - DisableARGB, - FadeMenuWindows, - NUMBEROFOPTIONS -} Option; - -const char * -options[NUMBEROFOPTIONS] = { - "Display", /*0*/ - "Compmode", /*1*/ - "ExcludeDockShadows", /*2*/ - "FadeWindows", /*3*/ - "FadeTrans", /*4*/ - "AutoRedirect", /*5*/ - "Synchronize", /*6*/ - "ShadowColor", /*7*/ - "ShadowRadius", /*8*/ - "ShadowOpacity", /*9*/ - "ShadowOffsetX", /*10*/ - "ShadowOffsetY", /*11*/ - "FadeOutStep", /*12*/ - "FadeInStep", /*13*/ - "FadeDelta", /*14*/ - "DisableARGB", /*15*/ - "FadeMenuWindows", /*16*/ - /*put your thingy in here...*/ -}; - -void -setValue(Option option, char *value ){ - int i; - - switch(option){ /*please keep that upside-down, because this way adding a new option is easier (all in one view)*/ - - case FadeDelta: - fade_delta = atoi(value); - if (fade_delta < 1) - fade_delta = 10; - break; - case FadeInStep: - fade_in_step = atof(value); - if (fade_in_step <= 0) - fade_in_step = 0.01; - break; - case FadeOutStep: - fade_out_step = atof(value); - if (fade_out_step <= 0) - fade_out_step = 0.01; - break; - case ShadowOffsetY: - shadowOffsetY = atoi(value); - break; - case ShadowOffsetX: - shadowOffsetX = atoi(value); - break; - case ShadowOpacity: - shadowOpacity = atof(value); - break; - case ShadowRadius: - shadowRadius = atoi(value); - break; - case ShadowColor: - setShadowColor(value); - break; - case Synchronize: - synchronize = ( strcasecmp(value, "true") == 0 ); - break; - case AutoRedirect: - autoRedirect = ( strcasecmp(value, "true") == 0 ); - break; - case FadeTrans: - fadeTrans = ( strcasecmp(value, "true") == 0 ); - break; - case FadeWindows: - if ( strcasecmp(value, "true") == 0 ) { - int i; - for (i = 0; i < NUM_WINTYPES; ++i) { - if (i != WINTYPE_POPUP_MENU) - winTypeFade[i] = True; - } - } - break; - case FadeMenuWindows: - if ( strcasecmp(value, "true") == 0 ) { - winTypeFade[WINTYPE_POPUP_MENU] = True; - } - break; - case ExcludeDockShadows: - if ( strcasecmp(value, "true") == 0 ) { - winTypeShadow[WINTYPE_DOCK] = False; - } - break; - case Compmode: - if( strcasecmp(value, "CompClientShadows") == 0 ){ - compMode = CompClientShadows; - for (i = 0; i < NUM_WINTYPES; ++i) - winTypeShadow[i] = True; - } - else if( strcasecmp(value, "CompServerShadows") == 0 ){ - compMode = CompServerShadows; - for (i = 0; i < NUM_WINTYPES; ++i) - winTypeShadow[i] = True; - } - else{ - compMode = CompSimple; /*default*/ - for (i = 0; i < NUM_WINTYPES; ++i) - winTypeShadow[i] = False; - } - break; - case Display_: - break; - display = strdup(value); - break; - case DisableARGB: - disable_argb = ( strcasecmp(value, "true") == 0 ); - break; - default: - break; - } -} - -int -setParameter(char *line){ - char *name = strtok(line, "="); - char *value = line+strlen(name)+1; - Option i; - for(i=Display_; i < NUMBEROFOPTIONS; i++){ - if( strcasecmp(name, *(options+i) ) == 0 ){ - setValue(i, value); - name = value = NULL; - return 1; - } - } - printf("ignored unknown option: <%s>\n", name); - name = value = NULL; - return 0; -} - -void -loadConfig(char *filename){ - FILE *file = NULL; - char line[ 1024 ]; - size_t length = 0; - Bool wasNull = False; - Bool section = False; - - if( filename == NULL ){ -#ifdef USE_ENV_HOME - const char *home = getenv("HOME"); -#else - const char *home; - struct passwd *p; - p = getpwuid(getuid()); - if (p) - home = p->pw_dir; - else - home = getenv("HOME"); -#endif - const char *configfile = "/.xcompmgrrc"; - int n = strlen(home)+strlen(configfile)+1; - filename = (char*)malloc(n*sizeof(char)); - memset(filename,0,n); - wasNull = True; - - strcat(filename, home); - strcat(filename, configfile); - } - - printf("trying '%s' as configfile\n\n", filename); - - if( (file = fopen(filename, "r")) == NULL ){ - printf("failed to open config file. does it exist?\n"); - if( wasNull ){ - free(filename); - filename = NULL; - } - return; - } - - /*find section*/ - while( !section && fgets(line, 1023, file) != NULL ){ - if( strcmp(line, "[xcompmgr]\n") == 0 ) - section = True; - } - /*read and set values*/ - while( section && fgets(line, 1023, file) != NULL ){ - int ret = strlen( line ); - if( ret > 1 ){ - if( *line == '[' )/*found new section - maybe check for '\n'?*/ - break; - *(line+ret-1) = '\0'; - setParameter(line); - } - } - printf("\nfinished parsing the config file\n"); - fclose(file); - if( wasNull ){ - free(filename); - filename = NULL; - } -} - - void -usage (char *program) -{ - fprintf (stderr, "%s v1.0\n", program); - fprintf (stderr, "usage: %s [options]\n", program); - fprintf (stderr, "Options\n"); - fprintf (stderr, " -d display\n Specifies which display should be managed.\n"); - fprintf (stderr, " -r radius\n Specifies the blur radius for client-side shadows. (default 12)\n"); - fprintf (stderr, " -o opacity\n Specifies the translucency for client-side shadows. (default .75)\n"); - fprintf (stderr, " -l left-offset\n Specifies the left offset for client-side shadows. (default -15)\n"); - fprintf (stderr, " -t top-offset\n Specifies the top offset for clinet-side shadows. (default -15)\n"); - fprintf (stderr, " -b color\n Specifies the background color to use if no root pixmap is set. (default is black)\n"); - fprintf (stderr, " -I fade-in-step\n Specifies the opacity change between steps while fading in. (default 0.028)\n"); - fprintf (stderr, " -O fade-out-step\n Specifies the opacity change between steps while fading out. (default 0.03)\n"); - fprintf (stderr, " -D fade-delta-time\n Specifies the time between steps in a fade in milliseconds. (default 10)\n"); - fprintf (stderr, " -a\n Use automatic server-side compositing. Faster, but no special effects.\n"); - fprintf (stderr, " -c\n Draw client-side shadows with fuzzy edges.\n"); - fprintf (stderr, " -C\n Avoid drawing shadows on dock/panel windows.\n"); - fprintf (stderr, " -f\n Fade windows in/out when opening/closing.\n"); - fprintf (stderr, " -F\n Fade windows during opacity changes.\n"); - fprintf (stderr, " -n\n Normal client-side compositing with transparency support\n"); - fprintf (stderr, " -s\n Draw server-side shadows with sharp edges.\n"); - fprintf (stderr, " -S\n Enable synchronous operation (for debugging).\n"); - fprintf (stderr, " -x [0x]XXXXXX\n Choose Custom Color in hex format\n"); - fprintf (stderr, " -v\n Print version Number and exit\n"); - fprintf (stderr, " -h\n Print this help\n"); - my_exit_code=2; - exit (2); -} - -static Bool -register_cm (void) -{ - Window w; - Atom a; - static char net_wm_cm[] = "_NET_WM_CM_Sxx"; - - snprintf (net_wm_cm, sizeof (net_wm_cm), "_NET_WM_CM_S%d", scr); - a = XInternAtom (dpy, net_wm_cm, False); - -/* w = XGetSelectionOwner (dpy, a); - if (w != None) - { - XTextProperty tp; - char **strs; - int count; - Atom winNameAtom = XInternAtom (dpy, "_NET_WM_NAME", False); - - if (!XGetTextProperty (dpy, w, &tp, winNameAtom) && - !XGetTextProperty (dpy, w, &tp, XA_WM_NAME)) - { - fprintf (stderr, - "Another composite manager is already running (0x%lx)\n", - (unsigned long) w); - return False; - } - if (XmbTextPropertyToTextList (dpy, &tp, &strs, &count) == Success) - { - fprintf (stderr, - "Another composite manager is already running (%s)\n", - strs[0]); - - XFreeStringList (strs); - } - - XFree (tp.value); - - return False; - }*/ - - w = XCreateSimpleWindow (dpy, RootWindow (dpy, scr), 0, 0, 1, 1, 0, None, - None); - Xutf8SetWMProperties(dpy, w, "kcompmgr", "kcompmgr", NULL, 0, NULL, NULL, - NULL); - - /* setting this causes kompmgr to abort on TDE login */ - /* XSetSelectionOwner (dpy, a, w, 0); */ - - return True; -} - -int -main (int argc, char **argv) -{ - XEvent ev; - Window root_return, parent_return; - Window *children; - Pixmap transPixmap; - Pixmap blackPixmap; - unsigned int nchildren; - int i; - XRenderPictureAttributes pa; - XRenderColor c; - XRectangle *expose_rects = 0; - int size_expose = 0; - int n_expose = 0; - struct pollfd ufd; - int n; - int last_update; - int now; - int p; - int composite_major, composite_minor; - Bool noDockShadow = False; - - for (i = 0; i < NUM_WINTYPES; ++i) { - winTypeFade[i] = False; - winTypeShadow[i] = False; - winTypeOpacity[i] = 1.0; - } - - int o; - char *fill_color_name = NULL; - char **res = NULL; - - shadowColor.red = 0; - shadowColor.green = 0; - shadowColor.blue = 0; - - // Initialize signal handlers - sigfillset(&block_mask); - usr_action.sa_handler = handle_siguser; - usr_action.sa_mask = block_mask; - usr_action.sa_flags = 0; - sigaction(SIGUSR1, &usr_action, NULL); - sigaction(SIGUSR2, &usr_action, NULL); - sigaction(SIGTERM, &usr_action, NULL); - - loadConfig(NULL); /*we do that before cmdline-parsing, so config-values can be overridden*/ - /*used for shadow colors*/ - - while ((o = getopt (argc, argv, "D:I:O:d:r:o:l:t:b:scnfFmCaSx:vhk")) != -1) - { - switch (o) { - case 'd': - display = optarg; - break; - case 'D': - fade_delta = atoi (optarg); - if (fade_delta < 1) - fade_delta = 10; - break; - case 'I': - fade_in_step = atof (optarg); - if (fade_in_step <= 0) - fade_in_step = 0.01; - break; - case 'O': - fade_out_step = atof (optarg); - if (fade_out_step <= 0) - fade_out_step = 0.01; - break; - case 's': - compMode = CompServerShadows; - for (i = 0; i < NUM_WINTYPES; ++i) - winTypeShadow[i] = True; - break; - case 'c': - compMode = CompClientShadows; - for (i = 0; i < NUM_WINTYPES; ++i) - winTypeShadow[i] = True; - break; - case 'C': - winTypeShadow[WINTYPE_DOCK] = False; - break; - case 'n': - compMode = CompSimple; - for (i = 0; i < NUM_WINTYPES; ++i) - winTypeShadow[i] = False; - break; - case 'f': - for (i = 0; i < NUM_WINTYPES; ++i) { - if (i != WINTYPE_POPUP_MENU) - winTypeFade[i] = True; - } - break; - case 'm': - winTypeFade[WINTYPE_POPUP_MENU] = True; - break; - case 'F': - fadeTrans = True; - break; - case 'a': - autoRedirect = True; - break; - case 'S': - synchronize = True; - break; - case 'r': - shadowRadius = atoi (optarg); - break; - case 'o': - shadowOpacity = atof (optarg); - break; - case 'l': - shadowOffsetX = atoi (optarg); - break; - case 't': - shadowOffsetY = atoi (optarg); - break; - case 'b': - fill_color_name = optarg; - break; - case 'x': - if( compMode != CompClientShadows ){ - fprintf(stderr, "sorry, but we need ClientShadows (-c) for coloring to work properly!\ndefaulting to black...\n"); - break; - } - setShadowColor(optarg); - break; - case 'v': fprintf (stderr, "%s v%-3.2f\n", argv[0], _VERSION_); my_exit_code=0; exit (0); - case 'k': - restartOnSigterm = False; - break; - case 'h': - default: - usage (argv[0]); - break; - } - } - - /* don't bother to do anything for the desktop */ - winTypeOpacity[WINTYPE_DESKTOP] = 1.0; - winTypeShadow[WINTYPE_DESKTOP] = False; - winTypeFade[WINTYPE_DESKTOP] = False; - - dpy = XOpenDisplay (display); - if (!dpy) - { - fprintf (stderr, "Can't open display\n"); - my_exit_code=2; - exit (2); - } - XSetErrorHandler (error); - if (synchronize) - XSynchronize (dpy, 1); - scr = DefaultScreen (dpy); - root = RootWindow (dpy, scr); - - if (!XRenderQueryExtension (dpy, &render_event, &render_error)) - { - fprintf (stderr, "No render extension\n"); - my_exit_code=2; - exit (2); - } - if (!XQueryExtension (dpy, COMPOSITE_NAME, &composite_opcode, - &composite_event, &composite_error)) - { - fprintf (stderr, "No composite extension\n"); - my_exit_code=2; - exit (2); - } - XCompositeQueryVersion (dpy, &composite_major, &composite_minor); -#if HAS_NAME_WINDOW_PIXMAP - if (composite_major > 0 || composite_minor >= 2) - hasNamePixmap = True; -#endif - - if (!XDamageQueryExtension (dpy, &damage_event, &damage_error)) - { - fprintf (stderr, "No damage extension\n"); - my_exit_code=2; - exit (2); - } - if (!XFixesQueryExtension (dpy, &xfixes_event, &xfixes_error)) - { - fprintf (stderr, "No XFixes extension\n"); - my_exit_code=2; - exit (2); - } - if (!XShapeQueryExtension (dpy, &xshape_event, &xshape_error)) - { - fprintf (stderr, "No XShape extension\n"); - my_exit_code=2; - exit (2); - } - - fprintf(stderr, "Started\n"); - - if (!register_cm()) - { - my_exit_code=2; - exit (2); - } - - /* get atoms */ - shadowAtom = XInternAtom (dpy, SHADOW_PROP, False); - opacityAtom = XInternAtom (dpy, OPACITY_PROP, False); - shadeAtom = XInternAtom (dpy, SHADE_PROP, False); - shapableAtom = XInternAtom (dpy, SHAPABLE_PROP, False); - decoHashAtom = XInternAtom (dpy, DECOHASH_PROP, False); - dimAtom = XInternAtom (dpy, DIM_PROP, False); - deskChangeAtom = XInternAtom (dpy, DESKCHANGE_PROP, False); - winTypeAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE", False); - winTDETTDAtom = XInternAtom (dpy, "_TDE_TRANSPARENT_TO_DESKTOP", False); - winTDETTBAtom = XInternAtom (dpy, "_TDE_TRANSPARENT_TO_BLACK", False); - winType[WINTYPE_DESKTOP] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False); - winType[WINTYPE_DOCK] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DOCK", False); - winType[WINTYPE_TOOLBAR] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False); - winType[WINTYPE_MENU] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_MENU", False); - winType[WINTYPE_UTILITY] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False); - winType[WINTYPE_SPLASH] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False); - winType[WINTYPE_DIALOG] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - winType[WINTYPE_NORMAL] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False); - winType[WINTYPE_DROPDOWN_MENU] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False); - winType[WINTYPE_POPUP_MENU] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", False); - winType[WINTYPE_TOOLTIP] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_TOOLTIP", False); - winType[WINTYPE_NOTIFY] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_NOTIFICATION", False); - winType[WINTYPE_COMBO] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_COMBO", False); - winType[WINTYPE_DND] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DND", False); - - pa.subwindow_mode = IncludeInferiors; - - if (compMode == CompClientShadows) - { - gaussianMap = make_gaussian_map(dpy, shadowRadius); - presum_gaussian (gaussianMap); - } - - if (fill_color_name) - { - XColor c; - if (! XParseColor (dpy, DefaultColormap (dpy, scr), - fill_color_name, &c)) - { - fprintf (stderr, "Could not parse fill color.\n"); - my_exit_code=2; - exit (2); - } - if (! XAllocColor (dpy, DefaultColormap (dpy, scr), &c)) - { - fprintf (stderr, "Could not allocate color.\n"); - my_exit_code=2; - exit (2); - } - - fill_color.red = c.red; - fill_color.green = c.green; - fill_color.blue = c.blue; - } - else - { - fill_color.red = fill_color.green = fill_color.blue = 0x0; - } - fill_color.alpha = 0xffff; - - root_width = DisplayWidth (dpy, scr); - root_height = DisplayHeight (dpy, scr); - - rootPicture = XRenderCreatePicture (dpy, root, - sXRenderFindVisualFormat (dpy, - DefaultVisual (dpy, scr)), - CPSubwindowMode, - &pa); - blackPicture = solid_picture (dpy, True, 1, (double)(shadowColor.red)/0xff, (double)(shadowColor.green)/0xff, (double)(shadowColor.blue)/0xff); - if (compMode == CompServerShadows) - transBlackPicture = solid_picture (dpy, True, 0.3, 0, 0, 0); - allDamage = None; - clipChanged = True; - XGrabServer (dpy); - if (autoRedirect) { - XCompositeRedirectSubwindows (dpy, root, CompositeRedirectAutomatic); - } - else - { - int dummy; - XCompositeRedirectSubwindows (dpy, root, CompositeRedirectManual); - XSelectInput (dpy, root, - SubstructureNotifyMask| - ExposureMask| - StructureNotifyMask| - PropertyChangeMask | - VisibilityChangeMask); - - /*shaping stuff*/ - XShapeQueryExtension(dpy, &shapeEvent, &dummy); - - XShapeSelectInput (dpy, root, ShapeNotifyMask); - XQueryTree (dpy, root, &root_return, &parent_return, &children, &nchildren); - for (i = 0; i < nchildren; i++) { - add_win (dpy, children[i], i ? children[i-1] : None); - } - XFree (children); - } - XUngrabServer (dpy); - ufd.fd = ConnectionNumber (dpy); - ufd.events = POLLIN; - if (!autoRedirect) { - paint_all (dpy, None); - } - - /* Under no circumstances should these two lines EVER be moved earlier in main() than this point */ - atexit(delete_pid_file); - write_pid_file(getpid()); - - for (;;) - { -#if DEBUG_WINDOWS - dump_wins (); -#endif - do { - if (autoRedirect) { - XFlush (dpy); - } - if (!QLength (dpy)) - { - if (poll (&ufd, 1, fade_timeout()) == 0) - { - run_fades (dpy); - break; - } - } - - XNextEvent (dpy, &ev); - if ((ev.type & 0x7f) != KeymapNotify) { - discard_ignore (dpy, ev.xany.serial); - } -#if DEBUG_EVENTS - printf ("event %10.10s serial 0x%08x window 0x%08x\n", - ev_name(&ev), ev_serial (&ev), ev_window (&ev)); -#endif - if (!autoRedirect) switch (ev.type) { - case CreateNotify: - add_win (dpy, ev.xcreatewindow.window, 0); - break; - case ConfigureNotify: - configure_win (dpy, &ev.xconfigure); - break; - case DestroyNotify: - destroy_win (dpy, ev.xdestroywindow.window, True, True); - break; - case MapNotify: - map_win (dpy, ev.xmap.window, ev.xmap.serial, True); - break; - case UnmapNotify: - unmap_win (dpy, ev.xunmap.window, True); - break; - case ReparentNotify: - if (ev.xreparent.parent == root) - add_win (dpy, ev.xreparent.window, 0); - else - destroy_win (dpy, ev.xreparent.window, False, True); - break; - case CirculateNotify: - circulate_win (dpy, &ev.xcirculate); - break; - case Expose: - if (ev.xexpose.window == root) - { - int more = ev.xexpose.count + 1; - if (n_expose == size_expose) - { - if (expose_rects) - { - expose_rects = realloc (expose_rects, - (size_expose + more) * - sizeof (XRectangle)); - size_expose += more; - } - else - { - expose_rects = malloc (more * sizeof (XRectangle)); - size_expose = more; - } - } - expose_rects[n_expose].x = ev.xexpose.x; - expose_rects[n_expose].y = ev.xexpose.y; - expose_rects[n_expose].width = ev.xexpose.width; - expose_rects[n_expose].height = ev.xexpose.height; - n_expose++; - if (ev.xexpose.count == 0) - { - expose_root (dpy, root, expose_rects, n_expose); - n_expose = 0; - } - } - break; - case PropertyNotify: - for (p = 0; backgroundProps[p]; p++) - { - if (ev.xproperty.atom == XInternAtom (dpy, backgroundProps[p], False)) - { - if (rootTile) - { - XRenderFreePicture (dpy, rootTile); - rootTile = None; - damage_screen (dpy); - break; - } - } - } - /* Window set shade? */ - if (ev.xproperty.atom == shadeAtom) - { - win * w = find_win(dpy, ev.xproperty.window); - if (w){ - unsigned int tmp = get_shade_prop(dpy, w); - if (tmp) - { - if (tmp == 1) - { - w->preShadeOpacity = w->opacity; - w->opacity = w->opacity-1; /*assuming that no human being will ever be able to shade an invisable window ;) */ - determine_mode(dpy, w); - } - else if (tmp == 2) - { - w->opacity = w->preShadeOpacity; - determine_mode(dpy, w); - } - } - break; - } - } - else if (ev.xproperty.atom == shapableAtom) - { - win * w = find_win(dpy, ev.xproperty.window); - if (w) - { - w->shapable = get_shapable_prop(dpy, w); - /* printf("%u is %s shapable\n",w->id,w->shapable?"":"not");*/ - } - else - printf("arrrg, window not found\n"); - } - else if (ev.xproperty.atom == decoHashAtom) - { - win * w = find_win(dpy, ev.xproperty.window); - if (w) - { - w->decoHash = get_decoHash_prop(dpy, w); - } - else - printf("arrrg, window not found\n"); - } - else if (ev.xproperty.atom == dimAtom) - { - win * w = find_win(dpy, ev.xproperty.window); - if (w) - { - unsigned int tmp = get_dim_prop(dpy, w); - if (w->dimPicture) - { - XRenderFreePicture (dpy, w->dimPicture); - w->dimPicture = None; - } - if (tmp < OPAQUE) - w->dimPicture = solid_picture (dpy, True, (double)tmp/OPAQUE, 0.1, 0.1, 0.1); - } - else - printf("arrrg, window not found\n"); - } - /* check if Trans or Shadow property was changed */ - else if (ev.xproperty.atom == opacityAtom || ev.xproperty.atom == shadowAtom) - { - /* reset mode and redraw window */ - win * w = find_win(dpy, ev.xproperty.window); - if (w) - { - unsigned int tmp; - unsigned int oldShadowSize = w->shadowSize; - if (ev.xproperty.atom == opacityAtom) - { - tmp = get_opacity_prop(dpy, w, OPAQUE); - /*This will most probably happen if window is in fade - resulting in that the fade process isn't updated or broken -> we may have a wrong opacity in the future*/ - /*if (tmp == w->opacity) - break;*/ /*skip if opacity does not change*/ - if (fadeTrans) - { - static double start, finish, step; - start = w->opacity*1.0/OPAQUE; - finish = (tmp*1.0)/OPAQUE; - - if ( start > finish ) - step = fade_out_step; - else - step = fade_in_step; - - set_fade (dpy, w, start, finish, step, 0, False, True, True, False); - break; - } - else { - w->opacity = tmp; - } - } - else - { - tmp = get_shadow_prop(dpy, w); - if (tmp == w->shadowSize) - break; /*skip if shadow does not change*/ - w->shadowSize = tmp; - /* if (w->isInFade) - break; */ - } - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - } - if (oldShadowSize < w->shadowSize) /* this is important to catch size changes on cleanup with determine_mode*/ - { - if( w->extents != None ) - XFixesDestroyRegion( dpy, w->extents ); - w->extents = win_extents (dpy, w); - determine_mode(dpy, w); - } - else - { - determine_mode(dpy, w); - if( w->extents != None ) - XFixesDestroyRegion( dpy, w->extents ); - w->extents = win_extents (dpy, w); - } - } - } - else if (ev.xproperty.atom == deskChangeAtom) - { - /*just set global variable*/ - unsigned int tmp = get_deskchange_prop(dpy, ev.xproperty.window); - printf("desk change, state:%d\n",tmp); - } - else if (ev.xproperty.atom == winTDETTDAtom) - { - win * w = find_win(dpy, ev.xproperty.window); - if (w) - { - w->show_root_tile = determine_window_transparent_to_desktop(dpy, ev.xproperty.window); - } - } - else if (ev.xproperty.atom == winTDETTBAtom) - { - win * w = find_win(dpy, ev.xproperty.window); - if (w) - { - w->show_black_background = determine_window_transparent_to_black(dpy, ev.xproperty.window); - } - } - break; - default: - if (ev.type == damage_event + XDamageNotify) - { - /* printf("damaging win: %u\n",ev.xany.window);*/ - damage_win (dpy, (XDamageNotifyEvent *) &ev); - repaint_root_overlay_window(); - } - if (ev.type == xshape_event + ShapeNotify) - { - shape_win (dpy, (XShapeEvent *) &ev); - } - if (ev.type == shapeEvent) - { - win * w = find_win(dpy, ev.xany.window); -#if 1 - if (w && w->shapable) -#endif -#if 0 - if (w) -#endif - { -#if 0 - XRectangle rect; - rect.x = ((XShapeEvent*)&ev)->x; - rect.y = ((XShapeEvent*)&ev)->y; - rect.width = ((XShapeEvent*)&ev)->width; - rect.height = ((XShapeEvent*)&ev)->height; - damage_shape(dpy, w, &rect); -#endif -#if 0 - if (w->shadowSize != 0) - { - w->shadowSize = 0; - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - determine_mode(dpy, w); - if( w->extents != None ) - XFixesDestroyRegion( dpy, w->extents ); - w->extents = win_extents (dpy, w); - } -#endif - /*this is hardly efficient, but a current workaraound - shaping support isn't that good so far (e.g. we lack shaped shadows) - IDEA: use XRender to scale/shift a copy of the window and then blur it*/ -#if 1 - if (w->picture) - { - clipChanged = True; - repair_win (dpy, w); - } -#endif - } - } - break; - } - } while (QLength (dpy)); - if (allDamage && !autoRedirect) - { - paint_all (dpy, allDamage); - XSync (dpy, False); - allDamage = None; - clipChanged = False; - } - } - - XClearArea (dpy, root, 0, 0, 0, 0, True); - XSync (dpy, False); -} |