summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Rusin <zack@kde.org>2006-01-02 07:11:21 +0000
committerZack Rusin <zack@kde.org>2006-01-02 07:11:21 +0000
commitba0bd60b9261a0bcedba9dfc1905d8929e14d440 (patch)
tree93be25405222a4e0732ccdf1511ddd92534adc30
parent7f820289fc18e20881b56227cef6d0f1b5353f3d (diff)
updating from airlied copy and adding cvsignores
-rw-r--r--.cvsignore13
-rw-r--r--README5
-rw-r--r--images/.cvsignore2
-rw-r--r--include/.cvsignore2
-rw-r--r--include/comp.h153
-rw-r--r--plugins/.cvsignore6
-rw-r--r--plugins/Makefile.am5
-rw-r--r--plugins/cube.c23
-rw-r--r--plugins/expose.c35
-rw-r--r--plugins/fade.c40
-rw-r--r--plugins/gconf.c126
-rw-r--r--plugins/rotate.c78
-rw-r--r--plugins/shadow.c902
-rw-r--r--plugins/wobbly.c467
-rw-r--r--src/.cvsignore5
-rw-r--r--src/display.c24
-rw-r--r--src/event.c64
-rw-r--r--src/glxcompmgr.c11
-rw-r--r--src/paint.c399
-rw-r--r--src/screen.c66
-rw-r--r--src/texture.c31
-rw-r--r--src/window.c69
22 files changed, 1942 insertions, 584 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..e98b755
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,13 @@
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config
+config.h
+config.h.in
+config.log
+config.status
+configure
+glxcomp.pc
+libtool
+stamp-h1
diff --git a/README b/README
index 7f4e753..36851dd 100644
--- a/README
+++ b/README
@@ -1,10 +1,5 @@
glxcompmgr - OpenGL compositing manager
-For now you need Mesa compiled with mesa-glx-x11-render-texture-3.diff
-patch in this directory to run it. We'll need to figure out a better way
-of creating textures from pixmaps: EXT_texture_from_drawable for example.
-
-
glxcompmgr is an OpenGL compositing manager that use GLX_MESA_render_texture
for binding redirected top-level windows to texture objects. It has a flexible
plug-in system and it is designed to run well on most graphics hardware.
diff --git a/images/.cvsignore b/images/.cvsignore
new file mode 100644
index 0000000..282522d
--- /dev/null
+++ b/images/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/include/.cvsignore b/include/.cvsignore
new file mode 100644
index 0000000..282522d
--- /dev/null
+++ b/include/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/include/comp.h b/include/comp.h
index 808ba84..38ad9f0 100644
--- a/include/comp.h
+++ b/include/comp.h
@@ -1,6 +1,6 @@
/*
* Copyright © 2005 Novell, Inc.
- *
+ *
* 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
@@ -12,11 +12,11 @@
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
- * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL NOVELL, INC. 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,
+ * 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.
*
@@ -69,16 +69,19 @@ typedef struct _CompTexture CompTexture;
#define OPAQUE 0xffff
-extern char *programName;
-extern char **programArgv;
-extern int programArgc;
-extern char *backgroundImage;
-extern char *windowImage;
-extern REGION emptyRegion;
-extern GLushort defaultColor[4];
-extern Window currentRoot;
-extern Bool testMode;
-extern Bool restartSignal;
+extern char *programName;
+extern char **programArgv;
+extern int programArgc;
+extern char *backgroundImage;
+extern char *windowImage;
+extern REGION emptyRegion;
+extern REGION infiniteRegion;
+extern GLushort defaultColor[4];
+extern Window currentRoot;
+extern Bool testMode;
+extern Bool restartSignal;
+extern CompWindow *lastFoundWindow;
+extern CompWindow *lastDamagedWindow;
extern int defaultRefreshRate;
extern char *defaultTextureFilter;
@@ -86,6 +89,8 @@ extern char *defaultTextureFilter;
#define RESTRICT_VALUE(value, min, max) \
(((value) < (min)) ? (min): ((value) > (max)) ? (max) : (value))
+#define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
+
/* privates.h */
@@ -100,7 +105,7 @@ typedef union _CompPrivate {
void *ptr;
long val;
unsigned long uval;
- void *(*fptr) (void);
+ void *(*fptr) (void);
} CompPrivate;
typedef int (*ReallocPrivatesProc) (int size, void *closure);
@@ -207,7 +212,7 @@ typedef struct _CompOption {
char *longDesc;
CompOptionType type;
CompOptionValue value;
- CompOptionRestriction rest;
+ CompOptionRestriction rest;
} CompOption;
typedef CompOption *(*DisplayOptionsProc) (CompDisplay *display, int *count);
@@ -257,11 +262,11 @@ compSetOptionList (CompOption *option,
typedef CompOption *(*GetDisplayOptionsProc) (CompDisplay *display,
int *count);
typedef Bool (*SetDisplayOptionProc) (CompDisplay *display,
- char *name,
+ char *name,
CompOptionValue *value);
typedef Bool (*SetDisplayOptionForPluginProc) (CompDisplay *display,
- char *plugin,
- char *name,
+ char *plugin,
+ char *name,
CompOptionValue *value);
typedef Bool (*InitPluginForDisplayProc) (CompPlugin *plugin,
@@ -272,8 +277,6 @@ typedef void (*FiniPluginForDisplayProc) (CompPlugin *plugin,
typedef void (*HandleEventProc) (CompDisplay *display,
XEvent *event);
-typedef void (*HandleDamageEventProc) (CompDisplay *display,
- XDamageNotifyEvent *event);
typedef Bool (*CallBackProc) (void *closure);
@@ -286,7 +289,7 @@ struct _CompDisplay {
int compositeEvent, compositeError, compositeOpcode;
int damageEvent, damageError;
-
+
Bool shapeExtension;
int shapeEvent, shapeError;
@@ -316,15 +319,14 @@ struct _CompDisplay {
CompOptionValue plugin;
Bool dirtyPluginList;
- SetDisplayOptionProc setDisplayOption;
+ SetDisplayOptionProc setDisplayOption;
SetDisplayOptionForPluginProc setDisplayOptionForPlugin;
InitPluginForDisplayProc initPluginForDisplay;
FiniPluginForDisplayProc finiPluginForDisplay;
- HandleEventProc handleEvent;
- HandleDamageEventProc handleDamageEvent;
-
+ HandleEventProc handleEvent;
+
CompPrivate *privates;
};
@@ -397,7 +399,7 @@ handleEvent (CompDisplay *display,
XEvent *event);
void
-handleDamageEvent (CompDisplay *display,
+handleDamageEvent (CompWindow *window,
XDamageNotifyEvent *event);
@@ -429,9 +431,14 @@ typedef struct _WindowPaintAttrib {
extern ScreenPaintAttrib defaultScreenPaintAttrib;
extern WindowPaintAttrib defaultWindowPaintAttrib;
-#define X_WINDOW_TO_TEXTURE_SPACE(w, _x) ((w)->texture.dx * (_x))
-#define Y_WINDOW_TO_TEXTURE_SPACE(w, _y) \
- ((w)->texture.dy * ((w)->height - (_y)))
+typedef struct _CompMatrix {
+ float xx; float yx;
+ float xy; float yy;
+ float x0; float y0;
+} CompMatrix;
+
+#define COMP_TEX_COORD_X(m, vx, vy) ((m)->xx * (vx) + (m)->yx * (vy) + (m)->x0)
+#define COMP_TEX_COORD_Y(m, vx, vy) ((m)->xy * (vx) + (m)->yy * (vy) + (m)->y0)
typedef void (*PreparePaintScreenProc) (CompScreen *screen,
int msSinceLastPaint);
@@ -457,13 +464,22 @@ typedef void (*PaintTransformedScreenProc) (CompScreen *screen,
#define PAINT_WINDOW_SOLID_MASK (1 << 0)
#define PAINT_WINDOW_TRANSLUCENT_MASK (1 << 1)
-#define PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK (1 << 2)
+#define PAINT_WINDOW_TRANSFORMED_MASK (1 << 2)
+#define PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK (1 << 3)
typedef Bool (*PaintWindowProc) (CompWindow *window,
const WindowPaintAttrib *attrib,
Region region,
unsigned int mask);
+typedef void (*AddWindowGeometryProc) (CompWindow *window,
+ CompMatrix *matrix,
+ int nMatrix,
+ Region region,
+ Region clip);
+
+typedef void (*DrawWindowGeometryProc) (CompWindow *window);
+
#define PAINT_BACKGROUND_ON_TRANSFORMED_SCREEN_MASK (1 << 0)
#define PAINT_BACKGROUND_WITH_STENCIL_MASK (1 << 1)
@@ -493,6 +509,24 @@ paintScreen (CompScreen *screen,
unsigned int mask);
Bool
+moreWindowVertices (CompWindow *w,
+ int newSize);
+
+Bool
+moreWindowIndices (CompWindow *w,
+ int newSize);
+
+void
+addWindowGeometry (CompWindow *w,
+ CompMatrix *matrix,
+ int nMatrix,
+ Region region,
+ Region clip);
+
+void
+drawWindowGeometry (CompWindow *w);
+
+Bool
paintWindow (CompWindow *w,
const WindowPaintAttrib *attrib,
Region region,
@@ -519,6 +553,7 @@ struct _CompTexture {
GLfloat dx, dy;
GLXPixmap pixmap;
CompTextureFilter filter;
+ CompMatrix matrix;
};
void
@@ -584,16 +619,20 @@ typedef Bool (*GLXQueryDrawableProc) (Display *display,
int attribute,
unsigned int *value);
+typedef void (*GLActiveTextureProc) (GLenum texture);
+typedef void (*GLClientActiveTextureProc) (GLenum texture);
+
+
#define MAX_DEPTH 32
typedef CompOption *(*GetScreenOptionsProc) (CompScreen *screen,
int *count);
typedef Bool (*SetScreenOptionProc) (CompScreen *screen,
- char *name,
+ char *name,
CompOptionValue *value);
typedef Bool (*SetScreenOptionForPluginProc) (CompScreen *screen,
- char *plugin,
- char *name,
+ char *plugin,
+ char *name,
CompOptionValue *value);
typedef Bool (*InitPluginForScreenProc) (CompPlugin *plugin,
@@ -606,6 +645,12 @@ typedef void (*InvisibleWindowMoveProc) (CompWindow *w,
int dx,
int dy);
+typedef Bool (*DamageWindowRectProc) (CompWindow *w,
+ Bool initial,
+ BoxPtr rect);
+
+typedef Bool (*DamageWindowRegionProc) (CompWindow *w,
+ Region region);
typedef struct _CompKeyGrab {
int keycode;
@@ -647,13 +692,13 @@ struct _CompScreen {
XVisualInfo *glxPixmapVisuals[MAX_DEPTH + 1];
int textureRectangle;
int textureNonPowerOfTwo;
+ int textureEnvCombine;
+ int maxTextureUnits;
Cursor invisibleCursor;
XRectangle *exposeRects;
int sizeExpose;
int nExpose;
CompTexture backgroundTexture;
- int backgroundWidth;
- int backgroundHeight;
unsigned int pendingDestroys;
int desktopWindowCount;
KeyCode escapeKeyCode;
@@ -666,9 +711,9 @@ struct _CompScreen {
CompGrab *grabs;
int grabSize;
int maxGrab;
-
+
int rasterX;
- int rasterY;
+ int rasterY;
struct timeval lastRedraw;
int nextRedraw;
int redrawTime;
@@ -676,12 +721,15 @@ struct _CompScreen {
GLint stencilRef;
Window activeWindow;
-
+
GLXGetProcAddressProc getProcAddress;
GLXBindTexImageProc bindTexImage;
GLXReleaseTexImageProc releaseTexImage;
GLXQueryDrawableProc queryDrawable;
+ GLActiveTextureProc activeTexture;
+ GLClientActiveTextureProc clientActiveTexture;
+
GLXContext ctx;
CompOption opt[COMP_SCREEN_OPTION_NUM];
@@ -698,7 +746,11 @@ struct _CompScreen {
PaintTransformedScreenProc paintTransformedScreen;
PaintBackgroundProc paintBackground;
PaintWindowProc paintWindow;
+ AddWindowGeometryProc addWindowGeometry;
+ DrawWindowGeometryProc drawWindowGeometry;
InvisibleWindowMoveProc invisibleWindowMove;
+ DamageWindowRectProc damageWindowRect;
+ DamageWindowRegionProc damageWindowRegion;
CompPrivate *privates;
};
@@ -773,8 +825,9 @@ updatePassiveGrabs (CompScreen *s);
/* window.c */
-#define WINDOW_INVISIBLE(w) \
+#define WINDOW_INVISIBLE(w) \
((w)->attrib.map_state != IsViewable || \
+ (!(w)->damaged) || \
(w)->attrib.x + (w)->width <= 0 || \
(w)->attrib.y + (w)->height <= 0 || \
(w)->attrib.x >= (w)->screen->width || \
@@ -796,6 +849,7 @@ struct _CompWindow {
XWindowAttributes attrib;
Pixmap pixmap;
CompTexture texture;
+ CompMatrix matrix;
Damage damage;
Bool alpha;
GLint width;
@@ -806,7 +860,15 @@ struct _CompWindow {
Bool invisible;
GLushort opacity;
Bool destroyed;
-
+ Bool damaged;
+
+ GLfloat *vertices;
+ int vertexSize;
+ GLushort *indices;
+ int indexSize;
+ int vCount;
+ int texUnits;
+
CompPrivate *privates;
};
@@ -867,6 +929,15 @@ circulateWindow (CompWindow *w,
void
addWindowDamage (CompWindow *w);
+Bool
+damageWindowRect (CompWindow *w,
+ Bool initial,
+ BoxPtr rect);
+
+Bool
+damageWindowRegion (CompWindow *w,
+ Region region);
+
void
invisibleWindowMove (CompWindow *w,
int dx,
@@ -882,7 +953,7 @@ typedef struct _CompPluginVTable {
char *name;
char *shortDesc;
char *longDesc;
-
+
InitPluginProc init;
FiniPluginProc fini;
diff --git a/plugins/.cvsignore b/plugins/.cvsignore
new file mode 100644
index 0000000..6e5ca7e
--- /dev/null
+++ b/plugins/.cvsignore
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+.deps
+.libs
+*.lo
+*.la
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 73cc860..827fc3d 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -22,6 +22,10 @@ libwobbly_la_LDFLAGS = -avoid-version
libwobbly_la_LIBADD = @GLXCOMP_LIBS@
libwobbly_la_SOURCES = wobbly.c
+libshadow_la_LDFLAGS = -avoid-version
+libshadow_la_LIBADD = @GLXCOMP_LIBS@
+libshadow_la_SOURCES = shadow.c
+
if GCONF_PLUGIN
libgconf_la_LDFLAGS = -avoid-version
libgconf_la_LIBADD = @GLXCOMP_LIBS@ @GCONF_LIBS@
@@ -46,4 +50,5 @@ module_LTLIBRARIES = \
libzoom.la \
libexpose.la \
libwobbly.la \
+ libshadow.la \
$(libgconf_library)
diff --git a/plugins/cube.c b/plugins/cube.c
index 03bb793..4845548 100644
--- a/plugins/cube.c
+++ b/plugins/cube.c
@@ -336,7 +336,9 @@ cubeTranslateWindows (CompScreen *s,
int tx)
{
CompWindow *w;
+ int m, wx;
+ tx = MOD (tx, s->width * 4);
if (tx == 0)
return;
@@ -349,7 +351,15 @@ cubeTranslateWindows (CompScreen *s,
w->type == s->display->winDockAtom)
continue;
- (*s->invisibleWindowMove) (w, tx, 0);
+ m = w->attrib.x + tx;
+ if (m < s->width * -3)
+ wx = s->width * 4 + tx;
+ else if (m > s->width * 3)
+ wx = tx - s->width * 4;
+ else
+ wx = tx;
+
+ (*s->invisibleWindowMove) (w, wx, 0);
}
}
@@ -371,7 +381,7 @@ cubePaintTransformedScreen (CompScreen *s,
if (sAttrib->xRotate > 0.0f)
{
cs->xrotations = (int) sAttrib->xRotate / 90;
- sa.xRotate = sAttrib->xRotate - (cs->xrotations * 90.0f);
+ sa.xRotate = (sAttrib->xRotate - cs->xrotations * 90.0f);
}
else
{
@@ -399,12 +409,13 @@ cubePaintTransformedScreen (CompScreen *s,
if (sAttrib->xRotate != 0.0f)
{
xMove = cs->xrotations * s->width;
- cubeTranslateWindows (s, xMove);
+ cubeTranslateWindows (s, xMove);
(*s->paintTransformedScreen) (s, &sa, wAttrib, mask);
+ cubeTranslateWindows (s, -xMove);
xMove += s->width;
- cubeTranslateWindows (s, s->width);
+ cubeTranslateWindows (s, xMove);
cs->paintTopBottom = FALSE;
}
@@ -448,8 +459,6 @@ cubePaintBackground (CompScreen *s,
rot = 2 * cs->xrotations;
-#define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
-
data[0] = cs->tc[MOD (0 - rot, 8)];
data[1] = cs->tc[MOD (1 - rot, 8)];
data[5] = cs->tc[MOD (2 - rot, 8)];
@@ -460,8 +469,6 @@ cubePaintBackground (CompScreen *s,
data[15] = cs->tc[MOD (6 - rot, 8)];
data[16] = cs->tc[MOD (7 - rot, 8)];
-#undef MOD
-
first = 0;
glVertexPointer (3, GL_FLOAT, sizeof (GLfloat) * 5, data + 2);
diff --git a/plugins/expose.c b/plugins/expose.c
index 62900d4..3d21a0e 100644
--- a/plugins/expose.c
+++ b/plugins/expose.c
@@ -79,6 +79,7 @@ typedef struct _ExposeScreen {
DonePaintScreenProc donePaintScreen;
PaintScreenProc paintScreen;
PaintWindowProc paintWindow;
+ DamageWindowRectProc damageWindowRect;
CompOption opt[EXPOSE_SCREEN_OPTION_NUM];
@@ -274,6 +275,8 @@ exposePaintWindow (CompWindow *w,
exposeAttrib.xScale *= ew->scale;
exposeAttrib.yScale *= ew->scale;
+ mask |= PAINT_WINDOW_TRANSFORMED_MASK;
+
UNWRAP (es, s, paintWindow);
status = (*s->paintWindow) (w, &exposeAttrib, region, mask);
WRAP (es, s, paintWindow, exposePaintWindow);
@@ -861,16 +864,20 @@ exposeHandleEvent (CompDisplay *d,
UNWRAP (ed, d, handleEvent);
(*d->handleEvent) (d, event);
WRAP (ed, d, handleEvent, exposeHandleEvent);
+}
- switch (event->type) {
- case CreateNotify:
- case MapNotify: {
- CompWindow *w;
+static Bool
+exposeDamageWindowRect (CompWindow *w,
+ Bool initial,
+ BoxPtr rect)
+{
+ Bool status;
+
+ EXPOSE_SCREEN (w->screen);
- w = findWindowAtDisplay (d, (event->type == CreateNotify) ?
- event->xcreatewindow.window :
- event->xmap.window);
- if (w && isExposeWin (w))
+ if (initial)
+ {
+ if (isExposeWin (w))
{
EXPOSE_SCREEN (w->screen);
@@ -882,11 +889,15 @@ exposeHandleEvent (CompDisplay *d,
}
}
}
- default:
- break;
- }
+
+ UNWRAP (es, w->screen, damageWindowRect);
+ status = (*w->screen->damageWindowRect) (w, initial, rect);
+ WRAP (es, w->screen, damageWindowRect, exposeDamageWindowRect);
+
+ return status;
}
+
static Bool
exposeInitDisplay (CompPlugin *p,
CompDisplay *d)
@@ -968,6 +979,7 @@ exposeInitScreen (CompPlugin *p,
WRAP (es, s, donePaintScreen, exposeDonePaintScreen);
WRAP (es, s, paintScreen, exposePaintScreen);
WRAP (es, s, paintWindow, exposePaintWindow);
+ WRAP (es, s, damageWindowRect, exposeDamageWindowRect);
es->cursor = XCreateFontCursor (s->display->display, XC_left_ptr);
@@ -986,6 +998,7 @@ exposeFiniScreen (CompPlugin *p,
UNWRAP (es, s, donePaintScreen);
UNWRAP (es, s, paintScreen);
UNWRAP (es, s, paintWindow);
+ UNWRAP (es, s, damageWindowRect);
if (es->slotsSize)
free (es->slots);
diff --git a/plugins/fade.c b/plugins/fade.c
index 86eb398..703f0a7 100644
--- a/plugins/fade.c
+++ b/plugins/fade.c
@@ -51,6 +51,7 @@ typedef struct _FadeScreen {
PreparePaintScreenProc preparePaintScreen;
PaintWindowProc paintWindow;
+ DamageWindowRectProc damageWindowRect;
} FadeScreen;
typedef struct _FadeWindow {
@@ -263,15 +264,14 @@ fadeHandleEvent (CompDisplay *d,
}
break;
case MapNotify:
- w = findWindowAtDisplay (d, event->xmap.window);
+ w = findWindowAtDisplay (d, event->xunmap.window);
if (w)
{
FADE_WINDOW (w);
- if (!fw->direction)
- fw->opacity = 1;
-
- fw->direction = 1;
+ /* make sure any pending unmap are processed */
+ if (fw->direction < 0)
+ unmapWindow (w);
}
default:
break;
@@ -283,7 +283,33 @@ fadeHandleEvent (CompDisplay *d,
}
static Bool
-fadeInitDisplay (CompPlugin *p,
+fadeDamageWindowRect (CompWindow *w,
+ Bool initial,
+ BoxPtr rect)
+{
+ Bool status;
+
+ FADE_SCREEN (w->screen);
+
+ if (initial)
+ {
+ FADE_WINDOW (w);
+
+ if (!fw->direction)
+ fw->opacity = 1;
+
+ fw->direction = 1;
+ }
+
+ UNWRAP (fs, w->screen, damageWindowRect);
+ status = (*w->screen->damageWindowRect) (w, initial, rect);
+ WRAP (fs, w->screen, damageWindowRect, fadeDamageWindowRect);
+
+ return status;
+}
+
+static Bool
+fadeInitDisplay (CompPlugin *p,
CompDisplay *d)
{
FadeDisplay *fd;
@@ -345,6 +371,7 @@ fadeInitScreen (CompPlugin *p,
WRAP (fs, s, preparePaintScreen, fadePreparePaintScreen);
WRAP (fs, s, paintWindow, fadePaintWindow);
+ WRAP (fs, s, damageWindowRect, fadeDamageWindowRect);
s->privates[fd->screenPrivateIndex].ptr = fs;
@@ -361,6 +388,7 @@ fadeFiniScreen (CompPlugin *p,
UNWRAP (fs, s, preparePaintScreen);
UNWRAP (fs, s, paintWindow);
+ UNWRAP (fs, s, damageWindowRect);
free (fs);
}
diff --git a/plugins/gconf.c b/plugins/gconf.c
index 9f0a342..3661166 100644
--- a/plugins/gconf.c
+++ b/plugins/gconf.c
@@ -1,6 +1,6 @@
/*
* Copyright © 2005 Novell, Inc.
- *
+ *
* 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
@@ -12,11 +12,11 @@
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
- * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL NOVELL, INC. 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,
+ * 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.
*
@@ -68,7 +68,7 @@ typedef struct _GConfDisplay {
GConfClient *client;
CompTimeoutHandle timeoutHandle;
-
+
InitPluginForDisplayProc initPluginForDisplay;
SetDisplayOptionProc setDisplayOption;
SetDisplayOptionForPluginProc setDisplayOptionForPlugin;
@@ -163,7 +163,7 @@ gconfSetValue (CompDisplay *d,
} break;
case CompOptionTypeBinding: {
guint modMask;
-
+
if (value->bind.type == CompBindingTypeButton)
modMask = value->bind.u.button.modifiers;
else
@@ -174,7 +174,7 @@ gconfSetValue (CompDisplay *d,
gchar *m, *mods = g_strdup ("");
gchar *binding;
gint i;
-
+
for (i = 0; i < N_MODIFIERS; i++)
{
if (modMask & modifiers[i].modifier)
@@ -187,7 +187,7 @@ gconfSetValue (CompDisplay *d,
}
}
}
-
+
if (value->bind.type == CompBindingTypeButton)
{
binding = g_strdup_printf ("%sButton%d", mods,
@@ -202,11 +202,11 @@ gconfSetValue (CompDisplay *d,
value->bind.u.key.keycode,
0);
keyname = XKeysymToString (keysym);
-
+
binding = g_strdup_printf ("%s%s", mods,
(keyname) ? keyname : "??");
}
-
+
gconf_value_set_string (gvalue, binding);
g_free (binding);
@@ -230,7 +230,7 @@ gconfSetOption (CompDisplay *d,
{
GConfValue *gvalue;
gchar *key;
-
+
GCONF_DISPLAY (d);
if (plugin)
@@ -263,9 +263,9 @@ gconfSetOption (CompDisplay *d,
int i;
gvalue = gconf_value_new (GCONF_VALUE_LIST);
-
+
type = gconfTypeFromCompType (o->value.list.type);
-
+
for (i = 0; i < o->value.list.nValue; i++)
{
gv = gconf_value_new (type);
@@ -288,7 +288,7 @@ gconfSetOption (CompDisplay *d,
default:
break;
}
-
+
g_free (key);
}
@@ -328,9 +328,9 @@ gconfGetValue (CompDisplay *d,
{
const gchar *color;
gint c[3];
-
+
color = gconf_value_get_string (gvalue);
-
+
if (sscanf (color, "#%2x%2x%2x", &c[0], &c[1], &c[2]) == 3)
{
value->c[0] = c[0] * 256;
@@ -347,7 +347,7 @@ gconfGetValue (CompDisplay *d,
gchar *binding, *ptr;
gint i;
guint mods = 0;
-
+
binding = (gchar *) gconf_value_get_string (gvalue);
if (strcasecmp (binding, "disabled") == 0)
{
@@ -371,14 +371,14 @@ gconfGetValue (CompDisplay *d,
ptr = strrchr (binding, '>');
if (ptr)
binding = ptr + 1;
-
+
while (*binding && !isalpha (*binding))
binding++;
-
+
if (strcmpskipifequal (&binding, "Button") == 0)
{
gint button;
-
+
if (sscanf (binding, "%d", &button) == 1)
{
value->bind.type = CompBindingTypeButton;
@@ -391,26 +391,26 @@ gconfGetValue (CompDisplay *d,
else
{
KeySym keysym;
-
+
keysym = XStringToKeysym (binding);
if (keysym != NoSymbol)
{
KeyCode keycode;
-
+
keycode = XKeysymToKeycode (d->display, keysym);
if (keycode)
{
value->bind.type = CompBindingTypeKey;
value->bind.u.key.keycode = keycode;
value->bind.u.key.modifiers = mods;
-
+
return TRUE;
}
}
}
}
}
-
+
return FALSE;
}
@@ -429,7 +429,7 @@ gconfGetOptionValue (CompDisplay *d,
if (!entry)
return FALSE;
-
+
ptr = entry->key;
if (strncmp (ptr, APP_NAME, strlen (APP_NAME)))
return FALSE;
@@ -453,13 +453,13 @@ gconfGetOptionValue (CompDisplay *d,
if (strcmpskipifequal (&ptr, "/screen") == 0)
{
int screenNum;
-
+
screenNum = strtol (ptr, &ptr, 0);
for (s = d->screens; s; s = s->next)
if (s->screenNum == screenNum)
break;
-
+
if (!s || !ptr)
return FALSE;
}
@@ -468,19 +468,19 @@ gconfGetOptionValue (CompDisplay *d,
if (strcmpskipifequal (&ptr, "/options/"))
return FALSE;
-
+
optionPtr = ptr;
ptr = strchr (ptr, '/');
if (!ptr)
return FALSE;
-
+
optionLen = ptr - optionPtr;
if (optionLen < 1)
return FALSE;
if (strcmp (ptr, "/value") != 0)
return FALSE;
-
+
if (pluginPtr)
{
pluginPtr = g_strndup (pluginPtr, pluginLen);
@@ -518,7 +518,7 @@ gconfGetOptionValue (CompDisplay *d,
{
GConfValue *gvalue;
CompOptionValue value;
-
+
gvalue = gconf_entry_get_value (entry);
if (gvalue)
{
@@ -555,7 +555,7 @@ gconfGetOptionValue (CompDisplay *d,
o->value.list.type,
(GConfValue *) list->data))
status = FALSE;
-
+
list = g_slist_next (list);
}
}
@@ -570,7 +570,7 @@ gconfGetOptionValue (CompDisplay *d,
{
status = gconfGetValue (d, &value, o->type, gvalue);
}
-
+
if (status)
{
if (s)
@@ -603,7 +603,7 @@ gconfGetOptionValue (CompDisplay *d,
}
}
}
-
+
g_free (optionPtr);
if (pluginPtr)
g_free (pluginPtr);
@@ -640,14 +640,14 @@ gconfInitOption (CompDisplay *d,
key = g_strconcat (gconfpath, "/long_description", NULL);
gconf_client_set_string (gd->client, key, o->longDesc, NULL);
- g_free (key);
+ g_free (key);
key = g_strconcat (gconfpath, "/type", NULL);
type = o->type;
if (type == CompOptionTypeList)
type = o->value.list.type;
-
+
switch (type) {
case CompOptionTypeBool:
gconf_client_set_string (gd->client, key, "Bool", NULL);
@@ -717,13 +717,13 @@ gconfInitOption (CompDisplay *d,
case CompOptionTypeString: {
GSList *list = NULL;
int i;
-
+
for (i = 0; i < o->rest.s.nString; i++)
list = g_slist_append (list, o->rest.s.string[i]);
-
+
gconf_client_set_list (gd->client, key, GCONF_VALUE_STRING, list,
NULL);
-
+
g_slist_free (list);
} break;
default:
@@ -734,7 +734,7 @@ gconfInitOption (CompDisplay *d,
key = g_strconcat (gconfpath, "/value", NULL);
entry = gconf_client_get_entry (gd->client, key, NULL, FALSE, NULL);
-
+
if (!gconfGetOptionValue (d, entry))
gconfSetOption (d, o, screen, plugin);
@@ -774,7 +774,7 @@ gconfSetDisplayOption (CompDisplay *d,
Bool status;
GCONF_DISPLAY (d);
-
+
UNWRAP (gd, d, setDisplayOption);
status = (*d->setDisplayOption) (d, name, value);
WRAP (gd, d, setDisplayOption, gconfSetDisplayOption);
@@ -783,12 +783,12 @@ gconfSetDisplayOption (CompDisplay *d,
{
CompOption *option;
int nOption;
-
+
option = compGetDisplayOptions (d, &nOption);
gconfSetOption (d, compFindOption (option, nOption, name, 0),
"allscreens", 0);
}
-
+
return status;
}
@@ -809,19 +809,19 @@ gconfSetDisplayOptionForPlugin (CompDisplay *d,
if (status)
{
CompPlugin *p;
-
+
p = findActivePlugin (plugin);
if (p && p->vTable->getDisplayOptions)
{
CompOption *option;
int nOption;
-
+
option = (*p->vTable->getDisplayOptions) (d, &nOption);
gconfSetOption (d, compFindOption (option, nOption, name, 0),
"allscreens", plugin);
}
}
-
+
return status;
}
@@ -844,15 +844,15 @@ gconfSetScreenOption (CompScreen *s,
int nOption;
gchar *screen;
- screen = g_strdup_printf ("screen%d", s->screenNum);
-
+ screen = g_strdup_printf ("screen%d", s->screenNum);
+
option = compGetScreenOptions (s, &nOption);
gconfSetOption (s->display, compFindOption (option, nOption, name, 0),
screen, 0);
g_free (screen);
}
-
+
return status;
}
@@ -873,14 +873,14 @@ gconfSetScreenOptionForPlugin (CompScreen *s,
if (status)
{
CompPlugin *p;
-
+
p = findActivePlugin (plugin);
if (p && p->vTable->getScreenOptions)
{
CompOption *option;
int nOption;
gchar *screen;
-
+
screen = g_strdup_printf ("screen%d", s->screenNum);
option = (*p->vTable->getScreenOptions) (s, &nOption);
@@ -891,7 +891,7 @@ gconfSetScreenOptionForPlugin (CompScreen *s,
g_free (screen);
}
}
-
+
return status;
}
@@ -914,7 +914,7 @@ gconfInitPluginForDisplay (CompPlugin *p,
{
CompOption *option;
int nOption;
-
+
option = (*p->vTable->getDisplayOptions) (d, &nOption);
while (nOption--)
gconfInitOption (d, option++, "allscreens", p->vTable->name);
@@ -946,7 +946,7 @@ gconfInitPluginForScreen (CompPlugin *p,
option = (*p->vTable->getScreenOptions) (s, &nOption);
while (nOption--)
gconfInitOption (s->display, option++, screen, p->vTable->name);
-
+
g_free (screen);
}
@@ -960,7 +960,7 @@ gconfKeyChanged (GConfClient *client,
gpointer user_data)
{
CompDisplay *display = (CompDisplay *) user_data;
-
+
gconfGetOptionValue (display, entry);
}
@@ -968,7 +968,7 @@ static Bool
gconfTimeout (void *closure)
{
while (g_main_pending ()) g_main_iteration (FALSE);
-
+
return TRUE;
}
@@ -979,7 +979,7 @@ gconfInitDisplay (CompPlugin *p,
CompOption *option;
int nOption;
GConfDisplay *gd;
-
+
gd = malloc (sizeof (GConfDisplay));
if (!gd)
return FALSE;
@@ -992,7 +992,7 @@ gconfInitDisplay (CompPlugin *p,
}
gd->client = gconf_client_get_default ();
-
+
gconf_client_add_dir (gd->client, APP_NAME,
GCONF_CLIENT_PRELOAD_NONE, NULL);
@@ -1010,7 +1010,7 @@ gconfInitDisplay (CompPlugin *p,
NULL, NULL);
gd->timeoutHandle = compAddTimeout (KEY_CHANGE_TIMEOUT, gconfTimeout, 0);
-
+
return TRUE;
}
@@ -1025,7 +1025,7 @@ gconfFiniDisplay (CompPlugin *p,
g_object_unref (gd->client);
freeScreenPrivateIndex (d, gd->screenPrivateIndex);
-
+
free (gd);
}
@@ -1036,7 +1036,7 @@ gconfInitScreen (CompPlugin *p,
CompOption *option;
int nOption;
GConfScreen *gs;
- gchar *screen;
+ gchar *screen;
GCONF_DISPLAY (s->display);
@@ -1055,7 +1055,7 @@ gconfInitScreen (CompPlugin *p,
option = compGetScreenOptions (s, &nOption);
while (nOption--)
gconfInitOption (s->display, option++, screen, 0);
-
+
return TRUE;
}
@@ -1074,10 +1074,10 @@ gconfInit (CompPlugin *p)
displayPrivateIndex = allocateDisplayPrivateIndex ();
if (displayPrivateIndex < 0)
return FALSE;
-
+
return TRUE;
}
-
+
static void
gconfFini (CompPlugin *p)
{
diff --git a/plugins/rotate.c b/plugins/rotate.c
index 1202227..53e03d4 100644
--- a/plugins/rotate.c
+++ b/plugins/rotate.c
@@ -371,18 +371,22 @@ rotatePreparePaintScreen (CompScreen *s,
if (fabs (rs->yrot) < 0.1f)
{
- int move;
+ float xrot;
+ int tx, m, wx;
- rs->xrot += rs->baseXrot;
- if (rs->xrot < 0.0f)
- move = (rs->xrot / 90.0f) - 0.5f;
+ xrot = rs->baseXrot + rs->xrot;
+ if (xrot < 0.0f)
+ tx = ((xrot / 90.0f) - 0.5f);
else
- move = (rs->xrot / 90.0f) + 0.5f;
+ tx = ((xrot / 90.0f) + 0.5f);
- if (move)
+ tx = MOD (tx, 4);
+ if (tx)
{
CompWindow *w;
+ tx *= s->width;
+
for (w = s->windows; w; w = w->next)
{
if (w->attrib.map_state != IsViewable)
@@ -392,7 +396,15 @@ rotatePreparePaintScreen (CompScreen *s,
w->type == s->display->winDockAtom)
continue;
- (*s->invisibleWindowMove) (w, s->width * move, 0);
+ m = w->attrib.x + tx;
+ if (m < s->width * -3)
+ wx = s->width * 4 + tx;
+ else if (m > s->width * 3)
+ wx = tx - s->width * 4;
+ else
+ wx = tx;
+
+ (*s->invisibleWindowMove) (w, wx, 0);
w->invisible = WINDOW_INVISIBLE (w);
@@ -555,6 +567,7 @@ static void
rotateHandleEvent (CompDisplay *d,
XEvent *event)
{
+ Window activeWindow = 0;
CompScreen *s;
ROTATE_DISPLAY (d);
@@ -647,6 +660,16 @@ rotateHandleEvent (CompDisplay *d,
return;
}
}
+ break;
+ case PropertyNotify:
+ if (event->xproperty.atom == d->winActiveAtom)
+ {
+ CompScreen *s;
+
+ s = findScreenAtDisplay (d, event->xproperty.window);
+ if (s)
+ activeWindow = s->activeWindow;
+ }
default:
break;
}
@@ -654,6 +677,47 @@ rotateHandleEvent (CompDisplay *d,
UNWRAP (rd, d, handleEvent);
(*d->handleEvent) (d, event);
WRAP (rd, d, handleEvent, rotateHandleEvent);
+
+ switch (event->type) {
+ case PropertyNotify:
+ if (event->xproperty.atom == d->winActiveAtom)
+ {
+ CompScreen *s;
+
+ s = findScreenAtDisplay (d, event->xproperty.window);
+ if (s && s->activeWindow != activeWindow)
+ {
+ CompWindow *w;
+
+ w = findClientWindowAtScreen (s, s->activeWindow);
+ if (w)
+ {
+ Window win;
+ int i, x, y, wx;
+ unsigned int ui;
+
+ XQueryPointer (d->display, s->root,
+ &win, &win, &x, &y, &i, &i, &ui);
+
+ if (w->attrib.x > s->width)
+ {
+ wx = w->attrib.x / s->width;
+ while (wx--)
+ rotateRight (s, x, y);
+
+ }
+ else if (w->attrib.x + w->width < 0)
+ {
+ wx = 1 - (w->attrib.x + w->width) / s->width;
+ while (wx--)
+ rotateLeft (s, x, y);
+ }
+ }
+ }
+ }
+ default:
+ break;
+ }
}
static Bool
diff --git a/plugins/shadow.c b/plugins/shadow.c
new file mode 100644
index 0000000..b3dbd3f
--- /dev/null
+++ b/plugins/shadow.c
@@ -0,0 +1,902 @@
+/*
+ * Copyright © 2005 Novell, Inc.
+ *
+ * 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
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <comp.h>
+
+#define SHADOW_RADIUS_DEFAULT 6.0f
+#define SHADOW_RADIUS_MIN 0.1f
+#define SHADOW_RADIUS_MAX 50.0f
+#define SHADOW_RADIUS_PRECISION 0.1f
+
+#define SHADOW_OPACITY_DEFAULT 0.75f
+#define SHADOW_OPACITY_MIN 0.01f
+#define SHADOW_OPACITY_MAX 1.0f
+#define SHADOW_OPACITY_PRECISION 0.01f
+
+#define SHADOW_EXPAND_DEFAULT 8
+#define SHADOW_EXPAND_MIN 0
+#define SHADOW_EXPAND_MAX 100
+
+#define SHADOW_OFFSET_X_DEFAULT 2
+#define SHADOW_OFFSET_X_MIN -50
+#define SHADOW_OFFSET_X_MAX 50
+
+#define SHADOW_OFFSET_Y_DEFAULT 2
+#define SHADOW_OFFSET_Y_MIN -50
+#define SHADOW_OFFSET_Y_MAX 50
+
+static int displayPrivateIndex;
+
+typedef struct _ShadowDisplay {
+ int screenPrivateIndex;
+} ShadowDisplay;
+
+#define SHADOW_SCREEN_OPTION_RADIUS 0
+#define SHADOW_SCREEN_OPTION_OPACITY 1
+#define SHADOW_SCREEN_OPTION_EXPAND 2
+#define SHADOW_SCREEN_OPTION_OFFSET_X 3
+#define SHADOW_SCREEN_OPTION_OFFSET_Y 4
+#define SHADOW_SCREEN_OPTION_NUM 5
+
+typedef struct _ShadowScreen {
+ CompOption opt[SHADOW_SCREEN_OPTION_NUM];
+
+ GLenum target;
+ GLuint texture;
+ float dx, dy;
+
+ int size;
+ int expand;
+ int xOffset;
+ int yOffset;
+
+ PaintWindowProc paintWindow;
+ DamageWindowRegionProc damageWindowRegion;
+ DamageWindowRectProc damageWindowRect;
+} ShadowScreen;
+
+#define GET_SHADOW_DISPLAY(d) \
+ ((ShadowDisplay *) (d)->privates[displayPrivateIndex].ptr)
+
+#define SHADOW_DISPLAY(d) \
+ ShadowDisplay *sd = GET_SHADOW_DISPLAY (d)
+
+#define GET_SHADOW_SCREEN(s, sd) \
+ ((ShadowScreen *) (s)->privates[(sd)->screenPrivateIndex].ptr)
+
+#define SHADOW_SCREEN(s) \
+ ShadowScreen *ss = GET_SHADOW_SCREEN (s, GET_SHADOW_DISPLAY (s->display))
+
+#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
+
+#define SHADOW_WINDOW(w) ((w)->type != (w)->screen->display->winDesktopAtom)
+
+static float
+gaussian (float r,
+ float x,
+ float y)
+{
+ return (1 / (sqrt (2 * M_PI * r))) * exp ((- (x * x + y * y)) / (2 * r * r));
+}
+
+typedef struct _ShadowMap {
+ int size;
+ float *data;
+} ShadowMap;
+
+static ShadowMap *
+shadowCreateGaussianMap (float r)
+{
+ ShadowMap *m;
+ int size = ((int) ceil ((r * 3)) + 1) & ~1;
+ int center = size / 2;
+ int x, y;
+ float t, g;
+
+ m = malloc (sizeof (ShadowMap) + size * size * sizeof (float));
+ m->size = size;
+ m->data = (float *) (m + 1);
+ t = 0.0;
+
+ for (y = 0; y < size; y++)
+ {
+ for (x = 0; x < size; x++)
+ {
+ g = gaussian (r, (float) (x - center), (float) (y - center));
+ t += g;
+ m->data[y * size + x] = g;
+ }
+ }
+
+ for (y = 0; y < size; y++)
+ {
+ for (x = 0; x < size; x++)
+ {
+ m->data[y * size + x] /= t;
+ }
+ }
+
+ return m;
+}
+
+static unsigned char
+shadowSumGaussian (ShadowMap *map,
+ float opacity,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ int fx, fy;
+ float *g_data;
+ float *g_line = map->data;
+ int g_size = map->size;
+ int center = g_size / 2;
+ int fx_start, fx_end;
+ int fy_start, fy_end;
+ float 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));
+}
+
+static unsigned char *
+shadowCreateImage (ShadowMap *map,
+ float opacity,
+ int *w,
+ int *h)
+{
+ unsigned char *data;
+ int gsize = map->size;
+ int width = gsize;
+ int height = gsize;
+ int ylimit, xlimit;
+ int swidth = width + gsize;
+ int sheight = height + gsize;
+ int center = gsize / 2;
+ int x, y;
+ unsigned char d;
+ int x_diff;
+
+ *w = swidth;
+ *h = sheight;
+
+ data = malloc (swidth * sheight * sizeof (unsigned char));
+ if (!data)
+ return 0;
+
+ /* center (fill the complete data array) */
+ d = shadowSumGaussian (map, 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++)
+ {
+ d = shadowSumGaussian (map, 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++)
+ {
+ d = shadowSumGaussian (map, 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++)
+ {
+ d = shadowSumGaussian (map, 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 data;
+}
+
+static void
+shadowComputeGaussian (CompScreen *s,
+ float radius,
+ float opacity)
+{
+ ShadowMap *map;
+ unsigned char *data;
+ int w, h;
+
+ SHADOW_SCREEN (s);
+
+ map = shadowCreateGaussianMap (radius);
+ if (!map)
+ return;
+
+ data = shadowCreateImage (map, opacity, &w, &h);
+ if (!data)
+ {
+ free (map);
+ return;
+ }
+
+ ss->size = map->size;
+
+ if (s->textureNonPowerOfTwo || (POWER_OF_TWO (w) && POWER_OF_TWO (h)))
+ {
+ ss->target = GL_TEXTURE_2D;
+ ss->dx = 1.0f / w;
+ ss->dy = 1.0f / h;
+ }
+ else
+ {
+ ss->target = GL_TEXTURE_RECTANGLE_NV;
+ ss->dx = 1.0f;
+ ss->dy = 1.0f;
+ }
+
+ if (!ss->texture)
+ glGenTextures (1, &ss->texture);
+
+ glBindTexture (ss->target, ss->texture);
+ glTexImage2D (ss->target, 0, GL_INTENSITY, w, h, 0,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
+
+ glTexParameteri (ss->target, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri (ss->target, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+ glTexParameteri (ss->target, GL_TEXTURE_MIN_FILTER,
+ s->display->textureFilter);
+ glTexParameteri (ss->target, GL_TEXTURE_MAG_FILTER,
+ s->display->textureFilter);
+
+ glBindTexture (GL_TEXTURE_2D, 0);
+
+ free (data);
+ free (map);
+}
+
+static CompOption *
+shadowGetScreenOptions (CompScreen *screen,
+ int *count)
+{
+ SHADOW_SCREEN (screen);
+
+ *count = NUM_OPTIONS (ss);
+ return ss->opt;
+}
+
+static Bool
+shadowSetScreenOption (CompScreen *screen,
+ char *name,
+ CompOptionValue *value)
+{
+ CompOption *o;
+ int index;
+
+ SHADOW_SCREEN (screen);
+
+ o = compFindOption (ss->opt, NUM_OPTIONS (ss), name, &index);
+ if (!o)
+ return FALSE;
+
+ switch (index) {
+ case SHADOW_SCREEN_OPTION_RADIUS:
+ if (compSetFloatOption (o, value))
+ {
+ shadowComputeGaussian (screen,
+ o->value.f,
+ ss->opt[SHADOW_SCREEN_OPTION_OPACITY].value.f);
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case SHADOW_SCREEN_OPTION_OPACITY:
+ if (compSetFloatOption (o, value))
+ {
+ shadowComputeGaussian (screen,
+ ss->opt[SHADOW_SCREEN_OPTION_RADIUS].value.f,
+ o->value.f);
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case SHADOW_SCREEN_OPTION_EXPAND:
+ if (compSetIntOption (o, value))
+ {
+ ss->expand = o->value.i;
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case SHADOW_SCREEN_OPTION_OFFSET_X:
+ if (compSetIntOption (o, value))
+ {
+ ss->xOffset = o->value.i;
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case SHADOW_SCREEN_OPTION_OFFSET_Y:
+ if (compSetIntOption (o, value))
+ {
+ ss->yOffset = o->value.i;
+ damageScreen (screen);
+ return TRUE;
+ }
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+shadowScreenInitOptions (ShadowScreen *fs)
+{
+ CompOption *o;
+
+ o = &fs->opt[SHADOW_SCREEN_OPTION_RADIUS];
+ o->name = "radius";
+ o->shortDesc = "Shadow radius";
+ o->longDesc = "Drop shadow gaussian radius";
+ o->type = CompOptionTypeFloat;
+ o->value.f = SHADOW_RADIUS_DEFAULT;
+ o->rest.f.min = SHADOW_RADIUS_MIN;
+ o->rest.f.max = SHADOW_RADIUS_MAX;
+ o->rest.f.precision = SHADOW_RADIUS_PRECISION;
+
+ o = &fs->opt[SHADOW_SCREEN_OPTION_OPACITY];
+ o->name = "opacity";
+ o->shortDesc = "Shadow opacity";
+ o->longDesc = "Drop shadow opacity";
+ o->type = CompOptionTypeFloat;
+ o->value.f = SHADOW_OPACITY_DEFAULT;
+ o->rest.f.min = SHADOW_OPACITY_MIN;
+ o->rest.f.max = SHADOW_OPACITY_MAX;
+ o->rest.f.precision = SHADOW_OPACITY_PRECISION;
+
+ o = &fs->opt[SHADOW_SCREEN_OPTION_EXPAND];
+ o->name = "expand";
+ o->shortDesc = "Shadow expansion";
+ o->longDesc = "Drop shadow expansion";
+ o->type = CompOptionTypeInt;
+ o->value.i = SHADOW_EXPAND_DEFAULT;
+ o->rest.i.min = SHADOW_EXPAND_MIN;
+ o->rest.i.max = SHADOW_EXPAND_MAX;
+
+ o = &fs->opt[SHADOW_SCREEN_OPTION_OFFSET_X];
+ o->name = "shadow_offset_x";
+ o->shortDesc = "Shadow X Offset";
+ o->longDesc = "Drop shadow X offset";
+ o->type = CompOptionTypeInt;
+ o->value.i = SHADOW_OFFSET_X_DEFAULT;
+ o->rest.i.min = SHADOW_OFFSET_X_MIN;
+ o->rest.i.max = SHADOW_OFFSET_X_MAX;
+
+ o = &fs->opt[SHADOW_SCREEN_OPTION_OFFSET_Y];
+ o->name = "shadow_offset_y";
+ o->shortDesc = "Shadow Y Offset";
+ o->longDesc = "Drop shadow Y offset";
+ o->type = CompOptionTypeInt;
+ o->value.i = SHADOW_OFFSET_Y_DEFAULT;
+ o->rest.i.min = SHADOW_OFFSET_Y_MIN;
+ o->rest.i.max = SHADOW_OFFSET_Y_MAX;
+}
+
+static Bool
+shadowDamageWindowRegion (CompWindow *w,
+ Region region)
+{
+ Bool status;
+
+ SHADOW_SCREEN (w->screen);
+
+ UNWRAP (ss, w->screen, damageWindowRegion);
+ status = (*w->screen->damageWindowRegion) (w, region);
+ WRAP (ss, w->screen, damageWindowRegion, shadowDamageWindowRegion);
+
+ if (SHADOW_WINDOW (w))
+ {
+ REGION rect;
+
+ rect.rects = &rect.extents;
+ rect.numRects = rect.size = 1;
+
+ rect.extents.x1 = region->extents.x1 - ss->expand + ss->xOffset;
+ rect.extents.y1 = region->extents.y1 - ss->expand + ss->yOffset;
+ rect.extents.x2 = region->extents.x2 + ss->expand + ss->xOffset;
+ rect.extents.y2 = region->extents.y2 + ss->expand + ss->yOffset;
+
+ damageScreenRegion (w->screen, &rect);
+
+ if (ss->expand >= ss->xOffset && ss->expand >= ss->yOffset)
+ status = TRUE;
+ }
+
+ return status;
+}
+
+static Bool
+shadowDamageWindowRect (CompWindow *w,
+ Bool initial,
+ BoxPtr rect)
+{
+ Bool status;
+
+ SHADOW_SCREEN (w->screen);
+
+ UNWRAP (ss, w->screen, damageWindowRect);
+ status = (*w->screen->damageWindowRect) (w, initial, rect);
+ WRAP (ss, w->screen, damageWindowRect, shadowDamageWindowRect);
+
+ if (SHADOW_WINDOW (w))
+ {
+ REGION region;
+
+ region.rects = &region.extents;
+ region.numRects = region.size = 1;
+
+ if (initial)
+ {
+ region.extents.x1 = w->region->extents.x1 - ss->expand + ss->xOffset;
+ region.extents.y1 = w->region->extents.y1 - ss->expand + ss->yOffset;
+ region.extents.x2 = w->region->extents.x2 + ss->expand + ss->xOffset;
+ region.extents.y2 = w->region->extents.y2 + ss->expand + ss->yOffset;
+ }
+ else if (w->alpha)
+ {
+ region.extents.x1 = rect->x1 - ss->expand + ss->xOffset;
+ region.extents.y1 = rect->y1 - ss->expand + ss->yOffset;
+ region.extents.x2 = rect->x2 + ss->expand + ss->xOffset;
+ region.extents.y2 = rect->y2 + ss->expand + ss->yOffset;
+ }
+ else
+ return status;
+
+ damageScreenRegion (w->screen, &region);
+
+ if (ss->expand >= ss->xOffset && ss->expand >= ss->yOffset)
+ status = TRUE;
+ }
+
+ return status;
+}
+
+static Bool
+shadowPaintWindow (CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ Region region,
+ unsigned int mask)
+{
+ Bool status;
+
+ SHADOW_SCREEN (w->screen);
+
+ if (SHADOW_WINDOW (w) && (!(mask & PAINT_WINDOW_SOLID_MASK)))
+ {
+ CompMatrix matrix[2];
+ GLushort opacity;
+ REGION rect;
+ BoxRec box;
+ int nMatrix = 1;
+
+ opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
+ if (w->alpha || opacity != OPAQUE)
+ mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+ else
+ mask |= PAINT_WINDOW_SOLID_MASK;
+
+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+ region = &infiniteRegion;
+
+ w->vCount = 0;
+
+ box.x1 = w->region->extents.x1 - ss->expand + ss->size;
+ box.y1 = w->region->extents.y1 - ss->expand + ss->size;
+ box.x2 = w->region->extents.x2 + ss->expand - ss->size;
+ box.y2 = w->region->extents.y2 + ss->expand - ss->size;
+
+ /* in case window width is too small */
+ if (box.x1 >= box.x2)
+ {
+ box.x1 = (w->region->extents.x1 + w->region->extents.x2) / 2;
+ box.x2 = box.x1 + 1;
+ }
+
+ /* in case window height is too small */
+ if (box.y1 >= box.y2)
+ {
+ box.y1 = (w->region->extents.y1 + w->region->extents.y2) / 2;
+ box.y2 = box.y1 + 1;
+ }
+
+ if (w->alpha &&
+ w->screen->textureEnvCombine &&
+ w->screen->maxTextureUnits > 1)
+ {
+ if (!w->pixmap)
+ bindWindow (w);
+
+ matrix[1] = w->texture.matrix;
+ matrix[1].x0 -= ((w->attrib.x + ss->xOffset) * w->matrix.xx);
+ matrix[1].y0 -= ((w->attrib.y + ss->yOffset) * w->matrix.yy);
+
+ nMatrix++;
+ }
+
+ rect.rects = &rect.extents;
+ rect.numRects = rect.size = 1;
+
+ /* top left */
+ matrix->xx = ss->dx; matrix->xy = 0.0f;
+ matrix->yx = 0.0f; matrix->yy = ss->dy;
+
+ matrix->x0 = -((box.x1 - ss->size + ss->xOffset) * ss->dx);
+ matrix->y0 = -((box.y1 - ss->size + ss->yOffset) * ss->dy);
+
+ rect.extents.x1 = box.x1 - ss->size + ss->xOffset;
+ rect.extents.y1 = box.y1 - ss->size + ss->yOffset;
+ rect.extents.x2 = rect.extents.x1 + ss->size;
+ rect.extents.y2 = rect.extents.y1 + ss->size;
+
+ (*w->screen->addWindowGeometry) (w, matrix, nMatrix, &rect, region);
+
+ /* top */
+ matrix->xx = 0.0f;
+ matrix->x0 = ss->dx * ss->size;
+
+ rect.extents.x1 = rect.extents.x2;
+ rect.extents.x2 = box.x2 + ss->xOffset;
+
+ (*w->screen->addWindowGeometry) (w, matrix, nMatrix, &rect, region);
+
+ /* top right */
+ matrix->x0 = -((box.x2 - ss->size + ss->xOffset) * ss->dx);
+ matrix->xx = ss->dx;
+
+ rect.extents.x1 = rect.extents.x2;
+ rect.extents.x2 = box.x2 + ss->size + ss->xOffset;
+
+ (*w->screen->addWindowGeometry) (w, matrix, nMatrix, &rect, region);
+
+ /* left */
+ matrix->x0 = -((box.x1 - ss->size + ss->xOffset) * ss->dx);
+ matrix->xx = ss->dx;
+ matrix->yy = 0.0f;
+ matrix->y0 = ss->dy * ss->size;
+
+ rect.extents.x1 = box.x1 - ss->size + ss->xOffset;
+ rect.extents.y1 = rect.extents.y2;
+ rect.extents.x2 = rect.extents.x1 + ss->size;
+ rect.extents.y2 = box.y2 + ss->yOffset;
+
+ (*w->screen->addWindowGeometry) (w, matrix, nMatrix, &rect, region);
+
+ /* middle */
+ matrix->xx = 0.0f;
+ matrix->x0 = ss->dx * ss->size;
+
+ rect.extents.x1 = rect.extents.x2;
+ rect.extents.x2 = box.x2 + ss->xOffset;
+
+ (*w->screen->addWindowGeometry) (w, matrix, nMatrix, &rect, region);
+
+ /* right */
+ matrix->x0 = -((box.x2 - ss->size + ss->xOffset) * ss->dx);
+ matrix->xx = ss->dx;
+
+ rect.extents.x1 = rect.extents.x2;
+ rect.extents.x2 = box.x2 + ss->size + ss->xOffset;
+
+ (*w->screen->addWindowGeometry) (w, matrix, nMatrix, &rect, region);
+
+ /* bottom left */
+ matrix->yy = ss->dy;
+ matrix->x0 = -((box.x1 - ss->size + ss->xOffset) * ss->dx);
+ matrix->y0 = -((box.y2 - ss->size + ss->yOffset) * ss->dy);
+
+ rect.extents.x1 = box.x1 - ss->size + ss->xOffset;
+ rect.extents.y1 = rect.extents.y2;
+ rect.extents.x2 = rect.extents.x1 + ss->size;
+ rect.extents.y2 = box.y2 + ss->size + ss->yOffset;
+
+ (*w->screen->addWindowGeometry) (w, matrix, nMatrix, &rect, region);
+
+ /* bottom */
+ matrix->xx = 0.0f;
+ matrix->x0 = ss->dx * ss->size;
+
+ rect.extents.x1 = rect.extents.x2;
+ rect.extents.x2 = box.x2 + ss->xOffset;
+
+ (*w->screen->addWindowGeometry) (w, matrix, nMatrix, &rect, region);
+
+ /* bottom right */
+ matrix->x0 = -((box.x2 - ss->size + ss->xOffset) * ss->dx);
+ matrix->xx = ss->dx;
+
+ rect.extents.x1 = rect.extents.x2;
+ rect.extents.x2 = box.x2 + ss->size + ss->xOffset;
+
+ (*w->screen->addWindowGeometry) (w, matrix, nMatrix, &rect, region);
+
+ if (w->vCount)
+ {
+ glEnable (GL_BLEND);
+
+ glPushMatrix ();
+
+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+ {
+ glTranslatef (w->attrib.x + attrib->xTranslate,
+ w->attrib.y + attrib->yTranslate, 0.0f);
+ glScalef (attrib->xScale, attrib->yScale, 0.0f);
+ glTranslatef (-w->attrib.x, -w->attrib.y, 0.0f);
+ }
+
+ glEnable (ss->target);
+ glBindTexture (ss->target, ss->texture);
+
+ glColor4us (0x0, 0x0, 0x0, opacity);
+ glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ if (nMatrix > 1)
+ {
+ w->screen->activeTexture (GL_TEXTURE1_ARB);
+
+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+ enableTexture (w->screen, &w->texture,
+ COMP_TEXTURE_FILTER_GOOD);
+ else
+ enableTexture (w->screen, &w->texture,
+ COMP_TEXTURE_FILTER_FAST);
+
+ glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
+ glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
+ glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
+ glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
+ glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
+ glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ }
+
+ (*w->screen->drawWindowGeometry) (w);
+
+ if (nMatrix > 1)
+ {
+ disableTexture (&w->texture);
+ w->screen->activeTexture (GL_TEXTURE0_ARB);
+ }
+
+ glBindTexture (ss->target, 0);
+ glDisable (ss->target);
+
+ glPopMatrix ();
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glColor4usv (defaultColor);
+ glDisable (GL_BLEND);
+
+ w->vCount = 0;
+ }
+ }
+
+ UNWRAP (ss, w->screen, paintWindow);
+ status = (*w->screen->paintWindow) (w, attrib, region, mask);
+ WRAP (ss, w->screen, paintWindow, shadowPaintWindow);
+
+ return status;
+}
+
+static Bool
+shadowInitDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ ShadowDisplay *sd;
+
+ sd = malloc (sizeof (ShadowDisplay));
+ if (!sd)
+ return FALSE;
+
+ sd->screenPrivateIndex = allocateScreenPrivateIndex (d);
+ if (sd->screenPrivateIndex < 0)
+ {
+ free (sd);
+ return FALSE;
+ }
+
+ d->privates[displayPrivateIndex].ptr = sd;
+
+ return TRUE;
+}
+
+static void
+shadowFiniDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ SHADOW_DISPLAY (d);
+
+ freeScreenPrivateIndex (d, sd->screenPrivateIndex);
+
+ free (sd);
+}
+
+static Bool
+shadowInitScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ ShadowScreen *ss;
+
+ SHADOW_DISPLAY (s->display);
+
+ ss = malloc (sizeof (ShadowScreen));
+ if (!ss)
+ return FALSE;
+
+ ss->texture = 0;
+
+ ss->expand = SHADOW_EXPAND_DEFAULT;
+ ss->xOffset = SHADOW_OFFSET_X_DEFAULT;
+ ss->yOffset = SHADOW_OFFSET_Y_DEFAULT;
+
+ shadowScreenInitOptions (ss);
+
+ WRAP (ss, s, paintWindow, shadowPaintWindow);
+ WRAP (ss, s, damageWindowRect, shadowDamageWindowRect);
+ WRAP (ss, s, damageWindowRegion, shadowDamageWindowRegion);
+
+ s->privates[sd->screenPrivateIndex].ptr = ss;
+
+ shadowComputeGaussian (s,
+ ss->opt[SHADOW_SCREEN_OPTION_RADIUS].value.f,
+ ss->opt[SHADOW_SCREEN_OPTION_OPACITY].value.f);
+
+ return TRUE;
+}
+
+static void
+shadowFiniScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ SHADOW_SCREEN (s);
+
+ if (ss->texture)
+ glDeleteTextures (1, &ss->texture);
+
+ UNWRAP (ss, s, paintWindow);
+ UNWRAP (ss, s, damageWindowRect);
+ UNWRAP (ss, s, damageWindowRegion);
+
+ free (ss);
+}
+
+static Bool
+shadowInit (CompPlugin *p)
+{
+ displayPrivateIndex = allocateDisplayPrivateIndex ();
+ if (displayPrivateIndex < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+shadowFini (CompPlugin *p)
+{
+ if (displayPrivateIndex >= 0)
+ freeDisplayPrivateIndex (displayPrivateIndex);
+}
+
+static CompPluginVTable shadowVTable = {
+ "shadow",
+ "Window Shadows",
+ "Window drop shadows",
+ shadowInit,
+ shadowFini,
+ shadowInitDisplay,
+ shadowFiniDisplay,
+ shadowInitScreen,
+ shadowFiniScreen,
+ 0, /* InitWindow */
+ 0, /* FiniWindow */
+ 0, /* GetDisplayOptions */
+ 0, /* SetDisplayOption */
+ shadowGetScreenOptions,
+ shadowSetScreenOption
+};
+
+CompPluginVTable *
+getCompPluginInfo (void)
+{
+ return &shadowVTable;
+}
diff --git a/plugins/wobbly.c b/plugins/wobbly.c
index 6a18845..5ba3499 100644
--- a/plugins/wobbly.c
+++ b/plugins/wobbly.c
@@ -65,6 +65,7 @@ typedef struct _Model {
float steps;
Vector translate;
Vector scale;
+ Bool transformed;
} Model;
#define WOBBLY_FRICTION_DEFAULT 2.5f
@@ -77,9 +78,13 @@ typedef struct _Model {
#define WOBBLY_SPRING_K_MAX 10.0f
#define WOBBLY_SPRING_K_PRECISION 0.1f
-#define WOBBLY_GRID_SIZE_DEFAULT 64
-#define WOBBLY_GRID_SIZE_MIN 16
-#define WOBBLY_GRID_SIZE_MAX 512
+#define WOBBLY_GRID_RESOLUTION_DEFAULT 8
+#define WOBBLY_GRID_RESOLUTION_MIN 1
+#define WOBBLY_GRID_RESOLUTION_MAX 64
+
+#define WOBBLY_MIN_GRID_SIZE_DEFAULT 8
+#define WOBBLY_MIN_GRID_SIZE_MIN 4
+#define WOBBLY_MIN_GRID_SIZE_MAX 128
typedef enum {
WobblyEffectNone = 0,
@@ -101,7 +106,7 @@ static WobblyEffect effectType[] = {
#define NUM_EFFECT (sizeof (effectType) / sizeof (effectType[0]))
-#define WOBBLY_MAP_DEFAULT (effectName[0])
+#define WOBBLY_MAP_DEFAULT (effectName[2])
#define WOBBLY_FOCUS_DEFAULT (effectName[0])
static int displayPrivateIndex;
@@ -111,20 +116,24 @@ typedef struct _WobblyDisplay {
HandleEventProc handleEvent;
} WobblyDisplay;
-#define WOBBLY_SCREEN_OPTION_FRICTION 0
-#define WOBBLY_SCREEN_OPTION_SPRING_K 1
-#define WOBBLY_SCREEN_OPTION_GRID_SIZE 2
-#define WOBBLY_SCREEN_OPTION_MAP_EFFECT 3
-#define WOBBLY_SCREEN_OPTION_FOCUS_EFFECT 4
-#define WOBBLY_SCREEN_OPTION_NUM 5
+#define WOBBLY_SCREEN_OPTION_FRICTION 0
+#define WOBBLY_SCREEN_OPTION_SPRING_K 1
+#define WOBBLY_SCREEN_OPTION_GRID_RESOLUTION 2
+#define WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE 3
+#define WOBBLY_SCREEN_OPTION_MAP_EFFECT 4
+#define WOBBLY_SCREEN_OPTION_FOCUS_EFFECT 5
+#define WOBBLY_SCREEN_OPTION_NUM 6
typedef struct _WobblyScreen {
- int windowPrivateIndex;
- PreparePaintScreenProc preparePaintScreen;
- DonePaintScreenProc donePaintScreen;
- PaintScreenProc paintScreen;
- PaintWindowProc paintWindow;
- InvisibleWindowMoveProc invisibleWindowMove;
+ int windowPrivateIndex;
+ PreparePaintScreenProc preparePaintScreen;
+ DonePaintScreenProc donePaintScreen;
+ PaintScreenProc paintScreen;
+ PaintWindowProc paintWindow;
+ DamageWindowRectProc damageWindowRect;
+ AddWindowGeometryProc addWindowGeometry;
+ DrawWindowGeometryProc drawWindowGeometry;
+ InvisibleWindowMoveProc invisibleWindowMove;
CompOption opt[WOBBLY_SCREEN_OPTION_NUM];
@@ -135,12 +144,8 @@ typedef struct _WobblyScreen {
} WobblyScreen;
typedef struct _WobblyWindow {
- Model *model;
- Bool wobbly;
- GLfloat *vertices;
- int vertexSize;
- GLushort *indices;
- int indexSize;
+ Model *model;
+ Bool wobbly;
} WobblyWindow;
#define GET_WOBBLY_DISPLAY(d) \
@@ -195,7 +200,11 @@ wobblySetScreenOption (CompScreen *screen,
if (compSetFloatOption (o, value))
return TRUE;
break;
- case WOBBLY_SCREEN_OPTION_GRID_SIZE:
+ case WOBBLY_SCREEN_OPTION_GRID_RESOLUTION:
+ if (compSetIntOption (o, value))
+ return TRUE;
+ break;
+ case WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE:
if (compSetIntOption (o, value))
return TRUE;
break;
@@ -260,14 +269,23 @@ wobblyScreenInitOptions (WobblyScreen *ws)
o->rest.f.max = WOBBLY_SPRING_K_MAX;
o->rest.f.precision = WOBBLY_SPRING_K_PRECISION;
- o = &ws->opt[WOBBLY_SCREEN_OPTION_GRID_SIZE];
- o->name = "grid_size";
- o->shortDesc = "Grid Size";
+ o = &ws->opt[WOBBLY_SCREEN_OPTION_GRID_RESOLUTION];
+ o->name = "grid_resolution";
+ o->shortDesc = "Grid Resolution";
o->longDesc = "Vertex Grid Resolution";
o->type = CompOptionTypeInt;
- o->value.i = WOBBLY_GRID_SIZE_DEFAULT;
- o->rest.i.min = WOBBLY_GRID_SIZE_MIN;
- o->rest.i.max = WOBBLY_GRID_SIZE_MAX;
+ o->value.i = WOBBLY_GRID_RESOLUTION_DEFAULT;
+ o->rest.i.min = WOBBLY_GRID_RESOLUTION_MIN;
+ o->rest.i.max = WOBBLY_GRID_RESOLUTION_MAX;
+
+ o = &ws->opt[WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE];
+ o->name = "min_grid_size";
+ o->shortDesc = "Minimum Grid Size";
+ o->longDesc = "Minimum Vertex Grid Size";
+ o->type = CompOptionTypeInt;
+ o->value.i = WOBBLY_MIN_GRID_SIZE_DEFAULT;
+ o->rest.i.min = WOBBLY_MIN_GRID_SIZE_MIN;
+ o->rest.i.max = WOBBLY_MIN_GRID_SIZE_MAX;
o = &ws->opt[WOBBLY_SCREEN_OPTION_MAP_EFFECT];
o->name = "map_effect";
@@ -555,6 +573,8 @@ createModel (int x,
model->scale.x = 1.0f;
model->scale.y = 1.0f;
+ model->transformed = FALSE;
+
modelInitObjects (model, x, y, width, height);
modelInitSprings (model, x, y, width, height);
@@ -788,6 +808,17 @@ isWobblyWin (CompWindow *w)
w->type == w->screen->display->winDockAtom)
return FALSE;
+ /* avoid tiny windows */
+ if (w->width == 1 && w->height == 1)
+ return FALSE;
+
+ /* avoid fullscreen windows */
+ if (w->attrib.x <= 0 &&
+ w->attrib.y <= 0 &&
+ w->attrib.x + w->width >= w->screen->width &&
+ w->attrib.y + w->height >= w->screen->height)
+ return FALSE;
+
return TRUE;
}
@@ -887,119 +918,80 @@ wobblyTransformWindow (CompWindow *w,
ww->wobbly = ws->wobblyWindows = TRUE;
}
+
+ if (ww->model->translate.x != 0.0f ||
+ ww->model->translate.y != 0.0f ||
+ ww->model->scale.x != 1.0f ||
+ ww->model->scale.y != 1.0f)
+ ww->model->transformed = 1;
+ else
+ ww->model->transformed = 0;
}
}
-static Bool
-wobblyPaintWindow (CompWindow *w,
- const WindowPaintAttrib *attrib,
- Region region,
- unsigned int mask)
+static void
+wobblyAddWindowGeometry (CompWindow *w,
+ CompMatrix *matrix,
+ int nMatrix,
+ Region region,
+ Region clip)
{
- BoxPtr pClip;
- int nClip, nVertices, nIndices;
- GLushort *i, *indices;
- GLfloat *v, *vertices;
- int x1, y1, x2, y2;
- float width, height;
- float deformedX, deformedY;
- int x, y, iw, ih;
-
WOBBLY_WINDOW (w);
WOBBLY_SCREEN (w->screen);
- if (ww->model)
- {
- if (attrib->xTranslate != ww->model->translate.x ||
- attrib->yTranslate != ww->model->translate.y ||
- attrib->xScale != ww->model->scale.x ||
- attrib->yScale != ww->model->scale.y)
- wobblyTransformWindow (w, attrib);
- }
- else
- {
- if (attrib->xTranslate != 0.0f ||
- attrib->yTranslate != 0.0f ||
- attrib->xScale != 1.0f ||
- attrib->yScale != 1.0f)
- {
- if (isWobblyWin (w))
- wobblyTransformWindow (w, attrib);
- }
- }
-
if (ww->wobbly)
{
- GLushort opacity;
- int gridSize;
-
- if (!region->numRects)
- return TRUE;
-
- if (w->destroyed || w->attrib.map_state != IsViewable)
- return TRUE;
+ BoxPtr pClip;
+ int nClip, nVertices, nIndices;
+ GLushort *i;
+ GLfloat *v;
+ int x1, y1, x2, y2;
+ float width, height;
+ float deformedX, deformedY;
+ int x, y, iw, ih;
+ int vSize, it;
+ int gridW, gridH;
- if (mask & PAINT_WINDOW_SOLID_MASK)
- {
- if (w->alpha)
- return FALSE;
+ width = w->width;
+ height = w->height;
- opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
- if (opacity != OPAQUE)
- return FALSE;
- }
- else if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
- {
- opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
- if (!w->alpha && opacity == OPAQUE)
- return FALSE;
- }
- else
- {
- opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
- if (w->alpha || opacity != OPAQUE)
- mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
- else
- mask |= PAINT_WINDOW_SOLID_MASK;
- }
+ gridW = width / ws->opt[WOBBLY_SCREEN_OPTION_GRID_RESOLUTION].value.i;
+ if (gridW < ws->opt[WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE].value.i)
+ gridW = ws->opt[WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE].value.i;
- gridSize = ws->opt[WOBBLY_SCREEN_OPTION_GRID_SIZE].value.i;
+ gridH = height / ws->opt[WOBBLY_SCREEN_OPTION_GRID_RESOLUTION].value.i;
+ if (gridH < ws->opt[WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE].value.i)
+ gridH = ws->opt[WOBBLY_SCREEN_OPTION_MIN_GRID_SIZE].value.i;
- if (!w->pixmap)
- bindWindow (w);
+ nClip = region->numRects;
+ pClip = region->rects;
- width = w->width;
- height = w->height;
+ w->texUnits = nMatrix;
- nClip = w->region->numRects;
- pClip = w->region->rects;
+ vSize = 2 + nMatrix * 2;
- nVertices = 0;
- nIndices = 0;
+ nVertices = w->vCount;
+ nIndices = w->vCount;
- i = ww->indices;
- v = ww->vertices;
+ v = w->vertices + (nVertices * vSize);
+ i = w->indices + nIndices;
while (nClip--)
{
- x1 = pClip->x1 - w->attrib.x;
- y1 = pClip->y1 - w->attrib.y;
- x2 = pClip->x2 - w->attrib.x;
- y2 = pClip->y2 - w->attrib.y;
+ x1 = pClip->x1;
+ y1 = pClip->y1;
+ x2 = pClip->x2;
+ y2 = pClip->y2;
- iw = ((x2 - x1 - 1) / gridSize) + 1;
- ih = ((y2 - y1 - 1) / gridSize) + 1;
+ iw = ((x2 - x1 - 1) / gridW) + 1;
+ ih = ((y2 - y1 - 1) / gridH) + 1;
- if (nIndices + (iw * ih * 4) > ww->indexSize)
+ if (nIndices + (iw * ih * 4) > w->indexSize)
{
- indices = realloc (ww->indices, sizeof (GLushort) *
- (ww->indexSize + (iw * ih * 4)));
- if (!indices)
- return FALSE;
-
- ww->indices = indices;
- ww->indexSize += iw * ih * 4;
- i = ww->indices + nIndices;
+ if (!moreWindowIndices (w, nIndices + (iw * ih * 4)))
+ return;
+
+ i = w->indices + nIndices;
}
iw++;
@@ -1018,35 +1010,36 @@ wobblyPaintWindow (CompWindow *w,
}
}
- if (((nVertices + iw * ih) * 4) > ww->vertexSize)
+ if (((nVertices + iw * ih) * vSize) > w->vertexSize)
{
- vertices = realloc (ww->vertices,
- sizeof (GLfloat) *
- (ww->vertexSize + (iw * ih * 4)));
- if (!vertices)
- return FALSE;
-
- ww->vertices = vertices;
- ww->vertexSize += iw * ih * 4;
- v = ww->vertices + (nVertices * 4);
+ if (!moreWindowVertices (w, (nVertices + iw * ih) * vSize))
+ return;
+
+ v = w->vertices + (nVertices * vSize);
}
- for (y = y1;; y += gridSize)
+ for (y = y1;; y += gridH)
{
if (y > y2)
y = y2;
- for (x = x1;; x += gridSize)
+ for (x = x1;; x += gridW)
{
if (x > x2)
x = x2;
bezierPatchEvaluate (ww->model,
- x / width, y / height,
- &deformedX, &deformedY);
+ (x - w->attrib.x) / width,
+ (y - w->attrib.y) / height,
+ &deformedX,
+ &deformedY);
+
+ for (it = 0; it < nMatrix; it++)
+ {
+ *v++ = COMP_TEX_COORD_X (&matrix[it], x, y);
+ *v++ = COMP_TEX_COORD_Y (&matrix[it], x, y);
+ }
- *v++ = X_WINDOW_TO_TEXTURE_SPACE (w, x);
- *v++ = Y_WINDOW_TO_TEXTURE_SPACE (w, y);
*v++ = deformedX;
*v++ = deformedY;
@@ -1063,47 +1056,100 @@ wobblyPaintWindow (CompWindow *w,
pClip++;
}
- glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat) * 4, ww->vertices);
- glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 4, ww->vertices + 2);
+ w->vCount = nIndices;
+ }
+ else
+ {
+ UNWRAP (ws, w->screen, addWindowGeometry);
+ (*w->screen->addWindowGeometry) (w, matrix, nMatrix, region, clip);
+ WRAP (ws, w->screen, addWindowGeometry, wobblyAddWindowGeometry);
+ }
+}
- if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
- {
- glEnable (GL_BLEND);
- if (opacity != OPAQUE)
- {
- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glColor4us (opacity, opacity, opacity, opacity);
- }
- }
+static void
+wobblyDrawWindowGeometry (CompWindow *w)
+{
+ WOBBLY_WINDOW (w);
- enableTexture (w->screen, &w->texture, COMP_TEXTURE_FILTER_GOOD);
- glDrawElements (GL_QUADS, nIndices, GL_UNSIGNED_SHORT, ww->indices);
- disableTexture (&w->texture);
+ if (ww->wobbly)
+ {
+ int texUnit = w->texUnits;
+ int currentTexUnit = 0;
+ int stride = (1 + texUnit) * 2;
+ GLfloat *vertices = w->vertices + (stride - 2);
+
+ stride *= sizeof (GLfloat);
- if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
+ glVertexPointer (2, GL_FLOAT, stride, vertices);
+
+ while (texUnit--)
{
- if (opacity != OPAQUE)
+ if (texUnit != currentTexUnit)
{
- glColor4usv (defaultColor);
- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ w->screen->clientActiveTexture (GL_TEXTURE0_ARB + texUnit);
+ currentTexUnit = texUnit;
}
- glDisable (GL_BLEND);
+ vertices -= 2;
+ glTexCoordPointer (2, GL_FLOAT, stride, vertices);
}
+
+ glDrawElements (GL_QUADS, w->vCount, GL_UNSIGNED_SHORT, w->indices);
}
else
{
- Bool status;
-
WOBBLY_SCREEN (w->screen);
- UNWRAP (ws, w->screen, paintWindow);
- status = (*w->screen->paintWindow) (w, attrib, region, mask);
- WRAP (ws, w->screen, paintWindow, wobblyPaintWindow);
+ UNWRAP (ws, w->screen, drawWindowGeometry);
+ (*w->screen->drawWindowGeometry) (w);
+ WRAP (ws, w->screen, drawWindowGeometry, wobblyDrawWindowGeometry);
+ }
+}
+
+static Bool
+wobblyPaintWindow (CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ Region region,
+ unsigned int mask)
+{
+ Bool status;
+
+ WOBBLY_WINDOW (w);
+ WOBBLY_SCREEN (w->screen);
+
+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+ {
+ if (ww->model || isWobblyWin (w))
+ wobblyTransformWindow (w, attrib);
+
+ if (ww->wobbly)
+ {
+ WindowPaintAttrib wobblyAttrib = *attrib;
+
+ wobblyAttrib.xTranslate = 0.0f;
+ wobblyAttrib.yTranslate = 0.0f;
+ wobblyAttrib.xScale = 1.0f;
+ wobblyAttrib.yScale = 1.0f;
+
+ UNWRAP (ws, w->screen, paintWindow);
+ status = (*w->screen->paintWindow) (w, &wobblyAttrib, region, mask);
+ WRAP (ws, w->screen, paintWindow, wobblyPaintWindow);
- return status;
+ return status;
+ }
+ }
+ else if (ww->model && ww->model->transformed)
+ {
+ wobblyTransformWindow (w, attrib);
}
- return TRUE;
+ if (ww->wobbly)
+ mask |= PAINT_WINDOW_TRANSFORMED_MASK;
+
+ UNWRAP (ws, w->screen, paintWindow);
+ status = (*w->screen->paintWindow) (w, attrib, region, mask);
+ WRAP (ws, w->screen, paintWindow, wobblyPaintWindow);
+
+ return status;
}
static void
@@ -1116,34 +1162,6 @@ wobblyHandleEvent (CompDisplay *d,
WOBBLY_DISPLAY (d);
switch (event->type) {
- case MapNotify:
- w = findWindowAtDisplay (d, event->xmap.window);
- if (w && isWobblyWin (w))
- {
- WOBBLY_WINDOW (w);
- WOBBLY_SCREEN (w->screen);
-
- if (ws->mapEffect && wobblyEnsureModel (w))
- {
- switch (ws->mapEffect) {
- case WobblyEffectExplode:
- modelAdjustObjectsForExplosion (ww->model,
- w->attrib.x, w->attrib.y,
- w->width, w->height);
- break;
- case WobblyEffectShiver:
- modelAdjustObjectsForShiver (ww->model,
- w->attrib.x, w->attrib.y,
- w->width, w->height);
- default:
- break;
- }
-
- ww->wobbly = ws->wobblyWindows = TRUE;
- damageScreen (w->screen);
- }
- }
- break;
case ConfigureNotify:
w = findWindowAtDisplay (d, event->xmap.window);
if (w && isWobblyWin (w))
@@ -1163,7 +1181,8 @@ wobblyHandleEvent (CompDisplay *d,
height = event->xconfigure.height;
height += event->xconfigure.border_width * 2;
- if (w->attrib.map_state == IsViewable && wobblyEnsureModel (w))
+ if (w->damaged && w->attrib.map_state == IsViewable &&
+ wobblyEnsureModel (w))
{
modelSetMiddleAnchor (ww->model,
w->attrib.x, w->attrib.y,
@@ -1193,7 +1212,8 @@ wobblyHandleEvent (CompDisplay *d,
{
WOBBLY_WINDOW (w);
- if (w->attrib.map_state == IsViewable && wobblyEnsureModel (w))
+ if (w->damaged && w->attrib.map_state == IsViewable &&
+ wobblyEnsureModel (w))
{
wobblyMoveWindow (w,
event->xconfigure.x - w->attrib.x,
@@ -1274,6 +1294,51 @@ wobblyHandleEvent (CompDisplay *d,
}
static Bool
+wobblyDamageWindowRect (CompWindow *w,
+ Bool initial,
+ BoxPtr rect)
+{
+ Bool status;
+
+ WOBBLY_SCREEN (w->screen);
+
+ if (initial)
+ {
+ if (isWobblyWin (w))
+ {
+ WOBBLY_WINDOW (w);
+ WOBBLY_SCREEN (w->screen);
+
+ if (ws->mapEffect && wobblyEnsureModel (w))
+ {
+ switch (ws->mapEffect) {
+ case WobblyEffectExplode:
+ modelAdjustObjectsForExplosion (ww->model,
+ w->attrib.x, w->attrib.y,
+ w->width, w->height);
+ break;
+ case WobblyEffectShiver:
+ modelAdjustObjectsForShiver (ww->model,
+ w->attrib.x, w->attrib.y,
+ w->width, w->height);
+ default:
+ break;
+ }
+
+ ww->wobbly = ws->wobblyWindows = TRUE;
+ damageScreen (w->screen);
+ }
+ }
+ }
+
+ UNWRAP (ws, w->screen, damageWindowRect);
+ status = (*w->screen->damageWindowRect) (w, initial, rect);
+ WRAP (ws, w->screen, damageWindowRect, wobblyDamageWindowRect);
+
+ return status;
+}
+
+static Bool
wobblyPaintScreen (CompScreen *s,
const ScreenPaintAttrib *sAttrib,
const WindowPaintAttrib *wAttrib,
@@ -1372,7 +1437,7 @@ wobblyInitScreen (CompPlugin *p,
ws->wobblyWindows = FALSE;
ws->mapEffect = WobblyEffectShiver;
- ws->focusEffect = WobblyEffectShiver;
+ ws->focusEffect = WobblyEffectNone;
wobblyScreenInitOptions (ws);
@@ -1380,6 +1445,9 @@ wobblyInitScreen (CompPlugin *p,
WRAP (ws, s, donePaintScreen, wobblyDonePaintScreen);
WRAP (ws, s, paintScreen, wobblyPaintScreen);
WRAP (ws, s, paintWindow, wobblyPaintWindow);
+ WRAP (ws, s, damageWindowRect, wobblyDamageWindowRect);
+ WRAP (ws, s, addWindowGeometry, wobblyAddWindowGeometry);
+ WRAP (ws, s, drawWindowGeometry, wobblyDrawWindowGeometry);
WRAP (ws, s, invisibleWindowMove, wobblyInvisibleWindowMove);
s->privates[wd->screenPrivateIndex].ptr = ws;
@@ -1402,6 +1470,9 @@ wobblyFiniScreen (CompPlugin *p,
UNWRAP (ws, s, donePaintScreen);
UNWRAP (ws, s, paintScreen);
UNWRAP (ws, s, paintWindow);
+ UNWRAP (ws, s, damageWindowRect);
+ UNWRAP (ws, s, addWindowGeometry);
+ UNWRAP (ws, s, drawWindowGeometry);
UNWRAP (ws, s, invisibleWindowMove);
free (ws);
@@ -1419,12 +1490,6 @@ wobblyInitWindow (CompPlugin *p,
if (!ww)
return FALSE;
- ww->vertices = 0;
- ww->vertexSize = 0;
-
- ww->indices = 0;
- ww->indexSize = 0;
-
ww->model = 0;
ww->wobbly = FALSE;
@@ -1439,12 +1504,6 @@ wobblyFiniWindow (CompPlugin *p,
{
WOBBLY_WINDOW (w);
- if (ww->vertices)
- free (ww->vertices);
-
- if (ww->indices)
- free (ww->indices);
-
if (ww->model)
{
free (ww->model->objects);
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644
index 0000000..51cbb8e
--- /dev/null
+++ b/src/.cvsignore
@@ -0,0 +1,5 @@
+Makefile
+Makefile.in
+glxcompmgr
+.deps
+.libs
diff --git a/src/display.c b/src/display.c
index 69d01b0..0a11d80 100644
--- a/src/display.c
+++ b/src/display.c
@@ -1010,8 +1010,7 @@ addDisplay (char *name,
d->initPluginForDisplay = initPluginForDisplay;
d->finiPluginForDisplay = finiPluginForDisplay;
- d->handleEvent = handleEvent;
- d->handleDamageEvent = handleDamageEvent;
+ d->handleEvent = handleEvent;
d->winTypeAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE", 0);
d->winDesktopAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", 0);
@@ -1135,14 +1134,21 @@ CompWindow *
findWindowAtDisplay (CompDisplay *d,
Window id)
{
- CompScreen *s;
- CompWindow *w;
-
- for (s = d->screens; s; s = s->next)
+ if (lastFoundWindow && lastFoundWindow->id == id)
+ {
+ return lastFoundWindow;
+ }
+ else
{
- w = findWindowAtScreen (s, id);
- if (w)
- return w;
+ CompScreen *s;
+ CompWindow *w;
+
+ for (s = d->screens; s; s = s->next)
+ {
+ w = findWindowAtScreen (s, id);
+ if (w)
+ return w;
+ }
}
return 0;
diff --git a/src/event.c b/src/event.c
index ccabfca..6dd80b7 100644
--- a/src/event.c
+++ b/src/event.c
@@ -230,39 +230,45 @@ handleEvent (CompDisplay *display,
}
else if (event->type == display->damageEvent + XDamageNotify)
{
- (*display->handleDamageEvent) (display,
- (XDamageNotifyEvent *) event);
- }
- break;
- }
-}
+ XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;
-void
-handleDamageEvent (CompDisplay *display,
- XDamageNotifyEvent *event)
-{
- CompScreen *screen;
- REGION rect;
-
- rect.rects = &rect.extents;
- rect.numRects = rect.size = 1;
+ if (lastDamagedWindow && de->drawable == lastDamagedWindow->id)
+ {
+ w = lastDamagedWindow;
+ }
+ else
+ {
+ w = findWindowAtDisplay (display, de->drawable);
+ if (w)
+ lastDamagedWindow = w;
+ }
- screen = display->screens;
- if (screen->next)
- {
- CompWindow *w;
+ if (w)
+ {
+ REGION region;
+ Bool initial = FALSE;
- w = findWindowAtDisplay (display, event->drawable);
- if (!w)
- return;
+ if (!w->damaged)
+ {
+ w->damaged = initial = TRUE;
+ w->invisible = WINDOW_INVISIBLE (w);
+ }
- screen = w->screen;
- }
+ region.extents.x1 = de->geometry.x + de->area.x;
+ region.extents.y1 = de->geometry.y + de->area.y;
+ region.extents.x2 = region.extents.x1 + de->area.width;
+ region.extents.y2 = region.extents.y1 + de->area.height;
- rect.extents.x1 = event->geometry.x + event->area.x;
- rect.extents.y1 = event->geometry.y + event->area.y;
- rect.extents.x2 = rect.extents.x1 + event->area.width;
- rect.extents.y2 = rect.extents.y1 + event->area.height;
+ if (!(*w->screen->damageWindowRect) (w, initial,
+ &region.extents))
+ {
+ region.rects = &region.extents;
+ region.numRects = region.size = 1;
- damageScreenRegion (screen, &rect);
+ damageScreenRegion (w->screen, &region);
+ }
+ }
+ }
+ break;
+ }
}
diff --git a/src/glxcompmgr.c b/src/glxcompmgr.c
index 21673f3..0862d38 100644
--- a/src/glxcompmgr.c
+++ b/src/glxcompmgr.c
@@ -39,6 +39,7 @@ char *backgroundImage = "background.png";
char *windowImage = "window.png";
REGION emptyRegion;
+REGION infiniteRegion;
GLushort defaultColor[4] = { 0, 0, 0, 0 };
Window currentRoot = 0;
@@ -48,6 +49,9 @@ char *defaultTextureFilter = "Good";
Bool testMode = FALSE;
Bool restartSignal = FALSE;
+CompWindow *lastFoundWindow = 0;
+CompWindow *lastDamagedWindow = 0;
+
static void
usage (void)
{
@@ -91,6 +95,13 @@ main (int argc, char **argv)
emptyRegion.extents.y2 = 0;
emptyRegion.size = 0;
+ infiniteRegion.rects = &infiniteRegion.extents;
+ infiniteRegion.numRects = 1;
+ infiniteRegion.extents.x1 = MINSHORT;
+ infiniteRegion.extents.y1 = MINSHORT;
+ infiniteRegion.extents.x2 = MAXSHORT;
+ infiniteRegion.extents.y2 = MAXSHORT;
+
for (i = 1; i < argc; i++)
{
if (!strcmp (argv[i], "--help"))
diff --git a/src/paint.c b/src/paint.c
index 5174e95..29e5646 100644
--- a/src/paint.c
+++ b/src/paint.c
@@ -86,8 +86,14 @@ paintTransformedScreen (CompScreen *screen,
glEnable (GL_STENCIL_TEST);
for (w = screen->windows; w; w = w->next)
- (*screen->paintWindow) (w, wAttrib, &screen->region,
- windowMask);
+ {
+ if (w->destroyed || w->attrib.map_state != IsViewable)
+ continue;
+
+ if (w->damaged)
+ (*screen->paintWindow) (w, wAttrib, &screen->region,
+ windowMask);
+ }
glDisable (GL_STENCIL_TEST);
@@ -102,7 +108,13 @@ paintTransformedScreen (CompScreen *screen,
(*screen->paintBackground) (screen, &screen->region, backgroundMask);
for (w = screen->windows; w; w = w->next)
- (*screen->paintWindow) (w, wAttrib, &screen->region, windowMask);
+ {
+ if (w->destroyed || w->attrib.map_state != IsViewable)
+ continue;
+
+ if (w->damaged)
+ (*screen->paintWindow) (w, wAttrib, &screen->region, windowMask);
+ }
glPopMatrix ();
}
@@ -164,7 +176,7 @@ paintScreen (CompScreen *screen,
/* paint solid windows */
for (w = screen->reverseWindows; w; w = w->prev)
{
- if (w->invisible)
+ if (w->destroyed || w->invisible)
continue;
if ((*screen->paintWindow) (w, wAttrib, tmpRegion,
@@ -173,18 +185,23 @@ paintScreen (CompScreen *screen,
/* copy region */
XSubtractRegion (tmpRegion, &emptyRegion, w->clip);
+
+ if (!tmpRegion->numRects)
+ break;
}
- (*screen->paintBackground) (screen, tmpRegion, 0);
+ if (tmpRegion->numRects)
+ (*screen->paintBackground) (screen, tmpRegion, 0);
/* paint translucent windows */
for (w = screen->windows; w; w = w->next)
{
- if (w->invisible)
+ if (w->destroyed || w->invisible)
continue;
- (*screen->paintWindow) (w, wAttrib, w->clip,
- PAINT_WINDOW_TRANSLUCENT_MASK);
+ if (w->clip->numRects)
+ (*screen->paintWindow) (w, wAttrib, w->clip,
+ PAINT_WINDOW_TRANSLUCENT_MASK);
}
glPopMatrix ();
@@ -192,146 +209,127 @@ paintScreen (CompScreen *screen,
return TRUE;
}
-#define ADD_QUAD(data, w, x1, y1, x2, y2) \
- if (!(w)->pixmap) \
- bindWindow (w); \
- *(data)++ = X_WINDOW_TO_TEXTURE_SPACE (w, x1); \
- *(data)++ = Y_WINDOW_TO_TEXTURE_SPACE (w, y2); \
- *(data)++ = (x1); \
- *(data)++ = (y2); \
- *(data)++ = X_WINDOW_TO_TEXTURE_SPACE (w, x2); \
- *(data)++ = Y_WINDOW_TO_TEXTURE_SPACE (w, y2); \
- *(data)++ = (x2); \
- *(data)++ = (y2); \
- *(data)++ = X_WINDOW_TO_TEXTURE_SPACE (w, x2); \
- *(data)++ = Y_WINDOW_TO_TEXTURE_SPACE (w, y1); \
- *(data)++ = (x2); \
- *(data)++ = (y1); \
- *(data)++ = X_WINDOW_TO_TEXTURE_SPACE (w, x1); \
- *(data)++ = Y_WINDOW_TO_TEXTURE_SPACE (w, y1); \
- *(data)++ = (x1); \
+#define ADD_QUAD(data, m, n, x1, y1, x2, y2) \
+ for (it = 0; it < n; it++) \
+ { \
+ *(data)++ = COMP_TEX_COORD_X (&m[it], x1, y2); \
+ *(data)++ = COMP_TEX_COORD_Y (&m[it], x1, y2); \
+ } \
+ *(data)++ = (x1); \
+ *(data)++ = (y2); \
+ for (it = 0; it < n; it++) \
+ { \
+ *(data)++ = COMP_TEX_COORD_X (&m[it], x2, y2); \
+ *(data)++ = COMP_TEX_COORD_Y (&m[it], x2, y2); \
+ } \
+ *(data)++ = (x2); \
+ *(data)++ = (y2); \
+ for (it = 0; it < n; it++) \
+ { \
+ *(data)++ = COMP_TEX_COORD_X (&m[it], x2, y1); \
+ *(data)++ = COMP_TEX_COORD_Y (&m[it], x2, y1); \
+ } \
+ *(data)++ = (x2); \
+ *(data)++ = (y1); \
+ for (it = 0; it < n; it++) \
+ { \
+ *(data)++ = COMP_TEX_COORD_X (&m[it], x1, y1); \
+ *(data)++ = COMP_TEX_COORD_Y (&m[it], x1, y1); \
+ } \
+ *(data)++ = (x1); \
*(data)++ = (y1)
-#define ADD_BOX(data, w, box) \
- ADD_QUAD (data, w, (box)->x1, (box)->y1, (box)->x2, (box)->y2)
-
Bool
-paintWindow (CompWindow *w,
- const WindowPaintAttrib *attrib,
- Region region,
- unsigned int mask)
+moreWindowVertices (CompWindow *w,
+ int newSize)
{
- BoxPtr pClip;
- int nClip, n;
- GLfloat *data, *d;
- GLushort opacity;
- int x1, y1, x2, y2;
-
- if (!region->numRects)
- return TRUE;
-
- if (w->destroyed || w->attrib.map_state != IsViewable)
- return TRUE;
-
- if (mask & PAINT_WINDOW_SOLID_MASK)
+ if (newSize > w->vertexSize)
{
- if (w->alpha)
- return FALSE;
+ GLfloat *vertices;
- opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
- if (opacity != OPAQUE)
+ vertices = realloc (w->vertices, sizeof (GLfloat) * newSize);
+ if (!vertices)
return FALSE;
+
+ w->vertices = vertices;
+ w->vertexSize = newSize;
}
- else if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
+
+ return TRUE;
+}
+
+Bool
+moreWindowIndices (CompWindow *w,
+ int newSize)
+{
+ if (newSize > w->indexSize)
{
- opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
- if (!w->alpha && opacity == OPAQUE)
+ GLushort *indices;
+
+ indices = realloc (w->indices, sizeof (GLushort) * newSize);
+ if (!indices)
return FALSE;
- }
- else
- {
- opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
- if (w->alpha || opacity != OPAQUE)
- mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
- else
- mask |= PAINT_WINDOW_SOLID_MASK;
+
+ w->indices = indices;
+ w->indexSize = newSize;
}
- if (attrib->xTranslate != 0.0f ||
- attrib->yTranslate != 0.0f ||
- attrib->xScale != 1.0f ||
- attrib->yScale != 1.0f)
- {
- nClip = w->region->numRects;
- pClip = w->region->rects;
+ return TRUE;
+}
- mask |= PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
+void
+addWindowGeometry (CompWindow *w,
+ CompMatrix *matrix,
+ int nMatrix,
+ Region region,
+ Region clip)
+{
+ BoxRec full;
- data = malloc (sizeof (GLfloat) * nClip * 16);
- if (!data)
- return FALSE;
+ w->texUnits = nMatrix;
- d = data;
+ full = clip->extents;
+ if (region->extents.x1 > full.x1)
+ full.x1 = region->extents.x1;
+ if (region->extents.y1 > full.y1)
+ full.y1 = region->extents.y1;
+ if (region->extents.x2 < full.x2)
+ full.x2 = region->extents.x2;
+ if (region->extents.y2 < full.y2)
+ full.y2 = region->extents.y2;
- n = nClip;
- while (nClip--)
- {
- x1 = pClip->x1 - w->attrib.x;
- y1 = pClip->y1 - w->attrib.y;
- x2 = pClip->x2 - w->attrib.x;
- y2 = pClip->y2 - w->attrib.y;
+ if (full.x1 < full.x2 && full.y1 < full.y2)
+ {
+ BoxPtr pBox;
+ int nBox;
+ BoxPtr pClip;
+ int nClip;
+ BoxRec cbox;
+ int vSize;
+ int n, it, x1, y1, x2, y2;
+ GLfloat *d;
- ADD_QUAD (d, w, x1, y1, x2, y2);
+ pBox = region->rects;
+ nBox = region->numRects;
- pClip++;
+ vSize = 2 + nMatrix * 2;
+
+ n = w->vCount / 4;
+
+ if ((n + nBox) * vSize * 4 > w->vertexSize)
+ {
+ if (!moreWindowVertices (w, (n + nBox) * vSize * 4))
+ return;
}
- }
- else
- {
- BoxRec clip, full;
- BoxPtr pExtent = &region->extents;
- BoxPtr pBox = region->rects;
- int nBox = region->numRects;
- int dataSize;
-
- full.x1 = 0;
- full.y1 = 0;
- full.x2 = w->width;
- full.y2 = w->height;
-
- x1 = pExtent->x1 - w->attrib.x;
- y1 = pExtent->y1 - w->attrib.y;
- x2 = pExtent->x2 - w->attrib.x;
- y2 = pExtent->y2 - w->attrib.y;
-
- if (x1 > 0)
- full.x1 = x1;
- if (y1 > 0)
- full.y1 = y1;
- if (x2 < w->width)
- full.x2 = x2;
- if (y2 < w->height)
- full.y2 = y2;
-
- if (full.x1 >= full.x2 || full.y1 >= full.y2)
- return TRUE;
-
- dataSize = nBox * 16;
- data = malloc (sizeof (GLfloat) * dataSize);
- if (!data)
- return FALSE;
- d = data;
- n = 0;
+ d = w->vertices + (w->vCount * vSize);
- pBox = region->rects;
- nBox = region->numRects;
while (nBox--)
{
- x1 = pBox->x1 - w->attrib.x;
- y1 = pBox->y1 - w->attrib.y;
- x2 = pBox->x2 - w->attrib.x;
- y2 = pBox->y2 - w->attrib.y;
+ x1 = pBox->x1;
+ y1 = pBox->y1;
+ x2 = pBox->x2;
+ y2 = pBox->y2;
pBox++;
@@ -346,50 +344,45 @@ paintWindow (CompWindow *w,
if (x1 < x2 && y1 < y2)
{
- nClip = w->region->numRects;
+ nClip = clip->numRects;
if (nClip == 1)
{
- ADD_QUAD (d, w, x1, y1, x2, y2);
+ ADD_QUAD (d, matrix, nMatrix, x1, y1, x2, y2);
n++;
}
else
{
- pClip = w->region->rects;
+ pClip = clip->rects;
+
+ if (((n + nClip) * vSize * 4) > w->vertexSize)
+ {
+ if (!moreWindowVertices (w, (n + nClip) * vSize * 4))
+ return;
+
+ d = w->vertices + (n * vSize * 4);
+ }
while (nClip--)
{
- clip.x1 = pClip->x1 - w->attrib.x;
- clip.y1 = pClip->y1 - w->attrib.y;
- clip.x2 = pClip->x2 - w->attrib.x;
- clip.y2 = pClip->y2 - w->attrib.y;
+ cbox = *pClip;
pClip++;
- if (clip.x1 < x1)
- clip.x1 = x1;
- if (clip.y1 < y1)
- clip.y1 = y1;
- if (clip.x2 > x2)
- clip.x2 = x2;
- if (clip.y2 > y2)
- clip.y2 = y2;
+ if (cbox.x1 < x1)
+ cbox.x1 = x1;
+ if (cbox.y1 < y1)
+ cbox.y1 = y1;
+ if (cbox.x2 > x2)
+ cbox.x2 = x2;
+ if (cbox.y2 > y2)
+ cbox.y2 = y2;
- if (clip.x1 < clip.x2 && clip.y1 < clip.y2)
+ if (cbox.x1 < cbox.x2 && cbox.y1 < cbox.y2)
{
- if ((n << 4) == dataSize)
- {
- dataSize <<= 2;
- data = realloc (data,
- sizeof (GLfloat) * dataSize);
- if (!data)
- return FALSE;
-
- d = data + (n * 16);
- }
-
- ADD_BOX (d, w, &clip);
+ ADD_QUAD (d, matrix, nMatrix,
+ cbox.x1, cbox.y1, cbox.x2, cbox.y2);
n++;
}
@@ -397,13 +390,78 @@ paintWindow (CompWindow *w,
}
}
}
+ w->vCount = n * 4;
+ }
+}
+
+void
+drawWindowGeometry (CompWindow *w)
+{
+ int texUnit = w->texUnits;
+ int currentTexUnit = 0;
+ int stride = (1 + texUnit) * 2;
+ GLfloat *vertices = w->vertices + (stride - 2);
+
+ stride *= sizeof (GLfloat);
+
+ glVertexPointer (2, GL_FLOAT, stride, vertices);
+
+ while (texUnit--)
+ {
+ if (texUnit != currentTexUnit)
+ {
+ w->screen->clientActiveTexture (GL_TEXTURE0_ARB + texUnit);
+ currentTexUnit = texUnit;
+ }
+ vertices -= 2;
+ glTexCoordPointer (2, GL_FLOAT, stride, vertices);
}
- if (n)
+ glDrawArrays (GL_QUADS, 0, w->vCount);
+}
+
+Bool
+paintWindow (CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ Region region,
+ unsigned int mask)
+{
+ GLushort opacity;
+
+ if (mask & PAINT_WINDOW_SOLID_MASK)
+ {
+ if (w->alpha)
+ return FALSE;
+
+ opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
+ if (opacity != OPAQUE)
+ return FALSE;
+ }
+ else if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
+ {
+ opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
+ if (!w->alpha && opacity == OPAQUE)
+ return FALSE;
+ }
+ else
{
- glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat) * 4, data);
- glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 4, data + 2);
+ opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
+ if (w->alpha || opacity != OPAQUE)
+ mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+ else
+ mask |= PAINT_WINDOW_SOLID_MASK;
+ }
+
+ if (!w->pixmap)
+ bindWindow (w);
+
+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+ region = &infiniteRegion;
+ w->vCount = 0;
+ (*w->screen->addWindowGeometry) (w, &w->matrix, 1, w->region, region);
+ if (w->vCount)
+ {
if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
{
glEnable (GL_BLEND);
@@ -416,22 +474,25 @@ paintWindow (CompWindow *w,
glPushMatrix ();
- if (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
{
glTranslatef (w->attrib.x + attrib->xTranslate,
w->attrib.y + attrib->yTranslate, 0.0f);
glScalef (attrib->xScale, attrib->yScale, 0.0f);
+ glTranslatef (-w->attrib.x, -w->attrib.y, 0.0f);
enableTexture (w->screen, &w->texture, COMP_TEXTURE_FILTER_GOOD);
}
+ else if (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
+ {
+ enableTexture (w->screen, &w->texture, COMP_TEXTURE_FILTER_GOOD);
+ }
else
{
- glTranslatef (w->attrib.x, w->attrib.y, 0.0f);
-
enableTexture (w->screen, &w->texture, COMP_TEXTURE_FILTER_FAST);
}
- glDrawArrays (GL_QUADS, 0, n * 4);
+ (*w->screen->drawWindowGeometry) (w);
disableTexture (&w->texture);
@@ -448,8 +509,6 @@ paintWindow (CompWindow *w,
}
}
- free (data);
-
return TRUE;
}
@@ -491,26 +550,26 @@ paintBackground (CompScreen *s,
n = nBox;
while (n--)
{
- *d++ = bg->dx * pBox->x1;
- *d++ = bg->dy * (s->backgroundHeight - pBox->y2);
+ *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x1, pBox->y2);
+ *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->x1, pBox->y2);
*d++ = pBox->x1;
*d++ = pBox->y2;
- *d++ = bg->dx * pBox->x2;
- *d++ = bg->dy * (s->backgroundHeight - pBox->y2);
+ *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x2, pBox->y2);
+ *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->x2, pBox->y2);
*d++ = pBox->x2;
*d++ = pBox->y2;
- *d++ = bg->dx * pBox->x2;
- *d++ = bg->dy * (s->backgroundHeight - pBox->y1);
+ *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x2, pBox->y1);
+ *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->x2, pBox->y1);
*d++ = pBox->x2;
*d++ = pBox->y1;
- *d++ = bg->dx * pBox->x1;
- *d++ = bg->dy * (s->backgroundHeight - pBox->y1);
+ *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x1, pBox->y1);
+ *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->x1, pBox->y1);
*d++ = pBox->x1;
*d++ = pBox->y1;
diff --git a/src/screen.c b/src/screen.c
index 3664961..8a8235d 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -346,9 +346,6 @@ updateScreenBackground (CompScreen *screen,
glTexParameteri (texture->target, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBindTexture (texture->target, 0);
}
-
- screen->backgroundWidth = width;
- screen->backgroundHeight = height;
}
Bool
@@ -530,7 +527,11 @@ addScreen (CompDisplay *display,
s->paintTransformedScreen = paintTransformedScreen;
s->paintBackground = paintBackground;
s->paintWindow = paintWindow;
+ s->addWindowGeometry = addWindowGeometry;
+ s->drawWindowGeometry = drawWindowGeometry;
s->invisibleWindowMove = invisibleWindowMove;
+ s->damageWindowRect = damageWindowRect;
+ s->damageWindowRegion = damageWindowRegion;
s->getProcAddress = 0;
@@ -714,12 +715,14 @@ addScreen (CompDisplay *display,
return FALSE;
}
+ s->textureRectangle = 0;
glExtensions = (const char *) glGetString (GL_EXTENSIONS);
if (strstr (glExtensions, "GL_NV_texture_rectangle") ||
strstr (glExtensions, "GL_EXT_texture_rectangle") ||
strstr (glExtensions, "GL_ARB_texture_rectangle"))
s->textureRectangle = 1;
+ s->textureNonPowerOfTwo = 0;
if (strstr (glExtensions, "GL_ARB_texture_non_power_of_two"))
s->textureNonPowerOfTwo = 1;
@@ -730,6 +733,22 @@ addScreen (CompDisplay *display,
return FALSE;
}
+ s->textureEnvCombine = 0;
+ if (strstr (glExtensions, "GL_ARB_texture_env_combine"))
+ s->textureEnvCombine = 1;
+
+ s->maxTextureUnits = 1;
+ if (strstr (glExtensions, "GL_ARB_multitexture"))
+ {
+ s->activeTexture = (GLActiveTextureProc)
+ getProcAddress (s, "glActiveTexture");
+ s->clientActiveTexture = (GLClientActiveTextureProc)
+ getProcAddress (s, "glClientActiveTexture");
+
+ if (s->activeTexture && s->clientActiveTexture)
+ glGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &s->maxTextureUnits);
+ }
+
initTexture (s, &s->backgroundTexture);
s->desktopWindowCount = 0;
@@ -747,9 +766,18 @@ addScreen (CompDisplay *display,
glEnable (GL_CULL_FACE);
glDisable (GL_BLEND);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glColor4usv (defaultColor);
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
- glColor4usv (defaultColor);
+
+ for (i = 1; i < s->maxTextureUnits; i++)
+ {
+ s->clientActiveTexture (GL_TEXTURE0_ARB + i);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ }
+
+ if (s->maxTextureUnits > 1)
+ s->clientActiveTexture (GL_TEXTURE0_ARB);
s->activeWindow = getActiveWindow (display, s->root);
@@ -806,11 +834,18 @@ CompWindow *
findWindowAtScreen (CompScreen *s,
Window id)
{
- CompWindow *w;
+ if (lastFoundWindow && lastFoundWindow->id == id)
+ {
+ return lastFoundWindow;
+ }
+ else
+ {
+ CompWindow *w;
- for (w = s->windows; w; w = w->next)
- if (w->id == id)
- return w;
+ for (w = s->windows; w; w = w->next)
+ if (w->id == id)
+ return (lastFoundWindow = w);
+ }
return 0;
}
@@ -819,11 +854,18 @@ CompWindow *
findClientWindowAtScreen (CompScreen *s,
Window id)
{
- CompWindow *w;
+ if (lastFoundWindow && lastFoundWindow->client == id)
+ {
+ return lastFoundWindow;
+ }
+ else
+ {
+ CompWindow *w;
- for (w = s->windows; w; w = w->next)
- if (w->client == id)
- return w;
+ for (w = s->windows; w; w = w->next)
+ if (w->client == id)
+ return (lastFoundWindow = w);
+ }
return 0;
}
diff --git a/src/texture.c b/src/texture.c
index 6ef4e74..3b7d384 100644
--- a/src/texture.c
+++ b/src/texture.c
@@ -29,16 +29,21 @@
#include <comp.h>
+static CompMatrix _identity_matrix = {
+ 1, 0,
+ 0, 1,
+ 0, 0
+};
+
void
initTexture (CompScreen *screen,
CompTexture *texture)
{
texture->name = 0;
texture->target = GL_TEXTURE_2D;
- texture->dx = 0.0f;
- texture->dy = 0.0f;
texture->pixmap = None;
texture->filter = COMP_TEXTURE_FILTER_FAST;
+ texture->matrix = _identity_matrix;
}
void
@@ -90,13 +95,16 @@ readImageToTexture (CompScreen *screen,
(POWER_OF_TWO (width) && POWER_OF_TWO (height)))
{
texture->target = GL_TEXTURE_2D;
- texture->dx = 1.0f / width;
- texture->dy = 1.0f / height;
+ texture->matrix.xx = 1.0f / width;
+ texture->matrix.yy = -1.0f / height;
+ texture->matrix.y0 = 1.0f;
}
else
{
texture->target = GL_TEXTURE_RECTANGLE_NV;
- texture->dx = texture->dy = 1.0f;
+ texture->matrix.xx = 1.0f;
+ texture->matrix.yy = -1.0f;
+ texture->matrix.y0 = height;
}
if (!texture->name)
@@ -119,8 +127,8 @@ readImageToTexture (CompScreen *screen,
glTexParameteri (texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri (texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri (texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri (texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri (texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP);
glBindTexture (texture->target, 0);
@@ -177,12 +185,15 @@ bindPixmapToTexture (CompScreen *screen,
switch (target) {
case GLX_TEXTURE_2D_EXT:
texture->target = GL_TEXTURE_2D;
- texture->dx = 1.0f / width;
- texture->dy = 1.0f / height;
+ texture->matrix.xx = 1.0f / width;
+ texture->matrix.yy = -1.0f / height;
+ texture->matrix.y0 = 1.0f;
break;
case GLX_TEXTURE_RECTANGLE_EXT:
texture->target = GL_TEXTURE_RECTANGLE_ARB;
- texture->dx = texture->dy = 1.0f;
+ texture->matrix.xx = 1.0f;
+ texture->matrix.yy = -1.0f;
+ texture->matrix.y0 = height;
break;
default:
fprintf (stderr, "%s: pixmap 0x%x can't be bound to texture\n",
diff --git a/src/window.c b/src/window.c
index 8c9a126..ae6d6bb 100644
--- a/src/window.c
+++ b/src/window.c
@@ -220,6 +220,14 @@ getWindowOpacity (CompDisplay *display,
return MAXSHORT;
}
+static void
+setWindowMatrix (CompWindow *w)
+{
+ w->matrix = w->texture.matrix;
+ w->matrix.x0 -= (w->attrib.x * w->matrix.xx);
+ w->matrix.y0 -= (w->attrib.y * w->matrix.yy);
+}
+
void
bindWindow (CompWindow *w)
{
@@ -257,6 +265,8 @@ bindWindow (CompWindow *w)
"texture\n", programName, (int) w->id);
}
}
+
+ setWindowMatrix (w);
}
void
@@ -290,14 +300,47 @@ freeWindow (CompWindow *w)
if (w->privates)
free (w->privates);
+ if (w->vertices)
+ free (w->vertices);
+
+ if (w->indices)
+ free (w->indices);
+
+ if (lastFoundWindow == w)
+ lastFoundWindow = 0;
+
+ if (lastDamagedWindow == w)
+ lastDamagedWindow = 0;
+
free (w);
}
+Bool
+damageWindowRegion (CompWindow *w,
+ Region region)
+{
+ return FALSE;
+}
+
+Bool
+damageWindowRect (CompWindow *w,
+ Bool initial,
+ BoxPtr rect)
+{
+ return FALSE;
+}
+
void
addWindowDamage (CompWindow *w)
{
- if (w->attrib.map_state == IsViewable)
- damageScreenRegion (w->screen, w->region);
+ if (w->screen->allDamaged)
+ return;
+
+ if (w->attrib.map_state == IsViewable && w->damaged)
+ {
+ if (!(*w->screen->damageWindowRegion) (w, w->region))
+ damageScreenRegion (w->screen, w->region);
+ }
}
void
@@ -367,6 +410,13 @@ addWindow (CompScreen *screen,
w->texture.name = 0;
w->pixmap = None;
w->destroyed = FALSE;
+ w->damaged = FALSE;
+
+ w->vertices = 0;
+ w->vertexSize = 0;
+ w->indices = 0;
+ w->indexSize = 0;
+ w->vCount = 0;
if (screen->windowPrivateLen)
{
@@ -437,14 +487,12 @@ addWindow (CompScreen *screen,
bindWindow (w);
}
- w->invisible = WINDOW_INVISIBLE (w);
+ w->invisible = TRUE;
if (w->type == w->screen->display->winDesktopAtom)
w->screen->desktopWindowCount++;
windowInitPlugins (w);
-
- addWindowDamage (w);
}
void
@@ -484,9 +532,8 @@ mapWindow (CompWindow *w)
w->screen->desktopWindowCount++;
w->attrib.map_state = IsViewable;
- w->invisible = WINDOW_INVISIBLE (w);
-
- addWindowDamage (w);
+ w->invisible = TRUE;
+ w->damaged = FALSE;
}
void
@@ -501,7 +548,7 @@ unmapWindow (CompWindow *w)
addWindowDamage (w);
w->attrib.map_state = IsUnmapped;
- w->invisible = WINDOW_INVISIBLE (w);
+ w->invisible = TRUE;
releaseWindow (w);
}
@@ -560,6 +607,8 @@ configureWindow (CompWindow *w,
w->attrib.x = ce->x;
w->attrib.y = ce->y;
+ setWindowMatrix (w);
+
damage = TRUE;
}
else
@@ -602,4 +651,6 @@ invisibleWindowMove (CompWindow *w,
w->attrib.y += dy;
XOffsetRegion (w->region, dx, dy);
+
+ setWindowMatrix (w);
}