2020-08-02 22:22:19 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-FileCopyrightText: 2008 Martin Gräßlin <mgraesslin@kde.org>
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2008-07-15 19:21:50 +00:00
|
|
|
#include "cube.h"
|
2012-09-12 16:39:13 +00:00
|
|
|
// KConfigSkeleton
|
|
|
|
#include "cubeconfig.h"
|
|
|
|
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2013-08-14 19:13:12 +00:00
|
|
|
#include <QAction>
|
2014-03-17 15:24:10 +00:00
|
|
|
#include <KGlobalAccel>
|
|
|
|
#include <KLocalizedString>
|
2008-07-15 19:21:50 +00:00
|
|
|
#include <kwinconfig.h>
|
|
|
|
|
2013-07-26 15:16:19 +00:00
|
|
|
#include <QApplication>
|
2008-07-15 19:21:50 +00:00
|
|
|
#include <QColor>
|
2013-09-02 09:03:29 +00:00
|
|
|
#include <QElapsedTimer>
|
2008-07-15 19:21:50 +00:00
|
|
|
#include <QRect>
|
|
|
|
#include <QEvent>
|
2012-05-01 11:53:56 +00:00
|
|
|
#include <QFutureWatcher>
|
2008-07-15 19:21:50 +00:00
|
|
|
#include <QKeyEvent>
|
2012-05-01 11:53:56 +00:00
|
|
|
#include <QtConcurrentRun>
|
2011-01-09 20:20:36 +00:00
|
|
|
#include <QVector2D>
|
2012-05-27 17:28:02 +00:00
|
|
|
#include <QVector3D>
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2019-07-09 19:19:26 +00:00
|
|
|
#include <cmath>
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2011-02-19 10:08:43 +00:00
|
|
|
#include <kwinglplatform.h>
|
2008-07-15 19:21:50 +00:00
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
|
|
|
CubeEffect::CubeEffect()
|
2011-01-30 14:34:42 +00:00
|
|
|
: activated(false)
|
|
|
|
, cube_painting(false)
|
|
|
|
, keyboard_grab(false)
|
|
|
|
, painting_desktop(1)
|
|
|
|
, frontDesktop(0)
|
|
|
|
, cubeOpacity(1.0)
|
|
|
|
, opacityDesktopOnly(true)
|
|
|
|
, displayDesktopName(false)
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
, desktopNameFrame(nullptr)
|
2011-01-30 14:34:42 +00:00
|
|
|
, reflection(true)
|
|
|
|
, desktopChangedWhileRotating(false)
|
|
|
|
, paintCaps(true)
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
, wallpaper(nullptr)
|
2011-01-30 14:34:42 +00:00
|
|
|
, texturedCaps(true)
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
, capTexture(nullptr)
|
2011-01-30 14:34:42 +00:00
|
|
|
, reflectionPainting(false)
|
|
|
|
, activeScreen(0)
|
|
|
|
, bottomCap(false)
|
|
|
|
, closeOnMouseRelease(false)
|
|
|
|
, zoom(0.0)
|
|
|
|
, zPosition(0.0)
|
|
|
|
, useForTabBox(false)
|
|
|
|
, tabBoxMode(false)
|
|
|
|
, shortcutsRegistered(false)
|
|
|
|
, mode(Cube)
|
|
|
|
, useShaders(false)
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
, cylinderShader(nullptr)
|
|
|
|
, sphereShader(nullptr)
|
2011-01-30 14:34:42 +00:00
|
|
|
, zOrderingFactor(0.0f)
|
|
|
|
, mAddedHeightCoeff1(0.0f)
|
|
|
|
, mAddedHeightCoeff2(0.0f)
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
, m_cubeCapBuffer(nullptr)
|
2011-01-30 14:34:42 +00:00
|
|
|
, m_proxy(this)
|
2017-04-01 17:30:44 +00:00
|
|
|
, m_cubeAction(new QAction(this))
|
|
|
|
, m_cylinderAction(new QAction(this))
|
|
|
|
, m_sphereAction(new QAction(this))
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2016-12-02 19:27:43 +00:00
|
|
|
initConfig<CubeConfig>();
|
2011-01-30 14:34:42 +00:00
|
|
|
desktopNameFont.setBold(true);
|
|
|
|
desktopNameFont.setPointSize(14);
|
2009-02-21 04:53:13 +00:00
|
|
|
|
2013-06-03 08:38:04 +00:00
|
|
|
if (effects->compositingType() == OpenGL2Compositing) {
|
2016-01-26 14:38:42 +00:00
|
|
|
m_reflectionShader = ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture, QString(), QStringLiteral("cube-reflection.glsl"));
|
|
|
|
m_capShader = ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture, QString(), QStringLiteral("cube-cap.glsl"));
|
2013-06-03 08:38:04 +00:00
|
|
|
} else {
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
m_reflectionShader = nullptr;
|
|
|
|
m_capShader = nullptr;
|
2013-06-03 08:38:04 +00:00
|
|
|
}
|
2011-01-01 18:34:16 +00:00
|
|
|
m_textureMirrorMatrix.scale(1.0, -1.0, 1.0);
|
|
|
|
m_textureMirrorMatrix.translate(0.0, -1.0, 0.0);
|
2019-01-01 20:48:53 +00:00
|
|
|
connect(effects, &EffectsHandler::tabBoxAdded, this, &CubeEffect::slotTabBoxAdded);
|
|
|
|
connect(effects, &EffectsHandler::tabBoxClosed, this, &CubeEffect::slotTabBoxClosed);
|
|
|
|
connect(effects, &EffectsHandler::tabBoxUpdated, this, &CubeEffect::slotTabBoxUpdated);
|
2019-06-23 15:59:44 +00:00
|
|
|
connect(effects, &EffectsHandler::screenAboutToLock, this, [this]() {
|
|
|
|
// Set active(false) does not release key grabs until the animation completes
|
|
|
|
// As we know the lockscreen is trying to grab them, release them early
|
|
|
|
// all other grabs are released in the normal way
|
|
|
|
setActive(false);
|
|
|
|
if (keyboard_grab) {
|
|
|
|
effects->ungrabKeyboard();
|
|
|
|
keyboard_grab = false;
|
|
|
|
}
|
|
|
|
});
|
2010-12-20 20:21:41 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
reconfigure(ReconfigureAll);
|
|
|
|
}
|
2008-08-17 11:51:27 +00:00
|
|
|
|
2008-12-04 08:47:07 +00:00
|
|
|
bool CubeEffect::supported()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-09-20 09:33:32 +00:00
|
|
|
return effects->isOpenGLCompositing();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-12-04 08:47:07 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void CubeEffect::reconfigure(ReconfigureFlags)
|
|
|
|
{
|
2014-03-25 15:29:03 +00:00
|
|
|
CubeConfig::self()->read();
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (ElectricBorder border, borderActivate) {
|
2013-01-22 11:47:06 +00:00
|
|
|
effects->unreserveElectricBorder(border, this);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
foreach (ElectricBorder border, borderActivateCylinder) {
|
2013-01-22 11:47:06 +00:00
|
|
|
effects->unreserveElectricBorder(border, this);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
foreach (ElectricBorder border, borderActivateSphere) {
|
2013-01-22 11:47:06 +00:00
|
|
|
effects->unreserveElectricBorder(border, this);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-03-29 12:57:20 +00:00
|
|
|
borderActivate.clear();
|
|
|
|
borderActivateCylinder.clear();
|
|
|
|
borderActivateSphere.clear();
|
|
|
|
QList<int> borderList = QList<int>();
|
2011-01-30 14:34:42 +00:00
|
|
|
borderList.append(int(ElectricNone));
|
2012-09-12 16:39:13 +00:00
|
|
|
borderList = CubeConfig::borderActivate();
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (int i, borderList) {
|
|
|
|
borderActivate.append(ElectricBorder(i));
|
2013-01-22 11:47:06 +00:00
|
|
|
effects->reserveElectricBorder(ElectricBorder(i), this);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-03-29 12:57:20 +00:00
|
|
|
borderList.clear();
|
2011-01-30 14:34:42 +00:00
|
|
|
borderList.append(int(ElectricNone));
|
2012-09-12 16:39:13 +00:00
|
|
|
borderList = CubeConfig::borderActivateCylinder();
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (int i, borderList) {
|
|
|
|
borderActivateCylinder.append(ElectricBorder(i));
|
2013-01-22 11:47:06 +00:00
|
|
|
effects->reserveElectricBorder(ElectricBorder(i), this);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-03-29 12:57:20 +00:00
|
|
|
borderList.clear();
|
2011-01-30 14:34:42 +00:00
|
|
|
borderList.append(int(ElectricNone));
|
2012-09-12 16:39:13 +00:00
|
|
|
borderList = CubeConfig::borderActivateSphere();
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (int i, borderList) {
|
|
|
|
borderActivateSphere.append(ElectricBorder(i));
|
2013-01-22 11:47:06 +00:00
|
|
|
effects->reserveElectricBorder(ElectricBorder(i), this);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2012-09-12 16:39:13 +00:00
|
|
|
cubeOpacity = (float)CubeConfig::opacity() / 100.0f;
|
|
|
|
opacityDesktopOnly = CubeConfig::opacityDesktopOnly();
|
|
|
|
displayDesktopName = CubeConfig::displayDesktopName();
|
|
|
|
reflection = CubeConfig::reflection();
|
2018-06-27 16:58:21 +00:00
|
|
|
// TODO: Rename rotationDuration to duration so we
|
|
|
|
// can use animationTime<CubeConfig>(500).
|
|
|
|
const int d = CubeConfig::rotationDuration() != 0
|
|
|
|
? CubeConfig::rotationDuration()
|
|
|
|
: 500;
|
|
|
|
rotationDuration = std::chrono::milliseconds(static_cast<int>(animationTime(d)));
|
2012-09-12 16:39:13 +00:00
|
|
|
backgroundColor = CubeConfig::backgroundColor();
|
|
|
|
capColor = CubeConfig::capColor();
|
|
|
|
paintCaps = CubeConfig::caps();
|
|
|
|
closeOnMouseRelease = CubeConfig::closeOnMouseRelease();
|
|
|
|
zPosition = CubeConfig::zPosition();
|
|
|
|
|
|
|
|
useForTabBox = CubeConfig::tabBox();
|
|
|
|
invertKeys = CubeConfig::invertKeys();
|
|
|
|
invertMouse = CubeConfig::invertMouse();
|
|
|
|
capDeformationFactor = (float)CubeConfig::capDeformation() / 100.0f;
|
|
|
|
useZOrdering = CubeConfig::zOrdering();
|
2008-10-02 09:27:32 +00:00
|
|
|
delete wallpaper;
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
wallpaper = nullptr;
|
2008-10-02 09:27:32 +00:00
|
|
|
delete capTexture;
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
capTexture = nullptr;
|
2012-09-12 16:39:13 +00:00
|
|
|
texturedCaps = CubeConfig::texturedCaps();
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2018-06-27 16:58:21 +00:00
|
|
|
timeLine.setEasingCurve(QEasingCurve::InOutSine);
|
2011-01-30 14:34:42 +00:00
|
|
|
timeLine.setDuration(rotationDuration);
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2018-06-27 16:58:21 +00:00
|
|
|
verticalTimeLine.setEasingCurve(QEasingCurve::InOutSine);
|
2011-01-30 14:34:42 +00:00
|
|
|
verticalTimeLine.setDuration(rotationDuration);
|
2009-02-06 09:51:04 +00:00
|
|
|
|
|
|
|
// do not connect the shortcut if we use cylinder or sphere
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!shortcutsRegistered) {
|
2017-04-01 17:30:44 +00:00
|
|
|
QAction* cubeAction = m_cubeAction;
|
2013-12-10 10:45:33 +00:00
|
|
|
cubeAction->setObjectName(QStringLiteral("Cube"));
|
2011-01-30 14:34:42 +00:00
|
|
|
cubeAction->setText(i18n("Desktop Cube"));
|
2013-08-14 19:13:12 +00:00
|
|
|
KGlobalAccel::self()->setDefaultShortcut(cubeAction, QList<QKeySequence>() << Qt::CTRL + Qt::Key_F11);
|
|
|
|
KGlobalAccel::self()->setShortcut(cubeAction, QList<QKeySequence>() << Qt::CTRL + Qt::Key_F11);
|
2013-07-10 10:26:50 +00:00
|
|
|
effects->registerGlobalShortcut(Qt::CTRL + Qt::Key_F11, cubeAction);
|
2013-07-14 20:58:30 +00:00
|
|
|
effects->registerPointerShortcut(Qt::ControlModifier | Qt::AltModifier, Qt::LeftButton, cubeAction);
|
2013-08-14 19:13:12 +00:00
|
|
|
cubeShortcut = KGlobalAccel::self()->shortcut(cubeAction);
|
2017-04-01 17:30:44 +00:00
|
|
|
QAction* cylinderAction = m_cylinderAction;
|
2013-12-10 10:45:33 +00:00
|
|
|
cylinderAction->setObjectName(QStringLiteral("Cylinder"));
|
2011-01-30 14:34:42 +00:00
|
|
|
cylinderAction->setText(i18n("Desktop Cylinder"));
|
2013-08-14 19:13:12 +00:00
|
|
|
KGlobalAccel::self()->setShortcut(cylinderAction, QList<QKeySequence>());
|
2013-07-10 10:26:50 +00:00
|
|
|
effects->registerGlobalShortcut(QKeySequence(), cylinderAction);
|
2013-08-14 19:13:12 +00:00
|
|
|
cylinderShortcut = KGlobalAccel::self()->shortcut(cylinderAction);
|
2017-04-01 17:30:44 +00:00
|
|
|
QAction* sphereAction = m_sphereAction;
|
2013-12-10 10:45:33 +00:00
|
|
|
sphereAction->setObjectName(QStringLiteral("Sphere"));
|
2011-01-30 14:34:42 +00:00
|
|
|
sphereAction->setText(i18n("Desktop Sphere"));
|
2013-08-14 19:13:12 +00:00
|
|
|
KGlobalAccel::self()->setShortcut(sphereAction, QList<QKeySequence>());
|
|
|
|
sphereShortcut = KGlobalAccel::self()->shortcut(sphereAction);
|
2013-07-10 10:26:50 +00:00
|
|
|
effects->registerGlobalShortcut(QKeySequence(), sphereAction);
|
2019-01-01 20:48:53 +00:00
|
|
|
connect(cubeAction, &QAction::triggered, this, &CubeEffect::toggleCube);
|
|
|
|
connect(cylinderAction, &QAction::triggered, this, &CubeEffect::toggleCylinder);
|
|
|
|
connect(sphereAction, &QAction::triggered, this, &CubeEffect::toggleSphere);
|
2013-08-14 19:13:12 +00:00
|
|
|
connect(KGlobalAccel::self(), &KGlobalAccel::globalShortcutChanged, this, &CubeEffect::globalShortcutChanged);
|
2009-02-06 09:51:04 +00:00
|
|
|
shortcutsRegistered = true;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-12-31 09:34:29 +00:00
|
|
|
|
|
|
|
// set the cap color on the shader
|
2013-06-03 08:38:04 +00:00
|
|
|
if (m_capShader && m_capShader->isValid()) {
|
2012-09-21 09:25:08 +00:00
|
|
|
ShaderBinder binder(m_capShader);
|
2015-11-30 10:39:04 +00:00
|
|
|
m_capShader->setUniform(GLShader::Color, capColor);
|
2010-12-31 09:34:29 +00:00
|
|
|
}
|
2017-04-01 17:30:44 +00:00
|
|
|
|
|
|
|
// touch borders
|
|
|
|
const QVector<ElectricBorder> relevantBorders{ElectricLeft, ElectricTop, ElectricRight, ElectricBottom};
|
|
|
|
for (auto e : relevantBorders) {
|
|
|
|
effects->unregisterTouchBorder(e, m_cubeAction);
|
|
|
|
effects->unregisterTouchBorder(e, m_sphereAction);
|
|
|
|
effects->unregisterTouchBorder(e, m_cylinderAction);
|
|
|
|
}
|
2017-08-24 11:36:22 +00:00
|
|
|
auto touchEdge = [&relevantBorders] (const QList<int> touchBorders, QAction *action) {
|
2017-04-01 17:30:44 +00:00
|
|
|
for (int i : touchBorders) {
|
2017-08-24 11:36:22 +00:00
|
|
|
if (!relevantBorders.contains(ElectricBorder(i))) {
|
|
|
|
continue;
|
|
|
|
}
|
2017-04-01 17:30:44 +00:00
|
|
|
effects->registerTouchBorder(ElectricBorder(i), action);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
touchEdge(CubeConfig::touchBorderActivate(), m_cubeAction);
|
|
|
|
touchEdge(CubeConfig::touchBorderActivateCylinder(), m_cylinderAction);
|
|
|
|
touchEdge(CubeConfig::touchBorderActivateSphere(), m_sphereAction);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
|
|
|
CubeEffect::~CubeEffect()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2008-07-15 19:21:50 +00:00
|
|
|
delete wallpaper;
|
2008-07-19 13:43:13 +00:00
|
|
|
delete capTexture;
|
2009-02-14 09:29:01 +00:00
|
|
|
delete cylinderShader;
|
|
|
|
delete sphereShader;
|
2010-07-18 16:32:37 +00:00
|
|
|
delete desktopNameFrame;
|
2010-12-20 20:21:41 +00:00
|
|
|
delete m_reflectionShader;
|
2010-12-31 09:34:29 +00:00
|
|
|
delete m_capShader;
|
|
|
|
delete m_cubeCapBuffer;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-14 09:29:01 +00:00
|
|
|
|
2012-05-01 11:53:56 +00:00
|
|
|
QImage CubeEffect::loadCubeCap(const QString &capPath)
|
|
|
|
{
|
|
|
|
if (!texturedCaps) {
|
|
|
|
return QImage();
|
|
|
|
}
|
|
|
|
return QImage(capPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CubeEffect::slotCubeCapLoaded()
|
|
|
|
{
|
|
|
|
QFutureWatcher<QImage> *watcher = dynamic_cast<QFutureWatcher<QImage>*>(sender());
|
|
|
|
if (!watcher) {
|
|
|
|
// not invoked from future watcher
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QImage img = watcher->result();
|
|
|
|
if (!img.isNull()) {
|
Better handling for making the compositing OpenGL context current
With QtQuick2 it's possible that the scene graph rendering context either
lives in an own thread or uses the main GUI thread. In the latter case
it's the same thread as our compositing OpenGL context lives in. This
means our basic assumption that between two rendering passes the context
stays current does not hold.
The code already ensured that before we start a rendering pass the
context is made current, but there are many more possible cases. If we
use OpenGL in areas not triggered by the rendering loop but in response
to other events the context needs to be made current. This includes the
loading and unloading of effects (some effects use OpenGL in the static
effect check, in the ctor and dtor), background loading of texture data,
lazy loading after first usage invoked by shortcut, etc. etc.
To properly handle these cases new methods are added to EffectsHandler
to make the compositing OpenGL context current. These calls delegate down
into the scene. On non-OpenGL scenes they are noop, but on OpenGL they go
into the backend and make the context current. In addition they ensure
that Qt doesn't think that it's QOpenGLContext is current by calling
doneCurrent() on the QOpenGLContext::currentContext(). This unfortunately
causes an additional call to makeCurrent with a null context, but there
is no other way to tell Qt - it doesn't notice when a different context
is made current with low level API calls. In the multi-threaded
architecture this doesn't matter as ::currentContext() returns null.
A short evaluation showed that a transition to QOpenGLContext doesn't
seem feasible. Qt only supports either GLX or EGL while KWin supports
both and when entering the transition phase for Wayland, it would become
extremely tricky if our native platform is X11, but we want a Wayland
EGL context. A future solution might be to have a "KWin-QPA plugin" which
uses either xcb or Wayland and hides everything from Qt.
The API documentation is extended to describe when the effects-framework
ensures that an OpenGL context is current. The effects are changed to
make the context current in cases where it's not guaranteed. This has
been done by looking for creation or deletion of GLTextures and Shaders.
If there are other OpenGL usages outside the rendering loop, ctor/dtor
this needs to be changed, too.
2013-11-22 14:05:36 +00:00
|
|
|
effects->makeOpenGLContextCurrent();
|
2012-05-01 11:53:56 +00:00
|
|
|
capTexture = new GLTexture(img);
|
|
|
|
capTexture->setFilter(GL_LINEAR);
|
2015-10-30 09:14:55 +00:00
|
|
|
if (!GLPlatform::instance()->isGLES()) {
|
|
|
|
capTexture->setWrapMode(GL_CLAMP_TO_BORDER);
|
|
|
|
}
|
2012-05-01 11:53:56 +00:00
|
|
|
// need to recreate the VBO for the cube cap
|
|
|
|
delete m_cubeCapBuffer;
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
m_cubeCapBuffer = nullptr;
|
2012-05-01 11:53:56 +00:00
|
|
|
effects->addRepaintFull();
|
|
|
|
}
|
|
|
|
watcher->deleteLater();
|
|
|
|
}
|
|
|
|
|
|
|
|
QImage CubeEffect::loadWallPaper(const QString &file)
|
|
|
|
{
|
|
|
|
return QImage(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CubeEffect::slotWallPaperLoaded()
|
|
|
|
{
|
|
|
|
QFutureWatcher<QImage> *watcher = dynamic_cast<QFutureWatcher<QImage>*>(sender());
|
|
|
|
if (!watcher) {
|
|
|
|
// not invoked from future watcher
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QImage img = watcher->result();
|
|
|
|
if (!img.isNull()) {
|
Better handling for making the compositing OpenGL context current
With QtQuick2 it's possible that the scene graph rendering context either
lives in an own thread or uses the main GUI thread. In the latter case
it's the same thread as our compositing OpenGL context lives in. This
means our basic assumption that between two rendering passes the context
stays current does not hold.
The code already ensured that before we start a rendering pass the
context is made current, but there are many more possible cases. If we
use OpenGL in areas not triggered by the rendering loop but in response
to other events the context needs to be made current. This includes the
loading and unloading of effects (some effects use OpenGL in the static
effect check, in the ctor and dtor), background loading of texture data,
lazy loading after first usage invoked by shortcut, etc. etc.
To properly handle these cases new methods are added to EffectsHandler
to make the compositing OpenGL context current. These calls delegate down
into the scene. On non-OpenGL scenes they are noop, but on OpenGL they go
into the backend and make the context current. In addition they ensure
that Qt doesn't think that it's QOpenGLContext is current by calling
doneCurrent() on the QOpenGLContext::currentContext(). This unfortunately
causes an additional call to makeCurrent with a null context, but there
is no other way to tell Qt - it doesn't notice when a different context
is made current with low level API calls. In the multi-threaded
architecture this doesn't matter as ::currentContext() returns null.
A short evaluation showed that a transition to QOpenGLContext doesn't
seem feasible. Qt only supports either GLX or EGL while KWin supports
both and when entering the transition phase for Wayland, it would become
extremely tricky if our native platform is X11, but we want a Wayland
EGL context. A future solution might be to have a "KWin-QPA plugin" which
uses either xcb or Wayland and hides everything from Qt.
The API documentation is extended to describe when the effects-framework
ensures that an OpenGL context is current. The effects are changed to
make the context current in cases where it's not guaranteed. This has
been done by looking for creation or deletion of GLTextures and Shaders.
If there are other OpenGL usages outside the rendering loop, ctor/dtor
this needs to be changed, too.
2013-11-22 14:05:36 +00:00
|
|
|
effects->makeOpenGLContextCurrent();
|
2012-05-01 11:53:56 +00:00
|
|
|
wallpaper = new GLTexture(img);
|
|
|
|
effects->addRepaintFull();
|
|
|
|
}
|
|
|
|
watcher->deleteLater();
|
|
|
|
}
|
|
|
|
|
2009-02-14 09:29:01 +00:00
|
|
|
bool CubeEffect::loadShader()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
Better handling for making the compositing OpenGL context current
With QtQuick2 it's possible that the scene graph rendering context either
lives in an own thread or uses the main GUI thread. In the latter case
it's the same thread as our compositing OpenGL context lives in. This
means our basic assumption that between two rendering passes the context
stays current does not hold.
The code already ensured that before we start a rendering pass the
context is made current, but there are many more possible cases. If we
use OpenGL in areas not triggered by the rendering loop but in response
to other events the context needs to be made current. This includes the
loading and unloading of effects (some effects use OpenGL in the static
effect check, in the ctor and dtor), background loading of texture data,
lazy loading after first usage invoked by shortcut, etc. etc.
To properly handle these cases new methods are added to EffectsHandler
to make the compositing OpenGL context current. These calls delegate down
into the scene. On non-OpenGL scenes they are noop, but on OpenGL they go
into the backend and make the context current. In addition they ensure
that Qt doesn't think that it's QOpenGLContext is current by calling
doneCurrent() on the QOpenGLContext::currentContext(). This unfortunately
causes an additional call to makeCurrent with a null context, but there
is no other way to tell Qt - it doesn't notice when a different context
is made current with low level API calls. In the multi-threaded
architecture this doesn't matter as ::currentContext() returns null.
A short evaluation showed that a transition to QOpenGLContext doesn't
seem feasible. Qt only supports either GLX or EGL while KWin supports
both and when entering the transition phase for Wayland, it would become
extremely tricky if our native platform is X11, but we want a Wayland
EGL context. A future solution might be to have a "KWin-QPA plugin" which
uses either xcb or Wayland and hides everything from Qt.
The API documentation is extended to describe when the effects-framework
ensures that an OpenGL context is current. The effects are changed to
make the context current in cases where it's not guaranteed. This has
been done by looking for creation or deletion of GLTextures and Shaders.
If there are other OpenGL usages outside the rendering loop, ctor/dtor
this needs to be changed, too.
2013-11-22 14:05:36 +00:00
|
|
|
effects->makeOpenGLContextCurrent();
|
2011-02-19 10:08:43 +00:00
|
|
|
if (!(GLPlatform::instance()->supports(GLSL) &&
|
2012-09-20 09:33:32 +00:00
|
|
|
(effects->compositingType() == OpenGL2Compositing)))
|
2009-02-14 09:29:01 +00:00
|
|
|
return false;
|
2015-12-01 11:05:14 +00:00
|
|
|
|
2016-01-26 14:38:42 +00:00
|
|
|
cylinderShader = ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture | ShaderTrait::AdjustSaturation | ShaderTrait::Modulate, QStringLiteral("cylinder.vert"), QString());
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!cylinderShader->isValid()) {
|
2015-07-31 08:17:43 +00:00
|
|
|
qCCritical(KWINEFFECTS) << "The cylinder shader failed to load!";
|
2009-02-14 09:29:01 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
2012-09-21 09:25:08 +00:00
|
|
|
ShaderBinder binder(cylinderShader);
|
2011-02-17 17:44:52 +00:00
|
|
|
cylinderShader->setUniform("sampler", 0);
|
2011-01-30 14:34:42 +00:00
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
|
|
|
cylinderShader->setUniform("width", (float)rect.width() * 0.5f);
|
|
|
|
}
|
2015-12-01 11:11:02 +00:00
|
|
|
|
2016-01-26 14:38:42 +00:00
|
|
|
sphereShader = ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture | ShaderTrait::AdjustSaturation | ShaderTrait::Modulate, QStringLiteral("sphere.vert"), QString());
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!sphereShader->isValid()) {
|
2015-07-31 08:17:43 +00:00
|
|
|
qCCritical(KWINEFFECTS) << "The sphere shader failed to load!";
|
2009-02-14 09:29:01 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
2012-09-21 09:25:08 +00:00
|
|
|
ShaderBinder binder(sphereShader);
|
2011-02-17 17:44:52 +00:00
|
|
|
sphereShader->setUniform("sampler", 0);
|
2011-01-30 14:34:42 +00:00
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
|
|
|
sphereShader->setUniform("width", (float)rect.width() * 0.5f);
|
|
|
|
sphereShader->setUniform("height", (float)rect.height() * 0.5f);
|
|
|
|
sphereShader->setUniform("u_offset", QVector2D(0, 0));
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2018-06-01 15:32:27 +00:00
|
|
|
void CubeEffect::startAnimation(AnimationState state)
|
|
|
|
{
|
2018-06-27 16:58:21 +00:00
|
|
|
QEasingCurve curve;
|
2018-06-01 15:32:27 +00:00
|
|
|
/* If this is first and only animation -> EaseInOut
|
|
|
|
* there is more -> EaseIn
|
|
|
|
* If there was an animation before, and this is the last one -> EaseOut
|
|
|
|
* there is more -> Linear */
|
|
|
|
if (animationState == AnimationState::None) {
|
2018-06-27 16:58:21 +00:00
|
|
|
curve.setType(animations.empty() ? QEasingCurve::InOutSine : QEasingCurve::InCurve);
|
2018-06-01 15:32:27 +00:00
|
|
|
} else {
|
2018-06-27 16:58:21 +00:00
|
|
|
curve.setType(animations.empty() ? QEasingCurve::OutCurve : QEasingCurve::Linear);
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2018-06-27 16:58:21 +00:00
|
|
|
timeLine.reset();
|
|
|
|
timeLine.setEasingCurve(curve);
|
2018-06-01 15:32:27 +00:00
|
|
|
startAngle = currentAngle;
|
|
|
|
startFrontDesktop = frontDesktop;
|
|
|
|
animationState = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CubeEffect::startVerticalAnimation(VerticalAnimationState state)
|
|
|
|
{
|
|
|
|
/* Ignore if there is nowhere to rotate */
|
|
|
|
if ((qFuzzyIsNull(verticalCurrentAngle - 90.0f) && state == VerticalAnimationState::Upwards) ||
|
|
|
|
(qFuzzyIsNull(verticalCurrentAngle + 90.0f) && state == VerticalAnimationState::Downwards)) {
|
|
|
|
return;
|
|
|
|
}
|
2018-06-27 16:58:21 +00:00
|
|
|
verticalTimeLine.reset();
|
2018-06-01 15:32:27 +00:00
|
|
|
verticalStartAngle = verticalCurrentAngle;
|
|
|
|
verticalAnimationState = state;
|
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void CubeEffect::prePaintScreen(ScreenPrePaintData& data, int time)
|
|
|
|
{
|
|
|
|
if (activated) {
|
2008-07-15 19:21:50 +00:00
|
|
|
data.mask |= PAINT_SCREEN_TRANSFORMED | Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS | PAINT_SCREEN_BACKGROUND_FIRST;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::None && !animations.empty()) {
|
|
|
|
startAnimation(animations.dequeue());
|
|
|
|
}
|
|
|
|
if (verticalAnimationState == VerticalAnimationState::None && !verticalAnimations.empty()) {
|
|
|
|
startVerticalAnimation(verticalAnimations.dequeue());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
|
|
|
|
if (animationState != AnimationState::None || verticalAnimationState != VerticalAnimationState::None) {
|
|
|
|
if (animationState != AnimationState::None) {
|
2018-06-27 16:58:21 +00:00
|
|
|
timeLine.update(std::chrono::milliseconds(time));
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
|
|
|
if (verticalAnimationState != VerticalAnimationState::None) {
|
2018-06-27 16:58:21 +00:00
|
|
|
verticalTimeLine.update(std::chrono::milliseconds(time));
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2011-01-01 18:19:16 +00:00
|
|
|
rotateCube();
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->prePaintScreen(data, time);
|
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2019-10-29 22:04:15 +00:00
|
|
|
void CubeEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (activated) {
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
2008-07-15 19:21:50 +00:00
|
|
|
|
|
|
|
// background
|
|
|
|
float clearColor[4];
|
2011-01-30 14:34:42 +00:00
|
|
|
glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor);
|
|
|
|
glClearColor(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF(), 1.0);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
|
2008-07-15 19:21:50 +00:00
|
|
|
|
|
|
|
// wallpaper
|
2011-01-30 14:34:42 +00:00
|
|
|
if (wallpaper) {
|
2015-11-27 09:58:05 +00:00
|
|
|
ShaderBinder binder(ShaderTrait::MapTexture);
|
|
|
|
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, data.projectionMatrix());
|
2008-07-15 19:21:50 +00:00
|
|
|
wallpaper->bind();
|
2011-01-30 14:34:42 +00:00
|
|
|
wallpaper->render(region, rect);
|
2008-07-15 19:21:50 +00:00
|
|
|
wallpaper->unbind();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2009-02-06 09:16:30 +00:00
|
|
|
// some veriables needed for painting the caps
|
2011-01-30 14:34:42 +00:00
|
|
|
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
|
|
|
|
float point = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
|
2009-02-06 09:16:30 +00:00
|
|
|
float zTranslate = zPosition + zoom;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
zTranslate *= timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
zTranslate *= (1.0 - timeLine.value());
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
// reflection
|
2018-06-01 15:32:27 +00:00
|
|
|
if (reflection) {
|
2008-12-03 19:51:41 +00:00
|
|
|
// we can use a huge scale factor (needed to calculate the rearground vertices)
|
2011-01-30 14:34:42 +00:00
|
|
|
float scaleFactor = 1000000 * tan(60.0 * M_PI / 360.0f) / rect.height();
|
2010-12-18 09:18:54 +00:00
|
|
|
m_reflectionMatrix.setToIdentity();
|
|
|
|
m_reflectionMatrix.scale(1.0, -1.0, 1.0);
|
2009-05-01 18:23:53 +00:00
|
|
|
|
2018-06-01 15:32:27 +00:00
|
|
|
double translate = 0.0;
|
|
|
|
if (mode == Cube) {
|
|
|
|
double addedHeight1 = -rect.height() * cos(verticalCurrentAngle*M_PI/180.0f) - rect.width() * sin(fabs(verticalCurrentAngle)*M_PI/180.0f)/tan(M_PI/effects->numberOfDesktops());
|
|
|
|
double addedHeight2 = -rect.width() * sin(fabs(verticalCurrentAngle)*M_PI/180.0f)*tan(M_PI*0.5f/effects->numberOfDesktops());
|
|
|
|
if (verticalCurrentAngle > 0.0f && effects->numberOfDesktops() & 1)
|
|
|
|
translate = cos(fabs(currentAngle)*effects->numberOfDesktops()*M_PI/360.0f) * addedHeight2 + addedHeight1 - float(rect.height());
|
|
|
|
else
|
|
|
|
translate = sin(fabs(currentAngle)*effects->numberOfDesktops()*M_PI/360.0f) * addedHeight2 + addedHeight1 - float(rect.height());
|
|
|
|
} else if (mode == Cylinder) {
|
|
|
|
double addedHeight1 = -rect.height() * cos(verticalCurrentAngle*M_PI/180.0f) - rect.width() * sin(fabs(verticalCurrentAngle)*M_PI/180.0f)/tan(M_PI/effects->numberOfDesktops());
|
|
|
|
translate = addedHeight1 - float(rect.height());
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
2018-06-01 15:32:27 +00:00
|
|
|
float radius = (rect.width() * 0.5) / cos(cubeAngle * 0.5 * M_PI / 180.0);
|
|
|
|
translate = -rect.height()-2*radius;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
m_reflectionMatrix.translate(0.0f, translate, 0.0f);
|
2008-08-04 14:18:05 +00:00
|
|
|
|
2008-07-15 19:21:50 +00:00
|
|
|
reflectionPainting = true;
|
2011-01-30 14:34:42 +00:00
|
|
|
glEnable(GL_CULL_FACE);
|
2015-11-30 10:39:04 +00:00
|
|
|
paintCap(true, -point - zTranslate, data.projectionMatrix());
|
2009-02-06 09:16:30 +00:00
|
|
|
|
|
|
|
// cube
|
2011-01-30 14:34:42 +00:00
|
|
|
glCullFace(GL_BACK);
|
2011-01-01 18:19:16 +00:00
|
|
|
paintCube(mask, region, data);
|
2009-10-22 07:06:44 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
glCullFace(GL_FRONT);
|
2011-01-01 18:19:16 +00:00
|
|
|
paintCube(mask, region, data);
|
2009-02-06 09:16:30 +00:00
|
|
|
|
2015-11-30 10:39:04 +00:00
|
|
|
paintCap(false, -point - zTranslate, data.projectionMatrix());
|
2011-01-30 14:34:42 +00:00
|
|
|
glDisable(GL_CULL_FACE);
|
2008-07-15 19:21:50 +00:00
|
|
|
reflectionPainting = false;
|
2008-08-04 14:18:05 +00:00
|
|
|
|
2012-11-26 09:27:02 +00:00
|
|
|
const float width = rect.width();
|
|
|
|
const float height = rect.height();
|
2008-07-15 19:21:50 +00:00
|
|
|
float vertices[] = {
|
2012-11-26 09:27:02 +00:00
|
|
|
-width * 0.5f, height, 0.0,
|
|
|
|
width * 0.5f, height, 0.0,
|
|
|
|
width * scaleFactor, height, -5000,
|
|
|
|
-width * scaleFactor, height, -5000
|
2011-01-30 14:34:42 +00:00
|
|
|
};
|
2008-07-15 19:21:50 +00:00
|
|
|
// foreground
|
2008-08-04 14:12:58 +00:00
|
|
|
float alpha = 0.7;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
alpha = 0.3 + 0.4 * timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
alpha = 0.3 + 0.4 * (1.0 - timeLine.value());
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2014-02-25 10:02:32 +00:00
|
|
|
if (m_reflectionShader && m_reflectionShader->isValid()) {
|
2010-12-20 20:21:41 +00:00
|
|
|
// ensure blending is enabled - no attribute stack
|
2012-09-21 09:25:08 +00:00
|
|
|
ShaderBinder binder(m_reflectionShader);
|
2015-11-30 10:51:02 +00:00
|
|
|
QMatrix4x4 windowTransformation = data.projectionMatrix();
|
2011-01-30 14:34:42 +00:00
|
|
|
windowTransformation.translate(rect.x() + rect.width() * 0.5f, 0.0, 0.0);
|
2015-11-30 10:51:02 +00:00
|
|
|
m_reflectionShader->setUniform(GLShader::ModelViewProjectionMatrix, windowTransformation);
|
2010-12-20 20:21:41 +00:00
|
|
|
m_reflectionShader->setUniform("u_alpha", alpha);
|
|
|
|
QVector<float> verts;
|
|
|
|
QVector<float> texcoords;
|
|
|
|
verts.reserve(18);
|
|
|
|
texcoords.reserve(12);
|
|
|
|
texcoords << 0.0 << 0.0;
|
|
|
|
verts << vertices[6] << vertices[7] << vertices[8];
|
|
|
|
texcoords << 0.0 << 0.0;
|
|
|
|
verts << vertices[9] << vertices[10] << vertices[11];
|
|
|
|
texcoords << 1.0 << 0.0;
|
|
|
|
verts << vertices[0] << vertices[1] << vertices[2];
|
|
|
|
texcoords << 1.0 << 0.0;
|
|
|
|
verts << vertices[0] << vertices[1] << vertices[2];
|
|
|
|
texcoords << 1.0 << 0.0;
|
|
|
|
verts << vertices[3] << vertices[4] << vertices[5];
|
|
|
|
texcoords << 0.0 << 0.0;
|
|
|
|
verts << vertices[6] << vertices[7] << vertices[8];
|
|
|
|
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
|
|
|
|
vbo->reset();
|
|
|
|
vbo->setData(6, 3, verts.data(), texcoords.data());
|
|
|
|
vbo->render(GL_TRIANGLES);
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
glDisable(GL_BLEND);
|
|
|
|
}
|
|
|
|
glEnable(GL_CULL_FACE);
|
2009-02-06 09:16:30 +00:00
|
|
|
// caps
|
2015-11-30 10:39:04 +00:00
|
|
|
paintCap(false, -point - zTranslate, data.projectionMatrix());
|
2009-02-06 09:16:30 +00:00
|
|
|
|
|
|
|
// cube
|
2011-01-30 14:34:42 +00:00
|
|
|
glCullFace(GL_FRONT);
|
2011-01-01 18:19:16 +00:00
|
|
|
paintCube(mask, region, data);
|
2009-10-22 07:06:44 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
glCullFace(GL_BACK);
|
2011-01-01 18:19:16 +00:00
|
|
|
paintCube(mask, region, data);
|
2008-08-04 14:12:58 +00:00
|
|
|
|
2009-02-06 09:16:30 +00:00
|
|
|
// cap
|
2015-11-30 10:39:04 +00:00
|
|
|
paintCap(true, -point - zTranslate, data.projectionMatrix());
|
2011-01-30 14:34:42 +00:00
|
|
|
glDisable(GL_CULL_FACE);
|
2009-02-06 09:16:30 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
glDisable(GL_BLEND);
|
2008-07-15 19:21:50 +00:00
|
|
|
|
|
|
|
// desktop name box - inspired from coverswitch
|
2011-01-30 14:34:42 +00:00
|
|
|
if (displayDesktopName) {
|
2009-02-21 04:53:13 +00:00
|
|
|
double opacity = 1.0;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = 1.0 - timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
QRect screenRect = effects->clientArea(ScreenArea, activeScreen, frontDesktop);
|
|
|
|
QRect frameRect = QRect(screenRect.width() * 0.33f + screenRect.x(), screenRect.height() * 0.95f + screenRect.y(),
|
|
|
|
screenRect.width() * 0.34f, QFontMetrics(desktopNameFont).height());
|
2012-05-01 17:50:22 +00:00
|
|
|
if (!desktopNameFrame) {
|
|
|
|
desktopNameFrame = effects->effectFrame(EffectFrameStyled);
|
|
|
|
desktopNameFrame->setFont(desktopNameFont);
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
desktopNameFrame->setGeometry(frameRect);
|
|
|
|
desktopNameFrame->setText(effects->desktopName(frontDesktop));
|
|
|
|
desktopNameFrame->render(region, opacity);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
|
|
|
effects->paintScreen(mask, region, data);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2009-02-06 09:16:30 +00:00
|
|
|
void CubeEffect::rotateCube()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
2010-12-18 09:18:54 +00:00
|
|
|
m_rotationMatrix.setToIdentity();
|
2008-07-15 19:21:50 +00:00
|
|
|
float internalCubeAngle = 360.0f / effects->numberOfDesktops();
|
2008-08-25 08:19:39 +00:00
|
|
|
float zTranslate = zPosition + zoom;
|
2011-01-30 14:34:42 +00:00
|
|
|
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
|
|
|
|
float point = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
|
2018-06-01 15:32:27 +00:00
|
|
|
/* Animations */
|
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
zTranslate *= timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
currentAngle = startAngle * (1.0 - timeLine.value());
|
|
|
|
zTranslate *= (1.0 - timeLine.value());
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState != AnimationState::None) {
|
|
|
|
/* Left or right */
|
|
|
|
float endAngle = animationState == AnimationState::Right ? internalCubeAngle : -internalCubeAngle;
|
2018-06-27 16:58:21 +00:00
|
|
|
currentAngle = startAngle + timeLine.value() * (endAngle - startAngle);
|
2018-06-01 15:32:27 +00:00
|
|
|
frontDesktop = startFrontDesktop;
|
|
|
|
}
|
|
|
|
/* Switching to next desktop: either by mouse or due to animation */
|
|
|
|
if (currentAngle > internalCubeAngle * 0.5f) {
|
|
|
|
currentAngle -= internalCubeAngle;
|
|
|
|
frontDesktop--;
|
|
|
|
if (frontDesktop < 1) {
|
|
|
|
frontDesktop = effects->numberOfDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
|
|
|
if (currentAngle < -internalCubeAngle * 0.5f) {
|
|
|
|
currentAngle += internalCubeAngle;
|
|
|
|
frontDesktop++;
|
|
|
|
if (frontDesktop > effects->numberOfDesktops()) {
|
|
|
|
frontDesktop = 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
|
|
|
/* Vertical animations */
|
|
|
|
if (verticalAnimationState != VerticalAnimationState::None) {
|
|
|
|
float verticalEndAngle = 0.0;
|
|
|
|
if (verticalAnimationState == VerticalAnimationState::Upwards && verticalStartAngle >= 0.0) {
|
|
|
|
verticalEndAngle = 90.0;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
if (verticalAnimationState == VerticalAnimationState::Downwards && verticalStartAngle <= 0.0) {
|
|
|
|
verticalEndAngle = -90.0;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
// This also handles the "VerticalAnimationState::Stop" correctly, since it has endAngle = 0.0
|
2018-06-27 16:58:21 +00:00
|
|
|
verticalCurrentAngle = verticalStartAngle + verticalTimeLine.value() * (verticalEndAngle - verticalStartAngle);
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
|
|
|
/* Updating rotation matrix */
|
|
|
|
if (verticalAnimationState != VerticalAnimationState::None || verticalCurrentAngle != 0.0f) {
|
2011-01-30 14:34:42 +00:00
|
|
|
m_rotationMatrix.translate(rect.width() / 2, rect.height() / 2, -point - zTranslate);
|
2018-06-01 15:32:27 +00:00
|
|
|
m_rotationMatrix.rotate(verticalCurrentAngle, 1.0, 0.0, 0.0);
|
2011-01-30 14:34:42 +00:00
|
|
|
m_rotationMatrix.translate(-rect.width() / 2, -rect.height() / 2, point + zTranslate);
|
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState != AnimationState::None || currentAngle != 0.0f) {
|
2011-01-30 14:34:42 +00:00
|
|
|
m_rotationMatrix.translate(rect.width() / 2, rect.height() / 2, -point - zTranslate);
|
2018-06-01 15:32:27 +00:00
|
|
|
m_rotationMatrix.rotate(currentAngle, 0.0, 1.0, 0.0);
|
2011-01-30 14:34:42 +00:00
|
|
|
m_rotationMatrix.translate(-rect.width() / 2, -rect.height() / 2, point + zTranslate);
|
2009-02-06 09:16:30 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void CubeEffect::paintCube(int mask, QRegion region, ScreenPaintData& data)
|
|
|
|
{
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
2009-02-06 09:16:30 +00:00
|
|
|
float internalCubeAngle = 360.0f / effects->numberOfDesktops();
|
|
|
|
cube_painting = true;
|
|
|
|
float zTranslate = zPosition + zoom;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
zTranslate *= timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
zTranslate *= (1.0 - timeLine.value());
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2009-02-06 09:16:30 +00:00
|
|
|
|
|
|
|
// Rotation of the cube
|
2011-01-30 14:34:42 +00:00
|
|
|
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
|
|
|
|
float point = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i < effects->numberOfDesktops(); i++) {
|
2008-07-15 19:21:50 +00:00
|
|
|
// start painting the cube
|
2011-01-30 14:34:42 +00:00
|
|
|
painting_desktop = (i + frontDesktop) % effects->numberOfDesktops();
|
|
|
|
if (painting_desktop == 0) {
|
2008-07-15 19:21:50 +00:00
|
|
|
painting_desktop = effects->numberOfDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2015-12-01 10:24:53 +00:00
|
|
|
QMatrix4x4 matrix;
|
|
|
|
matrix.translate(0, 0, -zTranslate);
|
|
|
|
const QVector3D origin(rect.width() / 2, 0.0, -point);
|
|
|
|
matrix.translate(origin);
|
|
|
|
matrix.rotate(internalCubeAngle * i, 0, 1, 0);
|
|
|
|
matrix.translate(-origin);
|
|
|
|
m_currentFaceMatrix = matrix;
|
|
|
|
effects->paintScreen(mask, region, data);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
cube_painting = false;
|
|
|
|
painting_desktop = effects->currentDesktop();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2015-11-30 10:39:04 +00:00
|
|
|
void CubeEffect::paintCap(bool frontFirst, float zOffset, const QMatrix4x4 &projection)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if ((!paintCaps) || effects->numberOfDesktops() <= 2)
|
2008-07-15 19:21:50 +00:00
|
|
|
return;
|
2010-12-31 09:34:29 +00:00
|
|
|
GLenum firstCull = frontFirst ? GL_FRONT : GL_BACK;
|
|
|
|
GLenum secondCull = frontFirst ? GL_BACK : GL_FRONT;
|
|
|
|
const QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
|
|
|
|
|
|
|
// create the VBO if not yet created
|
|
|
|
if (!m_cubeCapBuffer) {
|
2011-01-30 14:34:42 +00:00
|
|
|
switch(mode) {
|
2010-12-31 09:34:29 +00:00
|
|
|
case Cube:
|
|
|
|
paintCubeCap();
|
|
|
|
break;
|
|
|
|
case Cylinder:
|
|
|
|
paintCylinderCap();
|
|
|
|
break;
|
|
|
|
case Sphere:
|
|
|
|
paintSphereCap();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// impossible
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-30 10:39:04 +00:00
|
|
|
QMatrix4x4 capMvp;
|
2010-12-31 09:34:29 +00:00
|
|
|
QMatrix4x4 capMatrix;
|
2011-01-30 14:34:42 +00:00
|
|
|
capMatrix.translate(rect.width() / 2, 0.0, zOffset);
|
|
|
|
capMatrix.rotate((1 - frontDesktop) * 360.0f / effects->numberOfDesktops(), 0.0, 1.0, 0.0);
|
2010-12-31 09:34:29 +00:00
|
|
|
capMatrix.translate(0.0, rect.height(), 0.0);
|
|
|
|
if (mode == Sphere) {
|
|
|
|
capMatrix.scale(1.0, -1.0, 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool capShader = false;
|
2013-06-03 08:38:04 +00:00
|
|
|
if (effects->compositingType() == OpenGL2Compositing && m_capShader && m_capShader->isValid()) {
|
2010-12-31 09:34:29 +00:00
|
|
|
capShader = true;
|
|
|
|
ShaderManager::instance()->pushShader(m_capShader);
|
2010-12-31 11:32:43 +00:00
|
|
|
float opacity = cubeOpacity;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity *= timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity *= (1.0 - timeLine.value());
|
2010-12-31 11:32:43 +00:00
|
|
|
}
|
|
|
|
m_capShader->setUniform("u_opacity", opacity);
|
2010-12-31 09:53:12 +00:00
|
|
|
m_capShader->setUniform("u_mirror", 1);
|
2010-12-31 09:34:29 +00:00
|
|
|
if (reflectionPainting) {
|
2015-11-30 10:39:04 +00:00
|
|
|
capMvp = projection * m_reflectionMatrix * m_rotationMatrix;
|
2010-12-31 09:34:29 +00:00
|
|
|
} else {
|
2015-11-30 10:39:04 +00:00
|
|
|
capMvp = projection * m_rotationMatrix;
|
2010-12-31 09:34:29 +00:00
|
|
|
}
|
2015-11-30 10:39:04 +00:00
|
|
|
m_capShader->setUniform(GLShader::ModelViewProjectionMatrix, capMvp * capMatrix);
|
2011-05-01 09:18:02 +00:00
|
|
|
m_capShader->setUniform("u_untextured", texturedCaps ? 0 : 1);
|
2010-12-31 09:34:29 +00:00
|
|
|
if (texturedCaps && effects->numberOfDesktops() > 3 && capTexture) {
|
|
|
|
capTexture->bind();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glCullFace(firstCull);
|
|
|
|
m_cubeCapBuffer->render(GL_TRIANGLES);
|
|
|
|
|
|
|
|
if (mode == Sphere) {
|
|
|
|
capMatrix.scale(1.0, -1.0, 1.0);
|
|
|
|
}
|
|
|
|
capMatrix.translate(0.0, -rect.height(), 0.0);
|
|
|
|
if (capShader) {
|
2015-11-30 10:39:04 +00:00
|
|
|
m_capShader->setUniform(GLShader::ModelViewProjectionMatrix, capMvp * capMatrix);
|
2010-12-31 09:53:12 +00:00
|
|
|
m_capShader->setUniform("u_mirror", 0);
|
2010-12-31 09:34:29 +00:00
|
|
|
}
|
|
|
|
glCullFace(secondCull);
|
|
|
|
m_cubeCapBuffer->render(GL_TRIANGLES);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
|
|
|
|
if (capShader) {
|
|
|
|
ShaderManager::instance()->popShader();
|
|
|
|
if (texturedCaps && effects->numberOfDesktops() > 3 && capTexture) {
|
|
|
|
capTexture->unbind();
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-04 15:22:21 +00:00
|
|
|
|
2009-02-14 09:29:01 +00:00
|
|
|
void CubeEffect::paintCubeCap()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
|
|
|
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
|
|
|
|
float z = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
|
|
|
|
float zTexture = rect.width() / 2 * tan(45.0f * M_PI / 180.0f);
|
|
|
|
float angle = 360.0f / effects->numberOfDesktops();
|
2009-02-14 09:29:01 +00:00
|
|
|
bool texture = texturedCaps && effects->numberOfDesktops() > 3 && capTexture;
|
2010-12-31 09:34:29 +00:00
|
|
|
QVector<float> verts;
|
|
|
|
QVector<float> texCoords;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i < effects->numberOfDesktops(); i++) {
|
|
|
|
int triangleRows = effects->numberOfDesktops() * 5;
|
|
|
|
float zTriangleDistance = z / (float)triangleRows;
|
|
|
|
float widthTriangle = tan(angle * 0.5 * M_PI / 180.0) * zTriangleDistance;
|
2008-08-04 15:22:21 +00:00
|
|
|
float currentWidth = 0.0;
|
2011-01-30 14:34:42 +00:00
|
|
|
float cosValue = cos(i * angle * M_PI / 180.0);
|
|
|
|
float sinValue = sin(i * angle * M_PI / 180.0);
|
|
|
|
for (int j = 0; j < triangleRows; j++) {
|
2008-08-04 15:22:21 +00:00
|
|
|
float previousWidth = currentWidth;
|
2011-01-30 14:34:42 +00:00
|
|
|
currentWidth = tan(angle * 0.5 * M_PI / 180.0) * zTriangleDistance * (j + 1);
|
2008-08-04 15:22:21 +00:00
|
|
|
int evenTriangles = 0;
|
|
|
|
int oddTriangles = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int k = 0; k < floor(currentWidth / widthTriangle * 2 - 1 + 0.5f); k++) {
|
2008-08-04 15:22:21 +00:00
|
|
|
float x1 = -previousWidth;
|
|
|
|
float x2 = -currentWidth;
|
|
|
|
float x3 = 0.0;
|
|
|
|
float z1 = 0.0;
|
|
|
|
float z2 = 0.0;
|
|
|
|
float z3 = 0.0;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (k % 2 == 0) {
|
|
|
|
x1 += evenTriangles * widthTriangle * 2;
|
|
|
|
x2 += evenTriangles * widthTriangle * 2;
|
|
|
|
x3 = x2 + widthTriangle * 2;
|
|
|
|
z1 = j * zTriangleDistance;
|
|
|
|
z2 = (j + 1) * zTriangleDistance;
|
|
|
|
z3 = (j + 1) * zTriangleDistance;
|
2008-08-04 15:22:21 +00:00
|
|
|
float xRot = cosValue * x1 - sinValue * z1;
|
|
|
|
float zRot = sinValue * x1 + cosValue * z1;
|
|
|
|
x1 = xRot;
|
|
|
|
z1 = zRot;
|
|
|
|
xRot = cosValue * x2 - sinValue * z2;
|
|
|
|
zRot = sinValue * x2 + cosValue * z2;
|
|
|
|
x2 = xRot;
|
|
|
|
z2 = zRot;
|
|
|
|
xRot = cosValue * x3 - sinValue * z3;
|
|
|
|
zRot = sinValue * x3 + cosValue * z3;
|
|
|
|
x3 = xRot;
|
|
|
|
z3 = zRot;
|
|
|
|
evenTriangles++;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
|
|
|
x1 += oddTriangles * widthTriangle * 2;
|
|
|
|
x2 += (oddTriangles + 1) * widthTriangle * 2;
|
|
|
|
x3 = x1 + widthTriangle * 2;
|
|
|
|
z1 = j * zTriangleDistance;
|
|
|
|
z2 = (j + 1) * zTriangleDistance;
|
|
|
|
z3 = j * zTriangleDistance;
|
2008-08-04 15:22:21 +00:00
|
|
|
float xRot = cosValue * x1 - sinValue * z1;
|
|
|
|
float zRot = sinValue * x1 + cosValue * z1;
|
|
|
|
x1 = xRot;
|
|
|
|
z1 = zRot;
|
|
|
|
xRot = cosValue * x2 - sinValue * z2;
|
|
|
|
zRot = sinValue * x2 + cosValue * z2;
|
|
|
|
x2 = xRot;
|
|
|
|
z2 = zRot;
|
|
|
|
xRot = cosValue * x3 - sinValue * z3;
|
|
|
|
zRot = sinValue * x3 + cosValue * z3;
|
|
|
|
x3 = xRot;
|
|
|
|
z3 = zRot;
|
|
|
|
oddTriangles++;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-04 15:22:21 +00:00
|
|
|
float texX1 = 0.0;
|
|
|
|
float texX2 = 0.0;
|
|
|
|
float texX3 = 0.0;
|
|
|
|
float texY1 = 0.0;
|
|
|
|
float texY2 = 0.0;
|
|
|
|
float texY3 = 0.0;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (texture) {
|
2011-07-04 15:50:12 +00:00
|
|
|
if (capTexture->isYInverted()) {
|
|
|
|
texX1 = x1 / (rect.width()) + 0.5;
|
|
|
|
texY1 = 0.5 + z1 / zTexture * 0.5;
|
|
|
|
texX2 = x2 / (rect.width()) + 0.5;
|
|
|
|
texY2 = 0.5 + z2 / zTexture * 0.5;
|
|
|
|
texX3 = x3 / (rect.width()) + 0.5;
|
|
|
|
texY3 = 0.5 + z3 / zTexture * 0.5;
|
|
|
|
texCoords << texX1 << texY1;
|
|
|
|
} else {
|
|
|
|
texX1 = x1 / (rect.width()) + 0.5;
|
|
|
|
texY1 = 0.5 - z1 / zTexture * 0.5;
|
|
|
|
texX2 = x2 / (rect.width()) + 0.5;
|
|
|
|
texY2 = 0.5 - z2 / zTexture * 0.5;
|
|
|
|
texX3 = x3 / (rect.width()) + 0.5;
|
|
|
|
texY3 = 0.5 - z3 / zTexture * 0.5;
|
|
|
|
texCoords << texX1 << texY1;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-12-31 09:34:29 +00:00
|
|
|
verts << x1 << 0.0 << z1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (texture) {
|
2010-12-31 09:34:29 +00:00
|
|
|
texCoords << texX2 << texY2;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-12-31 09:34:29 +00:00
|
|
|
verts << x2 << 0.0 << z2;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (texture) {
|
2010-12-31 09:34:29 +00:00
|
|
|
texCoords << texX3 << texY3;
|
2008-08-04 15:22:21 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
verts << x3 << 0.0 << z3;
|
2008-08-04 15:22:21 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-12-31 09:34:29 +00:00
|
|
|
delete m_cubeCapBuffer;
|
|
|
|
m_cubeCapBuffer = new GLVertexBuffer(GLVertexBuffer::Static);
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
m_cubeCapBuffer->setData(verts.count() / 3, 3, verts.constData(), texture ? texCoords.constData() : nullptr);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2009-02-14 09:29:01 +00:00
|
|
|
void CubeEffect::paintCylinderCap()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
|
|
|
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
|
2009-02-14 09:29:01 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
float radian = (cubeAngle * 0.5) * M_PI / 180;
|
|
|
|
float radius = (rect.width() * 0.5) * tan(radian);
|
|
|
|
float segment = radius / 30.0f;
|
2009-02-14 09:29:01 +00:00
|
|
|
|
2009-02-19 20:32:20 +00:00
|
|
|
bool texture = texturedCaps && effects->numberOfDesktops() > 3 && capTexture;
|
2011-01-09 20:20:36 +00:00
|
|
|
QVector<float> verts;
|
|
|
|
QVector<float> texCoords;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 1; i <= 30; i++) {
|
2009-02-19 20:32:20 +00:00
|
|
|
int steps = 72;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int j = 0; j <= steps; j++) {
|
|
|
|
const float azimuthAngle = (j * (360.0f / steps)) * M_PI / 180.0f;
|
|
|
|
const float azimuthAngle2 = ((j + 1) * (360.0f / steps)) * M_PI / 180.0f;
|
|
|
|
const float x1 = segment * (i - 1) * sin(azimuthAngle);
|
|
|
|
const float x2 = segment * i * sin(azimuthAngle);
|
|
|
|
const float x3 = segment * (i - 1) * sin(azimuthAngle2);
|
|
|
|
const float x4 = segment * i * sin(azimuthAngle2);
|
|
|
|
const float z1 = segment * (i - 1) * cos(azimuthAngle);
|
|
|
|
const float z2 = segment * i * cos(azimuthAngle);
|
|
|
|
const float z3 = segment * (i - 1) * cos(azimuthAngle2);
|
|
|
|
const float z4 = segment * i * cos(azimuthAngle2);
|
|
|
|
if (texture) {
|
2011-07-04 15:50:12 +00:00
|
|
|
if (capTexture->isYInverted()) {
|
|
|
|
texCoords << (radius + x1) / (radius * 2.0f) << (z1 + radius) / (radius * 2.0f);
|
|
|
|
texCoords << (radius + x2) / (radius * 2.0f) << (z2 + radius) / (radius * 2.0f);
|
|
|
|
texCoords << (radius + x3) / (radius * 2.0f) << (z3 + radius) / (radius * 2.0f);
|
|
|
|
texCoords << (radius + x4) / (radius * 2.0f) << (z4 + radius) / (radius * 2.0f);
|
|
|
|
texCoords << (radius + x3) / (radius * 2.0f) << (z3 + radius) / (radius * 2.0f);
|
|
|
|
texCoords << (radius + x2) / (radius * 2.0f) << (z2 + radius) / (radius * 2.0f);
|
|
|
|
} else {
|
|
|
|
texCoords << (radius + x1) / (radius * 2.0f) << 1.0f - (z1 + radius) / (radius * 2.0f);
|
|
|
|
texCoords << (radius + x2) / (radius * 2.0f) << 1.0f - (z2 + radius) / (radius * 2.0f);
|
|
|
|
texCoords << (radius + x3) / (radius * 2.0f) << 1.0f - (z3 + radius) / (radius * 2.0f);
|
|
|
|
texCoords << (radius + x4) / (radius * 2.0f) << 1.0f - (z4 + radius) / (radius * 2.0f);
|
|
|
|
texCoords << (radius + x3) / (radius * 2.0f) << 1.0f - (z3 + radius) / (radius * 2.0f);
|
|
|
|
texCoords << (radius + x2) / (radius * 2.0f) << 1.0f - (z2 + radius) / (radius * 2.0f);
|
|
|
|
}
|
2011-01-09 20:20:36 +00:00
|
|
|
}
|
|
|
|
verts << x1 << 0.0 << z1;
|
|
|
|
verts << x2 << 0.0 << z2;
|
|
|
|
verts << x3 << 0.0 << z3;
|
|
|
|
verts << x4 << 0.0 << z4;
|
|
|
|
verts << x3 << 0.0 << z3;
|
|
|
|
verts << x2 << 0.0 << z2;
|
2009-02-14 09:29:01 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2011-01-09 20:20:36 +00:00
|
|
|
delete m_cubeCapBuffer;
|
|
|
|
m_cubeCapBuffer = new GLVertexBuffer(GLVertexBuffer::Static);
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
m_cubeCapBuffer->setData(verts.count() / 3, 3, verts.constData(), texture ? texCoords.constData() : nullptr);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-14 09:29:01 +00:00
|
|
|
|
|
|
|
void CubeEffect::paintSphereCap()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
|
|
|
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
|
|
|
|
float zTexture = rect.width() / 2 * tan(45.0f * M_PI / 180.0f);
|
|
|
|
float radius = (rect.width() * 0.5) / cos(cubeAngle * 0.5 * M_PI / 180.0);
|
|
|
|
float angle = acos((rect.height() * 0.5) / radius) * 180.0 / M_PI;
|
2009-02-14 09:29:01 +00:00
|
|
|
angle /= 30;
|
|
|
|
bool texture = texturedCaps && effects->numberOfDesktops() > 3 && capTexture;
|
2011-01-09 20:20:36 +00:00
|
|
|
QVector<float> verts;
|
|
|
|
QVector<float> texCoords;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i < 30; i++) {
|
|
|
|
float topAngle = angle * i * M_PI / 180.0;
|
|
|
|
float bottomAngle = angle * (i + 1) * M_PI / 180.0;
|
2018-06-01 15:32:27 +00:00
|
|
|
float yTop = (rect.height() * 0.5 - radius * cos(topAngle));
|
|
|
|
yTop *= (1.0f-capDeformationFactor);
|
2011-01-30 14:34:42 +00:00
|
|
|
float yBottom = rect.height() * 0.5 - radius * cos(bottomAngle);
|
2018-06-01 15:32:27 +00:00
|
|
|
yBottom *= (1.0f - capDeformationFactor);
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int j = 0; j < 36; j++) {
|
|
|
|
const float x1 = radius * sin(topAngle) * sin((90.0 + j * 10.0) * M_PI / 180.0);
|
|
|
|
const float z1 = radius * sin(topAngle) * cos((90.0 + j * 10.0) * M_PI / 180.0);
|
|
|
|
const float x2 = radius * sin(bottomAngle) * sin((90.0 + j * 10.0) * M_PI / 180.00);
|
|
|
|
const float z2 = radius * sin(bottomAngle) * cos((90.0 + j * 10.0) * M_PI / 180.0);
|
|
|
|
const float x3 = radius * sin(bottomAngle) * sin((90.0 + (j + 1) * 10.0) * M_PI / 180.0);
|
|
|
|
const float z3 = radius * sin(bottomAngle) * cos((90.0 + (j + 1) * 10.0) * M_PI / 180.0);
|
|
|
|
const float x4 = radius * sin(topAngle) * sin((90.0 + (j + 1) * 10.0) * M_PI / 180.0);
|
|
|
|
const float z4 = radius * sin(topAngle) * cos((90.0 + (j + 1) * 10.0) * M_PI / 180.0);
|
2011-01-09 20:20:36 +00:00
|
|
|
if (texture) {
|
2011-07-04 15:50:12 +00:00
|
|
|
if (capTexture->isYInverted()) {
|
|
|
|
texCoords << x4 / (rect.width()) + 0.5 << 0.5 + z4 / zTexture * 0.5;
|
|
|
|
texCoords << x1 / (rect.width()) + 0.5 << 0.5 + z1 / zTexture * 0.5;
|
|
|
|
texCoords << x2 / (rect.width()) + 0.5 << 0.5 + z2 / zTexture * 0.5;
|
|
|
|
texCoords << x2 / (rect.width()) + 0.5 << 0.5 + z2 / zTexture * 0.5;
|
|
|
|
texCoords << x3 / (rect.width()) + 0.5 << 0.5 + z3 / zTexture * 0.5;
|
|
|
|
texCoords << x4 / (rect.width()) + 0.5 << 0.5 + z4 / zTexture * 0.5;
|
|
|
|
} else {
|
|
|
|
texCoords << x4 / (rect.width()) + 0.5 << 0.5 - z4 / zTexture * 0.5;
|
|
|
|
texCoords << x1 / (rect.width()) + 0.5 << 0.5 - z1 / zTexture * 0.5;
|
|
|
|
texCoords << x2 / (rect.width()) + 0.5 << 0.5 - z2 / zTexture * 0.5;
|
|
|
|
texCoords << x2 / (rect.width()) + 0.5 << 0.5 - z2 / zTexture * 0.5;
|
|
|
|
texCoords << x3 / (rect.width()) + 0.5 << 0.5 - z3 / zTexture * 0.5;
|
|
|
|
texCoords << x4 / (rect.width()) + 0.5 << 0.5 - z4 / zTexture * 0.5;
|
|
|
|
}
|
2011-01-09 20:20:36 +00:00
|
|
|
}
|
|
|
|
verts << x4 << yTop << z4;
|
|
|
|
verts << x1 << yTop << z1;
|
|
|
|
verts << x2 << yBottom << z2;
|
|
|
|
verts << x2 << yBottom << z2;
|
|
|
|
verts << x3 << yBottom << z3;
|
|
|
|
verts << x4 << yTop << z4;
|
2009-02-14 09:29:01 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2011-01-09 20:20:36 +00:00
|
|
|
delete m_cubeCapBuffer;
|
|
|
|
m_cubeCapBuffer = new GLVertexBuffer(GLVertexBuffer::Static);
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
m_cubeCapBuffer->setData(verts.count() / 3, 3, verts.constData(), texture ? texCoords.constData() : nullptr);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-14 09:29:01 +00:00
|
|
|
|
2008-07-15 19:21:50 +00:00
|
|
|
void CubeEffect::postPaintScreen()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2008-07-15 19:21:50 +00:00
|
|
|
effects->postPaintScreen();
|
2018-06-01 15:32:27 +00:00
|
|
|
if (!activated)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool animation = (animationState != AnimationState::None || verticalAnimationState != VerticalAnimationState::None);
|
2018-06-27 16:58:21 +00:00
|
|
|
if (animationState != AnimationState::None && timeLine.done()) {
|
2018-06-01 15:32:27 +00:00
|
|
|
/* An animation have just finished! */
|
|
|
|
if (animationState == AnimationState::Stop) {
|
|
|
|
/* If the stop animation is finished, we're done */
|
|
|
|
if (keyboard_grab)
|
|
|
|
effects->ungrabKeyboard();
|
|
|
|
keyboard_grab = false;
|
|
|
|
effects->stopMouseInterception(this);
|
|
|
|
effects->setCurrentDesktop(frontDesktop);
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
effects->setActiveFullScreenEffect(nullptr);
|
2018-06-01 15:32:27 +00:00
|
|
|
delete m_cubeCapBuffer;
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
m_cubeCapBuffer = nullptr;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (desktopNameFrame)
|
|
|
|
desktopNameFrame->free();
|
|
|
|
activated = false;
|
|
|
|
// User can press Esc several times, and several Stop animations can be added to queue. We don't want it
|
|
|
|
animationState = AnimationState::None;
|
|
|
|
animations.clear();
|
|
|
|
verticalAnimationState = VerticalAnimationState::None;
|
|
|
|
verticalAnimations.clear();
|
|
|
|
} else {
|
|
|
|
if (!animations.empty())
|
|
|
|
startAnimation(animations.dequeue());
|
|
|
|
else
|
|
|
|
animationState = AnimationState::None;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
|
|
|
/* Vertical animation have finished */
|
2018-06-27 16:58:21 +00:00
|
|
|
if (verticalAnimationState != VerticalAnimationState::None && verticalTimeLine.done()) {
|
2018-06-01 15:32:27 +00:00
|
|
|
if (!verticalAnimations.empty()) {
|
|
|
|
startVerticalAnimation(verticalAnimations.dequeue());
|
|
|
|
} else {
|
|
|
|
verticalAnimationState = VerticalAnimationState::None;
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
/* Repaint if there is any animation */
|
|
|
|
if (animation) {
|
|
|
|
effects->addRepaintFull();
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void CubeEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time)
|
|
|
|
{
|
|
|
|
if (activated) {
|
|
|
|
if (cube_painting) {
|
|
|
|
if (mode == Cylinder || mode == Sphere) {
|
|
|
|
int leftDesktop = frontDesktop - 1;
|
2009-02-23 17:03:27 +00:00
|
|
|
int rightDesktop = frontDesktop + 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (leftDesktop == 0)
|
2009-02-23 17:03:27 +00:00
|
|
|
leftDesktop = effects->numberOfDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (rightDesktop > effects->numberOfDesktops())
|
2009-02-23 17:03:27 +00:00
|
|
|
rightDesktop = 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (painting_desktop == frontDesktop)
|
|
|
|
data.quads = data.quads.makeGrid(40);
|
|
|
|
else if (painting_desktop == leftDesktop || painting_desktop == rightDesktop)
|
|
|
|
data.quads = data.quads.makeGrid(100);
|
2009-02-23 17:03:27 +00:00
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
data.quads = data.quads.makeGrid(250);
|
|
|
|
}
|
|
|
|
if (w->isOnDesktop(painting_desktop)) {
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, painting_desktop);
|
|
|
|
if (w->x() < rect.x()) {
|
|
|
|
data.quads = data.quads.splitAtX(-w->x());
|
2009-02-23 17:03:27 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w->x() + w->width() > rect.x() + rect.width()) {
|
|
|
|
data.quads = data.quads.splitAtX(rect.width() - w->x());
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w->y() < rect.y()) {
|
|
|
|
data.quads = data.quads.splitAtY(-w->y());
|
|
|
|
}
|
|
|
|
if (w->y() + w->height() > rect.y() + rect.height()) {
|
|
|
|
data.quads = data.quads.splitAtY(rect.height() - w->y());
|
|
|
|
}
|
|
|
|
if (useZOrdering && !w->isDesktop() && !w->isDock() && !w->isOnAllDesktops())
|
|
|
|
data.setTransformed();
|
|
|
|
w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
|
|
|
|
} else {
|
2008-07-15 19:21:50 +00:00
|
|
|
// check for windows belonging to the previous desktop
|
2011-01-30 14:34:42 +00:00
|
|
|
int prev_desktop = painting_desktop - 1;
|
|
|
|
if (prev_desktop == 0)
|
2008-07-15 19:21:50 +00:00
|
|
|
prev_desktop = effects->numberOfDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w->isOnDesktop(prev_desktop) && mode == Cube && !useZOrdering) {
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, prev_desktop);
|
|
|
|
if (w->x() + w->width() > rect.x() + rect.width()) {
|
|
|
|
w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
|
|
|
|
data.quads = data.quads.splitAtX(rect.width() - w->x());
|
|
|
|
if (w->y() < rect.y()) {
|
|
|
|
data.quads = data.quads.splitAtY(-w->y());
|
|
|
|
}
|
|
|
|
if (w->y() + w->height() > rect.y() + rect.height()) {
|
|
|
|
data.quads = data.quads.splitAtY(rect.height() - w->y());
|
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
data.setTransformed();
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->prePaintWindow(w, data, time);
|
2008-07-15 19:21:50 +00:00
|
|
|
return;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
// check for windows belonging to the next desktop
|
2011-01-30 14:34:42 +00:00
|
|
|
int next_desktop = painting_desktop + 1;
|
|
|
|
if (next_desktop > effects->numberOfDesktops())
|
2008-07-15 19:21:50 +00:00
|
|
|
next_desktop = 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w->isOnDesktop(next_desktop) && mode == Cube && !useZOrdering) {
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, next_desktop);
|
|
|
|
if (w->x() < rect.x()) {
|
|
|
|
w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
|
|
|
|
data.quads = data.quads.splitAtX(-w->x());
|
|
|
|
if (w->y() < rect.y()) {
|
|
|
|
data.quads = data.quads.splitAtY(-w->y());
|
|
|
|
}
|
|
|
|
if (w->y() + w->height() > rect.y() + rect.height()) {
|
|
|
|
data.quads = data.quads.splitAtY(rect.height() - w->y());
|
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
data.setTransformed();
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->prePaintWindow(w, data, time);
|
2008-07-15 19:21:50 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->prePaintWindow(w, data, time);
|
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void CubeEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data)
|
|
|
|
{
|
2011-01-09 20:20:36 +00:00
|
|
|
ShaderManager *shaderManager = ShaderManager::instance();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (activated && cube_painting) {
|
2013-10-02 19:36:06 +00:00
|
|
|
region= infiniteRegion(); // we need to explicitly prevent any clipping, bug #325432
|
2013-11-29 05:18:28 +00:00
|
|
|
//qCDebug(KWINEFFECTS) << w->caption();
|
2008-07-15 19:21:50 +00:00
|
|
|
float opacity = cubeOpacity;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = 1.0 - (1.0 - opacity) * timeLine.value();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (reflectionPainting)
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = 0.5 + (cubeOpacity - 0.5) * timeLine.value();
|
2008-07-20 18:55:24 +00:00
|
|
|
// fade in windows belonging to different desktops
|
2011-01-30 14:34:42 +00:00
|
|
|
if (painting_desktop == effects->currentDesktop() && (!w->isOnDesktop(painting_desktop)))
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = timeLine.value() * cubeOpacity;
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = 1.0 - (1.0 - opacity) * (1.0 - timeLine.value());
|
2011-01-30 14:34:42 +00:00
|
|
|
if (reflectionPainting)
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = 0.5 + (cubeOpacity - 0.5) * (1.0 - timeLine.value());
|
2008-07-20 18:55:24 +00:00
|
|
|
// fade out windows belonging to different desktops
|
2011-01-30 14:34:42 +00:00
|
|
|
if (painting_desktop == effects->currentDesktop() && (!w->isOnDesktop(painting_desktop)))
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = cubeOpacity * (1.0 - timeLine.value());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-17 20:47:02 +00:00
|
|
|
// z-Ordering
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!w->isDesktop() && !w->isDock() && useZOrdering && !w->isOnAllDesktops()) {
|
|
|
|
float zOrdering = (effects->stackingOrder().indexOf(w) + 1) * zOrderingFactor;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
zOrdering *= timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
zOrdering *= (1.0 - timeLine.value());
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2012-05-28 12:45:46 +00:00
|
|
|
data.translate(0.0, 0.0, zOrdering);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
// check for windows belonging to the previous desktop
|
2011-01-30 14:34:42 +00:00
|
|
|
int prev_desktop = painting_desktop - 1;
|
|
|
|
if (prev_desktop == 0)
|
2008-07-15 19:21:50 +00:00
|
|
|
prev_desktop = effects->numberOfDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
int next_desktop = painting_desktop + 1;
|
|
|
|
if (next_desktop > effects->numberOfDesktops())
|
2008-07-15 19:21:50 +00:00
|
|
|
next_desktop = 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w->isOnDesktop(prev_desktop) && (mask & PAINT_WINDOW_TRANSFORMED)) {
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, prev_desktop);
|
2008-07-15 19:21:50 +00:00
|
|
|
WindowQuadList new_quads;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (const WindowQuad & quad, data.quads) {
|
|
|
|
if (quad.right() > rect.width() - w->x()) {
|
|
|
|
new_quads.append(quad);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
data.quads = new_quads;
|
2014-04-01 16:09:20 +00:00
|
|
|
data.setXTranslation(-rect.width());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (w->isOnDesktop(next_desktop) && (mask & PAINT_WINDOW_TRANSFORMED)) {
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, next_desktop);
|
2008-07-15 19:21:50 +00:00
|
|
|
WindowQuadList new_quads;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (const WindowQuad & quad, data.quads) {
|
|
|
|
if (w->x() + quad.right() <= rect.x()) {
|
|
|
|
new_quads.append(quad);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
data.quads = new_quads;
|
2014-04-01 16:09:20 +00:00
|
|
|
data.setXTranslation(rect.width());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, painting_desktop);
|
2008-07-20 18:55:24 +00:00
|
|
|
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start || animationState == AnimationState::Stop) {
|
2008-07-20 18:55:24 +00:00
|
|
|
// we have to change opacity values for fade in/out of windows which are shown on front-desktop
|
2011-01-30 14:34:42 +00:00
|
|
|
if (prev_desktop == effects->currentDesktop() && w->x() < rect.x()) {
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = timeLine.value() * cubeOpacity;
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = cubeOpacity * (1.0 - timeLine.value());
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (next_desktop == effects->currentDesktop() && w->x() + w->width() > rect.x() + rect.width()) {
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = timeLine.value() * cubeOpacity;
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
opacity = cubeOpacity * (1.0 - timeLine.value());
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2008-07-20 18:55:24 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-06 18:53:16 +00:00
|
|
|
// HACK set opacity to 0.99 in case of fully opaque to ensure that windows are painted in correct sequence
|
|
|
|
// bug #173214
|
2011-01-30 14:34:42 +00:00
|
|
|
if (opacity > 0.99f)
|
2009-02-06 18:53:16 +00:00
|
|
|
opacity = 0.99f;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (opacityDesktopOnly && !w->isDesktop())
|
2009-02-06 18:53:16 +00:00
|
|
|
opacity = 0.99f;
|
2012-07-12 15:20:17 +00:00
|
|
|
data.multiplyOpacity(opacity);
|
2008-07-20 18:55:24 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w->isOnDesktop(painting_desktop) && w->x() < rect.x()) {
|
2008-07-15 19:21:50 +00:00
|
|
|
WindowQuadList new_quads;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (const WindowQuad & quad, data.quads) {
|
|
|
|
if (quad.right() > -w->x()) {
|
|
|
|
new_quads.append(quad);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
data.quads = new_quads;
|
|
|
|
}
|
|
|
|
if (w->isOnDesktop(painting_desktop) && w->x() + w->width() > rect.x() + rect.width()) {
|
2008-07-15 19:21:50 +00:00
|
|
|
WindowQuadList new_quads;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (const WindowQuad & quad, data.quads) {
|
|
|
|
if (quad.right() <= rect.width() - w->x()) {
|
|
|
|
new_quads.append(quad);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
data.quads = new_quads;
|
|
|
|
}
|
|
|
|
if (w->y() < rect.y()) {
|
2008-07-15 19:21:50 +00:00
|
|
|
WindowQuadList new_quads;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (const WindowQuad & quad, data.quads) {
|
|
|
|
if (quad.bottom() > -w->y()) {
|
|
|
|
new_quads.append(quad);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
data.quads = new_quads;
|
|
|
|
}
|
|
|
|
if (w->y() + w->height() > rect.y() + rect.height()) {
|
2008-07-15 19:21:50 +00:00
|
|
|
WindowQuadList new_quads;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (const WindowQuad & quad, data.quads) {
|
|
|
|
if (quad.bottom() <= rect.height() - w->y()) {
|
|
|
|
new_quads.append(quad);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
data.quads = new_quads;
|
|
|
|
}
|
2015-12-01 10:24:53 +00:00
|
|
|
GLShader *currentShader = nullptr;
|
2014-04-01 16:09:20 +00:00
|
|
|
if (mode == Cylinder) {
|
|
|
|
shaderManager->pushShader(cylinderShader);
|
|
|
|
cylinderShader->setUniform("xCoord", (float)w->x());
|
|
|
|
cylinderShader->setUniform("cubeAngle", (effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 90.0f);
|
|
|
|
float factor = 0.0f;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
factor = 1.0f - timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
factor = timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2014-04-01 16:09:20 +00:00
|
|
|
cylinderShader->setUniform("timeLine", factor);
|
|
|
|
currentShader = cylinderShader;
|
|
|
|
}
|
|
|
|
if (mode == Sphere) {
|
|
|
|
shaderManager->pushShader(sphereShader);
|
|
|
|
sphereShader->setUniform("u_offset", QVector2D(w->x(), w->y()));
|
|
|
|
sphereShader->setUniform("cubeAngle", (effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 90.0f);
|
|
|
|
float factor = 0.0f;
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::Start) {
|
2018-06-27 16:58:21 +00:00
|
|
|
factor = 1.0f - timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
} else if (animationState == AnimationState::Stop) {
|
2018-06-27 16:58:21 +00:00
|
|
|
factor = timeLine.value();
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2014-04-01 16:09:20 +00:00
|
|
|
sphereShader->setUniform("timeLine", factor);
|
|
|
|
currentShader = sphereShader;
|
|
|
|
}
|
2015-12-01 10:24:53 +00:00
|
|
|
if (currentShader) {
|
|
|
|
data.shader = currentShader;
|
|
|
|
}
|
|
|
|
data.setProjectionMatrix(data.screenProjectionMatrix());
|
2014-04-01 16:09:20 +00:00
|
|
|
if (reflectionPainting) {
|
2015-12-01 10:24:53 +00:00
|
|
|
data.setModelViewMatrix(m_reflectionMatrix * m_rotationMatrix * m_currentFaceMatrix);
|
2014-04-01 16:09:20 +00:00
|
|
|
} else {
|
2015-12-01 10:24:53 +00:00
|
|
|
data.setModelViewMatrix(m_rotationMatrix * m_currentFaceMatrix);
|
2010-12-18 09:18:54 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
effects->paintWindow(w, mask, region, data);
|
|
|
|
if (activated && cube_painting) {
|
2014-04-01 16:09:20 +00:00
|
|
|
if (mode == Cylinder || mode == Sphere) {
|
2011-01-09 20:20:36 +00:00
|
|
|
shaderManager->popShader();
|
2010-12-18 09:18:54 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w->isDesktop() && effects->numScreens() > 1 && paintCaps) {
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, painting_desktop);
|
|
|
|
QRegion paint = QRegion(rect);
|
|
|
|
for (int i = 0; i < effects->numScreens(); i++) {
|
|
|
|
if (i == w->screen())
|
2009-02-06 09:20:34 +00:00
|
|
|
continue;
|
2011-01-30 14:34:42 +00:00
|
|
|
paint = paint.subtracted(QRegion(effects->clientArea(ScreenArea, i, painting_desktop)));
|
|
|
|
}
|
|
|
|
paint = paint.subtracted(QRegion(w->geometry()));
|
2009-02-06 09:20:34 +00:00
|
|
|
// in case of free area in multiscreen setup fill it with cap color
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!paint.isEmpty()) {
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2011-01-01 16:49:51 +00:00
|
|
|
QVector<float> verts;
|
2009-02-23 17:03:27 +00:00
|
|
|
float quadSize = 0.0f;
|
2011-01-30 14:34:42 +00:00
|
|
|
int leftDesktop = frontDesktop - 1;
|
2009-02-23 17:03:27 +00:00
|
|
|
int rightDesktop = frontDesktop + 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (leftDesktop == 0)
|
2009-02-23 17:03:27 +00:00
|
|
|
leftDesktop = effects->numberOfDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (rightDesktop > effects->numberOfDesktops())
|
2009-02-23 17:03:27 +00:00
|
|
|
rightDesktop = 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (painting_desktop == frontDesktop)
|
2009-02-23 17:03:27 +00:00
|
|
|
quadSize = 100.0f;
|
2011-01-30 14:34:42 +00:00
|
|
|
else if (painting_desktop == leftDesktop || painting_desktop == rightDesktop)
|
2009-02-23 17:03:27 +00:00
|
|
|
quadSize = 150.0f;
|
|
|
|
else
|
|
|
|
quadSize = 250.0f;
|
2019-07-09 20:08:47 +00:00
|
|
|
for (const QRect &paintRect : paint) {
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i <= (paintRect.height() / quadSize); i++) {
|
|
|
|
for (int j = 0; j <= (paintRect.width() / quadSize); j++) {
|
|
|
|
verts << qMin(paintRect.x() + (j + 1)*quadSize, (float)paintRect.x() + paintRect.width()) << paintRect.y() + i*quadSize;
|
|
|
|
verts << paintRect.x() + j*quadSize << paintRect.y() + i*quadSize;
|
|
|
|
verts << paintRect.x() + j*quadSize << qMin(paintRect.y() + (i + 1)*quadSize, (float)paintRect.y() + paintRect.height());
|
|
|
|
verts << paintRect.x() + j*quadSize << qMin(paintRect.y() + (i + 1)*quadSize, (float)paintRect.y() + paintRect.height());
|
|
|
|
verts << qMin(paintRect.x() + (j + 1)*quadSize, (float)paintRect.x() + paintRect.width()) << qMin(paintRect.y() + (i + 1)*quadSize, (float)paintRect.y() + paintRect.height());
|
|
|
|
verts << qMin(paintRect.x() + (j + 1)*quadSize, (float)paintRect.x() + paintRect.width()) << paintRect.y() + i*quadSize;
|
2009-02-22 10:58:26 +00:00
|
|
|
}
|
2009-02-06 09:20:34 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2011-05-01 09:24:46 +00:00
|
|
|
bool capShader = false;
|
2013-06-03 08:38:04 +00:00
|
|
|
if (effects->compositingType() == OpenGL2Compositing && m_capShader && m_capShader->isValid()) {
|
2011-05-01 09:24:46 +00:00
|
|
|
capShader = true;
|
|
|
|
ShaderManager::instance()->pushShader(m_capShader);
|
|
|
|
m_capShader->setUniform("u_mirror", 0);
|
|
|
|
m_capShader->setUniform("u_untextured", 1);
|
2015-12-01 10:24:53 +00:00
|
|
|
QMatrix4x4 mvp = data.screenProjectionMatrix();
|
2011-05-01 09:24:46 +00:00
|
|
|
if (reflectionPainting) {
|
2015-12-01 10:24:53 +00:00
|
|
|
mvp = mvp * m_reflectionMatrix * m_rotationMatrix * m_currentFaceMatrix;
|
2011-05-01 09:24:46 +00:00
|
|
|
} else {
|
2015-12-01 10:24:53 +00:00
|
|
|
mvp = mvp * m_rotationMatrix * m_currentFaceMatrix;
|
2011-05-01 09:24:46 +00:00
|
|
|
}
|
2015-12-01 10:24:53 +00:00
|
|
|
m_capShader->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
|
2011-05-01 09:24:46 +00:00
|
|
|
}
|
2011-01-01 16:49:51 +00:00
|
|
|
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
|
|
|
|
vbo->reset();
|
|
|
|
QColor color = capColor;
|
|
|
|
capColor.setAlphaF(cubeOpacity);
|
|
|
|
vbo->setColor(color);
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
vbo->setData(verts.size() / 2, 2, verts.constData(), nullptr);
|
2011-05-01 09:24:46 +00:00
|
|
|
if (!capShader || mode == Cube) {
|
|
|
|
// TODO: use sphere and cylinder shaders
|
|
|
|
vbo->render(GL_TRIANGLES);
|
|
|
|
}
|
|
|
|
if (capShader) {
|
|
|
|
ShaderManager::instance()->popShader();
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
glDisable(GL_BLEND);
|
2009-02-06 09:20:34 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool CubeEffect::borderActivated(ElectricBorder border)
|
|
|
|
{
|
|
|
|
if (!borderActivate.contains(border) &&
|
|
|
|
!borderActivateCylinder.contains(border) &&
|
|
|
|
!borderActivateSphere.contains(border))
|
2008-07-15 19:21:50 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this)
|
2009-02-14 09:29:01 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (borderActivate.contains(border)) {
|
|
|
|
if (!activated || (activated && mode == Cube))
|
2009-02-14 09:29:01 +00:00
|
|
|
toggleCube();
|
|
|
|
else
|
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (borderActivateCylinder.contains(border)) {
|
|
|
|
if (!activated || (activated && mode == Cylinder))
|
2009-02-14 09:29:01 +00:00
|
|
|
toggleCylinder();
|
|
|
|
else
|
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (borderActivateSphere.contains(border)) {
|
|
|
|
if (!activated || (activated && mode == Sphere))
|
2009-02-14 09:29:01 +00:00
|
|
|
toggleSphere();
|
|
|
|
else
|
|
|
|
return false;
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2009-02-14 09:29:01 +00:00
|
|
|
void CubeEffect::toggleCube()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-11-29 05:18:28 +00:00
|
|
|
qCDebug(KWINEFFECTS) << "toggle cube";
|
2011-01-30 14:34:42 +00:00
|
|
|
toggle(Cube);
|
|
|
|
}
|
2009-02-14 09:29:01 +00:00
|
|
|
|
|
|
|
void CubeEffect::toggleCylinder()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-11-29 05:18:28 +00:00
|
|
|
qCDebug(KWINEFFECTS) << "toggle cylinder";
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!useShaders)
|
2009-02-14 09:29:01 +00:00
|
|
|
useShaders = loadShader();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (useShaders)
|
|
|
|
toggle(Cylinder);
|
|
|
|
}
|
2009-02-14 09:29:01 +00:00
|
|
|
|
|
|
|
void CubeEffect::toggleSphere()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-11-29 05:18:28 +00:00
|
|
|
qCDebug(KWINEFFECTS) << "toggle sphere";
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!useShaders)
|
2009-02-14 09:29:01 +00:00
|
|
|
useShaders = loadShader();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (useShaders)
|
|
|
|
toggle(Sphere);
|
|
|
|
}
|
2009-02-14 09:29:01 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void CubeEffect::toggle(CubeMode newMode)
|
|
|
|
{
|
|
|
|
if ((effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this) ||
|
|
|
|
effects->numberOfDesktops() < 2)
|
2008-07-15 19:21:50 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!activated) {
|
2009-02-14 09:29:01 +00:00
|
|
|
mode = newMode;
|
2011-01-30 14:34:42 +00:00
|
|
|
setActive(true);
|
|
|
|
} else {
|
|
|
|
setActive(false);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void CubeEffect::grabbedKeyboardEvent(QKeyEvent* e)
|
|
|
|
{
|
2018-06-01 15:32:27 +00:00
|
|
|
// If either stop is running or is scheduled - ignore all events
|
|
|
|
if ((!animations.isEmpty() && animations.last() == AnimationState::Stop) || animationState == AnimationState::Stop) {
|
2008-07-15 19:21:50 +00:00
|
|
|
return;
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
// taken from desktopgrid.cpp
|
2011-01-30 14:34:42 +00:00
|
|
|
if (e->type() == QEvent::KeyPress) {
|
2009-03-30 11:27:57 +00:00
|
|
|
// check for global shortcuts
|
|
|
|
// HACK: keyboard grab disables the global shortcuts so we have to check for global shortcut (bug 156155)
|
2011-01-30 14:34:42 +00:00
|
|
|
if (mode == Cube && cubeShortcut.contains(e->key() + e->modifiers())) {
|
2009-03-30 11:27:57 +00:00
|
|
|
toggleCube();
|
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (mode == Cylinder && cylinderShortcut.contains(e->key() + e->modifiers())) {
|
2009-03-30 11:27:57 +00:00
|
|
|
toggleCylinder();
|
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (mode == Sphere && sphereShortcut.contains(e->key() + e->modifiers())) {
|
2009-03-30 11:27:57 +00:00
|
|
|
toggleSphere();
|
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-03-30 11:27:57 +00:00
|
|
|
|
2008-07-15 19:21:50 +00:00
|
|
|
int desktop = -1;
|
|
|
|
// switch by F<number> or just <number>
|
2011-01-30 14:34:42 +00:00
|
|
|
if (e->key() >= Qt::Key_F1 && e->key() <= Qt::Key_F35)
|
2008-07-15 19:21:50 +00:00
|
|
|
desktop = e->key() - Qt::Key_F1 + 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
else if (e->key() >= Qt::Key_0 && e->key() <= Qt::Key_9)
|
2008-07-15 19:21:50 +00:00
|
|
|
desktop = e->key() == Qt::Key_0 ? 10 : e->key() - Qt::Key_0;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (desktop != -1) {
|
|
|
|
if (desktop <= effects->numberOfDesktops()) {
|
2008-07-15 19:21:50 +00:00
|
|
|
// we have to rotate to chosen desktop
|
|
|
|
// and end effect when rotation finished
|
2011-01-30 14:34:42 +00:00
|
|
|
rotateToDesktop(desktop);
|
|
|
|
setActive(false);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
|
|
|
|
int key = e->key();
|
|
|
|
if (invertKeys) {
|
|
|
|
if (key == Qt::Key_Left)
|
|
|
|
key = Qt::Key_Right;
|
|
|
|
else if (key == Qt::Key_Right)
|
|
|
|
key = Qt::Key_Left;
|
|
|
|
else if (key == Qt::Key_Up)
|
|
|
|
key = Qt::Key_Down;
|
|
|
|
else if (key == Qt::Key_Down)
|
|
|
|
key = Qt::Key_Up;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(key) {
|
|
|
|
// wrap only on autorepeat
|
2011-01-30 14:34:42 +00:00
|
|
|
case Qt::Key_Left:
|
2013-11-29 05:18:28 +00:00
|
|
|
qCDebug(KWINEFFECTS) << "left";
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animations.count() < effects->numberOfDesktops())
|
|
|
|
animations.enqueue(AnimationState::Left);
|
2011-01-30 14:34:42 +00:00
|
|
|
break;
|
|
|
|
case Qt::Key_Right:
|
2013-11-29 05:18:28 +00:00
|
|
|
qCDebug(KWINEFFECTS) << "right";
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animations.count() < effects->numberOfDesktops())
|
|
|
|
animations.enqueue(AnimationState::Right);
|
2011-01-30 14:34:42 +00:00
|
|
|
break;
|
|
|
|
case Qt::Key_Up:
|
2013-11-29 05:18:28 +00:00
|
|
|
qCDebug(KWINEFFECTS) << "up";
|
2018-06-01 15:32:27 +00:00
|
|
|
verticalAnimations.enqueue(VerticalAnimationState::Upwards);
|
2011-01-30 14:34:42 +00:00
|
|
|
break;
|
|
|
|
case Qt::Key_Down:
|
2013-11-29 05:18:28 +00:00
|
|
|
qCDebug(KWINEFFECTS) << "down";
|
2018-06-01 15:32:27 +00:00
|
|
|
verticalAnimations.enqueue(VerticalAnimationState::Downwards);
|
|
|
|
break;
|
2011-01-30 14:34:42 +00:00
|
|
|
case Qt::Key_Escape:
|
|
|
|
rotateToDesktop(effects->currentDesktop());
|
|
|
|
setActive(false);
|
|
|
|
return;
|
|
|
|
case Qt::Key_Enter:
|
|
|
|
case Qt::Key_Return:
|
|
|
|
case Qt::Key_Space:
|
|
|
|
setActive(false);
|
|
|
|
return;
|
|
|
|
case Qt::Key_Plus:
|
2018-06-01 15:32:27 +00:00
|
|
|
case Qt::Key_Equal:
|
2011-01-30 14:34:42 +00:00
|
|
|
zoom -= 10.0;
|
|
|
|
zoom = qMax(-zPosition, zoom);
|
|
|
|
rotateCube();
|
|
|
|
break;
|
|
|
|
case Qt::Key_Minus:
|
|
|
|
zoom += 10.0f;
|
|
|
|
rotateCube();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
effects->addRepaintFull();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void CubeEffect::rotateToDesktop(int desktop)
|
|
|
|
{
|
2018-06-01 15:32:27 +00:00
|
|
|
// all scheduled animations will be removed as a speed up
|
|
|
|
animations.clear();
|
|
|
|
verticalAnimations.clear();
|
|
|
|
// we want only startAnimation to finish gracefully
|
|
|
|
// all the others can be interrupted
|
|
|
|
if (animationState != AnimationState::Start) {
|
|
|
|
animationState = AnimationState::None;
|
|
|
|
}
|
|
|
|
verticalAnimationState = VerticalAnimationState::None;
|
|
|
|
// find the fastest rotation path from frontDesktop to desktop
|
|
|
|
int rightRotations = frontDesktop - desktop;
|
|
|
|
if (rightRotations < 0) {
|
2008-07-15 19:21:50 +00:00
|
|
|
rightRotations += effects->numberOfDesktops();
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
|
|
|
int leftRotations = desktop - frontDesktop;
|
|
|
|
if (leftRotations < 0) {
|
2008-07-15 19:21:50 +00:00
|
|
|
leftRotations += effects->numberOfDesktops();
|
2018-06-01 15:32:27 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (leftRotations <= rightRotations) {
|
|
|
|
for (int i = 0; i < leftRotations; i++) {
|
2018-06-01 15:32:27 +00:00
|
|
|
animations.enqueue(AnimationState::Left);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
|
|
|
for (int i = 0; i < rightRotations; i++) {
|
2018-06-01 15:32:27 +00:00
|
|
|
animations.enqueue(AnimationState::Right);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
// we want the face of desktop to appear, it might need also vertical animation
|
|
|
|
if (verticalCurrentAngle > 0.0f) {
|
|
|
|
verticalAnimations.enqueue(VerticalAnimationState::Downwards);
|
|
|
|
}
|
|
|
|
if (verticalCurrentAngle < 0.0f) {
|
|
|
|
verticalAnimations.enqueue(VerticalAnimationState::Upwards);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
/* Start immediately, so there is no pause:
|
|
|
|
* during that pause, actual frontDesktop might change
|
|
|
|
* if user moves his mouse fast, leading to incorrect desktop */
|
|
|
|
if (animationState == AnimationState::None && !animations.empty()) {
|
|
|
|
startAnimation(animations.dequeue());
|
|
|
|
}
|
|
|
|
if (verticalAnimationState == VerticalAnimationState::None && !verticalAnimations.empty()) {
|
|
|
|
startVerticalAnimation(verticalAnimations.dequeue());
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void CubeEffect::setActive(bool active)
|
|
|
|
{
|
|
|
|
foreach (CubeInsideEffect * inside, m_cubeInsideEffects) {
|
|
|
|
inside->setActive(true);
|
|
|
|
}
|
|
|
|
if (active) {
|
2012-09-12 16:39:13 +00:00
|
|
|
QString capPath = CubeConfig::capPath();
|
2012-05-01 11:53:56 +00:00
|
|
|
if (texturedCaps && !capTexture && !capPath.isEmpty()) {
|
|
|
|
QFutureWatcher<QImage> *watcher = new QFutureWatcher<QImage>(this);
|
2019-01-01 20:48:53 +00:00
|
|
|
connect(watcher, &QFutureWatcher<QImage>::finished, this, &CubeEffect::slotCubeCapLoaded);
|
2012-05-01 11:53:56 +00:00
|
|
|
watcher->setFuture(QtConcurrent::run(this, &CubeEffect::loadCubeCap, capPath));
|
|
|
|
}
|
2012-09-12 16:39:13 +00:00
|
|
|
QString wallpaperPath = CubeConfig::wallpaper().toLocalFile();
|
2012-05-01 11:53:56 +00:00
|
|
|
if (!wallpaper && !wallpaperPath.isEmpty()) {
|
|
|
|
QFutureWatcher<QImage> *watcher = new QFutureWatcher<QImage>(this);
|
2019-01-01 20:48:53 +00:00
|
|
|
connect(watcher, &QFutureWatcher<QImage>::finished, this, &CubeEffect::slotWallPaperLoaded);
|
2012-05-01 11:53:56 +00:00
|
|
|
watcher->setFuture(QtConcurrent::run(this, &CubeEffect::loadWallPaper, wallpaperPath));
|
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
activated = true;
|
2008-08-04 14:23:22 +00:00
|
|
|
activeScreen = effects->activeScreen();
|
2011-01-30 14:34:42 +00:00
|
|
|
keyboard_grab = effects->grabKeyboard(this);
|
2013-04-24 14:51:04 +00:00
|
|
|
effects->startMouseInterception(this, Qt::OpenHandCursor);
|
2009-02-06 18:53:16 +00:00
|
|
|
frontDesktop = effects->currentDesktop();
|
|
|
|
zoom = 0.0;
|
2011-01-30 14:34:42 +00:00
|
|
|
zOrderingFactor = zPosition / (effects->stackingOrder().count() - 1);
|
2018-06-01 15:32:27 +00:00
|
|
|
animations.enqueue(AnimationState::Start);
|
|
|
|
animationState = AnimationState::None;
|
|
|
|
verticalAnimationState = VerticalAnimationState::None;
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->setActiveFullScreenEffect(this);
|
2013-11-29 05:18:28 +00:00
|
|
|
qCDebug(KWINEFFECTS) << "Cube is activated";
|
2018-06-01 15:32:27 +00:00
|
|
|
currentAngle = 0.0;
|
|
|
|
verticalCurrentAngle = 0.0;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (reflection) {
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
|
|
|
float temporaryCoeff = float(rect.width()) / tan(M_PI / float(effects->numberOfDesktops()));
|
|
|
|
mAddedHeightCoeff1 = sqrt(float(rect.height()) * float(rect.height()) + temporaryCoeff * temporaryCoeff);
|
|
|
|
mAddedHeightCoeff2 = sqrt(float(rect.height()) * float(rect.height()) + float(rect.width()) * float(rect.width()) + temporaryCoeff * temporaryCoeff);
|
|
|
|
}
|
2011-01-01 18:19:16 +00:00
|
|
|
m_rotationMatrix.setToIdentity();
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
2018-06-01 15:32:27 +00:00
|
|
|
animations.enqueue(AnimationState::Stop);
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
2018-06-01 15:32:27 +00:00
|
|
|
effects->addRepaintFull();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
|
2013-07-24 13:11:09 +00:00
|
|
|
void CubeEffect::windowInputMouseEvent(QEvent* e)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (!activated)
|
2008-07-15 19:21:50 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (tabBoxMode)
|
2008-08-29 09:22:36 +00:00
|
|
|
return;
|
2018-06-01 15:32:27 +00:00
|
|
|
if ((!animations.isEmpty() && animations.last() == AnimationState::Stop) || animationState == AnimationState::Stop)
|
2008-07-15 19:21:50 +00:00
|
|
|
return;
|
2013-07-24 13:11:09 +00:00
|
|
|
|
|
|
|
QMouseEvent *mouse = dynamic_cast< QMouseEvent* >(e);
|
|
|
|
if (!mouse)
|
|
|
|
return;
|
|
|
|
|
|
|
|
static QPoint oldpos;
|
2013-07-26 15:16:19 +00:00
|
|
|
static QElapsedTimer dblClckTime;
|
|
|
|
static int dblClckCounter(0);
|
2013-07-24 13:11:09 +00:00
|
|
|
if (mouse->type() == QEvent::MouseMove && mouse->buttons().testFlag(Qt::LeftButton)) {
|
|
|
|
const QPoint pos = mouse->pos();
|
|
|
|
QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop());
|
2008-07-15 19:21:50 +00:00
|
|
|
bool repaint = false;
|
|
|
|
// vertical movement only if there is not a rotation
|
2018-06-01 15:32:27 +00:00
|
|
|
if (verticalAnimationState == VerticalAnimationState::None) {
|
2008-07-15 19:21:50 +00:00
|
|
|
// display height corresponds to 180*
|
2008-08-18 09:39:48 +00:00
|
|
|
int deltaY = pos.y() - oldpos.y();
|
2011-01-30 14:34:42 +00:00
|
|
|
float deltaVerticalDegrees = (float)deltaY / rect.height() * 180.0f;
|
|
|
|
if (invertMouse)
|
2018-06-01 15:32:27 +00:00
|
|
|
verticalCurrentAngle += deltaVerticalDegrees;
|
2009-02-06 09:24:12 +00:00
|
|
|
else
|
2018-06-01 15:32:27 +00:00
|
|
|
verticalCurrentAngle -= deltaVerticalDegrees;
|
|
|
|
// don't get too excited
|
|
|
|
verticalCurrentAngle = qBound(-90.0f, verticalCurrentAngle, 90.0f);
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (deltaVerticalDegrees != 0.0)
|
2008-07-15 19:21:50 +00:00
|
|
|
repaint = true;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-07-15 19:21:50 +00:00
|
|
|
// horizontal movement only if there is not a rotation
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animationState == AnimationState::None) {
|
2008-07-15 19:21:50 +00:00
|
|
|
// display width corresponds to sum of angles of the polyhedron
|
|
|
|
int deltaX = oldpos.x() - pos.x();
|
2011-01-30 14:34:42 +00:00
|
|
|
float deltaDegrees = (float)deltaX / rect.width() * 360.0f;
|
|
|
|
if (deltaX == 0) {
|
|
|
|
if (pos.x() == 0)
|
2009-02-22 15:57:26 +00:00
|
|
|
deltaDegrees = 5.0f;
|
2014-02-24 15:13:30 +00:00
|
|
|
if (pos.x() == rect.width() - 1)
|
2009-02-22 15:57:26 +00:00
|
|
|
deltaDegrees = -5.0f;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (invertMouse)
|
2018-06-01 15:32:27 +00:00
|
|
|
currentAngle += deltaDegrees;
|
2009-02-06 09:24:12 +00:00
|
|
|
else
|
2018-06-01 15:32:27 +00:00
|
|
|
currentAngle -= deltaDegrees;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (deltaDegrees != 0.0)
|
2008-07-15 19:21:50 +00:00
|
|
|
repaint = true;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (repaint) {
|
2011-01-01 18:19:16 +00:00
|
|
|
rotateCube();
|
2008-07-15 19:21:50 +00:00
|
|
|
effects->addRepaintFull();
|
|
|
|
}
|
2013-07-24 13:11:09 +00:00
|
|
|
oldpos = pos;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2013-07-24 13:11:09 +00:00
|
|
|
|
|
|
|
else if (mouse->type() == QEvent::MouseButtonPress && mouse->button() == Qt::LeftButton) {
|
|
|
|
oldpos = mouse->pos();
|
2013-07-26 15:16:19 +00:00
|
|
|
if (dblClckTime.elapsed() > QApplication::doubleClickInterval())
|
|
|
|
dblClckCounter = 0;
|
|
|
|
if (!dblClckCounter)
|
|
|
|
dblClckTime.start();
|
2008-07-15 19:21:50 +00:00
|
|
|
}
|
|
|
|
|
2013-07-24 13:11:09 +00:00
|
|
|
else if (mouse->type() == QEvent::MouseButtonRelease) {
|
|
|
|
effects->defineCursor(Qt::OpenHandCursor);
|
2013-07-26 15:16:19 +00:00
|
|
|
if (mouse->button() == Qt::LeftButton && ++dblClckCounter == 2) {
|
|
|
|
dblClckCounter = 0;
|
|
|
|
if (dblClckTime.elapsed() < QApplication::doubleClickInterval()) {
|
|
|
|
setActive(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (mouse->button() == Qt::XButton1) {
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animations.count() < effects->numberOfDesktops()) {
|
2011-01-30 14:34:42 +00:00
|
|
|
if (invertMouse)
|
2018-06-01 15:32:27 +00:00
|
|
|
animations.enqueue(AnimationState::Right);
|
2009-02-06 09:45:34 +00:00
|
|
|
else
|
2018-06-01 15:32:27 +00:00
|
|
|
animations.enqueue(AnimationState::Left);
|
2009-02-06 09:45:34 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->addRepaintFull();
|
2013-07-24 13:11:09 +00:00
|
|
|
} else if (mouse->button() == Qt::XButton2) {
|
2018-06-01 15:32:27 +00:00
|
|
|
if (animations.count() < effects->numberOfDesktops()) {
|
2011-01-30 14:34:42 +00:00
|
|
|
if (invertMouse)
|
2018-06-01 15:32:27 +00:00
|
|
|
animations.enqueue(AnimationState::Left);
|
2009-02-06 09:45:34 +00:00
|
|
|
else
|
2018-06-01 15:32:27 +00:00
|
|
|
animations.enqueue(AnimationState::Right);
|
2009-02-06 09:45:34 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->addRepaintFull();
|
2013-07-24 13:11:09 +00:00
|
|
|
} else if (mouse->button() == Qt::RightButton || (mouse->button() == Qt::LeftButton && closeOnMouseRelease)) {
|
|
|
|
setActive(false);
|
2009-02-06 09:45:34 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-06 09:45:34 +00:00
|
|
|
|
2011-03-06 11:15:16 +00:00
|
|
|
void CubeEffect::slotTabBoxAdded(int mode)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (activated)
|
2008-08-29 09:22:36 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this)
|
2008-08-29 09:22:36 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (useForTabBox && mode == TabBoxDesktopListMode) {
|
2008-08-29 09:22:36 +00:00
|
|
|
effects->refTabBox();
|
|
|
|
tabBoxMode = true;
|
2011-01-30 14:34:42 +00:00
|
|
|
setActive(true);
|
|
|
|
rotateToDesktop(effects->currentTabBoxDesktop());
|
2008-08-29 09:22:36 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-29 09:22:36 +00:00
|
|
|
|
2011-03-06 11:15:16 +00:00
|
|
|
void CubeEffect::slotTabBoxUpdated()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (activated) {
|
|
|
|
rotateToDesktop(effects->currentTabBoxDesktop());
|
2009-10-29 20:21:09 +00:00
|
|
|
effects->addRepaintFull();
|
2008-08-29 09:22:36 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-29 09:22:36 +00:00
|
|
|
|
2011-03-06 11:15:16 +00:00
|
|
|
void CubeEffect::slotTabBoxClosed()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (activated) {
|
2008-08-29 09:22:36 +00:00
|
|
|
effects->unrefTabBox();
|
|
|
|
tabBoxMode = false;
|
2011-01-30 14:34:42 +00:00
|
|
|
setActive(false);
|
2008-08-29 09:22:36 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-29 09:22:36 +00:00
|
|
|
|
2013-08-14 19:13:12 +00:00
|
|
|
void CubeEffect::globalShortcutChanged(QAction *action, const QKeySequence &seq)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-08-14 19:13:12 +00:00
|
|
|
if (action->objectName() == QStringLiteral("Cube")) {
|
|
|
|
cubeShortcut.clear();
|
|
|
|
cubeShortcut.append(seq);
|
|
|
|
} else if (action->objectName() == QStringLiteral("Cylinder")) {
|
|
|
|
cylinderShortcut.clear();
|
|
|
|
cylinderShortcut.append(seq);
|
|
|
|
} else if (action->objectName() == QStringLiteral("Sphere")) {
|
|
|
|
sphereShortcut.clear();
|
|
|
|
sphereShortcut.append(seq);
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-03-30 11:27:57 +00:00
|
|
|
|
2009-10-22 07:06:44 +00:00
|
|
|
void* CubeEffect::proxy()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2009-10-22 07:06:44 +00:00
|
|
|
return &m_proxy;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-10-22 07:06:44 +00:00
|
|
|
|
|
|
|
void CubeEffect::registerCubeInsideEffect(CubeInsideEffect* effect)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
m_cubeInsideEffects.append(effect);
|
|
|
|
}
|
2009-10-22 07:06:44 +00:00
|
|
|
|
|
|
|
void CubeEffect::unregisterCubeInsideEffect(CubeInsideEffect* effect)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
m_cubeInsideEffects.removeAll(effect);
|
|
|
|
}
|
2009-10-22 07:06:44 +00:00
|
|
|
|
2011-08-27 09:21:31 +00:00
|
|
|
bool CubeEffect::isActive() const
|
|
|
|
{
|
2015-11-20 10:17:16 +00:00
|
|
|
return activated && !effects->isScreenLocked();
|
2011-08-27 09:21:31 +00:00
|
|
|
}
|
|
|
|
|
2008-07-15 19:21:50 +00:00
|
|
|
} // namespace
|