Merge lp:~mc-return/compiz/compiz.merge-plugin-stackswitch into lp:compiz/0.9.8

Proposed by MC Return
Status: Merged
Approved by: Didier Roche-Tolomelli
Approved revision: 3257
Merged at revision: 3277
Proposed branch: lp:~mc-return/compiz/compiz.merge-plugin-stackswitch
Merge into: lp:compiz/0.9.8
Diff against target: 1851 lines (+1825/-0)
5 files modified
plugins/stackswitch/CMakeLists.txt (+5/-0)
plugins/stackswitch/VERSION (+1/-0)
plugins/stackswitch/src/stackswitch.cpp (+1387/-0)
plugins/stackswitch/src/stackswitch.h (+239/-0)
plugins/stackswitch/stackswitch.xml.in (+193/-0)
To merge this branch: bzr merge lp:~mc-return/compiz/compiz.merge-plugin-stackswitch
Reviewer Review Type Date Requested Status
Daniel van Vugt Approve
Didier Roche-Tolomelli Pending
Sam Spilsbury Pending
Review via email: mp+111736@code.launchpad.net

Commit message

Added the plug-in "Stack Window Switcher" converted from git to bzr (including full history) to Compiz

Description of the change

Adds the plug-in "Stack Window Switcher" converted from git to bzr (including full history) to Compiz

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) :
review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-compiz-core/12/console reported an error when processing this lp:~mc-return/compiz/compiz.merge-plugin-stackswitch branch.
Not merging it.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

That's a problem with the auto-merger. Not a problem with the branch...

dh_install: usr/share/compiz/stackswitch.xml exists in debian/tmp but is not installed to anywhere
dh_install: usr/lib/compiz/libstackswitch.so exists in debian/tmp but is not installed to anywhere
dh_install: missing files, aborting

Revision history for this message
MC Return (mc-return) wrote :

Thanks, Daniel, for approving the branch merge.
How can we fix this auto-merger problem ?

Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote :

see our discussion on IRC, upstream should know in advance when they ship new files or add/change build-depencies :)

Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote :

packaging changed

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'plugins/stackswitch'
2=== added file 'plugins/stackswitch/CMakeLists.txt'
3--- plugins/stackswitch/CMakeLists.txt 1970-01-01 00:00:00 +0000
4+++ plugins/stackswitch/CMakeLists.txt 2012-06-24 07:14:19 +0000
5@@ -0,0 +1,5 @@
6+find_package (Compiz REQUIRED)
7+
8+include (CompizPlugin)
9+
10+compiz_plugin (stackswitch PLUGINDEPS opengl composite text)
11
12=== added file 'plugins/stackswitch/VERSION'
13--- plugins/stackswitch/VERSION 1970-01-01 00:00:00 +0000
14+++ plugins/stackswitch/VERSION 2012-06-24 07:14:19 +0000
15@@ -0,0 +1,1 @@
16+0.9.5.0
17
18=== added directory 'plugins/stackswitch/src'
19=== added file 'plugins/stackswitch/src/stackswitch.cpp'
20--- plugins/stackswitch/src/stackswitch.cpp 1970-01-01 00:00:00 +0000
21+++ plugins/stackswitch/src/stackswitch.cpp 2012-06-24 07:14:19 +0000
22@@ -0,0 +1,1387 @@
23+/*
24+ *
25+ * Compiz stackswitch switcher plugin
26+ *
27+ * stackswitch.cpp
28+ *
29+ * Copyright : (C) 2007 by Danny Baumann
30+ * E-mail : maniac@opencompositing.org
31+ *
32+ * Based on scale.c and switcher.c:
33+ * Copyright : (C) 2007 David Reveman
34+ * E-mail : davidr@novell.com
35+ *
36+ * This program is free software; you can redistribute it and/or
37+ * modify it under the terms of the GNU General Public License
38+ * as published by the Free Software Foundation; either version 2
39+ * of the License, or (at your option) any later version.
40+ *
41+ * This program is distributed in the hope that it will be useful,
42+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
43+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44+ * GNU General Public License for more details.
45+ *
46+ */
47+
48+#include "stackswitch.h"
49+
50+COMPIZ_PLUGIN_20090315 (stackswitch, StackswitchPluginVTable)
51+
52+bool textAvailable;
53+
54+bool
55+StackswitchWindow::isStackswitchable ()
56+{
57+ STACKSWITCH_SCREEN (screen);
58+
59+ if (window->overrideRedirect ())
60+ return false;
61+
62+ if (window->wmType () & (CompWindowTypeDockMask | CompWindowTypeDesktopMask))
63+ return false;
64+
65+ if (!window->mapNum () || !window->isViewable ())
66+ {
67+ if (ss->optionGetMinimized ())
68+ {
69+ if (!window->minimized () && !window->inShowDesktopMode () && !window->shaded ())
70+ return false;
71+ }
72+ else
73+ return false;
74+ }
75+
76+ if (ss->mType == StackswitchTypeNormal)
77+ {
78+ if (!window->mapNum () || !window->isViewable ())
79+ {
80+ if (window->serverX () + window->width () <= 0 ||
81+ window->serverY () + window->height () <= 0 ||
82+ window->serverX () >= screen->width () ||
83+ window->serverY () >= screen->height ())
84+ return false;
85+ }
86+ else
87+ {
88+ if (!window->focus ())
89+ return false;
90+ }
91+ }
92+ else if (ss->mType == StackswitchTypeGroup &&
93+ ss->mClientLeader != window->clientLeader () &&
94+ ss->mClientLeader != window->id ())
95+ {
96+ return false;
97+ }
98+
99+ if (window->state () & CompWindowStateSkipTaskbarMask)
100+ return false;
101+
102+ if (!ss->mCurrentMatch.evaluate (window))
103+ return false;
104+
105+ return true;
106+}
107+
108+void
109+StackswitchScreen::renderWindowTitle ()
110+{
111+ CompText::Attrib tA;
112+ bool showViewport;
113+
114+ if (!textAvailable)
115+ return;
116+
117+ if (!optionGetWindowTitle ())
118+ return;
119+
120+ CompRect oe = screen->getCurrentOutputExtents ();
121+
122+ /* 75% of the output device as maximum width */
123+ tA.maxWidth = oe.width () * 3 / 4;
124+ tA.maxHeight = 100;
125+
126+ tA.family = "Sans";
127+ tA.size = optionGetTitleFontSize ();
128+ tA.color[0] = optionGetTitleFontColorRed ();
129+ tA.color[1] = optionGetTitleFontColorGreen ();
130+ tA.color[2] = optionGetTitleFontColorBlue ();
131+ tA.color[3] = optionGetTitleFontColorAlpha ();
132+
133+ tA.flags = CompText::WithBackground | CompText::Ellipsized;
134+ if (optionGetTitleFontBold ())
135+ tA.flags |= CompText::StyleBold;
136+
137+ tA.bgHMargin = 15;
138+ tA.bgVMargin = 15;
139+ tA.bgColor[0] = optionGetTitleBackColorRed ();
140+ tA.bgColor[1] = optionGetTitleBackColorGreen ();
141+ tA.bgColor[2] = optionGetTitleBackColorBlue ();
142+ tA.bgColor[3] = optionGetTitleBackColorAlpha ();
143+
144+ showViewport = (mType == StackswitchTypeAll);
145+ mText.renderWindowTitle (mSelectedWindow, showViewport, tA);
146+}
147+
148+void
149+StackswitchScreen::drawWindowTitle (GLMatrix &transform,
150+ CompWindow *w)
151+{
152+ GLboolean wasBlend;
153+ GLint oldBlendSrc, oldBlendDst;
154+ GLMatrix wTransform (transform), mvp;
155+ float x, y, tx, width, height;
156+ GLTexture::Matrix m;
157+ GLTexture *icon;
158+
159+ STACKSWITCH_WINDOW (w);
160+
161+ CompRect oe = screen->getCurrentOutputExtents ();
162+
163+ width = mText.getWidth ();
164+ height = mText.getHeight ();
165+
166+ x = oe.centerX ();
167+ tx = x - width / 2;
168+
169+ switch (optionGetTitleTextPlacement ())
170+ {
171+ case StackswitchOptions::TitleTextPlacementOnThumbnail:
172+ {
173+ GLVector v (w->x () + (w->width () / 2.0),
174+ w->y () + (w->width () / 2.0),
175+ 0.0f,
176+ 1.0f);
177+ GLMatrix pm (gScreen->projectionMatrix ());
178+
179+ wTransform.scale (1.0, 1.0, 1.0 / screen->height ());
180+ wTransform.translate (sw->mTx, sw->mTy, 0.0f);
181+ wTransform.rotate (-mRotation, 1.0, 0.0, 0.0);
182+ wTransform.scale (sw->mScale, sw->mScale, 1.0);
183+ wTransform.translate (+w->border ().left, 0.0 - (w->height () +
184+ w->border ().bottom),
185+ 0.0f);
186+ wTransform.translate (-w->x (), -w->y (), 0.0f);
187+
188+ mvp = pm * wTransform;
189+ v = mvp * v;
190+ v.homogenize ();
191+
192+ x = (v[GLVector::x] + 1.0) * oe.width () * 0.5;
193+ y = (v[GLVector::y] - 1.0) * oe.height () * -0.5;
194+
195+ x += oe.x1 ();
196+ y += oe.y1 ();
197+
198+ tx = MAX (oe.x1 (), x - (width / 2.0));
199+ if (tx + width > oe.x2 ())
200+ tx = oe.x2 () - width;
201+ }
202+ break;
203+ case StackswitchOptions::TitleTextPlacementCenteredOnScreen:
204+ y = oe.centerY () + height / 2;
205+ break;
206+ case StackswitchOptions::TitleTextPlacementAbove:
207+ case StackswitchOptions::TitleTextPlacementBelow:
208+ {
209+ CompRect workArea = screen->currentOutputDev ().workArea ();
210+
211+ if (optionGetTitleTextPlacement () ==
212+ StackswitchOptions::TitleTextPlacementAbove)
213+ y = oe.y1 () + workArea.y () + height;
214+ else
215+ y = oe.y1 () + workArea.y2 () - 96;
216+ }
217+ break;
218+ default:
219+ return;
220+ break;
221+ }
222+
223+ tx = floor (tx);
224+ y = floor (y);
225+
226+ glGetIntegerv (GL_BLEND_SRC, &oldBlendSrc);
227+ glGetIntegerv (GL_BLEND_DST, &oldBlendDst);
228+
229+ wasBlend = glIsEnabled (GL_BLEND);
230+ if (!wasBlend)
231+ glEnable (GL_BLEND);
232+
233+ glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
234+
235+ glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
236+ glColor4f (1.0, 1.0, 1.0, 1.0);
237+
238+ glPushMatrix ();
239+ glLoadMatrixf (wTransform.getMatrix ());
240+
241+ icon = sw->gWindow->getIcon (96, 96);
242+ if (!icon)
243+ icon = gScreen->defaultIcon ();
244+
245+ if (icon && (icon->name ()))
246+ {
247+ int off;
248+ float ix = floor (x - (icon->width () / 2.0));
249+
250+ icon->enable (GLTexture::Good);
251+
252+ m = icon->matrix ();
253+
254+ glColor4f (0.0, 0.0, 0.0, 0.1);
255+
256+ for (off = 0; off < 6; off++)
257+ {
258+ glBegin (GL_QUADS);
259+
260+ glTexCoord2f (COMP_TEX_COORD_X (m, 0), COMP_TEX_COORD_Y (m ,0));
261+ glVertex2f (ix - off, y - off);
262+ glTexCoord2f (COMP_TEX_COORD_X (m, 0), COMP_TEX_COORD_Y (m, icon->height ()));
263+ glVertex2f (ix - off, y + icon->height () + off);
264+ glTexCoord2f (COMP_TEX_COORD_X (m, icon->width ()), COMP_TEX_COORD_Y (m, icon->height ()));
265+ glVertex2f (ix + icon->width () + off, y + icon->height () + off);
266+ glTexCoord2f (COMP_TEX_COORD_X (m, icon->width ()), COMP_TEX_COORD_Y (m, 0));
267+ glVertex2f (ix + icon->width () + off, y - off);
268+
269+ glEnd ();
270+ }
271+
272+ glColor4f (1.0, 1.0, 1.0, 1.0);
273+
274+ glBegin (GL_QUADS);
275+
276+ glTexCoord2f (COMP_TEX_COORD_X (m, 0), COMP_TEX_COORD_Y (m ,0));
277+ glVertex2f (ix, y);
278+ glTexCoord2f (COMP_TEX_COORD_X (m, 0), COMP_TEX_COORD_Y (m, icon->height ()));
279+ glVertex2f (ix, y + icon->height ());
280+ glTexCoord2f (COMP_TEX_COORD_X (m, icon->width ()), COMP_TEX_COORD_Y (m, icon->height ()));
281+ glVertex2f (ix + icon->width (), y + icon->height ());
282+ glTexCoord2f (COMP_TEX_COORD_X (m, icon->width ()), COMP_TEX_COORD_Y (m, 0));
283+ glVertex2f (ix + icon->width (), y);
284+
285+ glEnd ();
286+
287+ icon->disable ();
288+ }
289+
290+ mText.draw (x - mText.getWidth () / 2, y, 1.0);
291+
292+ glPopMatrix ();
293+
294+ glColor4usv (defaultColor);
295+
296+ if (!wasBlend)
297+ glDisable (GL_BLEND);
298+ glBlendFunc (oldBlendSrc, oldBlendDst);
299+}
300+
301+bool
302+StackswitchWindow::glPaint (const GLWindowPaintAttrib &attrib,
303+ const GLMatrix &transform,
304+ const CompRegion &region,
305+ unsigned int mask)
306+{
307+ bool status;
308+
309+ STACKSWITCH_SCREEN (screen);
310+
311+ if (ss->mState != StackswitchStateNone)
312+ {
313+ GLWindowPaintAttrib sAttrib (attrib);
314+ bool scaled = false;
315+ float rotation;
316+
317+ if (window->mapNum ())
318+ {
319+ if (!gWindow->textures ().size ())
320+ gWindow->bind ();
321+ }
322+
323+ if (mAdjust || mSlot)
324+ {
325+ scaled = (mAdjust && ss->mState != StackswitchStateSwitching) ||
326+ (mSlot && ss->mPaintingSwitcher);
327+ mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
328+ }
329+ else if (ss->mState != StackswitchStateIn)
330+ {
331+ if (ss->optionGetDarkenBack ())
332+ {
333+ /* modify brightness of the other windows */
334+ sAttrib.brightness = sAttrib.brightness / 2;
335+ }
336+ }
337+
338+ status = gWindow->glPaint (attrib, transform, region, mask);
339+
340+ if (ss->optionGetInactiveRotate ())
341+ rotation = MIN (mRotation, ss->mRotation);
342+ else
343+ rotation = ss->mRotation;
344+
345+ if (scaled && gWindow->textures ().size ())
346+ {
347+ GLFragment::Attrib fragment (gWindow->lastPaintAttrib ());
348+ GLMatrix wTransform (transform);
349+
350+ if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
351+ return false;
352+
353+ if (mSlot)
354+ {
355+ if (window->id () != ss->mSelectedWindow)
356+ fragment.setOpacity ((float)fragment.getOpacity () *
357+ ss->optionGetInactiveOpacity () / 100);
358+ }
359+
360+ if (window->alpha () || fragment.getOpacity () != OPAQUE)
361+ mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
362+
363+ wTransform.scale (1.0, 1.0, 1.0 / screen->height ());
364+ wTransform.translate (mTx, mTy, 0.0f);
365+
366+ wTransform.rotate (-rotation, 1.0, 0.0, 0.0);
367+ wTransform.scale (mScale, mScale, 1.0);
368+
369+ wTransform.translate (+window->border ().left,
370+ 0.0 -(window->height () +
371+ window->border ().bottom), 0.0f);
372+ wTransform.translate (-window->x (), -window->y (), 0.0f);
373+ glPushMatrix ();
374+ glLoadMatrixf (wTransform.getMatrix ());
375+
376+ gWindow->glDraw (wTransform, fragment, region,
377+ mask | PAINT_WINDOW_TRANSFORMED_MASK);
378+
379+ glPopMatrix ();
380+ }
381+
382+ if (scaled && !gWindow->textures ().size ())
383+ {
384+ GLTexture *icon = gWindow->getIcon (96, 96);
385+ if (!icon)
386+ icon = ss->gScreen->defaultIcon ();
387+
388+ if (icon && (icon->name ()))
389+ {
390+ CompRegion iconReg (0, 0,
391+ icon->width (),
392+ icon->height ());
393+ GLTexture::Matrix matrix;
394+ float scale;
395+
396+ scale = MIN (window->width () / icon->width (),
397+ window->height () / icon->height ());
398+ scale *= mScale;
399+
400+ mask |= PAINT_WINDOW_BLEND_MASK;
401+
402+ /* if we paint the icon for a minimized window, we need
403+ to force the usage of a good texture filter */
404+ if (!gWindow->textures ().size ())
405+ mask |= PAINT_WINDOW_TRANSFORMED_MASK;
406+
407+ matrix = icon->matrix ();
408+
409+ GLTexture::MatrixList matl;
410+ matl.push_back (matrix);
411+
412+ gWindow->geometry ().reset ();
413+ gWindow->glAddGeometry (matl, iconReg, infiniteRegion);
414+
415+ if (gWindow->geometry ().vCount)
416+ {
417+ GLFragment::Attrib fragment (attrib);
418+ GLMatrix wTransform (transform);
419+
420+ if (!gWindow->textures ().size ())
421+ fragment.setOpacity (gWindow->paintAttrib ().opacity);
422+
423+ wTransform.scale (1.0, 1.0, 1.0 / screen->height ());
424+ wTransform.translate (mTx, mTy, 0.0f);
425+
426+ wTransform.rotate (-rotation, 1.0, 0.0, 0.0);
427+ wTransform.scale (scale, scale, 1.0);
428+
429+ wTransform.translate (0.0, -icon->height (), 0.0f);
430+
431+ glPushMatrix ();
432+ glLoadMatrixf (wTransform.getMatrix ());
433+
434+ gWindow->glDrawTexture (icon, fragment, mask);
435+
436+ glPopMatrix ();
437+ }
438+ }
439+ }
440+ }
441+ else
442+ {
443+ status = gWindow->glPaint (attrib, transform, region, mask);
444+ }
445+
446+ return status;
447+}
448+
449+int
450+compareWindows (const void *elem1,
451+ const void *elem2)
452+{
453+ CompWindow *w1 = *((CompWindow **) elem1);
454+ CompWindow *w2 = *((CompWindow **) elem2);
455+
456+ if (w1->mapNum () && !w2->mapNum ())
457+ return -1;
458+
459+ if (w2->mapNum () && !w1->mapNum ())
460+ return 1;
461+
462+ return w2->activeNum () - w1->activeNum ();
463+}
464+
465+int
466+compareStackswitchWindowDepth (const void *elem1,
467+ const void *elem2)
468+{
469+ StackswitchSlot *a1 = *(((StackswitchDrawSlot *) elem1)->slot);
470+ StackswitchSlot *a2 = *(((StackswitchDrawSlot *) elem2)->slot);
471+
472+ if (a1->y < a2->y)
473+ return -1;
474+ else if (a1->y > a2->y)
475+ return 1;
476+ else
477+ {
478+ CompWindow *a1 = (((StackswitchDrawSlot *) elem1)->w);
479+ CompWindow *a2 = (((StackswitchDrawSlot *) elem2)->w);
480+ STACKSWITCH_SCREEN (screen);
481+ if (a1->id () == ss->mSelectedWindow)
482+ return 1;
483+ else if (a2->id () == ss->mSelectedWindow)
484+ return -1;
485+ else
486+ return 0;
487+ }
488+}
489+
490+bool
491+StackswitchScreen::layoutThumbs ()
492+{
493+ CompWindow *w;
494+ int index;
495+ int ww, wh;
496+ float xScale, yScale;
497+ float swi = 0.0, rh;
498+ int cols, rows, col = 0, row = 0, r, c;
499+ int cindex, ci, gap, hasActive = 0;
500+ bool exit;
501+
502+ if ((mState == StackswitchStateNone) || (mState == StackswitchStateIn))
503+ return false;
504+
505+ CompRect oe = screen->getCurrentOutputExtents ();
506+
507+ for (index = 0; index < mNWindows; index++)
508+ {
509+ w = mWindows[index];
510+
511+ ww = w->width () + w->border ().left + w->border ().right;
512+ wh = w->height () + w->border ().top + w->border ().bottom;
513+
514+ swi += ((float) ww / (float) wh) * (oe.width () / (float) oe.height ());
515+ }
516+
517+ cols = ceil (sqrtf (swi));
518+
519+ swi = 0.0;
520+ for (index = 0; index < mNWindows; index++)
521+ {
522+ w = mWindows[index];
523+
524+ ww = w->width () + w->border ().left + w->border ().right;
525+ wh = w->height () + w->border ().top + w->border ().bottom;
526+
527+ swi += (float)ww / (float)wh;
528+
529+ if (swi > cols)
530+ {
531+ row++;
532+ swi = (float)ww / (float)wh;
533+ col = 0;
534+ }
535+
536+ col++;
537+ }
538+ rows = row + 1;
539+
540+ oe.setHeight (oe.width () / cols);
541+ rh = ((float) oe.height () * 0.8) / rows;
542+
543+ for (index = 0; index < mNWindows; index++)
544+ {
545+ w = mWindows[index];
546+
547+ STACKSWITCH_WINDOW (w);
548+
549+ if (!sw->mSlot)
550+ sw->mSlot = (StackswitchSlot *) malloc (sizeof (StackswitchSlot));
551+
552+ if (!sw->mSlot)
553+ return false;
554+
555+ mDrawSlots[index].w = w;
556+ mDrawSlots[index].slot = &sw->mSlot;
557+ }
558+
559+ index = 0;
560+
561+ for (r = 0; r < rows && index < mNWindows; r++)
562+ {
563+ c = 0;
564+ swi = 0.0;
565+ cindex = index;
566+ exit = false;
567+ while (index < mNWindows && !exit)
568+ {
569+ w = mWindows[index];
570+
571+ STACKSWITCH_WINDOW (w);
572+ sw->mSlot->x = oe.x1 () + swi;
573+ sw->mSlot->y = oe.y2 () - (rh * r) - (oe.height () * 0.1);
574+
575+ ww = w->width () + w->border ().left + w->border ().right;
576+ wh = w->height () + w->border ().top + w->border ().bottom;
577+
578+ if (ww > oe.width ())
579+ xScale = oe.width () / (float) ww;
580+ else
581+ xScale = 1.0f;
582+
583+ if (wh > oe.height ())
584+ yScale = oe.height () / (float) wh;
585+ else
586+ yScale = 1.0f;
587+
588+ sw->mSlot->scale = MIN (xScale, yScale);
589+
590+ if (swi + (ww * sw->mSlot->scale) > oe.width () && cindex != index)
591+ {
592+ exit = true;
593+ continue;
594+ }
595+
596+ if (w->id () == mSelectedWindow)
597+ hasActive = 1;
598+ swi += ww * sw->mSlot->scale;
599+
600+ c++;
601+ index++;
602+ }
603+
604+ gap = oe.width () - swi;
605+ gap /= c + 1;
606+
607+ index = cindex;
608+ ci = 1;
609+ while (ci <= c)
610+ {
611+ w = mWindows[index];
612+
613+ STACKSWITCH_WINDOW (w);
614+ sw->mSlot->x += ci * gap;
615+
616+ if (hasActive == 0)
617+ sw->mSlot->y += sqrt(2 * oe.height () * oe.height ()) - rh;
618+
619+ ci++;
620+ index++;
621+ }
622+
623+ if (hasActive == 1)
624+ hasActive++;
625+ }
626+
627+ /* sort the draw list so that the windows with the
628+ lowest Y value (the windows being farest away)
629+ are drawn first */
630+ qsort (mDrawSlots, mNWindows, sizeof (StackswitchDrawSlot),
631+ compareStackswitchWindowDepth);
632+
633+ return true;
634+}
635+
636+void
637+StackswitchScreen::addWindowToList (CompWindow *w)
638+{
639+ if (mWindowsSize <= mNWindows)
640+ {
641+ mWindows = (CompWindow **) realloc (mWindows,
642+ sizeof (CompWindow *) * (mNWindows + 32));
643+ if (!mWindows)
644+ return;
645+
646+ mDrawSlots = (StackswitchDrawSlot *) realloc (mDrawSlots,
647+ sizeof (StackswitchDrawSlot) * (mNWindows + 32));
648+
649+ if (!mDrawSlots)
650+ {
651+ free (mDrawSlots);
652+ return;
653+ }
654+
655+ mWindowsSize = mNWindows + 32;
656+ }
657+
658+ mWindows[mNWindows++] = w;
659+}
660+
661+bool
662+StackswitchScreen::updateWindowList ()
663+{
664+ qsort (mWindows, mNWindows, sizeof (CompWindow *), compareWindows);
665+
666+ return layoutThumbs ();
667+}
668+
669+bool
670+StackswitchScreen::createWindowList ()
671+{
672+ mNWindows = 0;
673+
674+ foreach (CompWindow *w, screen->windows ())
675+ {
676+ STACKSWITCH_WINDOW (w);
677+
678+ if (sw->isStackswitchable ())
679+ {
680+ STACKSWITCH_WINDOW (w);
681+
682+ addWindowToList (w);
683+ sw->mAdjust = true;
684+ }
685+ }
686+
687+ return updateWindowList ();
688+}
689+
690+void
691+StackswitchScreen::switchToWindow (bool toNext)
692+{
693+ CompWindow *w;
694+ int cur;
695+
696+ if (!mGrabIndex)
697+ return;
698+
699+ for (cur = 0; cur < mNWindows; cur++)
700+ {
701+ if (mWindows[cur]->id () == mSelectedWindow)
702+ break;
703+ }
704+
705+ if (cur == mNWindows)
706+ return;
707+
708+ if (toNext)
709+ w = mWindows[(cur + 1) % mNWindows];
710+ else
711+ w = mWindows[(cur + mNWindows - 1) % mNWindows];
712+
713+ if (w)
714+ {
715+ Window old = mSelectedWindow;
716+
717+ mSelectedWindow = w->id ();
718+ if (old != w->id ())
719+ {
720+ mRotateAdjust = true;
721+ mMoreAdjust = true;
722+ foreach (CompWindow *w, screen->windows ())
723+ {
724+ STACKSWITCH_WINDOW (w);
725+ sw->mAdjust = true;
726+ }
727+
728+ cScreen->damageScreen ();
729+ renderWindowTitle ();
730+ }
731+ }
732+}
733+
734+int
735+StackswitchScreen::countWindows ()
736+{
737+ CompWindow *w;
738+ int count = 0;
739+
740+ foreach (w, screen->windows ())
741+ {
742+ if (StackswitchWindow::get (w)->isStackswitchable ())
743+ count++;
744+ }
745+
746+ return count;
747+}
748+
749+int
750+StackswitchScreen::adjustStackswitchRotation (float chunk)
751+{
752+ float dx, adjust, amount, rot;
753+
754+ if (mState != StackswitchStateNone && mState != StackswitchStateIn)
755+ rot = optionGetTilt ();
756+ else
757+ rot = 0.0;
758+
759+ dx = rot - mRotation;
760+
761+ adjust = dx * 0.15f;
762+ amount = fabs (dx) * 1.5f;
763+ if (amount < 0.2f)
764+ amount = 0.2f;
765+ else if (amount > 2.0f)
766+ amount = 2.0f;
767+
768+ mRVelocity = (amount * mRVelocity + adjust) / (amount + 1.0f);
769+
770+ if (fabs (dx) < 0.1f && fabs (mRVelocity) < 0.2f)
771+ {
772+ mRVelocity = 0.0f;
773+ mRotation = rot;
774+ return false;
775+ }
776+
777+ mRotation += mRVelocity * chunk;
778+ return true;
779+}
780+
781+int
782+StackswitchWindow::adjustVelocity ()
783+{
784+ float dx, dy, ds, dr, adjust, amount;
785+ float x1, y1, scale, rot;
786+
787+ STACKSWITCH_SCREEN (screen);
788+
789+ if (mSlot)
790+ {
791+ scale = mSlot->scale;
792+ x1 = mSlot->x;
793+ y1 = mSlot->y;
794+ }
795+ else
796+ {
797+ scale = 1.0f;
798+ x1 = window->x () - window->border ().left;
799+ y1 = window->y () + window->height () + window->border ().bottom;
800+ }
801+
802+ if (window->id () == ss->mSelectedWindow)
803+ rot = ss->mRotation;
804+ else
805+ rot = 0.0;
806+
807+ dx = x1 - mTx;
808+
809+ adjust = dx * 0.15f;
810+ amount = fabs (dx) * 1.5f;
811+ if (amount < 0.5f)
812+ amount = 0.5f;
813+ else if (amount > 5.0f)
814+ amount = 5.0f;
815+
816+ mXVelocity = (amount * mXVelocity + adjust) / (amount + 1.0f);
817+
818+ dy = y1 - mTy;
819+
820+ adjust = dy * 0.15f;
821+ amount = fabs (dy) * 1.5f;
822+ if (amount < 0.5f)
823+ amount = 0.5f;
824+ else if (amount > 5.0f)
825+ amount = 5.0f;
826+
827+ mYVelocity = (amount * mYVelocity + adjust) / (amount + 1.0f);
828+
829+ ds = scale - mScale;
830+ adjust = ds * 0.1f;
831+ amount = fabs (ds) * 7.0f;
832+ if (amount < 0.01f)
833+ amount = 0.01f;
834+ else if (amount > 0.15f)
835+ amount = 0.15f;
836+
837+ mScaleVelocity = (amount * mScaleVelocity + adjust) /
838+ (amount + 1.0f);
839+
840+ dr = rot - mRotation;
841+ adjust = dr * 0.15f;
842+ amount = fabs (dr) * 1.5f;
843+ if (amount < 0.2f)
844+ amount = 0.2f;
845+ else if (amount > 2.0f)
846+ amount = 2.0f;
847+
848+ mRotVelocity = (amount * mRotVelocity + adjust) / (amount + 1.0f);
849+
850+ if (fabs (dx) < 0.1f && fabs (mXVelocity) < 0.2f &&
851+ fabs (dy) < 0.1f && fabs (mYVelocity) < 0.2f &&
852+ fabs (ds) < 0.001f && fabs (mScaleVelocity) < 0.002f &&
853+ fabs (dr) < 0.1f && fabs (mRotVelocity) < 0.2f)
854+ {
855+ mXVelocity = mYVelocity = mScaleVelocity = 0.0f;
856+ mTx = x1;
857+ mTy = y1;
858+ mRotation = rot;
859+ mScale = scale;
860+
861+ return 0;
862+ }
863+
864+ return 1;
865+}
866+
867+bool
868+StackswitchScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
869+ const GLMatrix &transform,
870+ const CompRegion &region,
871+ CompOutput *output,
872+ unsigned int mask)
873+{
874+ bool status;
875+ GLMatrix sTransform (transform);
876+
877+ if (mState != StackswitchStateNone || mRotation != 0.0)
878+ {
879+ mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
880+ mask |= PAINT_SCREEN_TRANSFORMED_MASK;
881+ mask |= PAINT_SCREEN_CLEAR_MASK;
882+
883+ sTransform.translate (0.0, -0.5, -DEFAULT_Z_CAMERA);
884+ sTransform.rotate (-mRotation, 1.0, 0.0, 0.0);
885+ sTransform.translate (0.0, 0.5, DEFAULT_Z_CAMERA);
886+ }
887+
888+ status = gScreen->glPaintOutput (attrib, sTransform, region, output, mask);
889+
890+ if (mState != StackswitchStateNone &&
891+ ((unsigned int) output->id () == (unsigned int) ~0 ||
892+ screen->outputDevs ().at (screen->currentOutputDev ().id ()) == *output))
893+ {
894+ int i;
895+ CompWindow *aw = NULL;
896+
897+ sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
898+ glPushMatrix ();
899+ glLoadMatrixf (sTransform.getMatrix ());
900+
901+ mPaintingSwitcher = true;
902+
903+ for (i = 0; i < mNWindows; i++)
904+ {
905+ if (mDrawSlots[i].slot && *(mDrawSlots[i].slot))
906+ {
907+ CompWindow *w = mDrawSlots[i].w;
908+ if (w->id () == mSelectedWindow)
909+ aw = w;
910+
911+ STACKSWITCH_WINDOW (w);
912+
913+ sw->gWindow->glPaint (sw->gWindow->paintAttrib (), sTransform, infiniteRegion, 0);
914+ }
915+ }
916+
917+ GLMatrix tTransform (transform);
918+ tTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
919+ glLoadMatrixf (tTransform.getMatrix ());
920+
921+ if (mText.getWidth () && (mState != StackswitchStateIn) && aw)
922+ drawWindowTitle (sTransform, aw);
923+
924+ mPaintingSwitcher = false;
925+
926+ glPopMatrix ();
927+ }
928+
929+ return status;
930+}
931+
932+void
933+StackswitchScreen::preparePaint (int msSinceLastPaint)
934+{
935+ if (mState != StackswitchStateNone && (mMoreAdjust || mRotateAdjust))
936+ {
937+ CompWindow *w;
938+ int steps;
939+ float amount, chunk;
940+
941+ amount = msSinceLastPaint * 0.05f * optionGetSpeed ();
942+ steps = amount / (0.5f * optionGetTimestep ());
943+
944+ if (!steps)
945+ steps = 1;
946+ chunk = amount / (float) steps;
947+
948+ layoutThumbs ();
949+ while (steps--)
950+ {
951+ mRotateAdjust = adjustStackswitchRotation (chunk);
952+ mMoreAdjust = false;
953+
954+ foreach (w, screen->windows ())
955+ {
956+ STACKSWITCH_WINDOW (w);
957+
958+ if (sw->mAdjust)
959+ {
960+ sw->mAdjust = sw->adjustVelocity ();
961+
962+ mMoreAdjust |= sw->mAdjust;
963+
964+ sw->mTx += sw->mXVelocity * chunk;
965+ sw->mTy += sw->mYVelocity * chunk;
966+ sw->mScale += sw->mScaleVelocity * chunk;
967+ sw->mRotation += sw->mRotVelocity * chunk;
968+ }
969+ else if (sw->mSlot)
970+ {
971+ sw->mScale = sw->mSlot->scale;
972+ sw->mTx = sw->mSlot->x;
973+ sw->mTy = sw->mSlot->y;
974+ if (w->id () == mSelectedWindow)
975+ sw->mRotation = mRotation;
976+ else
977+ sw->mRotation = 0.0;
978+ }
979+ }
980+
981+ if (!mMoreAdjust && !mRotateAdjust)
982+ break;
983+ }
984+ }
985+
986+ cScreen->preparePaint (msSinceLastPaint);
987+}
988+
989+void
990+StackswitchScreen::donePaint ()
991+{
992+ if (mState != StackswitchStateNone)
993+ {
994+ if (mMoreAdjust)
995+ {
996+ cScreen->damageScreen ();
997+ }
998+ else
999+ {
1000+ if (mRotateAdjust)
1001+ cScreen->damageScreen ();
1002+
1003+ if (mState == StackswitchStateIn)
1004+ mState = StackswitchStateNone;
1005+ else if (mState == StackswitchStateOut)
1006+ mState = StackswitchStateSwitching;
1007+ }
1008+ }
1009+
1010+ cScreen->donePaint ();
1011+}
1012+
1013+bool
1014+StackswitchScreen::terminate (CompAction *action,
1015+ CompAction::State state,
1016+ CompOption::Vector options)
1017+{
1018+ if (mGrabIndex)
1019+ {
1020+ screen->removeGrab (mGrabIndex, 0);
1021+ mGrabIndex = 0;
1022+ }
1023+
1024+ if (mState != StackswitchStateNone)
1025+ {
1026+ CompWindow *w;
1027+
1028+ foreach (CompWindow *w, screen->windows ())
1029+ {
1030+ STACKSWITCH_WINDOW (w);
1031+
1032+ if (sw->mSlot)
1033+ {
1034+ free (sw->mSlot);
1035+ sw->mSlot = NULL;
1036+
1037+ sw->mAdjust = true;
1038+ }
1039+ }
1040+ mMoreAdjust = true;
1041+ mState = StackswitchStateIn;
1042+ cScreen->damageScreen ();
1043+
1044+ if (!(state & CompAction::StateCancel) && mSelectedWindow)
1045+ {
1046+ w = screen->findWindow (mSelectedWindow);
1047+ if (w)
1048+ screen->sendWindowActivationRequest (w->id ());
1049+ }
1050+ }
1051+
1052+ if (action)
1053+ action->setState (action->state () & ~(CompAction::StateTermKey |
1054+ CompAction::StateTermButton |
1055+ CompAction::StateTermEdge));
1056+
1057+ return false;
1058+}
1059+
1060+bool
1061+StackswitchScreen::initiate (CompAction *action,
1062+ CompAction::State state,
1063+ CompOption::Vector options)
1064+{
1065+ CompMatch match;
1066+ int count;
1067+
1068+ if (screen->otherGrabExist ("stackswitch", 0))
1069+ {
1070+ return false;
1071+ }
1072+
1073+ mCurrentMatch = optionGetWindowMatch ();
1074+
1075+ match = CompOption::getMatchOptionNamed (options, "match", CompMatch ());
1076+
1077+ mMatch = match;
1078+
1079+ count = countWindows ();
1080+
1081+ if (count < 1)
1082+ {
1083+ return false;
1084+ }
1085+
1086+ if (!mGrabIndex)
1087+ {
1088+ mGrabIndex = screen->pushGrab (screen->invisibleCursor (), "stackswitch");
1089+ }
1090+
1091+ if (mGrabIndex)
1092+ {
1093+ mState = StackswitchStateOut;
1094+
1095+ if (!createWindowList ())
1096+ return false;
1097+
1098+ mSelectedWindow = mWindows[0]->id ();
1099+ renderWindowTitle ();
1100+
1101+ foreach (CompWindow *w, screen->windows ())
1102+ {
1103+ STACKSWITCH_WINDOW (w);
1104+
1105+ sw->mTx = w->x () - w->border ().left;
1106+ sw->mTy = w->y () + w->height () + w->border ().bottom;
1107+ }
1108+ mMoreAdjust = true;
1109+ cScreen->damageScreen ();
1110+ }
1111+
1112+ return true;
1113+}
1114+
1115+bool
1116+StackswitchScreen::doSwitch (CompAction *action,
1117+ CompAction::State state,
1118+ CompOption::Vector options,
1119+ bool nextWindow,
1120+ StackswitchType type)
1121+{
1122+ bool ret = true;
1123+
1124+ if ((mState == StackswitchStateNone) || (mState == StackswitchStateIn))
1125+ {
1126+ if (mType == StackswitchTypeGroup)
1127+ {
1128+ CompWindow *w;
1129+ w = screen->findWindow (CompOption::getIntOptionNamed (options, "window", 0));
1130+ if (w)
1131+ {
1132+ mType = StackswitchTypeGroup;
1133+ mClientLeader =
1134+ (w->clientLeader ()) ? w->clientLeader () : w->id ();
1135+ ret = initiate (action, state, options);
1136+ }
1137+ }
1138+ else
1139+ {
1140+ mType = type;
1141+ ret = initiate (action, state, options);
1142+ }
1143+
1144+ if (state & CompAction::StateInitKey)
1145+ action->setState (action->state () | CompAction::StateTermKey);
1146+
1147+ if (state & CompAction::StateInitEdge)
1148+ action->setState (action->state () | CompAction::StateTermEdge);
1149+ else if (state & CompAction::StateInitButton)
1150+ action->setState (action->state () | CompAction::StateTermButton);
1151+ }
1152+
1153+ if (ret)
1154+ switchToWindow (nextWindow);
1155+
1156+ return ret;
1157+}
1158+
1159+void
1160+StackswitchScreen::windowRemove (Window id)
1161+{
1162+ CompWindow *w;
1163+
1164+ w = screen->findWindow (id);
1165+ if (w)
1166+ {
1167+ bool inList = false;
1168+ int j, i = 0;
1169+ Window selected;
1170+
1171+ STACKSWITCH_WINDOW (w);
1172+
1173+ if (mState == StackswitchStateNone)
1174+ return;
1175+
1176+ if (sw->isStackswitchable ())
1177+ return;
1178+
1179+ selected = mSelectedWindow;
1180+
1181+ while (i < mNWindows)
1182+ {
1183+ if (w->id () == mWindows[i]->id ())
1184+ {
1185+ inList = true;
1186+
1187+ if (w->id () == selected)
1188+ {
1189+ if (i < (mNWindows - 1))
1190+ selected = mWindows[i + 1]->id ();
1191+ else
1192+ selected = mWindows[0]->id ();
1193+
1194+ mSelectedWindow = selected;
1195+ }
1196+
1197+ mNWindows--;
1198+ for (j = i; j < mNWindows; j++)
1199+ mWindows[j] = mWindows[j + 1];
1200+ }
1201+ else
1202+ {
1203+ i++;
1204+ }
1205+ }
1206+
1207+ if (!inList)
1208+ return;
1209+
1210+ if (mNWindows == 0)
1211+ {
1212+ CompOption::Vector o;
1213+
1214+ terminate (NULL, 0, o);
1215+ return;
1216+ }
1217+
1218+ if (!mGrabIndex)
1219+ return;
1220+
1221+ if (updateWindowList ())
1222+ {
1223+ mMoreAdjust = true;
1224+ mState = StackswitchStateOut;
1225+ cScreen->damageScreen ();
1226+ }
1227+ }
1228+}
1229+
1230+void
1231+StackswitchScreen::handleEvent (XEvent *event)
1232+{
1233+ screen->handleEvent (event);
1234+
1235+ switch (event->type) {
1236+ case PropertyNotify:
1237+ if (event->xproperty.atom == XA_WM_NAME)
1238+ {
1239+ CompWindow *w;
1240+ w = screen->findWindow (event->xproperty.window);
1241+ if (w)
1242+ {
1243+ if (mGrabIndex && (w->id () == mSelectedWindow))
1244+ {
1245+ renderWindowTitle ();
1246+ cScreen->damageScreen ();
1247+ }
1248+ }
1249+ }
1250+ break;
1251+ case UnmapNotify:
1252+ windowRemove (event->xunmap.window);
1253+ break;
1254+ case DestroyNotify:
1255+ windowRemove (event->xdestroywindow.window);
1256+ break;
1257+ }
1258+}
1259+
1260+bool
1261+StackswitchWindow::damageRect (bool initial,
1262+ const CompRect &rect)
1263+{
1264+ bool status = false;
1265+
1266+ STACKSWITCH_SCREEN (screen);
1267+
1268+ if (initial)
1269+ {
1270+ if (ss->mGrabIndex && isStackswitchable ())
1271+ {
1272+ ss->addWindowToList (window);
1273+ if (ss->updateWindowList ())
1274+ {
1275+ mAdjust = true;
1276+ ss->mMoreAdjust = true;
1277+ ss->mState = StackswitchStateOut;
1278+ ss->cScreen->damageScreen ();
1279+ }
1280+ }
1281+ }
1282+ else if (ss->mState == StackswitchStateSwitching)
1283+ {
1284+ if (mSlot)
1285+ {
1286+ ss->cScreen->damageScreen ();
1287+ status = true;
1288+ }
1289+ }
1290+
1291+ status |= cWindow->damageRect (initial, rect);
1292+
1293+ return status;
1294+}
1295+
1296+
1297+StackswitchScreen::StackswitchScreen (CompScreen *screen) :
1298+ PluginClassHandler <StackswitchScreen, CompScreen> (screen),
1299+ cScreen (CompositeScreen::get (screen)),
1300+ gScreen (GLScreen::get (screen)),
1301+ mGrabIndex (0),
1302+ mState (StackswitchStateNone),
1303+ mMoreAdjust (false),
1304+ mRotateAdjust (false),
1305+ mPaintingSwitcher (false),
1306+ mRVelocity (0.0f),
1307+ mWindows (NULL),
1308+ mDrawSlots (NULL),
1309+ mWindowsSize (0),
1310+ mNWindows (0),
1311+ mClientLeader (None),
1312+ mSelectedWindow (None)
1313+{
1314+ ScreenInterface::setHandler (screen);
1315+ CompositeScreenInterface::setHandler (cScreen);
1316+ GLScreenInterface::setHandler (gScreen);
1317+
1318+#define STACKTERMBIND(opt, func) \
1319+ optionSet##opt##Terminate (boost::bind (&StackswitchScreen::func, \
1320+ this, _1, _2, _3));
1321+
1322+#define STACKSWITCHBIND(opt, func, next, type) \
1323+ optionSet##opt##Initiate (boost::bind (&StackswitchScreen::func, \
1324+ this, _1, _2, _3, \
1325+ next, type));
1326+
1327+ STACKSWITCHBIND (NextKey, doSwitch, true, StackswitchTypeNormal);
1328+ STACKSWITCHBIND (PrevKey, doSwitch, false, StackswitchTypeNormal);
1329+ STACKSWITCHBIND (NextAllKey, doSwitch, true, StackswitchTypeAll);
1330+ STACKSWITCHBIND (PrevAllKey, doSwitch, false, StackswitchTypeAll);
1331+ STACKSWITCHBIND (NextGroupKey, doSwitch, true, StackswitchTypeGroup);
1332+ STACKSWITCHBIND (PrevGroupKey, doSwitch, false, StackswitchTypeGroup);
1333+
1334+ STACKTERMBIND (NextKey, terminate);
1335+ STACKTERMBIND (PrevKey, terminate);
1336+ STACKTERMBIND (NextAllKey, terminate);
1337+ STACKTERMBIND (PrevAllKey, terminate);
1338+ STACKTERMBIND (NextGroupKey, terminate);
1339+ STACKTERMBIND (PrevGroupKey, terminate);
1340+
1341+ STACKSWITCHBIND (NextButton, doSwitch, true, StackswitchTypeNormal);
1342+ STACKSWITCHBIND (PrevButton, doSwitch, false, StackswitchTypeNormal);
1343+ STACKSWITCHBIND (NextAllButton, doSwitch, true, StackswitchTypeAll);
1344+ STACKSWITCHBIND (PrevAllButton, doSwitch, false, StackswitchTypeAll);
1345+ STACKSWITCHBIND (NextGroupButton, doSwitch, true, StackswitchTypeGroup);
1346+ STACKSWITCHBIND (PrevGroupButton, doSwitch, false, StackswitchTypeGroup);
1347+
1348+ STACKTERMBIND (NextButton, terminate);
1349+ STACKTERMBIND (PrevButton, terminate);
1350+ STACKTERMBIND (NextAllButton, terminate);
1351+ STACKTERMBIND (PrevAllButton, terminate);
1352+ STACKTERMBIND (NextGroupButton, terminate);
1353+ STACKTERMBIND (PrevGroupButton, terminate);
1354+}
1355+
1356+StackswitchScreen::~StackswitchScreen ()
1357+{
1358+ if (mWindows)
1359+ free (mWindows);
1360+
1361+ if (mDrawSlots)
1362+ free (mDrawSlots);
1363+}
1364+
1365+StackswitchWindow::StackswitchWindow (CompWindow *window) :
1366+ PluginClassHandler <StackswitchWindow, CompWindow> (window),
1367+ window (window),
1368+ cWindow (CompositeWindow::get (window)),
1369+ gWindow (GLWindow::get (window)),
1370+ mSlot (NULL),
1371+ mXVelocity (0.0f),
1372+ mYVelocity (0.0f),
1373+ mScaleVelocity (0.0f),
1374+ mRotVelocity (0.0f),
1375+ mTx (0.0f),
1376+ mTy (0.0f),
1377+ mScale (1.0f),
1378+ mRotation (0.0f),
1379+ mAdjust (false)
1380+{
1381+ CompositeWindowInterface::setHandler (cWindow);
1382+ GLWindowInterface::setHandler (gWindow);
1383+}
1384+
1385+StackswitchWindow::~StackswitchWindow ()
1386+{
1387+ if (mSlot)
1388+ free (mSlot);
1389+}
1390+
1391+bool
1392+StackswitchPluginVTable::init ()
1393+{
1394+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
1395+ !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
1396+ !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
1397+ return false;
1398+
1399+ if (!CompPlugin::checkPluginABI ("text", COMPIZ_TEXT_ABI))
1400+ {
1401+ compLogMessage ("stackswitch", CompLogLevelWarn, "No compatible text plugin"\
1402+ " loaded");
1403+ textAvailable = false;
1404+ }
1405+ else
1406+ textAvailable = true;
1407+
1408+ return true;
1409+}
1410
1411=== added file 'plugins/stackswitch/src/stackswitch.h'
1412--- plugins/stackswitch/src/stackswitch.h 1970-01-01 00:00:00 +0000
1413+++ plugins/stackswitch/src/stackswitch.h 2012-06-24 07:14:19 +0000
1414@@ -0,0 +1,239 @@
1415+/*
1416+ *
1417+ * Compiz stackswitch switcher plugin
1418+ *
1419+ * stackswitch.h
1420+ *
1421+ * Copyright : (C) 2007 by Danny Baumann
1422+ * E-mail : maniac@opencompositing.org
1423+ *
1424+ * Based on scale.c and switcher.c:
1425+ * Copyright : (C) 2007 David Reveman
1426+ * E-mail : davidr@novell.com
1427+ *
1428+ * This program is free software; you can redistribute it and/or
1429+ * modify it under the terms of the GNU General Public License
1430+ * as published by the Free Software Foundation; either version 2
1431+ * of the License, or (at your option) any later version.
1432+ *
1433+ * This program is distributed in the hope that it will be useful,
1434+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1435+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1436+ * GNU General Public License for more details.
1437+ *
1438+ */
1439+
1440+#include <cmath>
1441+
1442+#include <X11/Xatom.h>
1443+#include <X11/cursorfont.h>
1444+
1445+#include <core/core.h>
1446+#include <composite/composite.h>
1447+#include <opengl/opengl.h>
1448+#include <text/text.h>
1449+
1450+#include "stackswitch_options.h"
1451+
1452+typedef enum {
1453+ StackswitchStateNone = 0,
1454+ StackswitchStateOut,
1455+ StackswitchStateSwitching,
1456+ StackswitchStateIn
1457+} StackswitchState;
1458+
1459+typedef enum {
1460+ StackswitchTypeNormal = 0,
1461+ StackswitchTypeGroup,
1462+ StackswitchTypeAll
1463+} StackswitchType;
1464+
1465+typedef struct _StackswitchSlot {
1466+ int x, y; /* thumb center coordinates */
1467+ float scale; /* size scale (fit to maximal thumb size) */
1468+} StackswitchSlot;
1469+
1470+typedef struct _StackswitchDrawSlot {
1471+ CompWindow *w;
1472+ StackswitchSlot **slot;
1473+} StackswitchDrawSlot;
1474+
1475+class StackswitchScreen:
1476+ public PluginClassHandler <StackswitchScreen, CompScreen>,
1477+ public ScreenInterface,
1478+ public CompositeScreenInterface,
1479+ public GLScreenInterface,
1480+ public StackswitchOptions
1481+{
1482+ public:
1483+
1484+ StackswitchScreen (CompScreen *);
1485+ ~StackswitchScreen ();
1486+
1487+ public:
1488+
1489+ CompositeScreen *cScreen;
1490+ GLScreen *gScreen;
1491+
1492+ public:
1493+
1494+ void
1495+ handleEvent (XEvent *);
1496+
1497+ void
1498+ preparePaint (int);
1499+
1500+ void
1501+ donePaint ();
1502+
1503+ bool
1504+ glPaintOutput (const GLScreenPaintAttrib &,
1505+ const GLMatrix &,
1506+ const CompRegion &,
1507+ CompOutput *,
1508+ unsigned int );
1509+
1510+ public:
1511+
1512+ void
1513+ renderWindowTitle ();
1514+
1515+ void
1516+ drawWindowTitle (GLMatrix &transform, CompWindow *w);
1517+
1518+ bool
1519+ layoutThumbs ();
1520+
1521+ void
1522+ addWindowToList (CompWindow *w);
1523+
1524+ bool
1525+ updateWindowList ();
1526+
1527+ bool
1528+ createWindowList ();
1529+
1530+ void
1531+ switchToWindow (bool toNext);
1532+
1533+ int
1534+ countWindows ();
1535+
1536+ int
1537+ adjustStackswitchRotation (float chunk);
1538+
1539+ bool
1540+ terminate (CompAction *action,
1541+ CompAction::State state,
1542+ CompOption::Vector options);
1543+
1544+ bool
1545+ initiate (CompAction *action,
1546+ CompAction::State state,
1547+ CompOption::Vector options);
1548+
1549+ bool
1550+ doSwitch (CompAction *action,
1551+ CompAction::State state,
1552+ CompOption::Vector options,
1553+ bool nextWindow,
1554+ StackswitchType type);
1555+
1556+ void
1557+ windowRemove (Window id);
1558+
1559+ public:
1560+
1561+ CompText mText;
1562+
1563+ CompScreen::GrabHandle mGrabIndex;
1564+
1565+ StackswitchState mState;
1566+ StackswitchType mType;
1567+
1568+ bool mMoreAdjust;
1569+ bool mRotateAdjust;
1570+
1571+ bool mPaintingSwitcher;
1572+
1573+ GLfloat mRVelocity;
1574+ GLfloat mRotation;
1575+
1576+ /* only used for sorting */
1577+ CompWindow **mWindows;
1578+ StackswitchDrawSlot *mDrawSlots;
1579+ int mWindowsSize;
1580+ int mNWindows;
1581+
1582+ Window mClientLeader;
1583+ Window mSelectedWindow;
1584+
1585+ CompMatch mMatch;
1586+ CompMatch mCurrentMatch;
1587+};
1588+
1589+class StackswitchWindow:
1590+ public PluginClassHandler <StackswitchWindow, CompWindow>,
1591+ public CompositeWindowInterface,
1592+ public GLWindowInterface
1593+{
1594+ public:
1595+
1596+ StackswitchWindow (CompWindow *);
1597+ ~StackswitchWindow ();
1598+
1599+ public:
1600+
1601+ CompWindow *window;
1602+ CompositeWindow *cWindow;
1603+ GLWindow *gWindow;
1604+
1605+ public:
1606+
1607+ bool
1608+ glPaint (const GLWindowPaintAttrib &,
1609+ const GLMatrix &,
1610+ const CompRegion &,
1611+ unsigned int );
1612+
1613+ bool
1614+ damageRect (bool,
1615+ const CompRect &);
1616+
1617+ public:
1618+
1619+ int
1620+ adjustVelocity ();
1621+
1622+ bool
1623+ isStackswitchable ();
1624+
1625+ public:
1626+
1627+ StackswitchSlot *mSlot;
1628+
1629+ GLfloat mXVelocity;
1630+ GLfloat mYVelocity;
1631+ GLfloat mScaleVelocity;
1632+ GLfloat mRotVelocity;
1633+
1634+ GLfloat mTx;
1635+ GLfloat mTy;
1636+ GLfloat mScale;
1637+ GLfloat mRotation;
1638+ bool mAdjust;
1639+};
1640+
1641+#define STACKSWITCH_WINDOW(w) \
1642+ StackswitchWindow *sw = StackswitchWindow::get (w);
1643+
1644+#define STACKSWITCH_SCREEN(s) \
1645+ StackswitchScreen *ss = StackswitchScreen::get (s);
1646+
1647+class StackswitchPluginVTable:
1648+ public CompPlugin::VTableForScreenAndWindow <StackswitchScreen, StackswitchWindow>
1649+{
1650+ public:
1651+
1652+ bool init ();
1653+};
1654
1655=== added file 'plugins/stackswitch/stackswitch.xml.in'
1656--- plugins/stackswitch/stackswitch.xml.in 1970-01-01 00:00:00 +0000
1657+++ plugins/stackswitch/stackswitch.xml.in 2012-06-24 07:14:19 +0000
1658@@ -0,0 +1,193 @@
1659+<?xml version="1.0"?>
1660+<compiz>
1661+ <plugin name="stackswitch" useBcop="true">
1662+ <_short>Stack Window Switcher</_short>
1663+ <_long>Stack Window Switcher</_long>
1664+ <category>Window Management</category>
1665+ <deps>
1666+ <requirement>
1667+ <plugin>opengl</plugin>
1668+ </requirement>
1669+ <relation type="after">
1670+ <plugin>composite</plugin>
1671+ <plugin>opengl</plugin>
1672+ <plugin>text</plugin>
1673+ <plugin>decor</plugin>
1674+ </relation>
1675+ </deps>
1676+ <options>
1677+ <group>
1678+ <_short>Key bindings</_short>
1679+ <option name="next_key" type="key">
1680+ <_short>Next Window</_short>
1681+ <_long>Show switcher if not visible and select next window.</_long>
1682+ <default>&lt;Super&gt;Tab</default>
1683+ </option>
1684+ <option name="next_button" type="button">
1685+ <_short>Next Window</_short>
1686+ <_long>Show switcher if not visible and select next window.</_long>
1687+ </option>
1688+ <option name="prev_key" type="key">
1689+ <_short>Previous Window</_short>
1690+ <_long>Show switcher if not visible and select previous window.</_long>
1691+ <default>&lt;Super&gt;&lt;Shift&gt;Tab</default>
1692+ </option>
1693+ <option name="prev_button" type="button">
1694+ <_short>Previous Window</_short>
1695+ <_long>Show switcher if not visible and select previous window.</_long>
1696+ </option>
1697+ <option name="next_all_key" type="key">
1698+ <_short>Next Window (All Workspaces)</_short>
1699+ <_long>Show switcher if not visible and select next window out of all windows.</_long>
1700+ <default>&lt;Super&gt;&lt;Alt&gt;Tab</default>
1701+ </option>
1702+ <option name="next_all_button" type="button">
1703+ <_short>Next Window (All Workspaces)</_short>
1704+ <_long>Show switcher if not visible and select next window out of all windows.</_long>
1705+ </option>
1706+ <option name="prev_all_key" type="key">
1707+ <_short>Previous Window (All Workspaces)</_short>
1708+ <_long>Show switcher if not visible and select previous window out of all windows.</_long>
1709+ <default>&lt;Super&gt;&lt;Shift&gt;&lt;Alt&gt;Tab</default>
1710+ </option>
1711+ <option name="prev_all_button" type="button">
1712+ <_short>Previous Window (All Workspaces)</_short>
1713+ <_long>Show switcher if not visible and select previous window out of all windows.</_long>
1714+ </option>
1715+ <option name="next_group_key" type="key">
1716+ <_short>Next Window (Group)</_short>
1717+ <_long>Show switcher if not visible and select next window of the current application.</_long>
1718+ </option>
1719+ <option name="next_group_button" type="button">
1720+ <_short>Next Window (Group)</_short>
1721+ <_long>Show switcher if not visible and select next window of the current application.</_long>
1722+ </option>
1723+ <option name="prev_group_key" type="key">
1724+ <_short>Previous Window (Group)</_short>
1725+ <_long>Show switcher if not visible and select previous window of the current application.</_long>
1726+ </option>
1727+ <option name="prev_group_button" type="button">
1728+ <_short>Previous Window (Group)</_short>
1729+ <_long>Show switcher if not visible and select previous window of the current application.</_long>
1730+ </option>
1731+ </group>
1732+ <group>
1733+ <_short>Behavior</_short>
1734+ <option name="speed" type="float">
1735+ <_short>Speed</_short>
1736+ <_long>Animation speed</_long>
1737+ <default>1.5</default>
1738+ <min>0.1</min>
1739+ <max>50.0</max>
1740+ <precision>0.1</precision>
1741+ </option>
1742+ <option name="timestep" type="float">
1743+ <_short>Timestep</_short>
1744+ <_long>Animation timestep</_long>
1745+ <default>1.2</default>
1746+ <min>0.1</min>
1747+ <max>50.0</max>
1748+ <precision>0.1</precision>
1749+ </option>
1750+ <option name="inactive_opacity" type="int">
1751+ <_short>Inactive Window Opacity</_short>
1752+ <_long>Amount of opacity (in percent) for windows in the switcher which are not selected</_long>
1753+ <default>100</default>
1754+ <min>1</min>
1755+ <max>100</max>
1756+ </option>
1757+ <option name="inactive_rotate" type="bool">
1758+ <_short>Rotate inactive windows</_short>
1759+ <_long>Should not selected windows be rotated</_long>
1760+ <default>true</default>
1761+ </option>
1762+ <option name="window_match" type="match">
1763+ <_short>Windows</_short>
1764+ <_long>Windows that should be shown in the switcher</_long>
1765+ <default>Normal | Dialog | ModalDialog | Utility | Unknown</default>
1766+ </option>
1767+ <option name="darken_back" type="bool">
1768+ <_short>Darken Background</_short>
1769+ <_long>Darken background when showing the stack</_long>
1770+ <default>true</default>
1771+ </option>
1772+ <option name="minimized" type="bool">
1773+ <_short>Show Minimized</_short>
1774+ <_long>Show windows that are minimized, shaded or in show desktop mode.</_long>
1775+ <default>true</default>
1776+ </option>
1777+ <option name="tilt" type="int">
1778+ <_short>Tilt</_short>
1779+ <_long>Tilt angle of the background.</_long>
1780+ <default>30</default>
1781+ <min>0</min>
1782+ <max>90</max>
1783+ </option>
1784+ </group>
1785+ <group>
1786+ <_short>Window title display</_short>
1787+ <option name="window_title" type="bool">
1788+ <_short>Show Window Title</_short>
1789+ <_long>Show window title of currently selected window.</_long>
1790+ <default>true</default>
1791+ </option>
1792+ <option name="title_font_bold" type="bool">
1793+ <_short>Bold Font</_short>
1794+ <_long>Selects if the window title should be displayed in bold font or not.</_long>
1795+ <default>false</default>
1796+ </option>
1797+ <option name="title_font_size" type="int">
1798+ <_short>Font Size</_short>
1799+ <_long>Font size for the window title</_long>
1800+ <default>16</default>
1801+ <min>6</min>
1802+ <max>96</max>
1803+ </option>
1804+ <option name="title_back_color" type="color">
1805+ <_short>Background Color</_short>
1806+ <_long>Background color for the window title</_long>
1807+ <default>
1808+ <red>0x0000</red>
1809+ <green>0x0000</green>
1810+ <blue>0x0000</blue>
1811+ <alpha>0x9999</alpha>
1812+ </default>
1813+ </option>
1814+ <option name="title_font_color" type="color">
1815+ <_short>Font Color</_short>
1816+ <_long>Font color for the window title</_long>
1817+ <default>
1818+ <red>0xffff</red>
1819+ <green>0xffff</green>
1820+ <blue>0xffff</blue>
1821+ <alpha>0xffff</alpha>
1822+ </default>
1823+ </option>
1824+ <option name="title_text_placement" type="int">
1825+ <_short>Text Placement</_short>
1826+ <_long>Selects where to place the window title.</_long>
1827+ <default>0</default>
1828+ <min>0</min>
1829+ <max>3</max>
1830+ <desc>
1831+ <value>0</value>
1832+ <_name>On Thumbnail</_name>
1833+ </desc>
1834+
1835+ <desc>
1836+ <value>1</value>
1837+ <_name>Centered on screen</_name>
1838+ </desc>
1839+ <desc>
1840+ <value>2</value>
1841+ <_name>Above</_name>
1842+ </desc>
1843+ <desc>
1844+ <value>3</value>
1845+ <_name>Below</_name>
1846+ </desc>
1847+ </option>
1848+ </group>
1849+ </options>
1850+ </plugin>
1851+</compiz>

Subscribers

People subscribed via source and target branches