2
* Copyright © 2005 Novell, Inc.
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* Novell, Inc. not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* Novell, Inc. makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Author: David Reveman <davidr@novell.com>
26
#include <X11/Xatom.h>
34
#define MIN_SPEED_DEFAULT 1.5f
35
#define MIN_SPEED_MIN 0.1f
36
#define MIN_SPEED_MAX 50.0f
37
#define MIN_SPEED_PRECISION 0.1f
39
#define MIN_TIMESTEP_DEFAULT 0.5f
40
#define MIN_TIMESTEP_MIN 0.1f
41
#define MIN_TIMESTEP_MAX 50.0f
42
#define MIN_TIMESTEP_PRECISION 0.1f
44
static char *winType[] = {
50
#define N_WIN_TYPE (sizeof (winType) / sizeof (winType[0]))
52
static int displayPrivateIndex;
54
typedef struct _MinDisplay {
55
int screenPrivateIndex;
56
HandleEventProc handleEvent;
57
Atom winChangeStateAtom;
58
Atom winIconGeometryAtom;
61
#define MIN_SCREEN_OPTION_SPEED 0
62
#define MIN_SCREEN_OPTION_TIMESTEP 1
63
#define MIN_SCREEN_OPTION_WINDOW_TYPE 2
64
#define MIN_SCREEN_OPTION_NUM 3
66
typedef struct _MinScreen {
67
int windowPrivateIndex;
69
CompOption opt[MIN_SCREEN_OPTION_NUM];
71
PreparePaintScreenProc preparePaintScreen;
72
DonePaintScreenProc donePaintScreen;
73
PaintScreenProc paintScreen;
74
PaintWindowProc paintWindow;
75
DamageWindowRectProc damageWindowRect;
76
FocusWindowProc focusWindow;
86
typedef struct _MinWindow {
87
GLfloat xVelocity, yVelocity, xScaleVelocity, yScaleVelocity;
88
GLfloat xScale, yScale;
100
#define GET_MIN_DISPLAY(d) \
101
((MinDisplay *) (d)->privates[displayPrivateIndex].ptr)
103
#define MIN_DISPLAY(d) \
104
MinDisplay *md = GET_MIN_DISPLAY (d)
106
#define GET_MIN_SCREEN(s, md) \
107
((MinScreen *) (s)->privates[(md)->screenPrivateIndex].ptr)
109
#define MIN_SCREEN(s) \
110
MinScreen *ms = GET_MIN_SCREEN (s, GET_MIN_DISPLAY (s->display))
112
#define GET_MIN_WINDOW(w, ms) \
113
((MinWindow *) (w)->privates[(ms)->windowPrivateIndex].ptr)
115
#define MIN_WINDOW(w) \
116
MinWindow *mw = GET_MIN_WINDOW (w, \
117
GET_MIN_SCREEN (w->screen, \
118
GET_MIN_DISPLAY (w->screen->display)))
120
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
123
minGetScreenOptions (CompScreen *screen,
128
*count = NUM_OPTIONS (ms);
133
minSetScreenOption (CompScreen *screen,
135
CompOptionValue *value)
142
o = compFindOption (ms->opt, NUM_OPTIONS (ms), name, &index);
147
case MIN_SCREEN_OPTION_SPEED:
148
if (compSetFloatOption (o, value))
150
ms->speed = o->value.f;
154
case MIN_SCREEN_OPTION_TIMESTEP:
155
if (compSetFloatOption (o, value))
157
ms->timestep = o->value.f;
161
case MIN_SCREEN_OPTION_WINDOW_TYPE:
162
if (compSetOptionList (o, value))
164
ms->wMask = compWindowTypeMaskFromStringList (&o->value);
175
minScreenInitOptions (MinScreen *ms)
180
o = &ms->opt[MIN_SCREEN_OPTION_SPEED];
182
o->shortDesc = "Speed";
183
o->longDesc = "Minimize speed";
184
o->type = CompOptionTypeFloat;
185
o->value.f = MIN_SPEED_DEFAULT;
186
o->rest.f.min = MIN_SPEED_MIN;
187
o->rest.f.max = MIN_SPEED_MAX;
188
o->rest.f.precision = MIN_SPEED_PRECISION;
190
o = &ms->opt[MIN_SCREEN_OPTION_TIMESTEP];
191
o->name = "timestep";
192
o->shortDesc = "Timestep";
193
o->longDesc = "Minimize timestep";
194
o->type = CompOptionTypeFloat;
195
o->value.f = MIN_TIMESTEP_DEFAULT;
196
o->rest.f.min = MIN_TIMESTEP_MIN;
197
o->rest.f.max = MIN_TIMESTEP_MAX;
198
o->rest.f.precision = MIN_TIMESTEP_PRECISION;
200
o = &ms->opt[MIN_SCREEN_OPTION_WINDOW_TYPE];
201
o->name = "window_types";
202
o->shortDesc = "Window Types";
203
o->longDesc = "Window types that should be transformed when "
205
o->type = CompOptionTypeList;
206
o->value.list.type = CompOptionTypeString;
207
o->value.list.nValue = N_WIN_TYPE;
208
o->value.list.value = malloc (sizeof (CompOptionValue) * N_WIN_TYPE);
209
for (i = 0; i < N_WIN_TYPE; i++)
210
o->value.list.value[i].s = strdup (winType[i]);
211
o->rest.s.string = windowTypeString;
212
o->rest.s.nString = nWindowTypeString;
214
ms->wMask = compWindowTypeMaskFromStringList (&o->value);
218
minGetWindowIconGeometry (CompWindow *w,
223
unsigned long n, left;
226
MIN_DISPLAY (w->screen->display);
228
result = XGetWindowProperty (w->screen->display->display, w->id,
229
md->winIconGeometryAtom,
230
0L, 4L, FALSE, XA_CARDINAL, &actual, &format,
233
if (result == Success && n && data)
237
unsigned long *geometry = (unsigned long *) data;
239
rect->x = geometry[0];
240
rect->y = geometry[1];
241
rect->width = geometry[2];
242
rect->height = geometry[3];
256
minGetWindowState (CompWindow *w)
260
unsigned long n, left;
263
result = XGetWindowProperty (w->screen->display->display, w->id,
264
w->screen->display->wmStateAtom, 0L, 1L, FALSE,
265
w->screen->display->wmStateAtom,
266
&actual, &format, &n, &left, &data);
268
if (result == Success && n && data)
272
memcpy (&state, data, sizeof (int));
273
XFree ((void *) data);
278
return WithdrawnState;
282
adjustMinVelocity (CompWindow *w)
284
float dx, dy, dxs, dys, adjust, amount;
285
float x1, y1, xScale, yScale;
289
if (mw->newState == IconicState)
293
xScale = (float) mw->icon.width / w->width;
294
yScale = (float) mw->icon.height / w->height;
300
xScale = yScale = 1.0f;
303
dx = x1 - w->attrib.x;
306
amount = fabs (dx) * 1.5f;
309
else if (amount > 5.0f)
312
mw->xVelocity = (amount * mw->xVelocity + adjust) / (amount + 1.0f);
314
dy = y1 - w->attrib.y;
317
amount = fabs (dy) * 1.5f;
320
else if (amount > 5.0f)
323
mw->yVelocity = (amount * mw->yVelocity + adjust) / (amount + 1.0f);
325
dxs = xScale - mw->xScale;
327
adjust = dxs * 0.15f;
328
amount = fabs (dxs) * 10.0f;
331
else if (amount > 0.15f)
334
mw->xScaleVelocity = (amount * mw->xScaleVelocity + adjust) /
337
dys = yScale - mw->yScale;
339
adjust = dys * 0.15f;
340
amount = fabs (dys) * 10.0f;
343
else if (amount > 0.15f)
346
mw->yScaleVelocity = (amount * mw->yScaleVelocity + adjust) /
349
if (fabs (dx) < 0.1f && fabs (mw->xVelocity) < 0.2f &&
350
fabs (dy) < 0.1f && fabs (mw->yVelocity) < 0.2f &&
351
fabs (dxs) < 0.001f && fabs (mw->xScaleVelocity) < 0.002f &&
352
fabs (dys) < 0.001f && fabs (mw->yScaleVelocity) < 0.002f)
354
mw->xVelocity = mw->yVelocity = mw->xScaleVelocity =
355
mw->yScaleVelocity = 0.0f;
356
mw->tx = x1 - w->attrib.x;
357
mw->ty = y1 - w->attrib.y;
368
minPreparePaintScreen (CompScreen *s,
369
int msSinceLastPaint)
379
amount = msSinceLastPaint * 0.05f * ms->speed;
380
steps = amount / (0.5f * ms->timestep);
381
if (!steps) steps = 1;
382
chunk = amount / (float) steps;
388
for (w = s->windows; w; w = w->next)
394
mw->adjust = adjustMinVelocity (w);
396
ms->moreAdjust |= mw->adjust;
398
mw->tx += mw->xVelocity * chunk;
399
mw->ty += mw->yVelocity * chunk;
400
mw->xScale += mw->xScaleVelocity * chunk;
401
mw->yScale += mw->yScaleVelocity * chunk;
403
dx = (w->serverX + mw->tx) - w->attrib.x;
404
dy = (w->serverY + mw->ty) - w->attrib.y;
406
moveWindow (w, dx, dy, FALSE);
408
(*s->setWindowScale) (w, mw->xScale, mw->yScale);
412
mw->state = mw->newState;
429
for (w = s->windows; w; w = w->next)
439
UNWRAP (ms, s, preparePaintScreen);
440
(*s->preparePaintScreen) (s, msSinceLastPaint);
441
WRAP (ms, s, preparePaintScreen, minPreparePaintScreen);
445
minDonePaintScreen (CompScreen *s)
453
for (w = s->windows; w; w = w->next)
462
UNWRAP (ms, s, donePaintScreen);
463
(*s->donePaintScreen) (s);
464
WRAP (ms, s, donePaintScreen, minDonePaintScreen);
468
minPaintScreen (CompScreen *s,
469
const ScreenPaintAttrib *sAttrib,
478
mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
480
UNWRAP (ms, s, paintScreen);
481
status = (*s->paintScreen) (s, sAttrib, region, mask);
482
WRAP (ms, s, paintScreen, minPaintScreen);
488
minPaintWindow (CompWindow *w,
489
const WindowPaintAttrib *attrib,
493
CompScreen *s = w->screen;
500
mask |= PAINT_WINDOW_TRANSFORMED_MASK;
502
UNWRAP (ms, s, paintWindow);
503
status = (*s->paintWindow) (w, attrib, region, mask);
504
WRAP (ms, s, paintWindow, minPaintWindow);
510
minHandleEvent (CompDisplay *d,
517
switch (event->type) {
519
w = findWindowAtDisplay (d, event->xmap.window);
525
mw->state = mw->newState;
535
w = findWindowAtDisplay (d, event->xunmap.window);
536
if (w && (w->state & CompWindowStateHiddenMask))
538
MIN_SCREEN (w->screen);
540
if (!w->invisible && (ms->wMask & w->type))
544
mw->newState = IconicState;
546
if (minGetWindowIconGeometry (w, &mw->icon))
549
ms->moreAdjust = TRUE;
558
mw->state = mw->newState;
566
UNWRAP (md, d, handleEvent);
567
(*d->handleEvent) (d, event);
568
WRAP (md, d, handleEvent, minHandleEvent);
572
minDamageWindowRect (CompWindow *w,
578
MIN_SCREEN (w->screen);
580
if (initial && !w->invisible && (ms->wMask & w->type))
584
if (mw->state == IconicState)
586
if (minGetWindowIconGeometry (w, &mw->icon))
591
ms->moreAdjust = TRUE;
593
mw->tx = mw->icon.x - w->serverX;
594
mw->ty = mw->icon.y - w->serverY;
595
mw->xScale = (float) mw->icon.width / w->width;
596
mw->yScale = (float) mw->icon.height / w->height;
599
mw->icon.x - w->attrib.x,
600
mw->icon.y - w->attrib.y,
603
(*w->screen->setWindowScale) (w, mw->xScale, mw->yScale);
610
mw->newState = NormalState;
613
UNWRAP (ms, w->screen, damageWindowRect);
614
status = (*w->screen->damageWindowRect) (w, initial, rect);
615
WRAP (ms, w->screen, damageWindowRect, minDamageWindowRect);
621
minFocusWindow (CompWindow *w)
625
MIN_SCREEN (w->screen);
631
UNWRAP (ms, w->screen, focusWindow);
632
status = (*w->screen->focusWindow) (w);
633
WRAP (ms, w->screen, focusWindow, minFocusWindow);
639
minInitDisplay (CompPlugin *p,
644
md = malloc (sizeof (MinDisplay));
648
md->screenPrivateIndex = allocateScreenPrivateIndex (d);
649
if (md->screenPrivateIndex < 0)
655
md->winChangeStateAtom = XInternAtom (d->display, "WM_CHANGE_STATE", 0);
656
md->winIconGeometryAtom =
657
XInternAtom (d->display, "_NET_WM_ICON_GEOMETRY", 0);
659
WRAP (md, d, handleEvent, minHandleEvent);
661
d->privates[displayPrivateIndex].ptr = md;
667
minFiniDisplay (CompPlugin *p,
672
freeScreenPrivateIndex (d, md->screenPrivateIndex);
674
UNWRAP (md, d, handleEvent);
680
minInitScreen (CompPlugin *p,
685
MIN_DISPLAY (s->display);
687
ms = malloc (sizeof (MinScreen));
691
ms->windowPrivateIndex = allocateWindowPrivateIndex (s);
692
if (ms->windowPrivateIndex < 0)
698
ms->moreAdjust = FALSE;
700
ms->speed = MIN_SPEED_DEFAULT;
701
ms->timestep = MIN_TIMESTEP_DEFAULT;
703
minScreenInitOptions (ms);
705
WRAP (ms, s, preparePaintScreen, minPreparePaintScreen);
706
WRAP (ms, s, donePaintScreen, minDonePaintScreen);
707
WRAP (ms, s, paintScreen, minPaintScreen);
708
WRAP (ms, s, paintWindow, minPaintWindow);
709
WRAP (ms, s, damageWindowRect, minDamageWindowRect);
710
WRAP (ms, s, focusWindow, minFocusWindow);
712
s->privates[md->screenPrivateIndex].ptr = ms;
718
minFiniScreen (CompPlugin *p,
723
freeWindowPrivateIndex (s, ms->windowPrivateIndex);
725
UNWRAP (ms, s, preparePaintScreen);
726
UNWRAP (ms, s, donePaintScreen);
727
UNWRAP (ms, s, paintScreen);
728
UNWRAP (ms, s, paintWindow);
729
UNWRAP (ms, s, damageWindowRect);
730
UNWRAP (ms, s, focusWindow);
736
minInitWindow (CompPlugin *p,
741
MIN_SCREEN (w->screen);
743
mw = malloc (sizeof (MinWindow));
747
mw->xScale = mw->yScale = 1.0f;
748
mw->tx = mw->ty = 0.0f;
750
mw->xVelocity = mw->yVelocity = 0.0f;
751
mw->xScaleVelocity = mw->yScaleVelocity = 1.0f;
755
mw->state = mw->newState = minGetWindowState (w);
757
w->privates[ms->windowPrivateIndex].ptr = mw;
763
minFiniWindow (CompPlugin *p,
768
while (mw->unmapCnt--)
775
minInit (CompPlugin *p)
777
displayPrivateIndex = allocateDisplayPrivateIndex ();
778
if (displayPrivateIndex < 0)
785
minFini (CompPlugin *p)
787
if (displayPrivateIndex >= 0)
788
freeDisplayPrivateIndex (displayPrivateIndex);
791
CompPluginDep minDeps[] = {
792
{ CompPluginRuleBefore, "cube" },
793
{ CompPluginRuleBefore, "expose" }
796
static CompPluginVTable minVTable = {
799
"Transform windows when they are minimized and unminimized",
808
0, /* GetDisplayOptions */
809
0, /* SetDisplayOption */
813
sizeof (minDeps) / sizeof (minDeps[0])
817
getCompPluginInfo (void)