1
/********************************************************************
2
KWin - the KDE window manager
3
This file is part of the KDE project.
5
Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.com>
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program. If not, see <http://www.gnu.org/licenses/>.
19
*********************************************************************/
21
#include "cube_inside.h"
24
#include <kactioncollection.h>
26
#include <kwinconfig.h>
27
#include <kconfiggroup.h>
28
#include <kcolorscheme.h>
30
#include <kstandarddirs.h>
41
#include <kwinglutils.h>
42
#include <kwinglplatform.h>
47
KWIN_EFFECT(cube, CubeEffect)
48
KWIN_EFFECT_SUPPORTED(cube, CubeEffect::supported())
50
CubeEffect::CubeEffect()
53
, cube_painting(false)
54
, keyboard_grab(false)
55
, schedule_close(false)
59
, opacityDesktopOnly(true)
60
, displayDesktopName(false)
61
, desktopNameFrame(effects->effectFrame(EffectFrameStyled))
64
, desktopChangedWhileRotating(false)
66
, rotationDirection(Left)
67
, verticalRotationDirection(Upwards)
68
, verticalPosition(Normal)
73
, manualVerticalAngle(0.0)
74
, currentShape(QTimeLine::EaseInOutCurve)
77
, reflectionPainting(false)
80
, closeOnMouseRelease(false)
85
, shortcutsRegistered(false)
90
, zOrderingFactor(0.0f)
91
, mAddedHeightCoeff1(0.0f)
92
, mAddedHeightCoeff2(0.0f)
93
, m_cubeCapBuffer(NULL)
96
desktopNameFont.setBold(true);
97
desktopNameFont.setPointSize(14);
98
desktopNameFrame->setFont(desktopNameFont);
100
const QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/cube-reflection.glsl");
101
m_reflectionShader = ShaderManager::instance()->loadFragmentShader(ShaderManager::GenericShader, fragmentshader);
102
const QString capshader = KGlobal::dirs()->findResource("data", "kwin/cube-cap.glsl");
103
m_capShader = ShaderManager::instance()->loadFragmentShader(ShaderManager::GenericShader, capshader);
104
m_textureMirrorMatrix.scale(1.0, -1.0, 1.0);
105
m_textureMirrorMatrix.translate(0.0, -1.0, 0.0);
106
connect(effects, SIGNAL(tabBoxAdded(int)), this, SLOT(slotTabBoxAdded(int)));
107
connect(effects, SIGNAL(tabBoxClosed()), this, SLOT(slotTabBoxClosed()));
108
connect(effects, SIGNAL(tabBoxUpdated()), this, SLOT(slotTabBoxUpdated()));
109
connect(effects, SIGNAL(mouseChanged(QPoint,QPoint,Qt::MouseButtons,Qt::MouseButtons,Qt::KeyboardModifiers,Qt::KeyboardModifiers)),
110
this, SLOT(slotMouseChanged(QPoint,QPoint,Qt::MouseButtons,Qt::MouseButtons,Qt::KeyboardModifiers,Qt::KeyboardModifiers)));
112
reconfigure(ReconfigureAll);
115
bool CubeEffect::supported()
117
return effects->compositingType() == OpenGLCompositing;
120
void CubeEffect::reconfigure(ReconfigureFlags)
125
void CubeEffect::loadConfig(QString config)
127
KConfigGroup conf = effects->effectConfig(config);
128
foreach (ElectricBorder border, borderActivate) {
129
effects->unreserveElectricBorder(border);
131
foreach (ElectricBorder border, borderActivateCylinder) {
132
effects->unreserveElectricBorder(border);
134
foreach (ElectricBorder border, borderActivateSphere) {
135
effects->unreserveElectricBorder(border);
137
borderActivate.clear();
138
borderActivateCylinder.clear();
139
borderActivateSphere.clear();
140
QList<int> borderList = QList<int>();
141
borderList.append(int(ElectricNone));
142
borderList = conf.readEntry("BorderActivate", borderList);
143
foreach (int i, borderList) {
144
borderActivate.append(ElectricBorder(i));
145
effects->reserveElectricBorder(ElectricBorder(i));
148
borderList.append(int(ElectricNone));
149
borderList = conf.readEntry("BorderActivateCylinder", borderList);
150
foreach (int i, borderList) {
151
borderActivateCylinder.append(ElectricBorder(i));
152
effects->reserveElectricBorder(ElectricBorder(i));
155
borderList.append(int(ElectricNone));
156
borderList = conf.readEntry("BorderActivateSphere", borderList);
157
foreach (int i, borderList) {
158
borderActivateSphere.append(ElectricBorder(i));
159
effects->reserveElectricBorder(ElectricBorder(i));
162
cubeOpacity = (float)conf.readEntry("Opacity", 80) / 100.0f;
163
opacityDesktopOnly = conf.readEntry("OpacityDesktopOnly", false);
164
displayDesktopName = conf.readEntry("DisplayDesktopName", true);
165
reflection = conf.readEntry("Reflection", true);
166
rotationDuration = animationTime(conf, "RotationDuration", 500);
167
backgroundColor = conf.readEntry("BackgroundColor", QColor(Qt::black));
168
capColor = conf.readEntry("CapColor", KColorScheme(QPalette::Active, KColorScheme::Window).background().color());
169
paintCaps = conf.readEntry("Caps", true);
170
closeOnMouseRelease = conf.readEntry("CloseOnMouseRelease", false);
171
float defaultZPosition = 100.0f;
172
if (config == "Sphere")
173
defaultZPosition = 450.0f;
174
zPosition = conf.readEntry("ZPosition", defaultZPosition);
175
useForTabBox = conf.readEntry("TabBox", false);
176
invertKeys = conf.readEntry("InvertKeys", false);
177
invertMouse = conf.readEntry("InvertMouse", false);
178
capDeformationFactor = conf.readEntry("CapDeformation", 0) / 100.0f;
179
useZOrdering = conf.readEntry("ZOrdering", false);
180
QString file = conf.readEntry("Wallpaper", QString(""));
182
wallpaper->discard();
185
if (!file.isEmpty()) {
186
QImage img = QImage(file);
188
wallpaper = new GLTexture(img);
193
texturedCaps = conf.readEntry("TexturedCaps", true);
195
QString capPath = conf.readEntry("CapPath", KGlobal::dirs()->findResource("appdata", "cubecap.png"));
196
QImage img = QImage(capPath);
198
capTexture = new GLTexture(img);
199
capTexture->setFilter(GL_LINEAR);
200
#ifndef KWIN_HAVE_OPENGLES
201
capTexture->setWrapMode(GL_CLAMP_TO_BORDER);
206
timeLine.setCurveShape(QTimeLine::EaseInOutCurve);
207
timeLine.setDuration(rotationDuration);
209
verticalTimeLine.setCurveShape(QTimeLine::EaseInOutCurve);
210
verticalTimeLine.setDuration(rotationDuration);
212
// do not connect the shortcut if we use cylinder or sphere
213
if (!shortcutsRegistered) {
214
KActionCollection* actionCollection = new KActionCollection(this);
215
KAction* cubeAction = static_cast< KAction* >(actionCollection->addAction("Cube"));
216
cubeAction->setText(i18n("Desktop Cube"));
217
cubeAction->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F11));
218
cubeShortcut = cubeAction->globalShortcut();
219
KAction* cylinderAction = static_cast< KAction* >(actionCollection->addAction("Cylinder"));
220
cylinderAction->setText(i18n("Desktop Cylinder"));
221
cylinderAction->setGlobalShortcut(KShortcut(), KAction::ActiveShortcut);
222
cylinderShortcut = cylinderAction->globalShortcut();
223
KAction* sphereAction = static_cast< KAction* >(actionCollection->addAction("Sphere"));
224
sphereAction->setText(i18n("Desktop Sphere"));
225
sphereAction->setGlobalShortcut(KShortcut(), KAction::ActiveShortcut);
226
sphereShortcut = sphereAction->globalShortcut();
227
connect(cubeAction, SIGNAL(triggered(bool)), this, SLOT(toggleCube()));
228
connect(cylinderAction, SIGNAL(triggered(bool)), this, SLOT(toggleCylinder()));
229
connect(sphereAction, SIGNAL(triggered(bool)), this, SLOT(toggleSphere()));
230
connect(cubeAction, SIGNAL(globalShortcutChanged(QKeySequence)), this, SLOT(cubeShortcutChanged(QKeySequence)));
231
connect(cylinderAction, SIGNAL(globalShortcutChanged(QKeySequence)), this, SLOT(cylinderShortcutChanged(QKeySequence)));
232
connect(sphereAction, SIGNAL(globalShortcutChanged(QKeySequence)), this, SLOT(sphereShortcutChanged(QKeySequence)));
233
shortcutsRegistered = true;
236
// set the cap color on the shader
237
if (ShaderManager::instance()->isValid() && m_capShader->isValid()) {
238
ShaderManager::instance()->pushShader(m_capShader);
239
m_capShader->setUniform("u_capColor", capColor);
240
ShaderManager::instance()->popShader();
244
CubeEffect::~CubeEffect()
246
foreach (ElectricBorder border, borderActivate) {
247
effects->unreserveElectricBorder(border);
249
foreach (ElectricBorder border, borderActivateCylinder) {
250
effects->unreserveElectricBorder(border);
252
foreach (ElectricBorder border, borderActivateSphere) {
253
effects->unreserveElectricBorder(border);
257
delete cylinderShader;
259
delete desktopNameFrame;
260
delete m_reflectionShader;
262
delete m_cubeCapBuffer;
265
bool CubeEffect::loadShader()
267
if (!(GLPlatform::instance()->supports(GLSL) &&
268
(effects->compositingType() == OpenGLCompositing)))
270
QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/cylinder.frag");
271
QString cylinderVertexshader = KGlobal::dirs()->findResource("data", "kwin/cylinder.vert");
272
QString sphereVertexshader = KGlobal::dirs()->findResource("data", "kwin/sphere.vert");
273
if (fragmentshader.isEmpty() || cylinderVertexshader.isEmpty() || sphereVertexshader.isEmpty()) {
274
kError(1212) << "Couldn't locate shader files" << endl;
278
ShaderManager *shaderManager = ShaderManager::instance();
279
// TODO: use generic shader - currently it is failing in alpha/brightness manipulation
280
cylinderShader = new GLShader(cylinderVertexshader, fragmentshader);
281
if (!cylinderShader->isValid()) {
282
kError(1212) << "The cylinder shader failed to load!" << endl;
285
shaderManager->pushShader(cylinderShader);
286
cylinderShader->setUniform("sampler", 0);
287
QMatrix4x4 projection;
292
float ymax = zNear * tan(fovy * M_PI / 360.0f);
294
float xmin = ymin * aspect;
295
float xmax = ymax * aspect;
296
projection.frustum(xmin, xmax, ymin, ymax, zNear, zFar);
297
cylinderShader->setUniform("projection", projection);
298
QMatrix4x4 modelview;
299
float scaleFactor = 1.1 * tan(fovy * M_PI / 360.0f) / ymax;
300
modelview.translate(xmin * scaleFactor, ymax * scaleFactor, -1.1);
301
modelview.scale((xmax - xmin)*scaleFactor / displayWidth(), -(ymax - ymin)*scaleFactor / displayHeight(), 0.001);
302
cylinderShader->setUniform("modelview", modelview);
303
const QMatrix4x4 identity;
304
cylinderShader->setUniform("screenTransformation", identity);
305
cylinderShader->setUniform("windowTransformation", identity);
306
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
307
cylinderShader->setUniform("width", (float)rect.width() * 0.5f);
308
shaderManager->popShader();
310
// TODO: use generic shader - currently it is failing in alpha/brightness manipulation
311
sphereShader = new GLShader(sphereVertexshader, fragmentshader);
312
if (!sphereShader->isValid()) {
313
kError(1212) << "The sphere shader failed to load!" << endl;
316
shaderManager->pushShader(sphereShader);
317
sphereShader->setUniform("sampler", 0);
318
QMatrix4x4 projection;
323
float ymax = zNear * tan(fovy * M_PI / 360.0f);
325
float xmin = ymin * aspect;
326
float xmax = ymax * aspect;
327
projection.frustum(xmin, xmax, ymin, ymax, zNear, zFar);
328
sphereShader->setUniform("projection", projection);
329
QMatrix4x4 modelview;
330
float scaleFactor = 1.1 * tan(fovy * M_PI / 360.0f) / ymax;
331
modelview.translate(xmin * scaleFactor, ymax * scaleFactor, -1.1);
332
modelview.scale((xmax - xmin)*scaleFactor / displayWidth(), -(ymax - ymin)*scaleFactor / displayHeight(), 0.001);
333
sphereShader->setUniform("modelview", modelview);
334
const QMatrix4x4 identity;
335
sphereShader->setUniform("screenTransformation", identity);
336
sphereShader->setUniform("windowTransformation", identity);
337
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
338
sphereShader->setUniform("width", (float)rect.width() * 0.5f);
339
sphereShader->setUniform("height", (float)rect.height() * 0.5f);
340
sphereShader->setUniform("u_offset", QVector2D(0, 0));
341
shaderManager->popShader();
342
checkGLError("Loading Sphere Shader");
347
void CubeEffect::prePaintScreen(ScreenPrePaintData& data, int time)
350
data.mask |= PAINT_SCREEN_TRANSFORMED | Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS | PAINT_SCREEN_BACKGROUND_FIRST;
352
if (rotating || start || stop) {
353
timeLine.setCurrentTime(timeLine.currentTime() + time);
356
if (verticalRotating) {
357
verticalTimeLine.setCurrentTime(verticalTimeLine.currentTime() + time);
361
effects->prePaintScreen(data, time);
364
void CubeEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data)
367
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
371
glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor);
372
glClearColor(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF(), 1.0);
373
glClear(GL_COLOR_BUFFER_BIT);
374
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
378
if (ShaderManager::instance()->isValid()) {
379
ShaderManager::instance()->pushShader(ShaderManager::SimpleShader);
382
wallpaper->render(region, rect);
384
if (ShaderManager::instance()->isValid()) {
385
ShaderManager::instance()->popShader();
389
#ifndef KWIN_HAVE_OPENGLES
390
glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT);
393
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
395
// some veriables needed for painting the caps
396
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
397
float point = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
398
float zTranslate = zPosition + zoom;
400
zTranslate *= timeLine.currentValue();
402
zTranslate *= (1.0 - timeLine.currentValue());
404
if (reflection && mode != Sphere) {
405
// restrict painting the reflections to the current screen
406
PaintClipper::push(QRegion(rect));
407
// we can use a huge scale factor (needed to calculate the rearground vertices)
408
// as we restrict with a PaintClipper painting on the current screen
409
float scaleFactor = 1000000 * tan(60.0 * M_PI / 360.0f) / rect.height();
410
m_reflectionMatrix.setToIdentity();
411
m_reflectionMatrix.scale(1.0, -1.0, 1.0);
413
// TODO reflection is not correct when mixing manual (mouse) rotating with rotation by cursor keys
414
// there's also a small bug when zooming
415
float addedHeight1 = -sin(asin(float(rect.height()) / mAddedHeightCoeff1) + fabs(manualVerticalAngle) * M_PI / 180.0f) * mAddedHeightCoeff1;
416
float addedHeight2 = -sin(asin(float(rect.height()) / mAddedHeightCoeff2) + fabs(manualVerticalAngle) * M_PI / 180.0f) * mAddedHeightCoeff2 - addedHeight1;
417
if (manualVerticalAngle > 0.0f && effects->numberOfDesktops() & 1) {
418
m_reflectionMatrix.translate(0.0, cos(fabs(manualAngle) * M_PI / 360.0f * float(effects->numberOfDesktops())) * addedHeight2 + addedHeight1 - float(rect.height()), 0.0);
420
m_reflectionMatrix.translate(0.0, sin(fabs(manualAngle) * M_PI / 360.0f * float(effects->numberOfDesktops())) * addedHeight2 + addedHeight1 - float(rect.height()), 0.0);
422
pushMatrix(m_reflectionMatrix);
424
#ifndef KWIN_HAVE_OPENGLES
425
// TODO: find a solution for GLES
426
glEnable(GL_CLIP_PLANE0);
428
reflectionPainting = true;
429
glEnable(GL_CULL_FACE);
430
paintCap(true, -point - zTranslate);
434
pushMatrix(m_rotationMatrix);
435
paintCube(mask, region, data);
438
// call the inside cube effects
439
#ifndef KWIN_HAVE_OPENGLES
440
foreach (CubeInsideEffect * inside, m_cubeInsideEffects) {
441
pushMatrix(m_rotationMatrix);
442
glTranslatef(rect.width() / 2, rect.height() / 2, -point - zTranslate);
443
glRotatef((1 - frontDesktop) * 360.0f / effects->numberOfDesktops(), 0.0, 1.0, 0.0);
449
glCullFace(GL_FRONT);
450
pushMatrix(m_rotationMatrix);
451
paintCube(mask, region, data);
454
paintCap(false, -point - zTranslate);
455
glDisable(GL_CULL_FACE);
456
reflectionPainting = false;
457
#ifndef KWIN_HAVE_OPENGLES
458
// TODO: find a solution for GLES
459
glDisable(GL_CLIP_PLANE0);
464
-rect.width() * 0.5f, rect.height(), 0.0,
465
rect.width() * 0.5f, rect.height(), 0.0,
466
(float)rect.width()*scaleFactor, rect.height(), -5000,
467
-(float)rect.width()*scaleFactor, rect.height(), -5000
472
alpha = 0.3 + 0.4 * timeLine.currentValue();
474
alpha = 0.3 + 0.4 * (1.0 - timeLine.currentValue());
476
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
477
ShaderManager *shaderManager = ShaderManager::instance();
478
if (shaderManager->isValid() && m_reflectionShader->isValid()) {
479
// ensure blending is enabled - no attribute stack
480
shaderManager->pushShader(m_reflectionShader);
481
QMatrix4x4 windowTransformation;
482
windowTransformation.translate(rect.x() + rect.width() * 0.5f, 0.0, 0.0);
483
m_reflectionShader->setUniform("windowTransformation", windowTransformation);
484
m_reflectionShader->setUniform("u_alpha", alpha);
485
QVector<float> verts;
486
QVector<float> texcoords;
488
texcoords.reserve(12);
489
texcoords << 0.0 << 0.0;
490
verts << vertices[6] << vertices[7] << vertices[8];
491
texcoords << 0.0 << 0.0;
492
verts << vertices[9] << vertices[10] << vertices[11];
493
texcoords << 1.0 << 0.0;
494
verts << vertices[0] << vertices[1] << vertices[2];
495
texcoords << 1.0 << 0.0;
496
verts << vertices[0] << vertices[1] << vertices[2];
497
texcoords << 1.0 << 0.0;
498
verts << vertices[3] << vertices[4] << vertices[5];
499
texcoords << 0.0 << 0.0;
500
verts << vertices[6] << vertices[7] << vertices[8];
501
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
503
vbo->setData(6, 3, verts.data(), texcoords.data());
504
vbo->render(GL_TRIANGLES);
506
shaderManager->popShader();
508
#ifndef KWIN_HAVE_OPENGLES
509
glColor4f(0.0, 0.0, 0.0, alpha);
511
glTranslatef(rect.x() + rect.width() * 0.5f, 0.0, 0.0);
513
glVertex3f(vertices[0], vertices[1], vertices[2]);
514
glVertex3f(vertices[3], vertices[4], vertices[5]);
517
glColor4f(0.0, 0.0, 0.0, alpha);
518
glVertex3f(vertices[6], vertices[7], vertices[8]);
519
glVertex3f(vertices[9], vertices[10], vertices[11]);
525
PaintClipper::pop(QRegion(rect));
527
glEnable(GL_CULL_FACE);
529
paintCap(false, -point - zTranslate);
532
glCullFace(GL_FRONT);
533
pushMatrix(m_rotationMatrix);
534
paintCube(mask, region, data);
538
// call the inside cube effects
539
#ifndef KWIN_HAVE_OPENGLES
540
foreach (CubeInsideEffect * inside, m_cubeInsideEffects) {
541
pushMatrix(m_rotationMatrix);
542
glTranslatef(rect.width() / 2, rect.height() / 2, -point - zTranslate);
543
glRotatef((1 - frontDesktop) * 360.0f / effects->numberOfDesktops(), 0.0, 1.0, 0.0);
550
pushMatrix(m_rotationMatrix);
551
paintCube(mask, region, data);
555
paintCap(true, -point - zTranslate);
556
glDisable(GL_CULL_FACE);
559
#ifndef KWIN_HAVE_OPENGLES
563
// desktop name box - inspired from coverswitch
564
if (displayDesktopName) {
565
double opacity = 1.0;
567
opacity = timeLine.currentValue();
569
opacity = 1.0 - timeLine.currentValue();
570
QRect screenRect = effects->clientArea(ScreenArea, activeScreen, frontDesktop);
571
QRect frameRect = QRect(screenRect.width() * 0.33f + screenRect.x(), screenRect.height() * 0.95f + screenRect.y(),
572
screenRect.width() * 0.34f, QFontMetrics(desktopNameFont).height());
573
desktopNameFrame->setGeometry(frameRect);
574
desktopNameFrame->setText(effects->desktopName(frontDesktop));
575
desktopNameFrame->render(region, opacity);
578
effects->paintScreen(mask, region, data);
582
void CubeEffect::rotateCube()
584
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
586
m_rotationMatrix.setToIdentity();
587
float internalCubeAngle = 360.0f / effects->numberOfDesktops();
588
float zTranslate = zPosition + zoom;
590
zTranslate *= timeLine.currentValue();
592
zTranslate *= (1.0 - timeLine.currentValue());
593
// Rotation of the cube
594
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
595
float point = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
596
if (verticalRotating || verticalPosition != Normal || manualVerticalAngle != 0.0) {
597
// change the verticalPosition if manualVerticalAngle > 90 or < -90 degrees
598
if (manualVerticalAngle <= -90.0) {
599
manualVerticalAngle += 90.0;
600
if (verticalPosition == Normal)
601
verticalPosition = Down;
602
if (verticalPosition == Up)
603
verticalPosition = Normal;
605
if (manualVerticalAngle >= 90.0) {
606
manualVerticalAngle -= 90.0;
607
if (verticalPosition == Normal)
608
verticalPosition = Up;
609
if (verticalPosition == Down)
610
verticalPosition = Normal;
613
if (verticalPosition == Up) {
615
if (!verticalRotating) {
616
if (manualVerticalAngle < 0.0)
617
angle += manualVerticalAngle;
619
manualVerticalAngle = 0.0;
621
} else if (verticalPosition == Down) {
623
if (!verticalRotating) {
624
if (manualVerticalAngle > 0.0)
625
angle += manualVerticalAngle;
627
manualVerticalAngle = 0.0;
630
angle = manualVerticalAngle;
632
if (verticalRotating) {
633
angle *= verticalTimeLine.currentValue();
634
if (verticalPosition == Normal && verticalRotationDirection == Upwards)
635
angle = -90.0 + 90 * verticalTimeLine.currentValue();
636
if (verticalPosition == Normal && verticalRotationDirection == Downwards)
637
angle = 90.0 - 90 * verticalTimeLine.currentValue();
638
angle += manualVerticalAngle * (1.0 - verticalTimeLine.currentValue());
641
angle *= (1.0 - timeLine.currentValue());
642
m_rotationMatrix.translate(rect.width() / 2, rect.height() / 2, -point - zTranslate);
643
m_rotationMatrix.rotate(angle, 1.0, 0.0, 0.0);
644
m_rotationMatrix.translate(-rect.width() / 2, -rect.height() / 2, point + zTranslate);
646
if (rotating || (manualAngle != 0.0)) {
647
int tempFrontDesktop = frontDesktop;
648
if (manualAngle > internalCubeAngle * 0.5f) {
649
manualAngle -= internalCubeAngle;
651
if (tempFrontDesktop == 0)
652
tempFrontDesktop = effects->numberOfDesktops();
654
if (manualAngle < -internalCubeAngle * 0.5f) {
655
manualAngle += internalCubeAngle;
657
if (tempFrontDesktop > effects->numberOfDesktops())
658
tempFrontDesktop = 1;
660
float rotationAngle = internalCubeAngle * timeLine.currentValue();
661
if (rotationAngle > internalCubeAngle * 0.5f) {
662
rotationAngle -= internalCubeAngle;
663
if (!desktopChangedWhileRotating) {
664
desktopChangedWhileRotating = true;
665
if (rotationDirection == Left) {
667
} else if (rotationDirection == Right) {
670
if (tempFrontDesktop > effects->numberOfDesktops())
671
tempFrontDesktop = 1;
672
else if (tempFrontDesktop == 0)
673
tempFrontDesktop = effects->numberOfDesktops();
676
// don't change front desktop during stop animation as this would break some logic
678
frontDesktop = tempFrontDesktop;
679
if (rotationDirection == Left) {
683
rotationAngle = manualAngle * (1.0 - timeLine.currentValue());
685
rotationAngle += manualAngle * (1.0 - timeLine.currentValue());
686
m_rotationMatrix.translate(rect.width() / 2, rect.height() / 2, -point - zTranslate);
687
m_rotationMatrix.rotate(rotationAngle, 0.0, 1.0, 0.0);
688
m_rotationMatrix.translate(-rect.width() / 2, -rect.height() / 2, point + zTranslate);
692
void CubeEffect::paintCube(int mask, QRegion region, ScreenPaintData& data)
694
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
695
float internalCubeAngle = 360.0f / effects->numberOfDesktops();
696
cube_painting = true;
697
float zTranslate = zPosition + zoom;
699
zTranslate *= timeLine.currentValue();
701
zTranslate *= (1.0 - timeLine.currentValue());
703
// Rotation of the cube
704
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
705
float point = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
707
for (int i = 0; i < effects->numberOfDesktops(); i++) {
708
// start painting the cube
709
painting_desktop = (i + frontDesktop) % effects->numberOfDesktops();
710
if (painting_desktop == 0) {
711
painting_desktop = effects->numberOfDesktops();
713
ScreenPaintData newData = data;
714
RotationData rot = RotationData();
715
rot.axis = RotationData::YAxis;
716
rot.angle = internalCubeAngle * i;
717
rot.xRotationPoint = rect.width() / 2;
718
rot.zRotationPoint = -point;
719
newData.rotation = &rot;
720
newData.zTranslate = -zTranslate;
721
effects->paintScreen(mask, region, newData);
723
cube_painting = false;
724
painting_desktop = effects->currentDesktop();
727
void CubeEffect::paintCap(bool frontFirst, float zOffset)
729
if ((!paintCaps) || effects->numberOfDesktops() <= 2)
731
GLenum firstCull = frontFirst ? GL_FRONT : GL_BACK;
732
GLenum secondCull = frontFirst ? GL_BACK : GL_FRONT;
733
const QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
735
// create the VBO if not yet created
736
if (!m_cubeCapBuffer) {
753
QMatrix4x4 capMatrix;
754
capMatrix.translate(rect.width() / 2, 0.0, zOffset);
755
capMatrix.rotate((1 - frontDesktop) * 360.0f / effects->numberOfDesktops(), 0.0, 1.0, 0.0);
756
capMatrix.translate(0.0, rect.height(), 0.0);
757
if (mode == Sphere) {
758
capMatrix.scale(1.0, -1.0, 1.0);
761
bool capShader = false;
762
if (ShaderManager::instance()->isValid() && m_capShader->isValid()) {
764
ShaderManager::instance()->pushShader(m_capShader);
765
float opacity = cubeOpacity;
767
opacity *= timeLine.currentValue();
769
opacity *= (1.0 - timeLine.currentValue());
771
m_capShader->setUniform("u_opacity", opacity);
772
m_capShader->setUniform("u_mirror", 1);
773
if (reflectionPainting) {
774
m_capShader->setUniform("screenTransformation", m_reflectionMatrix * m_rotationMatrix);
776
m_capShader->setUniform("screenTransformation", m_rotationMatrix);
778
m_capShader->setUniform("windowTransformation", capMatrix);
779
m_capShader->setUniform("u_untextured", texturedCaps ? 0 : 1);
780
if (texturedCaps && effects->numberOfDesktops() > 3 && capTexture) {
784
pushMatrix(m_rotationMatrix * capMatrix);
786
#ifndef KWIN_HAVE_OPENGLES
787
glMatrixMode(GL_TEXTURE);
790
loadMatrix(m_textureMirrorMatrix);
791
#ifndef KWIN_HAVE_OPENGLES
792
glMatrixMode(GL_MODELVIEW);
794
glColor4f(capColor.redF(), capColor.greenF(), capColor.blueF(), cubeOpacity);
795
if (texturedCaps && effects->numberOfDesktops() > 3 && capTexture) {
796
// modulate the cap texture: cap color should be background for translucent pixels
797
// cube opacity should be used for all pixels
798
// blend with cap color
799
float color[4] = { capColor.redF(), capColor.greenF(), capColor.blueF(), cubeOpacity };
800
glActiveTexture(GL_TEXTURE0);
802
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
805
// set Opacity to cube opacity
806
// TODO: change opacity during start/stop animation
807
glActiveTexture(GL_TEXTURE1);
809
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
810
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
811
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
812
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
813
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);
814
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
815
glActiveTexture(GL_TEXTURE0);
816
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
822
glCullFace(firstCull);
823
m_cubeCapBuffer->render(GL_TRIANGLES);
825
if (mode == Sphere) {
826
capMatrix.scale(1.0, -1.0, 1.0);
828
capMatrix.translate(0.0, -rect.height(), 0.0);
830
m_capShader->setUniform("windowTransformation", capMatrix);
831
m_capShader->setUniform("u_mirror", 0);
833
#ifndef KWIN_HAVE_OPENGLES
834
glMatrixMode(GL_TEXTURE);
836
glMatrixMode(GL_MODELVIEW);
839
pushMatrix(m_rotationMatrix * capMatrix);
841
glCullFace(secondCull);
842
m_cubeCapBuffer->render(GL_TRIANGLES);
846
ShaderManager::instance()->popShader();
847
if (texturedCaps && effects->numberOfDesktops() > 3 && capTexture) {
848
capTexture->unbind();
852
if (texturedCaps && effects->numberOfDesktops() > 3 && capTexture) {
853
#ifndef KWIN_HAVE_OPENGLES
854
glActiveTexture(GL_TEXTURE1);
855
glDisable(capTexture->target());
856
glActiveTexture(GL_TEXTURE0);
857
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
858
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
859
capTexture->unbind();
865
void CubeEffect::paintCubeCap()
867
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
868
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
869
float z = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
870
float zTexture = rect.width() / 2 * tan(45.0f * M_PI / 180.0f);
871
float angle = 360.0f / effects->numberOfDesktops();
872
bool texture = texturedCaps && effects->numberOfDesktops() > 3 && capTexture;
873
QVector<float> verts;
874
QVector<float> texCoords;
875
for (int i = 0; i < effects->numberOfDesktops(); i++) {
876
int triangleRows = effects->numberOfDesktops() * 5;
877
float zTriangleDistance = z / (float)triangleRows;
878
float widthTriangle = tan(angle * 0.5 * M_PI / 180.0) * zTriangleDistance;
879
float currentWidth = 0.0;
880
float cosValue = cos(i * angle * M_PI / 180.0);
881
float sinValue = sin(i * angle * M_PI / 180.0);
882
for (int j = 0; j < triangleRows; j++) {
883
float previousWidth = currentWidth;
884
currentWidth = tan(angle * 0.5 * M_PI / 180.0) * zTriangleDistance * (j + 1);
885
int evenTriangles = 0;
886
int oddTriangles = 0;
887
for (int k = 0; k < floor(currentWidth / widthTriangle * 2 - 1 + 0.5f); k++) {
888
float x1 = -previousWidth;
889
float x2 = -currentWidth;
895
x1 += evenTriangles * widthTriangle * 2;
896
x2 += evenTriangles * widthTriangle * 2;
897
x3 = x2 + widthTriangle * 2;
898
z1 = j * zTriangleDistance;
899
z2 = (j + 1) * zTriangleDistance;
900
z3 = (j + 1) * zTriangleDistance;
901
float xRot = cosValue * x1 - sinValue * z1;
902
float zRot = sinValue * x1 + cosValue * z1;
905
xRot = cosValue * x2 - sinValue * z2;
906
zRot = sinValue * x2 + cosValue * z2;
909
xRot = cosValue * x3 - sinValue * z3;
910
zRot = sinValue * x3 + cosValue * z3;
915
x1 += oddTriangles * widthTriangle * 2;
916
x2 += (oddTriangles + 1) * widthTriangle * 2;
917
x3 = x1 + widthTriangle * 2;
918
z1 = j * zTriangleDistance;
919
z2 = (j + 1) * zTriangleDistance;
920
z3 = j * zTriangleDistance;
921
float xRot = cosValue * x1 - sinValue * z1;
922
float zRot = sinValue * x1 + cosValue * z1;
925
xRot = cosValue * x2 - sinValue * z2;
926
zRot = sinValue * x2 + cosValue * z2;
929
xRot = cosValue * x3 - sinValue * z3;
930
zRot = sinValue * x3 + cosValue * z3;
942
texX1 = x1 / (rect.width()) + 0.5;
943
texY1 = 0.5 - z1 / zTexture * 0.5;
944
texX2 = x2 / (rect.width()) + 0.5;
945
texY2 = 0.5 - z2 / zTexture * 0.5;
946
texX3 = x3 / (rect.width()) + 0.5;
947
texY3 = 0.5 - z3 / zTexture * 0.5;
948
texCoords << texX1 << texY1;
950
verts << x1 << 0.0 << z1;
952
texCoords << texX2 << texY2;
954
verts << x2 << 0.0 << z2;
956
texCoords << texX3 << texY3;
958
verts << x3 << 0.0 << z3;
962
delete m_cubeCapBuffer;
963
m_cubeCapBuffer = new GLVertexBuffer(GLVertexBuffer::Static);
964
m_cubeCapBuffer->setData(verts.count() / 3, 3, verts.constData(), texture ? texCoords.constData() : NULL);
967
void CubeEffect::paintCylinderCap()
969
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
970
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
972
float radian = (cubeAngle * 0.5) * M_PI / 180;
973
float radius = (rect.width() * 0.5) * tan(radian);
974
float segment = radius / 30.0f;
976
bool texture = texturedCaps && effects->numberOfDesktops() > 3 && capTexture;
977
QVector<float> verts;
978
QVector<float> texCoords;
979
for (int i = 1; i <= 30; i++) {
981
for (int j = 0; j <= steps; j++) {
982
const float azimuthAngle = (j * (360.0f / steps)) * M_PI / 180.0f;
983
const float azimuthAngle2 = ((j + 1) * (360.0f / steps)) * M_PI / 180.0f;
984
const float x1 = segment * (i - 1) * sin(azimuthAngle);
985
const float x2 = segment * i * sin(azimuthAngle);
986
const float x3 = segment * (i - 1) * sin(azimuthAngle2);
987
const float x4 = segment * i * sin(azimuthAngle2);
988
const float z1 = segment * (i - 1) * cos(azimuthAngle);
989
const float z2 = segment * i * cos(azimuthAngle);
990
const float z3 = segment * (i - 1) * cos(azimuthAngle2);
991
const float z4 = segment * i * cos(azimuthAngle2);
993
texCoords << (radius + x1) / (radius * 2.0f) << 1.0f - (z1 + radius) / (radius * 2.0f);
994
texCoords << (radius + x2) / (radius * 2.0f) << 1.0f - (z2 + radius) / (radius * 2.0f);
995
texCoords << (radius + x3) / (radius * 2.0f) << 1.0f - (z3 + radius) / (radius * 2.0f);
996
texCoords << (radius + x4) / (radius * 2.0f) << 1.0f - (z4 + radius) / (radius * 2.0f);
997
texCoords << (radius + x3) / (radius * 2.0f) << 1.0f - (z3 + radius) / (radius * 2.0f);
998
texCoords << (radius + x2) / (radius * 2.0f) << 1.0f - (z2 + radius) / (radius * 2.0f);
1000
verts << x1 << 0.0 << z1;
1001
verts << x2 << 0.0 << z2;
1002
verts << x3 << 0.0 << z3;
1003
verts << x4 << 0.0 << z4;
1004
verts << x3 << 0.0 << z3;
1005
verts << x2 << 0.0 << z2;
1008
delete m_cubeCapBuffer;
1009
m_cubeCapBuffer = new GLVertexBuffer(GLVertexBuffer::Static);
1010
m_cubeCapBuffer->setData(verts.count() / 3, 3, verts.constData(), texture ? texCoords.constData() : NULL);
1013
void CubeEffect::paintSphereCap()
1015
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
1016
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
1017
float zTexture = rect.width() / 2 * tan(45.0f * M_PI / 180.0f);
1018
float radius = (rect.width() * 0.5) / cos(cubeAngle * 0.5 * M_PI / 180.0);
1019
float angle = acos((rect.height() * 0.5) / radius) * 180.0 / M_PI;
1021
bool texture = texturedCaps && effects->numberOfDesktops() > 3 && capTexture;
1022
QVector<float> verts;
1023
QVector<float> texCoords;
1024
for (int i = 0; i < 30; i++) {
1025
float topAngle = angle * i * M_PI / 180.0;
1026
float bottomAngle = angle * (i + 1) * M_PI / 180.0;
1027
float yTop = rect.height() * 0.5 - radius * cos(topAngle);
1028
yTop -= (yTop - rect.height() * 0.5) * capDeformationFactor;
1029
float yBottom = rect.height() * 0.5 - radius * cos(bottomAngle);
1030
yBottom -= (yBottom - rect.height() * 0.5) * capDeformationFactor;
1031
for (int j = 0; j < 36; j++) {
1032
const float x1 = radius * sin(topAngle) * sin((90.0 + j * 10.0) * M_PI / 180.0);
1033
const float z1 = radius * sin(topAngle) * cos((90.0 + j * 10.0) * M_PI / 180.0);
1034
const float x2 = radius * sin(bottomAngle) * sin((90.0 + j * 10.0) * M_PI / 180.00);
1035
const float z2 = radius * sin(bottomAngle) * cos((90.0 + j * 10.0) * M_PI / 180.0);
1036
const float x3 = radius * sin(bottomAngle) * sin((90.0 + (j + 1) * 10.0) * M_PI / 180.0);
1037
const float z3 = radius * sin(bottomAngle) * cos((90.0 + (j + 1) * 10.0) * M_PI / 180.0);
1038
const float x4 = radius * sin(topAngle) * sin((90.0 + (j + 1) * 10.0) * M_PI / 180.0);
1039
const float z4 = radius * sin(topAngle) * cos((90.0 + (j + 1) * 10.0) * M_PI / 180.0);
1041
texCoords << x4 / (rect.width()) + 0.5 << 0.5 - z4 / zTexture * 0.5;
1042
texCoords << x1 / (rect.width()) + 0.5 << 0.5 - z1 / zTexture * 0.5;
1043
texCoords << x2 / (rect.width()) + 0.5 << 0.5 - z2 / zTexture * 0.5;
1044
texCoords << x2 / (rect.width()) + 0.5 << 0.5 - z2 / zTexture * 0.5;
1045
texCoords << x3 / (rect.width()) + 0.5 << 0.5 - z3 / zTexture * 0.5;
1046
texCoords << x4 / (rect.width()) + 0.5 << 0.5 - z4 / zTexture * 0.5;
1048
verts << x4 << yTop << z4;
1049
verts << x1 << yTop << z1;
1050
verts << x2 << yBottom << z2;
1051
verts << x2 << yBottom << z2;
1052
verts << x3 << yBottom << z3;
1053
verts << x4 << yTop << z4;
1056
delete m_cubeCapBuffer;
1057
m_cubeCapBuffer = new GLVertexBuffer(GLVertexBuffer::Static);
1058
m_cubeCapBuffer->setData(verts.count() / 3, 3, verts.constData(), texture ? texCoords.constData() : NULL);
1061
void CubeEffect::postPaintScreen()
1063
effects->postPaintScreen();
1066
if (timeLine.currentValue() == 1.0) {
1068
timeLine.setCurrentTime(0);
1070
if (!rotations.empty()) {
1071
rotationDirection = rotations.dequeue();
1073
// change the curve shape if current shape is not easeInOut
1074
if (currentShape != QTimeLine::EaseInOutCurve) {
1075
// more rotations follow -> linear curve
1076
if (!rotations.empty()) {
1077
currentShape = QTimeLine::LinearCurve;
1079
// last rotation step -> easeOut curve
1081
currentShape = QTimeLine::EaseOutCurve;
1083
timeLine.setCurveShape(currentShape);
1085
// if there is at least one more rotation, we can change to easeIn
1086
if (!rotations.empty()) {
1087
currentShape = QTimeLine::EaseInCurve;
1088
timeLine.setCurveShape(currentShape);
1093
effects->addRepaintFull();
1094
return; // schedule_close could have been called, start has to finish first
1097
if (timeLine.currentValue() == 1.0) {
1098
effects->setCurrentDesktop(frontDesktop);
1100
timeLine.setCurrentTime(0);
1102
// set the new desktop
1104
effects->ungrabKeyboard();
1105
keyboard_grab = false;
1106
effects->destroyInputWindow(input);
1108
effects->setActiveFullScreenEffect(0);
1110
delete m_cubeCapBuffer;
1111
m_cubeCapBuffer = NULL;
1112
desktopNameFrame->free();
1114
effects->addRepaintFull();
1116
if (rotating || verticalRotating) {
1117
if (rotating && timeLine.currentValue() == 1.0) {
1118
timeLine.setCurrentTime(0.0);
1120
desktopChangedWhileRotating = false;
1123
if (!rotations.empty()) {
1124
rotationDirection = rotations.dequeue();
1126
// change the curve shape if current shape is not easeInOut
1127
if (currentShape != QTimeLine::EaseInOutCurve) {
1128
// more rotations follow -> linear curve
1129
if (!rotations.empty()) {
1130
currentShape = QTimeLine::LinearCurve;
1132
// last rotation step -> easeOut curve
1134
currentShape = QTimeLine::EaseOutCurve;
1136
timeLine.setCurveShape(currentShape);
1138
// if there is at least one more rotation, we can change to easeIn
1139
if (!rotations.empty()) {
1140
currentShape = QTimeLine::EaseInCurve;
1141
timeLine.setCurveShape(currentShape);
1145
// reset curve shape if there are no more rotations
1146
if (currentShape != QTimeLine::EaseInOutCurve) {
1147
currentShape = QTimeLine::EaseInOutCurve;
1148
timeLine.setCurveShape(currentShape);
1152
if (verticalRotating && verticalTimeLine.currentValue() == 1.0) {
1153
verticalTimeLine.setCurrentTime(0);
1154
verticalRotating = false;
1155
manualVerticalAngle = 0.0;
1157
if (!verticalRotations.empty()) {
1158
verticalRotationDirection = verticalRotations.dequeue();
1159
verticalRotating = true;
1160
if (verticalRotationDirection == Upwards) {
1161
if (verticalPosition == Normal)
1162
verticalPosition = Up;
1163
if (verticalPosition == Down)
1164
verticalPosition = Normal;
1166
if (verticalRotationDirection == Downwards) {
1167
if (verticalPosition == Normal)
1168
verticalPosition = Down;
1169
if (verticalPosition == Up)
1170
verticalPosition = Normal;
1174
effects->addRepaintFull();
1175
return; // rotation has to end before cube is closed
1177
if (schedule_close) {
1178
schedule_close = false;
1180
effects->addRepaintFull();
1185
void CubeEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time)
1188
if (cube_painting) {
1189
if (mode == Cylinder || mode == Sphere) {
1190
int leftDesktop = frontDesktop - 1;
1191
int rightDesktop = frontDesktop + 1;
1192
if (leftDesktop == 0)
1193
leftDesktop = effects->numberOfDesktops();
1194
if (rightDesktop > effects->numberOfDesktops())
1196
if (painting_desktop == frontDesktop)
1197
data.quads = data.quads.makeGrid(40);
1198
else if (painting_desktop == leftDesktop || painting_desktop == rightDesktop)
1199
data.quads = data.quads.makeGrid(100);
1201
data.quads = data.quads.makeGrid(250);
1203
if (w->isOnDesktop(painting_desktop)) {
1204
QRect rect = effects->clientArea(FullArea, activeScreen, painting_desktop);
1205
if (w->x() < rect.x()) {
1206
data.quads = data.quads.splitAtX(-w->x());
1208
if (w->x() + w->width() > rect.x() + rect.width()) {
1209
data.quads = data.quads.splitAtX(rect.width() - w->x());
1211
if (w->y() < rect.y()) {
1212
data.quads = data.quads.splitAtY(-w->y());
1214
if (w->y() + w->height() > rect.y() + rect.height()) {
1215
data.quads = data.quads.splitAtY(rect.height() - w->y());
1217
if (useZOrdering && !w->isDesktop() && !w->isDock() && !w->isOnAllDesktops())
1218
data.setTransformed();
1219
w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
1221
// check for windows belonging to the previous desktop
1222
int prev_desktop = painting_desktop - 1;
1223
if (prev_desktop == 0)
1224
prev_desktop = effects->numberOfDesktops();
1225
if (w->isOnDesktop(prev_desktop) && mode == Cube && !useZOrdering) {
1226
QRect rect = effects->clientArea(FullArea, activeScreen, prev_desktop);
1227
if (w->x() + w->width() > rect.x() + rect.width()) {
1228
w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
1229
data.quads = data.quads.splitAtX(rect.width() - w->x());
1230
if (w->y() < rect.y()) {
1231
data.quads = data.quads.splitAtY(-w->y());
1233
if (w->y() + w->height() > rect.y() + rect.height()) {
1234
data.quads = data.quads.splitAtY(rect.height() - w->y());
1236
data.setTransformed();
1237
effects->prePaintWindow(w, data, time);
1241
// check for windows belonging to the next desktop
1242
int next_desktop = painting_desktop + 1;
1243
if (next_desktop > effects->numberOfDesktops())
1245
if (w->isOnDesktop(next_desktop) && mode == Cube && !useZOrdering) {
1246
QRect rect = effects->clientArea(FullArea, activeScreen, next_desktop);
1247
if (w->x() < rect.x()) {
1248
w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
1249
data.quads = data.quads.splitAtX(-w->x());
1250
if (w->y() < rect.y()) {
1251
data.quads = data.quads.splitAtY(-w->y());
1253
if (w->y() + w->height() > rect.y() + rect.height()) {
1254
data.quads = data.quads.splitAtY(rect.height() - w->y());
1256
data.setTransformed();
1257
effects->prePaintWindow(w, data, time);
1261
w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
1265
effects->prePaintWindow(w, data, time);
1268
void CubeEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data)
1270
ShaderManager *shaderManager = ShaderManager::instance();
1271
GLShader *shader = shaderManager->pushShader(ShaderManager::GenericShader);
1272
QMatrix4x4 origMatrix;
1273
if (activated && cube_painting) {
1274
//kDebug(1212) << w->caption();
1275
float opacity = cubeOpacity;
1277
opacity = 1.0 - (1.0 - opacity) * timeLine.currentValue();
1278
if (reflectionPainting)
1279
opacity = 0.5 + (cubeOpacity - 0.5) * timeLine.currentValue();
1280
// fade in windows belonging to different desktops
1281
if (painting_desktop == effects->currentDesktop() && (!w->isOnDesktop(painting_desktop)))
1282
opacity = timeLine.currentValue() * cubeOpacity;
1285
opacity = 1.0 - (1.0 - opacity) * (1.0 - timeLine.currentValue());
1286
if (reflectionPainting)
1287
opacity = 0.5 + (cubeOpacity - 0.5) * (1.0 - timeLine.currentValue());
1288
// fade out windows belonging to different desktops
1289
if (painting_desktop == effects->currentDesktop() && (!w->isOnDesktop(painting_desktop)))
1290
opacity = cubeOpacity * (1.0 - timeLine.currentValue());
1293
if (!w->isDesktop() && !w->isDock() && useZOrdering && !w->isOnAllDesktops()) {
1294
float zOrdering = (effects->stackingOrder().indexOf(w) + 1) * zOrderingFactor;
1296
zOrdering *= timeLine.currentValue();
1298
zOrdering *= (1.0 - timeLine.currentValue());
1299
data.zTranslate += zOrdering;
1301
// check for windows belonging to the previous desktop
1302
int prev_desktop = painting_desktop - 1;
1303
if (prev_desktop == 0)
1304
prev_desktop = effects->numberOfDesktops();
1305
int next_desktop = painting_desktop + 1;
1306
if (next_desktop > effects->numberOfDesktops())
1311
if (w->isOnDesktop(prev_desktop) && (mask & PAINT_WINDOW_TRANSFORMED)) {
1312
QRect rect = effects->clientArea(FullArea, activeScreen, prev_desktop);
1313
WindowQuadList new_quads;
1314
foreach (const WindowQuad & quad, data.quads) {
1315
if (quad.right() > rect.width() - w->x()) {
1316
new_quads.append(quad);
1319
data.quads = new_quads;
1321
data.xTranslate = -rect.width();
1323
RotationData rot = RotationData();
1324
rot.axis = RotationData::YAxis;
1325
rot.xRotationPoint = rect.width() - w->x();
1326
rot.angle = 360.0f / effects->numberOfDesktops();
1327
data.rotation = &rot;
1328
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
1329
float point = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
1331
matrix.translate(rect.width() / 2, 0.0, -point);
1332
matrix.rotate(-360.0f / effects->numberOfDesktops(), 0.0, 1.0, 0.0);
1333
matrix.translate(-rect.width() / 2, 0.0, point);
1334
multiplyMatrix(matrix);
1337
if (w->isOnDesktop(next_desktop) && (mask & PAINT_WINDOW_TRANSFORMED)) {
1338
QRect rect = effects->clientArea(FullArea, activeScreen, next_desktop);
1339
WindowQuadList new_quads;
1340
foreach (const WindowQuad & quad, data.quads) {
1341
if (w->x() + quad.right() <= rect.x()) {
1342
new_quads.append(quad);
1345
data.quads = new_quads;
1347
data.xTranslate = rect.width();
1349
RotationData rot = RotationData();
1350
rot.axis = RotationData::YAxis;
1351
rot.xRotationPoint = -w->x();
1352
rot.angle = -360.0f / effects->numberOfDesktops();
1353
data.rotation = &rot;
1354
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
1355
float point = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
1357
matrix.translate(rect.width() / 2, 0.0, -point);
1358
matrix.rotate(360.0f / effects->numberOfDesktops(), 0.0, 1.0, 0.0);
1359
matrix.translate(-rect.width() / 2, 0.0, point);
1360
multiplyMatrix(matrix);
1363
QRect rect = effects->clientArea(FullArea, activeScreen, painting_desktop);
1365
if (start || stop) {
1366
// we have to change opacity values for fade in/out of windows which are shown on front-desktop
1367
if (prev_desktop == effects->currentDesktop() && w->x() < rect.x()) {
1369
opacity = timeLine.currentValue() * cubeOpacity;
1371
opacity = cubeOpacity * (1.0 - timeLine.currentValue());
1373
if (next_desktop == effects->currentDesktop() && w->x() + w->width() > rect.x() + rect.width()) {
1375
opacity = timeLine.currentValue() * cubeOpacity;
1377
opacity = cubeOpacity * (1.0 - timeLine.currentValue());
1380
// HACK set opacity to 0.99 in case of fully opaque to ensure that windows are painted in correct sequence
1382
if (opacity > 0.99f)
1384
if (opacityDesktopOnly && !w->isDesktop())
1386
data.opacity *= opacity;
1388
if (w->isOnDesktop(painting_desktop) && w->x() < rect.x()) {
1389
WindowQuadList new_quads;
1390
foreach (const WindowQuad & quad, data.quads) {
1391
if (quad.right() > -w->x()) {
1392
new_quads.append(quad);
1395
data.quads = new_quads;
1397
if (w->isOnDesktop(painting_desktop) && w->x() + w->width() > rect.x() + rect.width()) {
1398
WindowQuadList new_quads;
1399
foreach (const WindowQuad & quad, data.quads) {
1400
if (quad.right() <= rect.width() - w->x()) {
1401
new_quads.append(quad);
1404
data.quads = new_quads;
1406
if (w->y() < rect.y()) {
1407
WindowQuadList new_quads;
1408
foreach (const WindowQuad & quad, data.quads) {
1409
if (quad.bottom() > -w->y()) {
1410
new_quads.append(quad);
1413
data.quads = new_quads;
1415
if (w->y() + w->height() > rect.y() + rect.height()) {
1416
WindowQuadList new_quads;
1417
foreach (const WindowQuad & quad, data.quads) {
1418
if (quad.bottom() <= rect.height() - w->y()) {
1419
new_quads.append(quad);
1422
data.quads = new_quads;
1425
origMatrix = shader->getUniformMatrix4x4("screenTransformation");
1426
GLShader *currentShader = shader;
1427
if (mode == Cylinder) {
1428
shaderManager->pushShader(cylinderShader);
1429
cylinderShader->setUniform("xCoord", (float)w->x());
1430
cylinderShader->setUniform("cubeAngle", (effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 90.0f);
1431
float factor = 0.0f;
1433
factor = 1.0f - timeLine.currentValue();
1435
factor = timeLine.currentValue();
1436
cylinderShader->setUniform("timeLine", factor);
1437
data.shader = cylinderShader;
1438
currentShader = cylinderShader;
1440
if (mode == Sphere) {
1441
shaderManager->pushShader(sphereShader);
1442
sphereShader->setUniform("u_offset", QVector2D(w->x(), w->y()));
1443
sphereShader->setUniform("cubeAngle", (effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 90.0f);
1444
float factor = 0.0f;
1446
factor = 1.0f - timeLine.currentValue();
1448
factor = timeLine.currentValue();
1449
sphereShader->setUniform("timeLine", factor);
1450
data.shader = sphereShader;
1451
currentShader = sphereShader;
1453
if (reflectionPainting) {
1454
currentShader->setUniform("screenTransformation", m_reflectionMatrix * m_rotationMatrix * origMatrix);
1456
currentShader->setUniform("screenTransformation", m_rotationMatrix*origMatrix);
1460
effects->paintWindow(w, mask, region, data);
1461
if (activated && cube_painting) {
1463
if (mode == Cylinder || mode == Sphere) {
1464
shaderManager->popShader();
1466
shader->setUniform("screenTransformation", origMatrix);
1468
shaderManager->popShader();
1470
if (w->isDesktop() && effects->numScreens() > 1 && paintCaps) {
1471
QRect rect = effects->clientArea(FullArea, activeScreen, painting_desktop);
1472
QRegion paint = QRegion(rect);
1473
for (int i = 0; i < effects->numScreens(); i++) {
1474
if (i == w->screen())
1476
paint = paint.subtracted(QRegion(effects->clientArea(ScreenArea, i, painting_desktop)));
1478
paint = paint.subtracted(QRegion(w->geometry()));
1479
// in case of free area in multiscreen setup fill it with cap color
1480
if (!paint.isEmpty()) {
1481
#ifndef KWIN_HAVE_OPENGLES
1482
glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT);
1485
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1486
QVector<float> verts;
1487
float quadSize = 0.0f;
1488
int leftDesktop = frontDesktop - 1;
1489
int rightDesktop = frontDesktop + 1;
1490
if (leftDesktop == 0)
1491
leftDesktop = effects->numberOfDesktops();
1492
if (rightDesktop > effects->numberOfDesktops())
1494
if (painting_desktop == frontDesktop)
1496
else if (painting_desktop == leftDesktop || painting_desktop == rightDesktop)
1500
foreach (const QRect & paintRect, paint.rects()) {
1501
for (int i = 0; i <= (paintRect.height() / quadSize); i++) {
1502
for (int j = 0; j <= (paintRect.width() / quadSize); j++) {
1503
verts << qMin(paintRect.x() + (j + 1)*quadSize, (float)paintRect.x() + paintRect.width()) << paintRect.y() + i*quadSize;
1504
verts << paintRect.x() + j*quadSize << paintRect.y() + i*quadSize;
1505
verts << paintRect.x() + j*quadSize << qMin(paintRect.y() + (i + 1)*quadSize, (float)paintRect.y() + paintRect.height());
1506
verts << paintRect.x() + j*quadSize << qMin(paintRect.y() + (i + 1)*quadSize, (float)paintRect.y() + paintRect.height());
1507
verts << qMin(paintRect.x() + (j + 1)*quadSize, (float)paintRect.x() + paintRect.width()) << qMin(paintRect.y() + (i + 1)*quadSize, (float)paintRect.y() + paintRect.height());
1508
verts << qMin(paintRect.x() + (j + 1)*quadSize, (float)paintRect.x() + paintRect.width()) << paintRect.y() + i*quadSize;
1512
bool capShader = false;
1513
if (ShaderManager::instance()->isValid() && m_capShader->isValid()) {
1515
ShaderManager::instance()->pushShader(m_capShader);
1516
m_capShader->setUniform("u_mirror", 0);
1517
m_capShader->setUniform("u_untextured", 1);
1518
if (reflectionPainting) {
1519
m_capShader->setUniform("screenTransformation", m_reflectionMatrix * m_rotationMatrix * origMatrix);
1521
m_capShader->setUniform("screenTransformation", m_rotationMatrix * origMatrix);
1523
m_capShader->setUniform("windowTransformation", QMatrix4x4());
1525
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
1527
QColor color = capColor;
1528
capColor.setAlphaF(cubeOpacity);
1529
vbo->setColor(color);
1530
vbo->setData(verts.size() / 2, 2, verts.constData(), NULL);
1531
if (!capShader || mode == Cube) {
1532
// TODO: use sphere and cylinder shaders
1533
vbo->render(GL_TRIANGLES);
1536
ShaderManager::instance()->popShader();
1538
glDisable(GL_BLEND);
1539
#ifndef KWIN_HAVE_OPENGLES
1550
bool CubeEffect::borderActivated(ElectricBorder border)
1552
if (!borderActivate.contains(border) &&
1553
!borderActivateCylinder.contains(border) &&
1554
!borderActivateSphere.contains(border))
1556
if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this)
1558
if (borderActivate.contains(border)) {
1559
if (!activated || (activated && mode == Cube))
1564
if (borderActivateCylinder.contains(border)) {
1565
if (!activated || (activated && mode == Cylinder))
1570
if (borderActivateSphere.contains(border)) {
1571
if (!activated || (activated && mode == Sphere))
1579
void CubeEffect::toggleCube()
1581
kDebug(1212) << "toggle cube";
1585
void CubeEffect::toggleCylinder()
1587
kDebug(1212) << "toggle cylinder";
1589
useShaders = loadShader();
1593
kError(1212) << "Sorry shaders are not available - cannot activate Cylinder";
1596
void CubeEffect::toggleSphere()
1598
kDebug(1212) << "toggle sphere";
1600
useShaders = loadShader();
1604
kError(1212) << "Sorry shaders are not available - cannot activate Sphere";
1607
void CubeEffect::toggle(CubeMode newMode)
1609
if ((effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this) ||
1610
effects->numberOfDesktops() < 2)
1620
void CubeEffect::grabbedKeyboardEvent(QKeyEvent* e)
1624
// taken from desktopgrid.cpp
1625
if (e->type() == QEvent::KeyPress) {
1626
// check for global shortcuts
1627
// HACK: keyboard grab disables the global shortcuts so we have to check for global shortcut (bug 156155)
1628
if (mode == Cube && cubeShortcut.contains(e->key() + e->modifiers())) {
1632
if (mode == Cylinder && cylinderShortcut.contains(e->key() + e->modifiers())) {
1636
if (mode == Sphere && sphereShortcut.contains(e->key() + e->modifiers())) {
1642
// switch by F<number> or just <number>
1643
if (e->key() >= Qt::Key_F1 && e->key() <= Qt::Key_F35)
1644
desktop = e->key() - Qt::Key_F1 + 1;
1645
else if (e->key() >= Qt::Key_0 && e->key() <= Qt::Key_9)
1646
desktop = e->key() == Qt::Key_0 ? 10 : e->key() - Qt::Key_0;
1647
if (desktop != -1) {
1648
if (desktop <= effects->numberOfDesktops()) {
1649
// we have to rotate to chosen desktop
1650
// and end effect when rotation finished
1651
rotateToDesktop(desktop);
1657
// wrap only on autorepeat
1659
// rotate to previous desktop
1660
kDebug(1212) << "left";
1661
if (!rotating && !start) {
1664
rotationDirection = Right;
1666
rotationDirection = Left;
1668
if (rotations.count() < effects->numberOfDesktops()) {
1670
rotations.enqueue(Right);
1672
rotations.enqueue(Left);
1677
// rotate to next desktop
1678
kDebug(1212) << "right";
1679
if (!rotating && !start) {
1682
rotationDirection = Left;
1684
rotationDirection = Right;
1686
if (rotations.count() < effects->numberOfDesktops()) {
1688
rotations.enqueue(Left);
1690
rotations.enqueue(Right);
1695
kDebug(1212) << "up";
1697
if (verticalPosition != Down) {
1698
if (!verticalRotating) {
1699
verticalRotating = true;
1700
verticalRotationDirection = Downwards;
1701
if (verticalPosition == Normal)
1702
verticalPosition = Down;
1703
if (verticalPosition == Up)
1704
verticalPosition = Normal;
1706
verticalRotations.enqueue(Downwards);
1708
} else if (manualVerticalAngle > 0.0 && !verticalRotating) {
1709
// rotate to down position from the manual position
1710
verticalRotating = true;
1711
verticalRotationDirection = Downwards;
1712
verticalPosition = Down;
1713
manualVerticalAngle -= 90.0;
1716
if (verticalPosition != Up) {
1717
if (!verticalRotating) {
1718
verticalRotating = true;
1719
verticalRotationDirection = Upwards;
1720
if (verticalPosition == Normal)
1721
verticalPosition = Up;
1722
if (verticalPosition == Down)
1723
verticalPosition = Normal;
1725
verticalRotations.enqueue(Upwards);
1727
} else if (manualVerticalAngle < 0.0 && !verticalRotating) {
1728
// rotate to up position from the manual position
1729
verticalRotating = true;
1730
verticalRotationDirection = Upwards;
1731
verticalPosition = Up;
1732
manualVerticalAngle += 90.0;
1737
kDebug(1212) << "down";
1739
if (verticalPosition != Up) {
1740
if (!verticalRotating) {
1741
verticalRotating = true;
1742
verticalRotationDirection = Upwards;
1743
if (verticalPosition == Normal)
1744
verticalPosition = Up;
1745
if (verticalPosition == Down)
1746
verticalPosition = Normal;
1748
verticalRotations.enqueue(Upwards);
1750
} else if (manualVerticalAngle < 0.0 && !verticalRotating) {
1751
// rotate to up position from the manual position
1752
verticalRotating = true;
1753
verticalRotationDirection = Upwards;
1754
verticalPosition = Up;
1755
manualVerticalAngle += 90.0;
1758
if (verticalPosition != Down) {
1759
if (!verticalRotating) {
1760
verticalRotating = true;
1761
verticalRotationDirection = Downwards;
1762
if (verticalPosition == Normal)
1763
verticalPosition = Down;
1764
if (verticalPosition == Up)
1765
verticalPosition = Normal;
1767
verticalRotations.enqueue(Downwards);
1769
} else if (manualVerticalAngle > 0.0 && !verticalRotating) {
1770
// rotate to down position from the manual position
1771
verticalRotating = true;
1772
verticalRotationDirection = Downwards;
1773
verticalPosition = Down;
1774
manualVerticalAngle -= 90.0;
1778
case Qt::Key_Escape:
1779
rotateToDesktop(effects->currentDesktop());
1783
case Qt::Key_Return:
1789
zoom = qMax(-zPosition, zoom);
1799
effects->addRepaintFull();
1803
void CubeEffect::rotateToDesktop(int desktop)
1805
int tempFrontDesktop = frontDesktop;
1806
if (!rotations.empty()) {
1807
// all scheduled rotations will be removed as a speed up
1810
if (rotating && !desktopChangedWhileRotating) {
1811
// front desktop will change during the actual rotation - this has to be considered
1812
if (rotationDirection == Left) {
1814
} else if (rotationDirection == Right) {
1817
if (tempFrontDesktop > effects->numberOfDesktops())
1818
tempFrontDesktop = 1;
1819
else if (tempFrontDesktop == 0)
1820
tempFrontDesktop = effects->numberOfDesktops();
1822
// find the fastest rotation path from tempFrontDesktop to desktop
1823
int rightRotations = tempFrontDesktop - desktop;
1824
if (rightRotations < 0)
1825
rightRotations += effects->numberOfDesktops();
1826
int leftRotations = desktop - tempFrontDesktop;
1827
if (leftRotations < 0)
1828
leftRotations += effects->numberOfDesktops();
1829
if (leftRotations <= rightRotations) {
1830
for (int i = 0; i < leftRotations; i++) {
1831
rotations.enqueue(Left);
1834
for (int i = 0; i < rightRotations; i++) {
1835
rotations.enqueue(Right);
1838
if (!start && !rotating && !rotations.empty()) {
1840
rotationDirection = rotations.dequeue();
1842
// change timeline curve if more rotations are following
1843
if (!rotations.empty()) {
1844
currentShape = QTimeLine::EaseInCurve;
1845
timeLine.setCurveShape(currentShape);
1849
void CubeEffect::setActive(bool active)
1851
foreach (CubeInsideEffect * inside, m_cubeInsideEffects) {
1852
inside->setActive(true);
1855
if (!mousePolling) {
1856
effects->startMousePolling();
1857
mousePolling = true;
1860
activeScreen = effects->activeScreen();
1861
keyboard_grab = effects->grabKeyboard(this);
1862
input = effects->createInputWindow(this, 0, 0, displayWidth(), displayHeight(),
1863
Qt::OpenHandCursor);
1864
frontDesktop = effects->currentDesktop();
1866
zOrderingFactor = zPosition / (effects->stackingOrder().count() - 1);
1868
effects->setActiveFullScreenEffect(this);
1869
kDebug(1212) << "Cube is activated";
1870
verticalPosition = Normal;
1871
verticalRotating = false;
1873
manualVerticalAngle = 0.0;
1875
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
1876
#ifndef KWIN_HAVE_OPENGLES
1877
// clip parts above the reflection area
1878
double eqn[4] = {0.0, 1.0, 0.0, 0.0};
1880
glTranslatef(0.0, rect.height(), 0.0);
1881
glClipPlane(GL_CLIP_PLANE0, eqn);
1884
float temporaryCoeff = float(rect.width()) / tan(M_PI / float(effects->numberOfDesktops()));
1885
mAddedHeightCoeff1 = sqrt(float(rect.height()) * float(rect.height()) + temporaryCoeff * temporaryCoeff);
1886
mAddedHeightCoeff2 = sqrt(float(rect.height()) * float(rect.height()) + float(rect.width()) * float(rect.width()) + temporaryCoeff * temporaryCoeff);
1888
m_rotationMatrix.setToIdentity();
1889
effects->addRepaintFull();
1892
effects->stopMousePolling();
1893
mousePolling = false;
1895
schedule_close = true;
1896
// we have to add a repaint, to start the deactivating
1897
effects->addRepaintFull();
1901
void CubeEffect::slotMouseChanged(const QPoint& pos, const QPoint& oldpos, Qt::MouseButtons buttons,
1902
Qt::MouseButtons oldbuttons, Qt::KeyboardModifiers, Qt::KeyboardModifiers)
1910
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
1911
if (buttons.testFlag(Qt::LeftButton)) {
1912
bool repaint = false;
1913
// vertical movement only if there is not a rotation
1914
if (!verticalRotating) {
1915
// display height corresponds to 180*
1916
int deltaY = pos.y() - oldpos.y();
1917
float deltaVerticalDegrees = (float)deltaY / rect.height() * 180.0f;
1919
manualVerticalAngle += deltaVerticalDegrees;
1921
manualVerticalAngle -= deltaVerticalDegrees;
1922
if (deltaVerticalDegrees != 0.0)
1925
// horizontal movement only if there is not a rotation
1927
// display width corresponds to sum of angles of the polyhedron
1928
int deltaX = oldpos.x() - pos.x();
1929
float deltaDegrees = (float)deltaX / rect.width() * 360.0f;
1932
deltaDegrees = 5.0f;
1933
if (pos.x() == displayWidth() - 1)
1934
deltaDegrees = -5.0f;
1937
manualAngle += deltaDegrees;
1939
manualAngle -= deltaDegrees;
1940
if (deltaDegrees != 0.0)
1945
effects->addRepaintFull();
1948
if (!oldbuttons.testFlag(Qt::LeftButton) && buttons.testFlag(Qt::LeftButton)) {
1949
XDefineCursor(display(), input, QCursor(Qt::ClosedHandCursor).handle());
1951
if (oldbuttons.testFlag(Qt::LeftButton) && !buttons.testFlag(Qt::LeftButton)) {
1952
XDefineCursor(display(), input, QCursor(Qt::OpenHandCursor).handle());
1953
if (closeOnMouseRelease)
1956
if (oldbuttons.testFlag(Qt::RightButton) && !buttons.testFlag(Qt::RightButton)) {
1957
// end effect on right mouse button
1962
void CubeEffect::windowInputMouseEvent(Window w, QEvent* e)
1966
QMouseEvent *mouse = dynamic_cast< QMouseEvent* >(e);
1967
if (mouse && mouse->type() == QEvent::MouseButtonRelease) {
1968
if (mouse->button() == Qt::XButton1) {
1969
if (!rotating && !start) {
1972
rotationDirection = Right;
1974
rotationDirection = Left;
1976
if (rotations.count() < effects->numberOfDesktops()) {
1978
rotations.enqueue(Right);
1980
rotations.enqueue(Left);
1983
effects->addRepaintFull();
1985
if (mouse->button() == Qt::XButton2) {
1986
if (!rotating && !start) {
1989
rotationDirection = Left;
1991
rotationDirection = Right;
1993
if (rotations.count() < effects->numberOfDesktops()) {
1995
rotations.enqueue(Left);
1997
rotations.enqueue(Right);
2000
effects->addRepaintFull();
2005
void CubeEffect::slotTabBoxAdded(int mode)
2009
if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this)
2011
if (useForTabBox && mode == TabBoxDesktopListMode) {
2012
effects->refTabBox();
2015
rotateToDesktop(effects->currentTabBoxDesktop());
2019
void CubeEffect::slotTabBoxUpdated()
2022
rotateToDesktop(effects->currentTabBoxDesktop());
2023
effects->addRepaintFull();
2027
void CubeEffect::slotTabBoxClosed()
2030
effects->unrefTabBox();
2036
void CubeEffect::cubeShortcutChanged(const QKeySequence& seq)
2038
cubeShortcut = KShortcut(seq);
2041
void CubeEffect::cylinderShortcutChanged(const QKeySequence& seq)
2043
cylinderShortcut = KShortcut(seq);
2046
void CubeEffect::sphereShortcutChanged(const QKeySequence& seq)
2048
sphereShortcut = KShortcut(seq);
2051
void* CubeEffect::proxy()
2056
void CubeEffect::registerCubeInsideEffect(CubeInsideEffect* effect)
2058
m_cubeInsideEffects.append(effect);
2061
void CubeEffect::unregisterCubeInsideEffect(CubeInsideEffect* effect)
2063
m_cubeInsideEffects.removeAll(effect);