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>
28
COMPIZ_PLUGIN_20081216 (switcher, SwitchPluginVTable)
30
static float _boxVertices[] =
33
-(WIDTH >> 1), BOX_WIDTH,
34
(WIDTH >> 1), BOX_WIDTH,
37
-(WIDTH >> 1), BOX_WIDTH,
38
-(WIDTH >> 1), HEIGHT - BOX_WIDTH,
39
-(WIDTH >> 1) + BOX_WIDTH, HEIGHT - BOX_WIDTH,
40
-(WIDTH >> 1) + BOX_WIDTH, 0,
42
(WIDTH >> 1) - BOX_WIDTH, BOX_WIDTH,
43
(WIDTH >> 1) - BOX_WIDTH, HEIGHT - BOX_WIDTH,
44
(WIDTH >> 1), HEIGHT - BOX_WIDTH,
47
-(WIDTH >> 1), HEIGHT - BOX_WIDTH,
48
-(WIDTH >> 1), HEIGHT,
50
(WIDTH >> 1), HEIGHT - BOX_WIDTH
55
SwitchScreen::setSelectedWindowHint ()
57
XChangeProperty (screen->dpy (), popupWindow, selectWinAtom,
58
XA_WINDOW, 32, PropModeReplace,
59
(unsigned char *) &selectedWindow, 1);
63
SwitchWindow::isSwitchWin ()
65
if (!window->isViewable ())
67
if (sScreen->opt[SWITCH_OPTION_MINIMIZED].value ().b ())
69
if (!window->minimized () && !window->inShowDesktopMode () &&
79
if (!window->isFocussable ())
82
if (window->overrideRedirect ())
85
if (sScreen->selection == Panels)
87
if (!(window->type () &
88
(CompWindowTypeDockMask | CompWindowTypeDesktopMask)))
95
if (window->wmType () &
96
(CompWindowTypeDockMask | CompWindowTypeDesktopMask))
99
if (window->state () & CompWindowStateSkipTaskbarMask)
102
match = &sScreen->opt[SWITCH_OPTION_WINDOW_MATCH].value ().match ();
103
if (!match->evaluate (window))
108
if (sScreen->selection == CurrentViewport)
110
if (!window->mapNum () || !window->isViewable ())
112
CompWindow::Geometry &sg = window->serverGeometry ();
113
if (sg.x () + sg.width () <= 0 ||
114
sg.y () + sg.height () <= 0 ||
115
sg.x () >= screen->width () ||
116
sg.y () >= screen->height ())
121
if (!window->focus ())
130
SwitchScreen::activateEvent (bool activating)
132
CompOption::Vector o (0);
134
o.push_back (CompOption ("root", CompOption::TypeInt));
135
o.push_back (CompOption ("active", CompOption::TypeBool));
137
o[0].value ().set ((int) screen->root ());
138
o[1].value ().set (activating);
140
screen->handleCompizEvent ("switcher", "activate", o);
145
compareWindows (CompWindow *w1,
149
if (w1->mapNum () && !w2->mapNum ())
152
if (w2->mapNum () && !w1->mapNum ())
155
return w2->activeNum () < w1->activeNum ();
160
SwitchScreen::updateWindowList (int count)
166
count -= (count + 1) & 1;
171
pos = ((count >> 1) - windows.size ()) * WIDTH;
174
selectedWindow = windows.front ()->id ();
176
x = screen->currentOutputDev ().x1 () +
177
screen->currentOutputDev ().width () / 2;
178
y = screen->currentOutputDev ().y1 () +
179
screen->currentOutputDev ().height () / 2;
183
CompWindow *w = screen->findWindow (popupWindow);
186
w->resize (x - WINDOW_WIDTH (count) / 2,
187
y - WINDOW_HEIGHT / 2,
188
WINDOW_WIDTH (count),
191
XMoveResizeWindow (screen->dpy (), popupWindow,
192
x - WINDOW_WIDTH (count) / 2,
193
y - WINDOW_HEIGHT / 2,
194
WINDOW_WIDTH (count),
200
SwitchScreen::createWindowList (int count)
205
foreach (CompWindow *w, screen->windows ())
207
if (SwitchWindow::get (w)->isSwitchWin ())
210
windows.push_back (w);
212
sw->cWindow->damageRectSetEnabled (sw, true);
216
windows.sort (compareWindows);
218
if (windows.size () == 2)
220
windows.push_back (windows.front ());
221
windows.push_back ((*++windows.begin ()));
224
updateWindowList (count);
228
SwitchScreen::switchToWindow (bool toNext)
230
CompWindow *w = NULL;
231
CompWindowList::iterator it;
236
for (it = windows.begin (); it != windows.end (); it++)
238
if ((*it)->id () == selectedWindow)
242
if (it == windows.end ())
248
if (it == windows.end ())
249
w = windows.front ();
255
if (it == windows.begin ())
263
Window old = selectedWindow;
265
if (selection == AllViewports &&
266
opt[SWITCH_OPTION_AUTO_ROTATE].value ().b ())
269
CompPoint pnt = w->defaultViewport ();
271
xev.xclient.type = ClientMessage;
272
xev.xclient.display = screen->dpy ();
273
xev.xclient.format = 32;
275
xev.xclient.message_type = Atoms::desktopViewport;
276
xev.xclient.window = screen->root ();
278
xev.xclient.data.l[0] = pnt.x () * screen->width ();
279
xev.xclient.data.l[1] = pnt.y () * screen->height ();
280
xev.xclient.data.l[2] = 0;
281
xev.xclient.data.l[3] = 0;
282
xev.xclient.data.l[4] = 0;
284
XSendEvent (screen->dpy (), screen->root (), FALSE,
285
SubstructureRedirectMask | SubstructureNotifyMask,
289
lastActiveNum = w->activeNum ();
290
selectedWindow = w->id ();
293
zoomedWindow = selectedWindow;
309
popup = screen->findWindow (popupWindow);
311
CompositeWindow::get (popup)->addDamage ();
313
setSelectedWindowHint ();
316
CompositeWindow::get (w)->addDamage ();
320
w = screen->findWindow (old);
322
CompositeWindow::get (w)->addDamage ();
328
SwitchScreen::countWindows ()
332
foreach (CompWindow *w, screen->windows ())
333
if (SwitchWindow::get (w)->isSwitchWin ())
340
if (count == 5 && screen->width () <= WINDOW_WIDTH (5))
347
findArgbVisual (Display *dpy, int scr)
353
XRenderPictFormat *format;
358
temp.c_class = TrueColor;
360
xvi = XGetVisualInfo (dpy,
370
for (i = 0; i < nvi; i++)
372
format = XRenderFindVisualFormat (dpy, xvi[i].visual);
373
if (format->type == PictTypeDirect && format->direct.alphaMask)
375
visual = xvi[i].visual;
387
SwitchScreen::initiate (SwitchWindowSelection selection,
392
if (screen->otherGrabExist ("switcher", "scale", "cube", 0))
395
this->selection = selection;
396
selectedWindow = None;
398
count = countWindows ();
402
if (!popupWindow && showPopup)
404
Display *dpy = screen->dpy ();
409
XSetWindowAttributes attr;
412
visual = findArgbVisual (dpy, screen->screenNum ());
418
count -= (count + 1) & 1;
423
xsh.flags = PSize | PPosition | PWinGravity;
424
xsh.width = WINDOW_WIDTH (count);
425
xsh.height = WINDOW_HEIGHT;
426
xsh.win_gravity = StaticGravity;
428
xwmh.flags = InputHint;
431
attr.background_pixel = 0;
432
attr.border_pixel = 0;
433
attr.colormap = XCreateColormap (dpy, screen->root (), visual,
437
XCreateWindow (dpy, screen->root (),
438
screen->width () / 2 - xsh.width / 2,
439
screen->height () / 2 - xsh.height / 2,
440
xsh.width, xsh.height, 0,
441
32, InputOutput, visual,
442
CWBackPixel | CWBorderPixel | CWColormap, &attr);
444
XSetWMProperties (dpy, popupWindow, NULL, NULL,
445
programArgv, programArgc,
448
state[nState++] = Atoms::winStateAbove;
449
state[nState++] = Atoms::winStateSticky;
450
state[nState++] = Atoms::winStateSkipTaskbar;
451
state[nState++] = Atoms::winStateSkipPager;
453
XChangeProperty (dpy, popupWindow,
455
XA_ATOM, 32, PropModeReplace,
456
(unsigned char *) state, nState);
458
XChangeProperty (dpy, popupWindow,
460
XA_ATOM, 32, PropModeReplace,
461
(unsigned char *) &Atoms::winTypeUtil, 1);
463
screen->setWindowProp (popupWindow, Atoms::winDesktop, 0xffffffff);
465
setSelectedWindowHint ();
469
grabIndex = screen->pushGrab (screen->invisibleCursor (), "switcher");
475
lastActiveNum = screen->activeNum ();
477
createWindowList (count);
481
if (popupWindow && showPopup)
486
w = screen->findWindow (popupWindow);
487
if (w && (w->state () & CompWindowStateHiddenMask))
493
XMapWindow (screen->dpy (), popupWindow);
495
setSelectedWindowHint ();
498
activateEvent (true);
501
cScreen->damageScreen ();
506
screen->handleEventSetEnabled (this, true);
507
cScreen->preparePaintSetEnabled (this, true);
508
cScreen->donePaintSetEnabled (this, true);
509
gScreen->glPaintOutputSetEnabled (this, true);
511
foreach (CompWindow *w, screen->windows ())
515
sw->gWindow->glPaintSetEnabled (sw, true);
522
switchTerminate (CompAction *action,
523
CompAction::State state,
524
CompOption::Vector &options)
529
xid = CompOption::getIntOptionNamed (options, "root");
532
action->setState (action->state () & ~(CompAction::StateTermKey |
533
CompAction::StateTermButton));
535
if (xid && xid != screen->root ())
538
SWITCH_SCREEN (screen);
547
w = screen->findWindow (ss->popupWindow);
548
if (w && w->managed () && w->mapNum ())
554
XUnmapWindow (screen->dpy (), ss->popupWindow);
558
ss->switching = false;
560
if (state & CompAction::StateCancel)
562
ss->selectedWindow = None;
563
ss->zoomedWindow = None;
566
if (state && ss->selectedWindow)
568
w = screen->findWindow (ss->selectedWindow);
570
screen->sendWindowActivationRequest (w->id ());
573
screen->removeGrab (ss->grabIndex, 0);
574
ss->grabIndex = NULL;
576
if (!ss->popupWindow)
577
screen->handleEventSetEnabled (ss, false);
581
ss->selectedWindow = None;
582
ss->zoomedWindow = None;
584
ss->activateEvent (false);
588
ss->moreAdjust = true;
591
ss->selectedWindow = None;
592
ss->setSelectedWindowHint ();
594
ss->lastActiveNum = 0;
596
ss->cScreen->damageScreen ();
604
switchInitiateCommon (CompAction *action,
605
CompAction::State state,
606
CompOption::Vector &options,
607
SwitchWindowSelection selection,
614
xid = CompOption::getIntOptionNamed (options, "root");
616
if (xid != screen->root ())
619
SWITCH_SCREEN (screen);
623
ss->initiate (selection, showPopup);
625
if (state & CompAction::StateInitKey)
626
action->setState (action->state () | CompAction::StateTermKey);
628
if (state & CompAction::StateInitEdge)
629
action->setState (action->state () | CompAction::StateTermEdge);
630
else if (state & CompAction::StateInitButton)
631
action->setState (action->state () | CompAction::StateTermButton);
634
ss->switchToWindow (nextWindow);
639
#define SWITCHBIND(a,b,c) boost::bind (switchInitiateCommon, _1, _2, _3, a, b, c)
641
static const CompMetadata::OptionInfo switchOptionInfo[] = {
642
{ "next_button", "button", 0,
643
SWITCHBIND (CurrentViewport, true, true), switchTerminate },
644
{ "next_key", "key", 0,
645
SWITCHBIND (CurrentViewport, true, true), switchTerminate },
646
{ "prev_button", "button", 0,
647
SWITCHBIND (CurrentViewport, true, false), switchTerminate },
648
{ "prev_key", "key", 0,
649
SWITCHBIND (CurrentViewport, true, false), switchTerminate },
650
{ "next_all_button", "button", 0,
651
SWITCHBIND (AllViewports, true, true), switchTerminate },
652
{ "next_all_key", "key", 0,
653
SWITCHBIND (AllViewports, true, true), switchTerminate },
654
{ "prev_all_button", "button", 0,
655
SWITCHBIND (AllViewports, true, false), switchTerminate },
656
{ "prev_all_key", "key", 0,
657
SWITCHBIND (AllViewports, true, false), switchTerminate },
658
{ "next_no_popup_button", "button", 0,
659
SWITCHBIND (CurrentViewport, false, true), switchTerminate },
660
{ "next_no_popup_key", "key", 0,
661
SWITCHBIND (CurrentViewport, false, true), switchTerminate },
662
{ "prev_no_popup_button", "button", 0,
663
SWITCHBIND (CurrentViewport, false, false), switchTerminate },
664
{ "prev_no_popup_key", "key", 0,
665
SWITCHBIND (CurrentViewport, false, false), switchTerminate },
666
{ "next_panel_button", "button", 0,
667
SWITCHBIND (Panels, false, true), switchTerminate },
668
{ "next_panel_key", "key", 0,
669
SWITCHBIND (Panels, false, true), switchTerminate },
670
{ "prev_panel_button", "button", 0,
671
SWITCHBIND (Panels, false, false), switchTerminate },
672
{ "prev_panel_key", "key", 0,
673
SWITCHBIND (Panels, false, false), switchTerminate },
674
{ "speed", "float", "<min>0.1</min>", 0, 0 },
675
{ "timestep", "float", "<min>0.1</min>", 0, 0 },
676
{ "window_match", "match", 0, 0, 0 },
677
{ "mipmap", "bool", 0, 0, 0 },
678
{ "saturation", "int", "<min>0</min><max>100</max>", 0, 0 },
679
{ "brightness", "int", "<min>0</min><max>100</max>", 0, 0 },
680
{ "opacity", "int", "<min>0</min><max>100</max>", 0, 0 },
681
{ "bring_to_front", "bool", 0, 0, 0 },
682
{ "zoom", "float", "<min>0</min>", 0, 0 },
683
{ "icon", "bool", 0, 0, 0 },
684
{ "minimized", "bool", 0, 0, 0 },
685
{ "auto_rotate", "bool", 0, 0, 0 }
691
SwitchScreen::windowRemove (Window id)
695
w = screen->findWindow (id);
700
Window selected, old;
704
if (!sw->isSwitchWin ())
707
sw->cWindow->damageRectSetEnabled (sw, false);
708
sw->gWindow->glPaintSetEnabled (sw, false);
710
old = selected = selectedWindow;
712
CompWindowList::iterator it = windows.begin ();
713
while (it != windows.end ())
719
if (w->id () == selected)
722
if (it == windows.end ())
723
selected = windows.front ()->id ();
725
selected = (*it)->id ();
729
CompWindowList::iterator del = it;
740
count = windows.size ();
742
if (windows.size () == 2)
744
if (windows.front () == windows.back ())
751
windows.push_back (windows.front ());
752
windows.push_back ((*++windows.begin ()));
756
if (windows.size () == 0)
758
CompOption::Vector o (0);
760
o.push_back (CompOption ("root", CompOption::TypeInt));
762
o[0].value ().set ((int) screen->root ());
764
switchTerminate (NULL, 0, o);
771
updateWindowList (count);
773
foreach (CompWindow *w, windows)
775
selectedWindow = w->id ();
777
if (selectedWindow == selected)
781
if (pos < -windows.size () * WIDTH)
782
pos += windows.size () * WIDTH;
789
popup = screen->findWindow (popupWindow);
791
CompositeWindow::get (popup)->addDamage ();
793
setSelectedWindowHint ();
796
if (old != selectedWindow)
798
CompositeWindow::get (w)->addDamage ();
800
w = screen->findWindow (old);
802
CompositeWindow::get (w)->addDamage ();
810
SwitchScreen::updateForegroundColor ()
814
unsigned long n, left;
815
unsigned char *propData;
821
result = XGetWindowProperty (screen->dpy (), popupWindow,
822
selectFgColorAtom, 0L, 4L, FALSE,
823
XA_INTEGER, &actual, &format,
824
&n, &left, &propData);
826
if (result == Success && n && propData)
828
if (n == 3 || n == 4)
830
long *data = (long *) propData;
832
fgColor[0] = MIN (0xffff, data[0]);
833
fgColor[1] = MIN (0xffff, data[1]);
834
fgColor[2] = MIN (0xffff, data[2]);
837
fgColor[3] = MIN (0xffff, data[3]);
854
SwitchScreen::handleEvent (XEvent *event)
858
screen->handleEvent (event);
860
switch (event->type) {
862
windowRemove (event->xunmap.window);
865
windowRemove (event->xdestroywindow.window);
868
if (event->xproperty.atom == selectFgColorAtom)
870
if (event->xproperty.window == popupWindow)
871
updateForegroundColor ();
880
SwitchScreen::adjustVelocity ()
882
float dx, adjust, amount;
887
amount = fabs (dx) * 1.5f;
890
else if (amount > 2.0f)
893
mVelocity = (amount * mVelocity + adjust) / (amount + 1.0f);
900
dt = zoom - translate;
902
dt = 0.0f - translate;
905
amount = fabs (dt) * 1.5f;
908
else if (amount > 2.0f)
911
tVelocity = (amount * tVelocity + adjust) / (amount + 1.0f);
913
if (selectedWindow == zoomedWindow)
914
ds = zoom - sTranslate;
916
ds = 0.0f - sTranslate;
919
amount = fabs (ds) * 5.0f;
922
else if (amount > 6.0f)
925
sVelocity = (amount * sVelocity + adjust) / (amount + 1.0f);
927
if (selectedWindow == zoomedWindow)
929
if (fabs (dx) < 0.1f && fabs (mVelocity) < 0.2f &&
930
fabs (dt) < 0.001f && fabs (tVelocity) < 0.001f &&
931
fabs (ds) < 0.001f && fabs (sVelocity) < 0.001f)
933
mVelocity = tVelocity = sVelocity = 0.0f;
940
if (fabs (dx) < 0.1f && fabs (mVelocity) < 0.2f)
951
SwitchScreen::preparePaint (int msSinceLastPaint)
958
amount = msSinceLastPaint * 0.05f *
959
opt[SWITCH_OPTION_SPEED].value ().f ();
961
(0.5f * opt[SWITCH_OPTION_TIMESTEP].value ().f ());
962
if (!steps) steps = 1;
963
chunk = amount / (float) steps;
967
moreAdjust = adjustVelocity ();
985
selectedWindow = None;
990
screen->removeGrab (grabIndex, 0);
994
activateEvent (false);
1000
m = mVelocity * chunk;
1004
m = (move > 0) ? 1 : -1;
1009
if (pos < -windows.size () * WIDTH)
1010
pos += windows.size () * WIDTH;
1012
pos -= windows.size () * WIDTH;
1014
translate += tVelocity * chunk;
1015
sTranslate += sVelocity * chunk;
1017
if (selectedWindow != zoomedWindow)
1019
if (sTranslate < 0.01f)
1020
zoomedWindow = selectedWindow;
1025
cScreen->preparePaint (msSinceLastPaint);
1029
SwitchScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib,
1030
const GLMatrix &transform,
1031
const CompRegion ®ion,
1037
zoomMask = ZOOMED_WINDOW_MASK | NORMAL_WINDOW_MASK;
1039
if (grabIndex || (zooming && translate > 0.001f))
1041
GLMatrix sTransform (transform);
1043
CompWindow *switcher;
1044
Window zoomedAbove = None;
1048
mask &= ~PAINT_SCREEN_REGION_MASK;
1049
mask |= PAINT_SCREEN_TRANSFORMED_MASK | PAINT_SCREEN_CLEAR_MASK;
1051
sTransform.translate (0.0f, 0.0f, -translate);
1053
zoomMask = NORMAL_WINDOW_MASK;
1056
if (opt[SWITCH_OPTION_BRINGTOFRONT].value ().b ())
1058
zoomed = screen->findWindow (zoomedWindow);
1063
for (w = zoomed->prev; w && w->id () <= 1; w = w->prev);
1064
zoomedAbove = (w) ? w->id () : None;
1066
screen->unhookWindow (zoomed);
1067
screen->insertWindow (zoomed,
1068
screen->windows ().back ()->id ());
1076
ignoreSwitcher = true;
1078
status = gScreen->glPaintOutput (sAttrib, sTransform, region, output,
1085
mask &= ~PAINT_SCREEN_CLEAR_MASK;
1086
mask |= PAINT_SCREEN_NO_BACKGROUND_MASK;
1088
zoomMask = ZOOMED_WINDOW_MASK;
1090
zTranslate = MIN (sTranslate, translate);
1091
sTransform.translate (0.0f, 0.0f, zTranslate);
1093
status = gScreen->glPaintOutput (sAttrib, sTransform, region,
1099
screen->unhookWindow (zoomed);
1100
screen->insertWindow (zoomed, zoomedAbove);
1103
ignoreSwitcher = false;
1105
switcher = screen->findWindow (popupWindow);
1109
SWITCH_WINDOW (switcher);
1111
sTransform = transform;
1113
sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
1116
glLoadMatrixf (sTransform.getMatrix ());
1118
if (!switcher->destroyed () &&
1119
switcher->isViewable () &&
1120
sw->cWindow->damaged ())
1122
sw->gWindow->glPaint (sw->gWindow->paintAttrib (),
1123
sTransform, infiniteRegion, 0);
1131
status = gScreen->glPaintOutput (sAttrib, transform, region, output,
1139
SwitchScreen::donePaint ()
1141
if ((grabIndex || zooming) && moreAdjust)
1145
cScreen->damageScreen ();
1151
w = screen->findWindow (popupWindow);
1153
CompositeWindow::get (w)->addDamage ();
1156
else if (!grabIndex && !(zooming && translate > 0.001f) && !moreAdjust)
1158
cScreen->preparePaintSetEnabled (this, false);
1159
cScreen->donePaintSetEnabled (this, false);
1160
gScreen->glPaintOutputSetEnabled (this, false);
1162
foreach (CompWindow *w, screen->windows ())
1165
sw->cWindow->damageRectSetEnabled (sw, false);
1166
sw->gWindow->glPaintSetEnabled (sw, false);
1170
cScreen->donePaint ();
1175
SwitchWindow::paintThumb (const GLWindowPaintAttrib &attrib,
1176
const GLMatrix &transform,
1183
GLWindowPaintAttrib sAttrib (attrib);
1185
float width, height;
1186
GLTexture *icon = NULL;
1187
CompWindow::Geometry &g = window->geometry ();
1189
mask |= PAINT_WINDOW_TRANSFORMED_MASK;
1191
if (window->mapNum ())
1193
if (gWindow->textures ().empty ())
1197
if (!gWindow->textures ().empty ())
1199
GLMatrix wTransform (transform);
1201
int addWindowGeometryIndex =
1202
gWindow->glAddGeometryGetCurrentIndex ();
1204
width = WIDTH - (SPACE << 1);
1205
height = HEIGHT - (SPACE << 1);
1207
ww = g.width () + window->input ().left +
1208
window->input ().right;
1209
wh = g.height () + window->input ().top +
1210
window->input ().bottom;
1213
sAttrib.xScale = width / ww;
1215
sAttrib.xScale = 1.0f;
1218
sAttrib.yScale = height / wh;
1220
sAttrib.yScale = 1.0f;
1222
if (sAttrib.xScale < sAttrib.yScale)
1223
sAttrib.yScale = sAttrib.xScale;
1225
sAttrib.xScale = sAttrib.yScale;
1227
width = ww * sAttrib.xScale;
1228
height = wh * sAttrib.yScale;
1230
wx = x + SPACE + ((WIDTH - (SPACE << 1)) - width) / 2;
1231
wy = y + SPACE + ((HEIGHT - (SPACE << 1)) - height) / 2;
1233
sAttrib.xTranslate = wx - g.x () +
1234
window->input ().left * sAttrib.xScale;
1235
sAttrib.yTranslate = wy - g.y () +
1236
window->input ().top * sAttrib.yScale;
1238
GLFragment::Attrib fragment (sAttrib);
1240
if (window->alpha () || fragment.getOpacity () != OPAQUE)
1241
mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
1243
wTransform.translate (g.x (), g.y (), 0.0f);
1244
wTransform.scale (sAttrib.xScale, sAttrib.yScale, 1.0f);
1245
wTransform.translate (sAttrib.xTranslate / sAttrib.xScale - g.x (),
1246
sAttrib.yTranslate / sAttrib.yScale - g.y (),
1250
glLoadMatrixf (wTransform.getMatrix ());
1252
/* XXX: replacing the addWindowGeometry function like this is
1253
very ugly but necessary until the vertex stage has been made
1255
gWindow->glAddGeometrySetCurrentIndex (MAXSHORT);
1256
gWindow->glDraw (wTransform, fragment, infiniteRegion, mask);
1257
gWindow->glAddGeometrySetCurrentIndex (addWindowGeometryIndex);
1261
if (sScreen->opt[SWITCH_OPTION_ICON].value ().b ())
1263
icon = gWindow->getIcon (ICON_SIZE, ICON_SIZE);
1266
sAttrib.xScale = sAttrib.yScale = 1.0f;
1268
wx = x + WIDTH - icon->width () - SPACE;
1269
wy = y + HEIGHT - icon->height () - SPACE;
1275
width = WIDTH - (WIDTH >> 2);
1276
height = HEIGHT - (HEIGHT >> 2);
1278
icon = gWindow->getIcon (ICON_SIZE, ICON_SIZE);
1280
icon = gScreen->defaultIcon ();
1287
ih = height - SPACE;
1289
if (icon->width () < (iw >> 1))
1290
sAttrib.xScale = (iw / icon->width ());
1292
sAttrib.xScale = 1.0f;
1294
if (icon->height () < (ih >> 1))
1295
sAttrib.yScale = (ih / icon->height ());
1297
sAttrib.yScale = 1.0f;
1299
if (sAttrib.xScale < sAttrib.yScale)
1300
sAttrib.yScale = sAttrib.xScale;
1302
sAttrib.xScale = sAttrib.yScale;
1304
width = icon->width () * sAttrib.xScale;
1305
height = icon->height () * sAttrib.yScale;
1307
wx = x + SPACE + ((WIDTH - (SPACE << 1)) - width) / 2;
1308
wy = y + SPACE + ((HEIGHT - (SPACE << 1)) - height) / 2;
1314
CompRegion iconReg (g.x (), g.y (), icon->width (),
1316
GLTexture::MatrixList matrix (1);
1317
int addWindowGeometryIndex =
1318
gWindow->glAddGeometryGetCurrentIndex ();
1320
mask |= PAINT_WINDOW_BLEND_MASK;
1322
matrix[0] = icon->matrix ();
1323
matrix[0].x0 -= (g.x () * matrix[0].xx);
1324
matrix[0].y0 -= (g.y () * matrix[0].yy);
1326
sAttrib.xTranslate = wx - g.x ();
1327
sAttrib.yTranslate = wy - g.y ();
1329
gWindow->geometry ().reset ();
1331
gWindow->glAddGeometrySetCurrentIndex (MAXSHORT);
1332
gWindow->glAddGeometry (matrix, iconReg, infiniteRegion);
1333
gWindow->glAddGeometrySetCurrentIndex (addWindowGeometryIndex);
1335
if (gWindow->geometry ().vCount)
1337
GLFragment::Attrib fragment (sAttrib);
1338
GLMatrix wTransform (transform);
1340
wTransform.translate (g.x (), g.y (), 0.0f);
1341
wTransform.scale (sAttrib.xScale, sAttrib.yScale, 1.0f);
1342
wTransform.translate (sAttrib.xTranslate / sAttrib.xScale - g.x (),
1343
sAttrib.yTranslate / sAttrib.yScale - g.y (),
1347
glLoadMatrixf (wTransform.getMatrix ());
1349
gWindow->glDrawTexture (icon, fragment, mask);
1357
SwitchWindow::glPaint (const GLWindowPaintAttrib &attrib,
1358
const GLMatrix &transform,
1359
const CompRegion ®ion,
1362
int zoomType = NORMAL_WINDOW_MASK;
1365
if (window->id () == sScreen->popupWindow)
1368
int x, y, x1, x2, cx, i;
1369
unsigned short color[4];
1371
CompWindow::Geometry &g = window->geometry ();
1373
if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK ||
1374
sScreen->ignoreSwitcher)
1377
status = gWindow->glPaint (attrib, transform, region, mask);
1379
if (!(mask & PAINT_WINDOW_TRANSFORMED_MASK) && region.isEmpty ())
1382
x1 = g.x () + SPACE;
1383
x2 = g.x () + g.width () - SPACE;
1385
x = x1 + sScreen->pos;
1388
filter = gScreen->textureFilter ();
1390
if (sScreen->opt[SWITCH_OPTION_MIPMAP].value ().b ())
1391
gScreen->setTextureFilter (GL_LINEAR_MIPMAP_LINEAR);
1393
glPushAttrib (GL_SCISSOR_BIT);
1395
glEnable (GL_SCISSOR_TEST);
1396
glScissor (x1, 0, x2 - x1, screen->height ());
1398
foreach (CompWindow *w, sScreen->windows)
1401
SwitchWindow::get (w)->paintThumb (
1402
gWindow->lastPaintAttrib (), transform,
1403
mask, x, y, x1, x2);
1407
foreach (CompWindow *w, sScreen->windows)
1412
SwitchWindow::get (w)->paintThumb (
1413
gWindow->lastPaintAttrib (), transform,
1414
mask, x, y, x1, x2);
1420
gScreen->setTextureFilter (filter);
1422
cx = g.x () + (g.width () >> 1);
1424
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1425
glEnable (GL_BLEND);
1426
for (i = 0; i < 4; i++)
1427
color[i] = (unsigned int)sScreen->fgColor[i] *
1428
gWindow->lastPaintAttrib ().opacity /
1430
glColor4usv (color);
1432
glTranslatef (cx, y, 0.0f);
1433
glVertexPointer (2, GL_FLOAT, 0, _boxVertices);
1434
glDrawArrays (GL_QUADS, 0, 16);
1436
glColor4usv (defaultColor);
1437
glDisable (GL_BLEND);
1438
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1440
else if (window->id () == sScreen->selectedWindow)
1442
if (sScreen->opt[SWITCH_OPTION_BRINGTOFRONT].value ().b () &&
1443
sScreen->selectedWindow == sScreen->zoomedWindow)
1444
zoomType = ZOOMED_WINDOW_MASK;
1446
if (!(sScreen->zoomMask & zoomType))
1447
return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
1450
status = gWindow->glPaint (attrib, transform, region, mask);
1452
else if (sScreen->switching)
1454
GLWindowPaintAttrib sAttrib (attrib);
1457
value = sScreen->opt[SWITCH_OPTION_SATURATION].value ().i ();
1459
sAttrib.saturation = sAttrib.saturation * value / 100;
1461
value = sScreen->opt[SWITCH_OPTION_BRIGHTNESS].value ().i ();
1463
sAttrib.brightness = sAttrib.brightness * value / 100;
1465
if (window->wmType () & ~(CompWindowTypeDockMask |
1466
CompWindowTypeDesktopMask))
1468
value = sScreen->opt[SWITCH_OPTION_OPACITY].value ().i ();
1470
sAttrib.opacity = sAttrib.opacity * value / 100;
1473
if (sScreen->opt[SWITCH_OPTION_BRINGTOFRONT].value ().b () &&
1474
window->id () == sScreen->zoomedWindow)
1475
zoomType = ZOOMED_WINDOW_MASK;
1477
if (!(sScreen->zoomMask & zoomType))
1478
return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
1481
status = gWindow->glPaint (sAttrib, transform, region, mask);
1485
if (!(sScreen->zoomMask & zoomType))
1486
return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
1489
status = gWindow->glPaint (attrib, transform, region, mask);
1496
SwitchWindow::damageRect (bool initial, const CompRect &rect)
1500
if (sScreen->grabIndex)
1505
foreach (CompWindow *w, sScreen->windows)
1509
popup = screen->findWindow (sScreen->popupWindow);
1511
CompositeWindow::get (popup)->addDamage ();
1518
cWindow->damageRect (initial, rect);
1523
CompOption::Vector &
1524
SwitchScreen::getOptions ()
1530
SwitchScreen::setOption (const char *name,
1531
CompOption::Value &value)
1536
o = CompOption::findOption (opt, name, &index);
1541
case SWITCH_OPTION_ZOOM:
1544
if (o->value ().f () < 0.05f)
1552
zoom = o->value ().f () / 30.0f;
1559
return CompOption::setOption (*o, value);
1565
SwitchScreen::SwitchScreen (CompScreen *screen) :
1566
PrivateHandler<SwitchScreen,CompScreen> (screen),
1567
cScreen (CompositeScreen::get (screen)),
1568
gScreen (GLScreen::get (screen)),
1569
opt(SWITCH_OPTION_NUM),
1571
selectedWindow (None),
1572
zoomedWindow (None),
1586
selection (CurrentViewport),
1587
ignoreSwitcher (false)
1589
if (!switcherVTable->getMetadata ()->initOptions (switchOptionInfo,
1590
SWITCH_OPTION_NUM, opt))
1596
zoom = opt[SWITCH_OPTION_ZOOM].value ().f () / 30.0f;
1598
zooming = (opt[SWITCH_OPTION_ZOOM].value ().f () > 0.05f);
1603
fgColor[3] = 0xffff;
1606
XInternAtom (screen->dpy (), DECOR_SWITCH_WINDOW_ATOM_NAME, 0);
1608
XInternAtom (screen->dpy (), DECOR_SWITCH_FOREGROUND_COLOR_ATOM_NAME, 0);
1611
ScreenInterface::setHandler (screen, false);
1612
CompositeScreenInterface::setHandler (cScreen, false);
1613
GLScreenInterface::setHandler (gScreen, false);
1616
SwitchScreen::~SwitchScreen ()
1619
XDestroyWindow (screen->dpy (), popupWindow);
1623
SwitchPluginVTable::init ()
1625
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) |
1626
!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) |
1627
!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
1630
getMetadata ()->addFromOptionInfo (switchOptionInfo, SWITCH_OPTION_NUM);
1631
getMetadata ()->addFromFile (name ());