You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1060 lines
22 KiB
1060 lines
22 KiB
4 years ago
|
/*
|
||
|
* 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 <X11/Xatom.h>
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
#include <compiz-core.h>
|
||
|
|
||
|
static CompMetadata minMetadata;
|
||
|
|
||
|
static int displayPrivateIndex;
|
||
|
|
||
|
typedef struct _MinDisplay {
|
||
|
int screenPrivateIndex;
|
||
|
HandleEventProc handleEvent;
|
||
|
Atom winChangeStateAtom;
|
||
|
} MinDisplay;
|
||
|
|
||
|
#define MIN_SCREEN_OPTION_SPEED 0
|
||
|
#define MIN_SCREEN_OPTION_TIMESTEP 1
|
||
|
#define MIN_SCREEN_OPTION_WINDOW_MATCH 2
|
||
|
#define MIN_SCREEN_OPTION_SHADE_RESISTANCE 3
|
||
|
#define MIN_SCREEN_OPTION_NUM 4
|
||
|
|
||
|
typedef struct _MinScreen {
|
||
|
int windowPrivateIndex;
|
||
|
|
||
|
CompOption opt[MIN_SCREEN_OPTION_NUM];
|
||
|
|
||
|
PreparePaintScreenProc preparePaintScreen;
|
||
|
DonePaintScreenProc donePaintScreen;
|
||
|
PaintOutputProc paintOutput;
|
||
|
PaintWindowProc paintWindow;
|
||
|
DamageWindowRectProc damageWindowRect;
|
||
|
FocusWindowProc focusWindow;
|
||
|
|
||
|
int shadeStep;
|
||
|
int moreAdjust;
|
||
|
} MinScreen;
|
||
|
|
||
|
typedef struct _MinWindow {
|
||
|
GLfloat xVelocity, yVelocity, xScaleVelocity, yScaleVelocity;
|
||
|
GLfloat xScale, yScale;
|
||
|
GLfloat tx, ty;
|
||
|
|
||
|
Bool adjust;
|
||
|
|
||
|
int state, newState;
|
||
|
|
||
|
int shade;
|
||
|
Region region;
|
||
|
|
||
|
int unmapCnt;
|
||
|
|
||
|
Bool ignoreDamage;
|
||
|
} MinWindow;
|
||
|
|
||
|
#define GET_MIN_DISPLAY(d) \
|
||
|
((MinDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
|
||
|
|
||
|
#define MIN_DISPLAY(d) \
|
||
|
MinDisplay *md = GET_MIN_DISPLAY (d)
|
||
|
|
||
|
#define GET_MIN_SCREEN(s, md) \
|
||
|
((MinScreen *) (s)->base.privates[(md)->screenPrivateIndex].ptr)
|
||
|
|
||
|
#define MIN_SCREEN(s) \
|
||
|
MinScreen *ms = GET_MIN_SCREEN (s, GET_MIN_DISPLAY (s->display))
|
||
|
|
||
|
#define GET_MIN_WINDOW(w, ms) \
|
||
|
((MinWindow *) (w)->base.privates[(ms)->windowPrivateIndex].ptr)
|
||
|
|
||
|
#define MIN_WINDOW(w) \
|
||
|
MinWindow *mw = GET_MIN_WINDOW (w, \
|
||
|
GET_MIN_SCREEN (w->screen, \
|
||
|
GET_MIN_DISPLAY (w->screen->display)))
|
||
|
|
||
|
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
|
||
|
|
||
|
static CompOption *
|
||
|
minGetScreenOptions (CompPlugin *plugin,
|
||
|
CompScreen *screen,
|
||
|
int *count)
|
||
|
{
|
||
|
MIN_SCREEN (screen);
|
||
|
|
||
|
*count = NUM_OPTIONS (ms);
|
||
|
return ms->opt;
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
minSetScreenOption (CompPlugin *plugin,
|
||
|
CompScreen *screen,
|
||
|
const char *name,
|
||
|
CompOptionValue *value)
|
||
|
{
|
||
|
CompOption *o;
|
||
|
int index;
|
||
|
|
||
|
MIN_SCREEN (screen);
|
||
|
|
||
|
o = compFindOption (ms->opt, NUM_OPTIONS (ms), name, &index);
|
||
|
if (!o)
|
||
|
return FALSE;
|
||
|
|
||
|
switch (index) {
|
||
|
case MIN_SCREEN_OPTION_SHADE_RESISTANCE:
|
||
|
if (compSetIntOption (o, value))
|
||
|
{
|
||
|
if (o->value.i)
|
||
|
ms->shadeStep = o->rest.i.max - o->value.i + 1;
|
||
|
else
|
||
|
ms->shadeStep = 0;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
if (compSetOption (o, value))
|
||
|
return TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
minSetShade (CompWindow *w,
|
||
|
int shade)
|
||
|
{
|
||
|
REGION rect;
|
||
|
int h = w->attrib.height + w->attrib.border_width * 2;
|
||
|
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
EMPTY_REGION (w->region);
|
||
|
|
||
|
rect.rects = &rect.extents;
|
||
|
rect.numRects = rect.size = 1;
|
||
|
|
||
|
w->height = shade;
|
||
|
|
||
|
rect.extents.x1 = 0;
|
||
|
rect.extents.y1 = h - shade;
|
||
|
rect.extents.x2 = w->width;
|
||
|
rect.extents.y2 = h;
|
||
|
|
||
|
XIntersectRegion (mw->region, &rect, w->region);
|
||
|
XOffsetRegion (w->region, w->attrib.x, w->attrib.y - (h - shade));
|
||
|
|
||
|
w->matrix = w->texture->matrix;
|
||
|
w->matrix.x0 -= (w->attrib.x * w->matrix.xx);
|
||
|
w->matrix.y0 -= ((w->attrib.y - (h - shade)) * w->matrix.yy);
|
||
|
|
||
|
(*w->screen->windowResizeNotify) (w, 0, 0, 0, 0);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
minGetWindowState (CompWindow *w)
|
||
|
{
|
||
|
Atom actual;
|
||
|
int result, format;
|
||
|
unsigned long n, left;
|
||
|
unsigned char *data;
|
||
|
int retval = WithdrawnState;
|
||
|
|
||
|
result = XGetWindowProperty (w->screen->display->display, w->id,
|
||
|
w->screen->display->wmStateAtom, 0L, 1L, FALSE,
|
||
|
w->screen->display->wmStateAtom,
|
||
|
&actual, &format, &n, &left, &data);
|
||
|
|
||
|
if (result == Success && data)
|
||
|
{
|
||
|
if (n)
|
||
|
memcpy (&retval, data, sizeof (int));
|
||
|
|
||
|
XFree ((void *) data);
|
||
|
}
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
adjustMinVelocity (CompWindow *w)
|
||
|
{
|
||
|
float dx, dy, dxs, dys, adjust, amount;
|
||
|
float x1, y1, xScale, yScale;
|
||
|
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
if (mw->newState == IconicState)
|
||
|
{
|
||
|
x1 = w->iconGeometry.x;
|
||
|
y1 = w->iconGeometry.y;
|
||
|
xScale = (float) w->iconGeometry.width / w->width;
|
||
|
yScale = (float) w->iconGeometry.height / w->height;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
x1 = w->serverX;
|
||
|
y1 = w->serverY;
|
||
|
xScale = yScale = 1.0f;
|
||
|
}
|
||
|
|
||
|
dx = x1 - (w->attrib.x + mw->tx);
|
||
|
|
||
|
adjust = dx * 0.15f;
|
||
|
amount = fabs (dx) * 1.5f;
|
||
|
if (amount < 0.5f)
|
||
|
amount = 0.5f;
|
||
|
else if (amount > 5.0f)
|
||
|
amount = 5.0f;
|
||
|
|
||
|
mw->xVelocity = (amount * mw->xVelocity + adjust) / (amount + 1.0f);
|
||
|
|
||
|
dy = y1 - (w->attrib.y + mw->ty);
|
||
|
|
||
|
adjust = dy * 0.15f;
|
||
|
amount = fabs (dy) * 1.5f;
|
||
|
if (amount < 0.5f)
|
||
|
amount = 0.5f;
|
||
|
else if (amount > 5.0f)
|
||
|
amount = 5.0f;
|
||
|
|
||
|
mw->yVelocity = (amount * mw->yVelocity + adjust) / (amount + 1.0f);
|
||
|
|
||
|
dxs = xScale - mw->xScale;
|
||
|
|
||
|
adjust = dxs * 0.15f;
|
||
|
amount = fabs (dxs) * 10.0f;
|
||
|
if (amount < 0.01f)
|
||
|
amount = 0.01f;
|
||
|
else if (amount > 0.15f)
|
||
|
amount = 0.15f;
|
||
|
|
||
|
mw->xScaleVelocity = (amount * mw->xScaleVelocity + adjust) /
|
||
|
(amount + 1.0f);
|
||
|
|
||
|
dys = yScale - mw->yScale;
|
||
|
|
||
|
adjust = dys * 0.15f;
|
||
|
amount = fabs (dys) * 10.0f;
|
||
|
if (amount < 0.01f)
|
||
|
amount = 0.01f;
|
||
|
else if (amount > 0.15f)
|
||
|
amount = 0.15f;
|
||
|
|
||
|
mw->yScaleVelocity = (amount * mw->yScaleVelocity + adjust) /
|
||
|
(amount + 1.0f);
|
||
|
|
||
|
if (fabs (dx) < 0.1f && fabs (mw->xVelocity) < 0.2f &&
|
||
|
fabs (dy) < 0.1f && fabs (mw->yVelocity) < 0.2f &&
|
||
|
fabs (dxs) < 0.001f && fabs (mw->xScaleVelocity) < 0.002f &&
|
||
|
fabs (dys) < 0.001f && fabs (mw->yScaleVelocity) < 0.002f)
|
||
|
{
|
||
|
mw->xVelocity = mw->yVelocity = mw->xScaleVelocity =
|
||
|
mw->yScaleVelocity = 0.0f;
|
||
|
mw->tx = x1 - w->attrib.x;
|
||
|
mw->ty = y1 - w->attrib.y;
|
||
|
mw->xScale = xScale;
|
||
|
mw->yScale = yScale;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
minPreparePaintScreen (CompScreen *s,
|
||
|
int msSinceLastPaint)
|
||
|
{
|
||
|
MIN_SCREEN (s);
|
||
|
|
||
|
if (ms->moreAdjust)
|
||
|
{
|
||
|
CompWindow *w;
|
||
|
int steps, h;
|
||
|
float amount, chunk;
|
||
|
|
||
|
amount = msSinceLastPaint * 0.05f *
|
||
|
ms->opt[MIN_SCREEN_OPTION_SPEED].value.f;
|
||
|
steps = amount / (0.5f * ms->opt[MIN_SCREEN_OPTION_TIMESTEP].value.f);
|
||
|
if (!steps) steps = 1;
|
||
|
chunk = amount / (float) steps;
|
||
|
|
||
|
while (steps--)
|
||
|
{
|
||
|
ms->moreAdjust = 0;
|
||
|
|
||
|
for (w = s->windows; w; w = w->next)
|
||
|
{
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
if (mw->adjust)
|
||
|
{
|
||
|
mw->adjust = adjustMinVelocity (w);
|
||
|
|
||
|
ms->moreAdjust |= mw->adjust;
|
||
|
|
||
|
mw->tx += mw->xVelocity * chunk;
|
||
|
mw->ty += mw->yVelocity * chunk;
|
||
|
mw->xScale += mw->xScaleVelocity * chunk;
|
||
|
mw->yScale += mw->yScaleVelocity * chunk;
|
||
|
|
||
|
if (!mw->adjust)
|
||
|
{
|
||
|
mw->state = mw->newState;
|
||
|
|
||
|
mw->ignoreDamage = TRUE;
|
||
|
while (mw->unmapCnt)
|
||
|
{
|
||
|
unmapWindow (w);
|
||
|
mw->unmapCnt--;
|
||
|
}
|
||
|
mw->ignoreDamage = FALSE;
|
||
|
}
|
||
|
}
|
||
|
else if (mw->region && w->damaged)
|
||
|
{
|
||
|
if (w->shaded)
|
||
|
{
|
||
|
if (mw->shade > 0)
|
||
|
{
|
||
|
mw->shade -= (chunk * ms->shadeStep) + 1;
|
||
|
|
||
|
if (mw->shade > 0)
|
||
|
{
|
||
|
ms->moreAdjust = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mw->shade = 0;
|
||
|
|
||
|
mw->ignoreDamage = TRUE;
|
||
|
while (mw->unmapCnt)
|
||
|
{
|
||
|
unmapWindow (w);
|
||
|
mw->unmapCnt--;
|
||
|
}
|
||
|
mw->ignoreDamage = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
h = w->attrib.height + w->attrib.border_width * 2;
|
||
|
if (mw->shade < h)
|
||
|
{
|
||
|
mw->shade += (chunk * ms->shadeStep) + 1;
|
||
|
|
||
|
if (mw->shade < h)
|
||
|
{
|
||
|
ms->moreAdjust = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mw->shade = MAXSHORT;
|
||
|
|
||
|
minSetShade (w, h);
|
||
|
|
||
|
XDestroyRegion (mw->region);
|
||
|
mw->region = NULL;
|
||
|
|
||
|
addWindowDamage (w);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!ms->moreAdjust)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (ms->moreAdjust)
|
||
|
{
|
||
|
for (w = s->windows; w; w = w->next)
|
||
|
{
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
if (mw->adjust)
|
||
|
{
|
||
|
addWindowDamage (w);
|
||
|
}
|
||
|
else if (mw->region && w->damaged)
|
||
|
{
|
||
|
h = w->attrib.height + w->attrib.border_width * 2;
|
||
|
if (mw->shade && mw->shade < h)
|
||
|
{
|
||
|
minSetShade (w, mw->shade);
|
||
|
addWindowDamage (w);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UNWRAP (ms, s, preparePaintScreen);
|
||
|
(*s->preparePaintScreen) (s, msSinceLastPaint);
|
||
|
WRAP (ms, s, preparePaintScreen, minPreparePaintScreen);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
minDonePaintScreen (CompScreen *s)
|
||
|
{
|
||
|
MIN_SCREEN (s);
|
||
|
|
||
|
if (ms->moreAdjust)
|
||
|
{
|
||
|
CompWindow *w;
|
||
|
int h;
|
||
|
|
||
|
for (w = s->windows; w; w = w->next)
|
||
|
{
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
if (mw->adjust)
|
||
|
{
|
||
|
addWindowDamage (w);
|
||
|
}
|
||
|
else if (mw->region)
|
||
|
{
|
||
|
h = w->attrib.height + w->attrib.border_width * 2;
|
||
|
if (mw->shade && mw->shade < h)
|
||
|
addWindowDamage (w);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UNWRAP (ms, s, donePaintScreen);
|
||
|
(*s->donePaintScreen) (s);
|
||
|
WRAP (ms, s, donePaintScreen, minDonePaintScreen);
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
minPaintOutput (CompScreen *s,
|
||
|
const ScreenPaintAttrib *sAttrib,
|
||
|
const CompTransform *transform,
|
||
|
Region region,
|
||
|
CompOutput *output,
|
||
|
unsigned int mask)
|
||
|
{
|
||
|
Bool status;
|
||
|
|
||
|
MIN_SCREEN (s);
|
||
|
|
||
|
if (ms->moreAdjust)
|
||
|
mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
|
||
|
|
||
|
UNWRAP (ms, s, paintOutput);
|
||
|
status = (*s->paintOutput) (s, sAttrib, transform, region, output, mask);
|
||
|
WRAP (ms, s, paintOutput, minPaintOutput);
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
minPaintWindow (CompWindow *w,
|
||
|
const WindowPaintAttrib *attrib,
|
||
|
const CompTransform *transform,
|
||
|
Region region,
|
||
|
unsigned int mask)
|
||
|
{
|
||
|
CompScreen *s = w->screen;
|
||
|
Bool status;
|
||
|
|
||
|
MIN_SCREEN (s);
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
if (mw->adjust)
|
||
|
{
|
||
|
FragmentAttrib fragment;
|
||
|
CompTransform wTransform = *transform;
|
||
|
|
||
|
if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
|
||
|
return FALSE;
|
||
|
|
||
|
UNWRAP (ms, s, paintWindow);
|
||
|
status = (*s->paintWindow) (w, attrib, transform, region,
|
||
|
mask | PAINT_WINDOW_NO_CORE_INSTANCE_MASK);
|
||
|
WRAP (ms, s, paintWindow, minPaintWindow);
|
||
|
|
||
|
initFragmentAttrib (&fragment, &w->lastPaint);
|
||
|
|
||
|
if (w->alpha || fragment.opacity != OPAQUE)
|
||
|
mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
|
||
|
|
||
|
matrixTranslate (&wTransform, w->attrib.x, w->attrib.y, 0.0f);
|
||
|
matrixScale (&wTransform, mw->xScale, mw->yScale, 1.0f);
|
||
|
matrixTranslate (&wTransform,
|
||
|
mw->tx / mw->xScale - w->attrib.x,
|
||
|
mw->ty / mw->yScale - w->attrib.y,
|
||
|
0.0f);
|
||
|
|
||
|
glPushMatrix ();
|
||
|
glLoadMatrixf (wTransform.m);
|
||
|
|
||
|
(*s->drawWindow) (w, &wTransform, &fragment, region,
|
||
|
mask | PAINT_WINDOW_TRANSFORMED_MASK);
|
||
|
|
||
|
glPopMatrix ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* no core instance from windows that have been animated */
|
||
|
if (mw->state == IconicState)
|
||
|
mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
|
||
|
|
||
|
UNWRAP (ms, s, paintWindow);
|
||
|
status = (*s->paintWindow) (w, attrib, transform, region, mask);
|
||
|
WRAP (ms, s, paintWindow, minPaintWindow);
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
minHandleEvent (CompDisplay *d,
|
||
|
XEvent *event)
|
||
|
{
|
||
|
CompWindow *w;
|
||
|
|
||
|
MIN_DISPLAY (d);
|
||
|
|
||
|
switch (event->type) {
|
||
|
case MapNotify:
|
||
|
w = findWindowAtDisplay (d, event->xmap.window);
|
||
|
if (w)
|
||
|
{
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
if (mw->adjust)
|
||
|
mw->state = mw->newState;
|
||
|
|
||
|
if (mw->region)
|
||
|
w->height = 0;
|
||
|
|
||
|
mw->ignoreDamage = TRUE;
|
||
|
while (mw->unmapCnt)
|
||
|
{
|
||
|
unmapWindow (w);
|
||
|
mw->unmapCnt--;
|
||
|
}
|
||
|
mw->ignoreDamage = FALSE;
|
||
|
}
|
||
|
break;
|
||
|
case UnmapNotify:
|
||
|
w = findWindowAtDisplay (d, event->xunmap.window);
|
||
|
if (w)
|
||
|
{
|
||
|
MIN_SCREEN (w->screen);
|
||
|
|
||
|
if (w->pendingUnmaps && onCurrentDesktop (w)) /* Normal -> Iconic */
|
||
|
{
|
||
|
CompMatch *match =
|
||
|
&ms->opt[MIN_SCREEN_OPTION_WINDOW_MATCH].value.match;
|
||
|
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
if (w->shaded)
|
||
|
{
|
||
|
if (!mw->region)
|
||
|
mw->region = XCreateRegion ();
|
||
|
|
||
|
if (mw->region && ms->shadeStep)
|
||
|
{
|
||
|
XSubtractRegion (w->region, &emptyRegion, mw->region);
|
||
|
XOffsetRegion (mw->region, -w->attrib.x,
|
||
|
w->attrib.height +
|
||
|
w->attrib.border_width * 2 -
|
||
|
w->height - w->attrib.y);
|
||
|
|
||
|
mw->shade = w->height;
|
||
|
|
||
|
mw->adjust = FALSE;
|
||
|
ms->moreAdjust = TRUE;
|
||
|
|
||
|
mw->unmapCnt++;
|
||
|
w->unmapRefCnt++;
|
||
|
|
||
|
addWindowDamage (w);
|
||
|
}
|
||
|
}
|
||
|
else if (!w->invisible && matchEval (match, w))
|
||
|
{
|
||
|
if (w->iconGeometrySet)
|
||
|
{
|
||
|
mw->newState = IconicState;
|
||
|
|
||
|
mw->xScale = w->paint.xScale;
|
||
|
mw->yScale = w->paint.yScale;
|
||
|
mw->tx = w->attrib.x - w->serverX;
|
||
|
mw->ty = w->attrib.y - w->serverY;
|
||
|
|
||
|
if (mw->region)
|
||
|
{
|
||
|
XDestroyRegion (mw->region);
|
||
|
mw->region = NULL;
|
||
|
}
|
||
|
|
||
|
mw->shade = MAXSHORT;
|
||
|
|
||
|
mw->adjust = TRUE;
|
||
|
ms->moreAdjust = TRUE;
|
||
|
|
||
|
mw->unmapCnt++;
|
||
|
w->unmapRefCnt++;
|
||
|
|
||
|
addWindowDamage (w);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else /* X -> Withdrawn */
|
||
|
{
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
if (mw->adjust)
|
||
|
{
|
||
|
mw->adjust = FALSE;
|
||
|
mw->xScale = mw->yScale = 1.0f;
|
||
|
mw->tx = mw->ty = 0.0f;
|
||
|
mw->xVelocity = mw->yVelocity = 0.0f;
|
||
|
mw->xScaleVelocity = mw->yScaleVelocity = 1.0f;
|
||
|
mw->shade = MAXSHORT;
|
||
|
|
||
|
if (mw->region)
|
||
|
{
|
||
|
XDestroyRegion (mw->region);
|
||
|
mw->region = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mw->state = NormalState;
|
||
|
}
|
||
|
}
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
UNWRAP (md, d, handleEvent);
|
||
|
(*d->handleEvent) (d, event);
|
||
|
WRAP (md, d, handleEvent, minHandleEvent);
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
minDamageWindowRect (CompWindow *w,
|
||
|
Bool initial,
|
||
|
BoxPtr rect)
|
||
|
{
|
||
|
Bool status = FALSE;
|
||
|
|
||
|
MIN_SCREEN (w->screen);
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
if (mw->ignoreDamage)
|
||
|
return TRUE;
|
||
|
|
||
|
if (initial)
|
||
|
{
|
||
|
if (mw->state == IconicState)
|
||
|
{
|
||
|
CompMatch *match =
|
||
|
&ms->opt[MIN_SCREEN_OPTION_WINDOW_MATCH].value.match;
|
||
|
|
||
|
mw->state = NormalState;
|
||
|
|
||
|
if (!w->invisible &&
|
||
|
w->iconGeometrySet &&
|
||
|
matchEval (match, w))
|
||
|
{
|
||
|
if (!mw->adjust)
|
||
|
{
|
||
|
mw->adjust = TRUE;
|
||
|
ms->moreAdjust = TRUE;
|
||
|
|
||
|
mw->tx = w->iconGeometry.x - w->serverX;
|
||
|
mw->ty = w->iconGeometry.y - w->serverY;
|
||
|
mw->xScale = (float) w->iconGeometry.width / w->width;
|
||
|
mw->yScale = (float) w->iconGeometry.height / w->height;
|
||
|
|
||
|
addWindowDamage (w);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (mw->region && mw->shade < w->height)
|
||
|
{
|
||
|
if (ms->shadeStep && !w->invisible)
|
||
|
{
|
||
|
XSubtractRegion (w->region, &emptyRegion, mw->region);
|
||
|
XOffsetRegion (mw->region, -w->attrib.x, -w->attrib.y);
|
||
|
|
||
|
/* bind pixmap here so we have something to unshade with */
|
||
|
if (!w->texture->pixmap && !w->bindFailed)
|
||
|
bindWindow (w);
|
||
|
|
||
|
ms->moreAdjust = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mw->shade = MAXSHORT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mw->newState = NormalState;
|
||
|
}
|
||
|
else if (mw->adjust)
|
||
|
{
|
||
|
damageTransformedWindowRect (w,
|
||
|
mw->xScale,
|
||
|
mw->yScale,
|
||
|
mw->tx,
|
||
|
mw->ty,
|
||
|
rect);
|
||
|
|
||
|
status = TRUE;
|
||
|
}
|
||
|
|
||
|
UNWRAP (ms, w->screen, damageWindowRect);
|
||
|
status |= (*w->screen->damageWindowRect) (w, initial, rect);
|
||
|
WRAP (ms, w->screen, damageWindowRect, minDamageWindowRect);
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
minFocusWindow (CompWindow *w)
|
||
|
{
|
||
|
Bool status;
|
||
|
|
||
|
MIN_SCREEN (w->screen);
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
if (mw->unmapCnt)
|
||
|
return FALSE;
|
||
|
|
||
|
UNWRAP (ms, w->screen, focusWindow);
|
||
|
status = (*w->screen->focusWindow) (w);
|
||
|
WRAP (ms, w->screen, focusWindow, minFocusWindow);
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
minInitDisplay (CompPlugin *p,
|
||
|
CompDisplay *d)
|
||
|
{
|
||
|
MinDisplay *md;
|
||
|
|
||
|
if (!checkPluginABI ("core", CORE_ABIVERSION))
|
||
|
return FALSE;
|
||
|
|
||
|
md = malloc (sizeof (MinDisplay));
|
||
|
if (!md)
|
||
|
return FALSE;
|
||
|
|
||
|
md->screenPrivateIndex = allocateScreenPrivateIndex (d);
|
||
|
if (md->screenPrivateIndex < 0)
|
||
|
{
|
||
|
free (md);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
md->winChangeStateAtom = XInternAtom (d->display, "WM_CHANGE_STATE", 0);
|
||
|
|
||
|
WRAP (md, d, handleEvent, minHandleEvent);
|
||
|
|
||
|
d->base.privates[displayPrivateIndex].ptr = md;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
minFiniDisplay (CompPlugin *p,
|
||
|
CompDisplay *d)
|
||
|
{
|
||
|
MIN_DISPLAY (d);
|
||
|
|
||
|
freeScreenPrivateIndex (d, md->screenPrivateIndex);
|
||
|
|
||
|
UNWRAP (md, d, handleEvent);
|
||
|
|
||
|
free (md);
|
||
|
}
|
||
|
|
||
|
static const CompMetadataOptionInfo minScreenOptionInfo[] = {
|
||
|
{ "speed", "float", "<min>0.1</min>", 0, 0 },
|
||
|
{ "timestep", "float", "<min>0.1</min>", 0, 0 },
|
||
|
{ "window_match", "match", 0, 0, 0 },
|
||
|
{ "shade_resistance", "int", "<min>0</min><max>100</max>", 0, 0 }
|
||
|
};
|
||
|
|
||
|
static Bool
|
||
|
minInitScreen (CompPlugin *p,
|
||
|
CompScreen *s)
|
||
|
{
|
||
|
MinScreen *ms;
|
||
|
|
||
|
MIN_DISPLAY (s->display);
|
||
|
|
||
|
ms = malloc (sizeof (MinScreen));
|
||
|
if (!ms)
|
||
|
return FALSE;
|
||
|
|
||
|
if (!compInitScreenOptionsFromMetadata (s,
|
||
|
&minMetadata,
|
||
|
minScreenOptionInfo,
|
||
|
ms->opt,
|
||
|
MIN_SCREEN_OPTION_NUM))
|
||
|
{
|
||
|
free (ms);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ms->windowPrivateIndex = allocateWindowPrivateIndex (s);
|
||
|
if (ms->windowPrivateIndex < 0)
|
||
|
{
|
||
|
compFiniScreenOptions (s, ms->opt, MIN_SCREEN_OPTION_NUM);
|
||
|
free (ms);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ms->moreAdjust = FALSE;
|
||
|
ms->shadeStep = ms->opt[MIN_SCREEN_OPTION_SHADE_RESISTANCE].rest.i.max -
|
||
|
ms->opt[MIN_SCREEN_OPTION_SHADE_RESISTANCE].value.i + 1;
|
||
|
|
||
|
WRAP (ms, s, preparePaintScreen, minPreparePaintScreen);
|
||
|
WRAP (ms, s, donePaintScreen, minDonePaintScreen);
|
||
|
WRAP (ms, s, paintOutput, minPaintOutput);
|
||
|
WRAP (ms, s, paintWindow, minPaintWindow);
|
||
|
WRAP (ms, s, damageWindowRect, minDamageWindowRect);
|
||
|
WRAP (ms, s, focusWindow, minFocusWindow);
|
||
|
|
||
|
s->base.privates[md->screenPrivateIndex].ptr = ms;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
minFiniScreen (CompPlugin *p,
|
||
|
CompScreen *s)
|
||
|
{
|
||
|
MIN_SCREEN (s);
|
||
|
|
||
|
freeWindowPrivateIndex (s, ms->windowPrivateIndex);
|
||
|
|
||
|
UNWRAP (ms, s, preparePaintScreen);
|
||
|
UNWRAP (ms, s, donePaintScreen);
|
||
|
UNWRAP (ms, s, paintOutput);
|
||
|
UNWRAP (ms, s, paintWindow);
|
||
|
UNWRAP (ms, s, damageWindowRect);
|
||
|
UNWRAP (ms, s, focusWindow);
|
||
|
|
||
|
compFiniScreenOptions (s, ms->opt, MIN_SCREEN_OPTION_NUM);
|
||
|
|
||
|
free (ms);
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
minInitWindow (CompPlugin *p,
|
||
|
CompWindow *w)
|
||
|
{
|
||
|
MinWindow *mw;
|
||
|
|
||
|
MIN_SCREEN (w->screen);
|
||
|
|
||
|
mw = malloc (sizeof (MinWindow));
|
||
|
if (!mw)
|
||
|
return FALSE;
|
||
|
|
||
|
mw->xScale = mw->yScale = 1.0f;
|
||
|
mw->tx = mw->ty = 0.0f;
|
||
|
mw->adjust = FALSE;
|
||
|
mw->xVelocity = mw->yVelocity = 0.0f;
|
||
|
mw->xScaleVelocity = mw->yScaleVelocity = 1.0f;
|
||
|
|
||
|
mw->unmapCnt = 0;
|
||
|
|
||
|
mw->ignoreDamage = FALSE;
|
||
|
|
||
|
if (w->state & CompWindowStateHiddenMask)
|
||
|
{
|
||
|
if (w->shaded)
|
||
|
{
|
||
|
mw->state = mw->newState = NormalState;
|
||
|
mw->shade = 0;
|
||
|
mw->region = XCreateRegion ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mw->state = mw->newState = minGetWindowState (w);
|
||
|
mw->shade = MAXSHORT;
|
||
|
mw->region = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mw->state = mw->newState = NormalState;
|
||
|
mw->shade = MAXSHORT;
|
||
|
mw->region = NULL;
|
||
|
}
|
||
|
|
||
|
w->base.privates[ms->windowPrivateIndex].ptr = mw;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
minFiniWindow (CompPlugin *p,
|
||
|
CompWindow *w)
|
||
|
{
|
||
|
MIN_WINDOW (w);
|
||
|
|
||
|
mw->ignoreDamage = TRUE;
|
||
|
while (mw->unmapCnt--)
|
||
|
unmapWindow (w);
|
||
|
mw->ignoreDamage = FALSE;
|
||
|
|
||
|
if (mw->region)
|
||
|
XDestroyRegion (mw->region);
|
||
|
|
||
|
free (mw);
|
||
|
}
|
||
|
|
||
|
static CompBool
|
||
|
minInitObject (CompPlugin *p,
|
||
|
CompObject *o)
|
||
|
{
|
||
|
static InitPluginObjectProc dispTab[] = {
|
||
|
(InitPluginObjectProc) 0, /* InitCore */
|
||
|
(InitPluginObjectProc) minInitDisplay,
|
||
|
(InitPluginObjectProc) minInitScreen,
|
||
|
(InitPluginObjectProc) minInitWindow
|
||
|
};
|
||
|
|
||
|
RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
minFiniObject (CompPlugin *p,
|
||
|
CompObject *o)
|
||
|
{
|
||
|
static FiniPluginObjectProc dispTab[] = {
|
||
|
(FiniPluginObjectProc) 0, /* FiniCore */
|
||
|
(FiniPluginObjectProc) minFiniDisplay,
|
||
|
(FiniPluginObjectProc) minFiniScreen,
|
||
|
(FiniPluginObjectProc) minFiniWindow
|
||
|
};
|
||
|
|
||
|
DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
|
||
|
}
|
||
|
|
||
|
static CompOption *
|
||
|
minGetObjectOptions (CompPlugin *plugin,
|
||
|
CompObject *object,
|
||
|
int *count)
|
||
|
{
|
||
|
static GetPluginObjectOptionsProc dispTab[] = {
|
||
|
(GetPluginObjectOptionsProc) 0, /* GetCoreOptions */
|
||
|
(GetPluginObjectOptionsProc) 0, /* GetDisplayOptions */
|
||
|
(GetPluginObjectOptionsProc) minGetScreenOptions
|
||
|
};
|
||
|
|
||
|
*count = 0;
|
||
|
RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab),
|
||
|
(void *) count, (plugin, object, count));
|
||
|
}
|
||
|
|
||
|
static CompBool
|
||
|
minSetObjectOption (CompPlugin *plugin,
|
||
|
CompObject *object,
|
||
|
const char *name,
|
||
|
CompOptionValue *value)
|
||
|
{
|
||
|
static SetPluginObjectOptionProc dispTab[] = {
|
||
|
(SetPluginObjectOptionProc) 0, /* SetCoreOption */
|
||
|
(SetPluginObjectOptionProc) 0, /* SetDisplayOption */
|
||
|
(SetPluginObjectOptionProc) minSetScreenOption
|
||
|
};
|
||
|
|
||
|
RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab), FALSE,
|
||
|
(plugin, object, name, value));
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
minInit (CompPlugin *p)
|
||
|
{
|
||
|
if (!compInitPluginMetadataFromInfo (&minMetadata,
|
||
|
p->vTable->name, 0, 0,
|
||
|
minScreenOptionInfo,
|
||
|
MIN_SCREEN_OPTION_NUM))
|
||
|
return FALSE;
|
||
|
|
||
|
displayPrivateIndex = allocateDisplayPrivateIndex ();
|
||
|
if (displayPrivateIndex < 0)
|
||
|
{
|
||
|
compFiniMetadata (&minMetadata);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
compAddMetadataFromFile (&minMetadata, p->vTable->name);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
minFini (CompPlugin *p)
|
||
|
{
|
||
|
freeDisplayPrivateIndex (displayPrivateIndex);
|
||
|
compFiniMetadata (&minMetadata);
|
||
|
}
|
||
|
|
||
|
static CompMetadata *
|
||
|
minGetMetadata (CompPlugin *plugin)
|
||
|
{
|
||
|
return &minMetadata;
|
||
|
}
|
||
|
|
||
|
static CompPluginVTable minVTable = {
|
||
|
"minimize",
|
||
|
minGetMetadata,
|
||
|
minInit,
|
||
|
minFini,
|
||
|
minInitObject,
|
||
|
minFiniObject,
|
||
|
minGetObjectOptions,
|
||
|
minSetObjectOption
|
||
|
};
|
||
|
|
||
|
CompPluginVTable *
|
||
|
getCompPluginInfo20070830 (void)
|
||
|
{
|
||
|
return &minVTable;
|
||
|
}
|