diff options
author | Zack Rusin <zack@kde.org> | 2006-01-02 07:11:21 +0000 |
---|---|---|
committer | Zack Rusin <zack@kde.org> | 2006-01-02 07:11:21 +0000 |
commit | ba0bd60b9261a0bcedba9dfc1905d8929e14d440 (patch) | |
tree | 93be25405222a4e0732ccdf1511ddd92534adc30 | |
parent | 7f820289fc18e20881b56227cef6d0f1b5353f3d (diff) |
updating from airlied copy and adding cvsignores
-rw-r--r-- | .cvsignore | 13 | ||||
-rw-r--r-- | README | 5 | ||||
-rw-r--r-- | images/.cvsignore | 2 | ||||
-rw-r--r-- | include/.cvsignore | 2 | ||||
-rw-r--r-- | include/comp.h | 153 | ||||
-rw-r--r-- | plugins/.cvsignore | 6 | ||||
-rw-r--r-- | plugins/Makefile.am | 5 | ||||
-rw-r--r-- | plugins/cube.c | 23 | ||||
-rw-r--r-- | plugins/expose.c | 35 | ||||
-rw-r--r-- | plugins/fade.c | 40 | ||||
-rw-r--r-- | plugins/gconf.c | 126 | ||||
-rw-r--r-- | plugins/rotate.c | 78 | ||||
-rw-r--r-- | plugins/shadow.c | 902 | ||||
-rw-r--r-- | plugins/wobbly.c | 467 | ||||
-rw-r--r-- | src/.cvsignore | 5 | ||||
-rw-r--r-- | src/display.c | 24 | ||||
-rw-r--r-- | src/event.c | 64 | ||||
-rw-r--r-- | src/glxcompmgr.c | 11 | ||||
-rw-r--r-- | src/paint.c | 399 | ||||
-rw-r--r-- | src/screen.c | 66 | ||||
-rw-r--r-- | src/texture.c | 31 | ||||
-rw-r--r-- | src/window.c | 69 |
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 @@ -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 = ®ion.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, ®ion); + + 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, + ®ion.extents)) + { + region.rects = ®ion.extents; + region.numRects = region.size = 1; - damageScreenRegion (screen, &rect); + damageScreenRegion (w->screen, ®ion); + } + } + } + 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 = ®ion->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); } |