[effects] Rewrite the Glide effect
Summary: There are several reasons why I "re-wrote" the Glide effect: * it doesn't work correctly because it suffers from undesired perspective distortions: {F5914378} The worst part is that windows are distorted so much on multiple monitor setups that it's hard to say whether that's glide animation. * window close animation is not quite intuitive: if the close button is located at the top and I click it, I would expect that window is rotated around the bottom edge, not the top; (IMHO) * it's too much distracting when working on something for quite good amount of time: e.g. when editing photos, which involves a big number of different dialogs; * there are issues with deletion of QTimeLine; * windows are not gracefully released if some other effect grabs them; * its code doesn't follow common coding style in KWin. So, the "new" Glide effect is more subtle, it's possible to have different rotation edges for window open/close animations, it doesn't animate special windows(like audio volume feedback), the code is simpler and readable. Yet, there are some issues with QTimeLine, which are common to all effects in KWin anyway. ### Demos {F5889803} //Window Open Animation// {F5889804} //Window Close Animation// {F5889805, layout=center, size=full} //KCM// CCBUG: 394245 Test Plan: * Enabled the Glide effect * Closed System Settings * Opened it again Reviewers: #kwin, #plasma, #vdg, davidedmundson Reviewed By: #kwin, #plasma, #vdg, davidedmundson Subscribers: ngraham, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D13338icc-effect-5.14.5
parent
df802d49a1
commit
6a7e780d74
|
@ -5,6 +5,7 @@
|
||||||
Copyright (C) 2007 Philip Falkner <philip.falkner@gmail.com>
|
Copyright (C) 2007 Philip Falkner <philip.falkner@gmail.com>
|
||||||
Copyright (C) 2009 Martin Gräßlin <mgraesslin@kde.org>
|
Copyright (C) 2009 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
Copyright (C) 2010 Alexandre Pereira <pereira.alex@gmail.com>
|
Copyright (C) 2010 Alexandre Pereira <pereira.alex@gmail.com>
|
||||||
|
Copyright (C) 2018 Vlad Zagorodniy <vladzzag@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,246 +21,293 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
|
// own
|
||||||
#include "glide.h"
|
#include "glide.h"
|
||||||
|
|
||||||
// KConfigSkeleton
|
// KConfigSkeleton
|
||||||
#include "glideconfig.h"
|
#include "glideconfig.h"
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QMatrix4x4>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QString>
|
|
||||||
#include <QTimeLine>
|
|
||||||
|
|
||||||
// Effect is based on fade effect by Philip Falkner
|
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
static const int IsGlideWindow = 0x22A982D4;
|
|
||||||
|
|
||||||
static const QSet<QString> s_blacklist {
|
static const QSet<QString> s_blacklist {
|
||||||
"ksmserver ksmserver",
|
QStringLiteral("ksmserver ksmserver"),
|
||||||
"ksplashx ksplashx",
|
QStringLiteral("ksplashqml ksplashqml"),
|
||||||
"ksplashsimple ksplashsimple",
|
QStringLiteral("ksplashsimple ksplashsimple"),
|
||||||
"ksplashqml ksplashqml"
|
QStringLiteral("ksplashx ksplashx")
|
||||||
};
|
};
|
||||||
|
|
||||||
GlideEffect::GlideEffect()
|
GlideEffect::GlideEffect()
|
||||||
: Effect()
|
|
||||||
{
|
{
|
||||||
initConfig<GlideConfig>();
|
initConfig<GlideConfig>();
|
||||||
reconfigure(ReconfigureAll);
|
reconfigure(ReconfigureAll);
|
||||||
connect(effects, SIGNAL(windowAdded(KWin::EffectWindow*)), this, SLOT(slotWindowAdded(KWin::EffectWindow*)));
|
|
||||||
connect(effects, SIGNAL(windowClosed(KWin::EffectWindow*)), this, SLOT(slotWindowClosed(KWin::EffectWindow*)));
|
|
||||||
connect(effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), this, SLOT(slotWindowDeleted(KWin::EffectWindow*)));
|
|
||||||
|
|
||||||
|
connect(effects, &EffectsHandler::windowAdded, this, &GlideEffect::windowAdded);
|
||||||
connect(effects, &EffectsHandler::windowDataChanged, this, &GlideEffect::cancelWindowGrab);
|
connect(effects, &EffectsHandler::windowClosed, this, &GlideEffect::windowClosed);
|
||||||
|
connect(effects, &EffectsHandler::windowDeleted, this, &GlideEffect::windowDeleted);
|
||||||
|
connect(effects, &EffectsHandler::windowDataChanged, this, &GlideEffect::windowDataChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlideEffect::~GlideEffect() = default;
|
GlideEffect::~GlideEffect() = default;
|
||||||
|
|
||||||
bool GlideEffect::supported()
|
void GlideEffect::reconfigure(ReconfigureFlags flags)
|
||||||
{
|
{
|
||||||
return effects->isOpenGLCompositing() && effects->animationsSupported();
|
Q_UNUSED(flags)
|
||||||
}
|
|
||||||
|
|
||||||
void GlideEffect::reconfigure(ReconfigureFlags)
|
|
||||||
{
|
|
||||||
// Fetch config with KConfigXT
|
|
||||||
GlideConfig::self()->read();
|
GlideConfig::self()->read();
|
||||||
duration = animationTime<GlideConfig>(350);
|
m_duration = std::chrono::milliseconds(animationTime<GlideConfig>(160));
|
||||||
effect = (EffectStyle) GlideConfig::glideEffect();
|
|
||||||
angle = GlideConfig::glideAngle();
|
m_inParams.edge = static_cast<RotationEdge>(GlideConfig::inRotationEdge());
|
||||||
|
m_inParams.angle.from = GlideConfig::inRotationAngle();
|
||||||
|
m_inParams.angle.to = 0.0;
|
||||||
|
m_inParams.distance.from = GlideConfig::inDistance();
|
||||||
|
m_inParams.distance.to = 0.0;
|
||||||
|
m_inParams.opacity.from = GlideConfig::inOpacity();
|
||||||
|
m_inParams.opacity.to = 1.0;
|
||||||
|
|
||||||
|
m_outParams.edge = static_cast<RotationEdge>(GlideConfig::outRotationEdge());
|
||||||
|
m_outParams.angle.from = 0.0;
|
||||||
|
m_outParams.angle.to = GlideConfig::outRotationAngle();
|
||||||
|
m_outParams.distance.from = 0.0;
|
||||||
|
m_outParams.distance.to = GlideConfig::outDistance();
|
||||||
|
m_outParams.opacity.from = 1.0;
|
||||||
|
m_outParams.opacity.to = GlideConfig::outOpacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlideEffect::prePaintScreen(ScreenPrePaintData& data, int time)
|
void GlideEffect::prePaintScreen(ScreenPrePaintData &data, int time)
|
||||||
{
|
{
|
||||||
if (!windows.isEmpty())
|
const std::chrono::milliseconds delta(time);
|
||||||
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
|
|
||||||
|
auto animationIt = m_animations.begin();
|
||||||
|
while (animationIt != m_animations.end()) {
|
||||||
|
(*animationIt).update(delta);
|
||||||
|
++animationIt;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
|
||||||
|
|
||||||
effects->prePaintScreen(data, time);
|
effects->prePaintScreen(data, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlideEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time)
|
void GlideEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time)
|
||||||
{
|
{
|
||||||
InfoHash::iterator info = windows.find(w);
|
if (m_animations.contains(w)) {
|
||||||
if (info != windows.end()) {
|
|
||||||
data.setTransformed();
|
data.setTransformed();
|
||||||
if (info->added)
|
w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE);
|
||||||
info->timeLine->setCurrentTime(info->timeLine->currentTime() + time);
|
|
||||||
else if (info->closed) {
|
|
||||||
info->timeLine->setCurrentTime(info->timeLine->currentTime() - time);
|
|
||||||
if (info->deleted)
|
|
||||||
w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
effects->prePaintWindow(w, data, time);
|
effects->prePaintWindow(w, data, time);
|
||||||
|
|
||||||
// if the window isn't to be painted, then let's make sure
|
|
||||||
// to track its progress
|
|
||||||
if (info != windows.end() && !w->isPaintingEnabled() && !effects->activeFullScreenEffect())
|
|
||||||
w->addRepaintFull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlideEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data)
|
void GlideEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data)
|
||||||
{
|
{
|
||||||
InfoHash::const_iterator info = windows.constFind(w);
|
auto animationIt = m_animations.constFind(w);
|
||||||
if (info != windows.constEnd()) {
|
if (animationIt == m_animations.constEnd()) {
|
||||||
const double progress = info->timeLine->currentValue();
|
effects->paintWindow(w, mask, region, data);
|
||||||
data.setRotationAxis(Qt::XAxis);
|
return;
|
||||||
data.setRotationAngle(angle * (1 - progress));
|
|
||||||
data.multiplyOpacity(progress);
|
|
||||||
switch(effect) {
|
|
||||||
default:
|
|
||||||
case GlideInOut:
|
|
||||||
if (info->added)
|
|
||||||
glideIn(w, data, info);
|
|
||||||
else if (info->closed)
|
|
||||||
glideOut(w, data, info);
|
|
||||||
break;
|
|
||||||
case GlideOutIn:
|
|
||||||
if (info->added)
|
|
||||||
glideOut(w, data, info);
|
|
||||||
if (info->closed)
|
|
||||||
glideIn(w, data, info);
|
|
||||||
break;
|
|
||||||
case GlideIn: glideIn(w, data, info); break;
|
|
||||||
case GlideOut: glideOut(w, data, info); break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perspective projection distorts objects near edges
|
||||||
|
// of the viewport. This is critical because distortions
|
||||||
|
// near edges of the viewport are not desired with this effect.
|
||||||
|
// To fix this, the center of the window will be moved to the origin,
|
||||||
|
// after applying perspective projection, the center is moved back
|
||||||
|
// to its "original" projected position. Overall, this is how the window
|
||||||
|
// will be transformed:
|
||||||
|
// [move to the origin] -> [rotate] -> [translate] ->
|
||||||
|
// -> [perspective projection] -> [reverse "move to the origin"]
|
||||||
|
const QMatrix4x4 oldProjMatrix = data.screenProjectionMatrix();
|
||||||
|
const QRectF windowGeo = w->geometry();
|
||||||
|
const QVector3D invOffset = oldProjMatrix.map(QVector3D(windowGeo.center()));
|
||||||
|
QMatrix4x4 invOffsetMatrix;
|
||||||
|
invOffsetMatrix.translate(invOffset.x(), invOffset.y());
|
||||||
|
data.setProjectionMatrix(invOffsetMatrix * oldProjMatrix);
|
||||||
|
|
||||||
|
// Move the center of the window to the origin.
|
||||||
|
const QRectF screenGeo = effects->virtualScreenGeometry();
|
||||||
|
const QPointF offset = screenGeo.center() - windowGeo.center();
|
||||||
|
data.translate(offset.x(), offset.y());
|
||||||
|
|
||||||
|
const GlideParams params = w->isDeleted() ? m_outParams : m_inParams;
|
||||||
|
const qreal t = (*animationIt).value();
|
||||||
|
|
||||||
|
switch (params.edge) {
|
||||||
|
case RotationEdge::Top:
|
||||||
|
data.setRotationAxis(Qt::XAxis);
|
||||||
|
data.setRotationOrigin(QVector3D(0, 0, 0));
|
||||||
|
data.setRotationAngle(-interpolate(params.angle.from, params.angle.to, t));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RotationEdge::Right:
|
||||||
|
data.setRotationAxis(Qt::YAxis);
|
||||||
|
data.setRotationOrigin(QVector3D(w->width(), 0, 0));
|
||||||
|
data.setRotationAngle(-interpolate(params.angle.from, params.angle.to, t));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RotationEdge::Bottom:
|
||||||
|
data.setRotationAxis(Qt::XAxis);
|
||||||
|
data.setRotationOrigin(QVector3D(0, w->height(), 0));
|
||||||
|
data.setRotationAngle(interpolate(params.angle.from, params.angle.to, t));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RotationEdge::Left:
|
||||||
|
data.setRotationAxis(Qt::YAxis);
|
||||||
|
data.setRotationOrigin(QVector3D(0, 0, 0));
|
||||||
|
data.setRotationAngle(interpolate(params.angle.from, params.angle.to, t));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Fallback to Top.
|
||||||
|
data.setRotationAxis(Qt::XAxis);
|
||||||
|
data.setRotationOrigin(QVector3D(0, 0, 0));
|
||||||
|
data.setRotationAngle(-interpolate(params.angle.from, params.angle.to, t));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.setZTranslation(-interpolate(params.distance.from, params.distance.to, t));
|
||||||
|
data.multiplyOpacity(interpolate(params.opacity.from, params.opacity.to, t));
|
||||||
|
|
||||||
effects->paintWindow(w, mask, region, data);
|
effects->paintWindow(w, mask, region, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlideEffect::glideIn(EffectWindow* w, WindowPaintData& data, const InfoHash::const_iterator &info)
|
void GlideEffect::postPaintScreen()
|
||||||
{
|
{
|
||||||
const double progress = info->timeLine->currentValue();
|
auto animationIt = m_animations.begin();
|
||||||
data *= progress;
|
while (animationIt != m_animations.end()) {
|
||||||
data.translate(int(w->width() / 2 * (1 - progress)), int(w->height() / 2 * (1 - progress)));
|
if ((*animationIt).done()) {
|
||||||
}
|
EffectWindow *w = animationIt.key();
|
||||||
|
if (w->isDeleted()) {
|
||||||
void GlideEffect::glideOut(EffectWindow* w, WindowPaintData& data, const InfoHash::const_iterator &info)
|
|
||||||
{
|
|
||||||
const double progress = info->timeLine->currentValue();
|
|
||||||
data *= (2 - progress);
|
|
||||||
data.translate(- int(w->width() / 2 * (1 - progress)), - int(w->height() / 2 * (1 - progress)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GlideEffect::postPaintWindow(EffectWindow* w)
|
|
||||||
{
|
|
||||||
InfoHash::iterator info = windows.find(w);
|
|
||||||
if (info != windows.end()) {
|
|
||||||
if (info->added && info->timeLine->currentValue() == 1.0) {
|
|
||||||
windows.remove(w);
|
|
||||||
effects->addRepaintFull();
|
|
||||||
} else if (info->closed && info->timeLine->currentValue() == 0.0) {
|
|
||||||
info->closed = false;
|
|
||||||
if (info->deleted) {
|
|
||||||
windows.remove(w);
|
|
||||||
w->unrefWindow();
|
w->unrefWindow();
|
||||||
}
|
}
|
||||||
effects->addRepaintFull();
|
animationIt = m_animations.erase(animationIt);
|
||||||
|
} else {
|
||||||
|
++animationIt;
|
||||||
}
|
}
|
||||||
if (info->added || info->closed)
|
|
||||||
w->addRepaintFull();
|
|
||||||
}
|
}
|
||||||
effects->postPaintWindow(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GlideEffect::slotWindowAdded(EffectWindow* w)
|
effects->addRepaintFull();
|
||||||
{
|
effects->postPaintScreen();
|
||||||
if (!isGlideWindow(w))
|
|
||||||
return;
|
|
||||||
w->setData(IsGlideWindow, true);
|
|
||||||
const void *addGrab = w->data(WindowAddedGrabRole).value<void*>();
|
|
||||||
if (addGrab && addGrab != this)
|
|
||||||
return;
|
|
||||||
w->setData(WindowAddedGrabRole, QVariant::fromValue(static_cast<void*>(this)));
|
|
||||||
|
|
||||||
InfoHash::iterator it = windows.find(w);
|
|
||||||
WindowInfo *info = (it == windows.end()) ? &windows[w] : &it.value();
|
|
||||||
info->added = true;
|
|
||||||
info->closed = false;
|
|
||||||
info->deleted = false;
|
|
||||||
delete info->timeLine;
|
|
||||||
info->timeLine = new QTimeLine(duration);
|
|
||||||
info->timeLine->setCurveShape(QTimeLine::EaseOutCurve);
|
|
||||||
w->addRepaintFull();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GlideEffect::slotWindowClosed(EffectWindow* w)
|
|
||||||
{
|
|
||||||
if (!isGlideWindow(w))
|
|
||||||
return;
|
|
||||||
const void *closeGrab = w->data(WindowClosedGrabRole).value<void*>();
|
|
||||||
if (closeGrab && closeGrab != this)
|
|
||||||
return;
|
|
||||||
w->refWindow();
|
|
||||||
w->setData(WindowClosedGrabRole, QVariant::fromValue(static_cast<void*>(this)));
|
|
||||||
|
|
||||||
InfoHash::iterator it = windows.find(w);
|
|
||||||
WindowInfo *info = (it == windows.end()) ? &windows[w] : &it.value();
|
|
||||||
info->added = false;
|
|
||||||
info->closed = true;
|
|
||||||
info->deleted = true;
|
|
||||||
delete info->timeLine;
|
|
||||||
info->timeLine = new QTimeLine(duration);
|
|
||||||
info->timeLine->setCurveShape(QTimeLine::EaseInCurve);
|
|
||||||
info->timeLine->setCurrentTime(info->timeLine->duration());
|
|
||||||
w->addRepaintFull();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GlideEffect::slotWindowDeleted(EffectWindow* w)
|
|
||||||
{
|
|
||||||
windows.remove(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GlideEffect::isGlideWindow(EffectWindow* w)
|
|
||||||
{
|
|
||||||
if (effects->activeFullScreenEffect())
|
|
||||||
return false;
|
|
||||||
if (!w->isVisible())
|
|
||||||
return false;
|
|
||||||
if (s_blacklist.contains(w->windowClass()))
|
|
||||||
return false;
|
|
||||||
if (w->data(IsGlideWindow).toBool())
|
|
||||||
return true;
|
|
||||||
if (w->hasDecoration())
|
|
||||||
return true;
|
|
||||||
if (!w->isManaged() || w->isMenu() || w->isNotification() || w->isDesktop() ||
|
|
||||||
w->isDock() || w->isSplash() || w->isToolbar())
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GlideEffect::isActive() const
|
bool GlideEffect::isActive() const
|
||||||
{
|
{
|
||||||
return !windows.isEmpty();
|
return !m_animations.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlideEffect::cancelWindowGrab(EffectWindow *w, int grabRole)
|
bool GlideEffect::supported()
|
||||||
{
|
{
|
||||||
if (grabRole != WindowAddedGrabRole && grabRole != WindowClosedGrabRole) {
|
return effects->isOpenGLCompositing()
|
||||||
|
&& effects->animationsSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlideEffect::windowAdded(EffectWindow *w)
|
||||||
|
{
|
||||||
|
if (effects->activeFullScreenEffect()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!w->data(IsGlideWindow).toBool()) {
|
|
||||||
|
if (!isGlideWindow(w)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (w->data(grabRole).value<void*>() != this) {
|
|
||||||
windows.remove(w);
|
if (!w->isVisible()) {
|
||||||
w->setData(IsGlideWindow, false);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void *addGrab = w->data(WindowAddedGrabRole).value<void*>();
|
||||||
|
if (addGrab && addGrab != this) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
w->setData(WindowAddedGrabRole, QVariant::fromValue(static_cast<void*>(this)));
|
||||||
|
|
||||||
|
TimeLine &timeLine = m_animations[w];
|
||||||
|
timeLine.reset();
|
||||||
|
timeLine.setDirection(TimeLine::Forward);
|
||||||
|
timeLine.setDuration(m_duration);
|
||||||
|
timeLine.setEasingCurve(QEasingCurve::InCurve);
|
||||||
|
|
||||||
|
effects->addRepaintFull();
|
||||||
}
|
}
|
||||||
|
|
||||||
GlideEffect::WindowInfo::WindowInfo()
|
void GlideEffect::windowClosed(EffectWindow *w)
|
||||||
: deleted(false)
|
|
||||||
, added(false)
|
|
||||||
, closed(false)
|
|
||||||
, timeLine(0)
|
|
||||||
{
|
{
|
||||||
|
if (effects->activeFullScreenEffect()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isGlideWindow(w)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!w->isVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *closeGrab = w->data(WindowClosedGrabRole).value<void*>();
|
||||||
|
if (closeGrab && closeGrab != this) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
w->refWindow();
|
||||||
|
w->setData(WindowClosedGrabRole, QVariant::fromValue(static_cast<void*>(this)));
|
||||||
|
|
||||||
|
TimeLine &timeLine = m_animations[w];
|
||||||
|
timeLine.reset();
|
||||||
|
timeLine.setDirection(TimeLine::Forward);
|
||||||
|
timeLine.setDuration(m_duration);
|
||||||
|
timeLine.setEasingCurve(QEasingCurve::OutCurve);
|
||||||
|
|
||||||
|
effects->addRepaintFull();
|
||||||
}
|
}
|
||||||
|
|
||||||
GlideEffect::WindowInfo::~WindowInfo()
|
void GlideEffect::windowDeleted(EffectWindow *w)
|
||||||
{
|
{
|
||||||
delete timeLine;
|
m_animations.remove(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
void GlideEffect::windowDataChanged(EffectWindow *w, int role)
|
||||||
|
{
|
||||||
|
if (role != WindowAddedGrabRole && role != WindowClosedGrabRole) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w->data(role).value<void*>() == this) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto animationIt = m_animations.find(w);
|
||||||
|
if (animationIt == m_animations.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w->isDeleted() && role == WindowClosedGrabRole) {
|
||||||
|
w->unrefWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_animations.erase(animationIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GlideEffect::isGlideWindow(EffectWindow *w) const
|
||||||
|
{
|
||||||
|
if (s_blacklist.contains(w->windowClass())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w->hasDecoration()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!w->isManaged()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return w->isNormalWindow()
|
||||||
|
|| w->isDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace KWin
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
Copyright (C) 2007 Philip Falkner <philip.falkner@gmail.com>
|
Copyright (C) 2007 Philip Falkner <philip.falkner@gmail.com>
|
||||||
Copyright (C) 2009 Martin Gräßlin <mgraesslin@kde.org>
|
Copyright (C) 2009 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
Copyright (C) 2010 Alexandre Pereira <pereira.alex@gmail.com>
|
Copyright (C) 2010 Alexandre Pereira <pereira.alex@gmail.com>
|
||||||
|
Copyright (C) 2018 Vlad Zagorodniy <vladzzag@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -23,81 +24,133 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#ifndef KWIN_GLIDE_H
|
#ifndef KWIN_GLIDE_H
|
||||||
#define KWIN_GLIDE_H
|
#define KWIN_GLIDE_H
|
||||||
|
|
||||||
|
// kwineffects
|
||||||
#include <kwineffects.h>
|
#include <kwineffects.h>
|
||||||
|
|
||||||
class QTimeLine;
|
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
class GlideEffect
|
class GlideEffect : public Effect
|
||||||
: public Effect
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(int duration READ configuredDuration)
|
Q_PROPERTY(int duration READ duration)
|
||||||
Q_PROPERTY(int effect READ configuredEffect)
|
Q_PROPERTY(RotationEdge inRotationEdge READ inRotationEdge)
|
||||||
Q_PROPERTY(int angle READ configuredAngle)
|
Q_PROPERTY(qreal inRotationAngle READ inRotationAngle)
|
||||||
|
Q_PROPERTY(qreal inDistance READ inDistance)
|
||||||
|
Q_PROPERTY(qreal inOpacity READ inOpacity)
|
||||||
|
Q_PROPERTY(RotationEdge outRotationEdge READ outRotationEdge)
|
||||||
|
Q_PROPERTY(qreal outRotationAngle READ outRotationAngle)
|
||||||
|
Q_PROPERTY(qreal outDistance READ outDistance)
|
||||||
|
Q_PROPERTY(qreal outOpacity READ outOpacity)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GlideEffect();
|
GlideEffect();
|
||||||
~GlideEffect();
|
~GlideEffect() override;
|
||||||
virtual void reconfigure(ReconfigureFlags);
|
|
||||||
virtual void prePaintScreen(ScreenPrePaintData& data, int time);
|
|
||||||
virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time);
|
|
||||||
virtual void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);
|
|
||||||
virtual void postPaintWindow(EffectWindow* w);
|
|
||||||
virtual bool isActive() const;
|
|
||||||
|
|
||||||
int requestedEffectChainPosition() const override {
|
void reconfigure(ReconfigureFlags flags) override;
|
||||||
return 50;
|
|
||||||
}
|
void prePaintScreen(ScreenPrePaintData &data, int time) override;
|
||||||
|
void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override;
|
||||||
|
void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override;
|
||||||
|
void postPaintScreen() override;
|
||||||
|
|
||||||
|
bool isActive() const override;
|
||||||
|
int requestedEffectChainPosition() const override;
|
||||||
|
|
||||||
static bool supported();
|
static bool supported();
|
||||||
|
|
||||||
// for properties
|
enum RotationEdge {
|
||||||
int configuredDuration() const {
|
Top = 0,
|
||||||
return duration;
|
Right = 1,
|
||||||
}
|
Bottom = 2,
|
||||||
int configuredEffect() const {
|
Left = 3
|
||||||
return effect;
|
};
|
||||||
}
|
Q_ENUM(RotationEdge)
|
||||||
int configuredAngle() const {
|
|
||||||
return angle;
|
int duration() const;
|
||||||
}
|
RotationEdge inRotationEdge() const;
|
||||||
public Q_SLOTS:
|
qreal inRotationAngle() const;
|
||||||
void slotWindowAdded(KWin::EffectWindow* c);
|
qreal inDistance() const;
|
||||||
void slotWindowClosed(KWin::EffectWindow *c);
|
qreal inOpacity() const;
|
||||||
void slotWindowDeleted(KWin::EffectWindow *w);
|
RotationEdge outRotationEdge() const;
|
||||||
|
qreal outRotationAngle() const;
|
||||||
|
qreal outDistance() const;
|
||||||
|
qreal outOpacity() const;
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void windowAdded(EffectWindow *w);
|
||||||
|
void windowClosed(EffectWindow *w);
|
||||||
|
void windowDeleted(EffectWindow *w);
|
||||||
|
void windowDataChanged(EffectWindow *w, int role);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class WindowInfo;
|
bool isGlideWindow(EffectWindow *w) const;
|
||||||
typedef QMap< const EffectWindow*, WindowInfo > InfoHash;
|
|
||||||
void glideIn(EffectWindow* w, WindowPaintData& data, const InfoHash::const_iterator &info);
|
std::chrono::milliseconds m_duration;
|
||||||
void glideOut(EffectWindow* w, WindowPaintData& data, const InfoHash::const_iterator &info);
|
QHash<EffectWindow*, TimeLine> m_animations;
|
||||||
bool isGlideWindow(EffectWindow* w);
|
|
||||||
void cancelWindowGrab(EffectWindow *w, int grabRole);
|
struct GlideParams {
|
||||||
InfoHash windows;
|
RotationEdge edge;
|
||||||
float duration;
|
struct {
|
||||||
int angle;
|
qreal from;
|
||||||
enum EffectStyle {
|
qreal to;
|
||||||
GlideIn = 0,
|
} angle, distance, opacity;
|
||||||
GlideInOut = 1,
|
|
||||||
GlideOutIn = 2,
|
|
||||||
GlideOut = 3
|
|
||||||
};
|
};
|
||||||
EffectStyle effect;
|
|
||||||
|
GlideParams m_inParams;
|
||||||
|
GlideParams m_outParams;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlideEffect::WindowInfo
|
inline int GlideEffect::requestedEffectChainPosition() const
|
||||||
{
|
{
|
||||||
public:
|
return 50;
|
||||||
WindowInfo();
|
}
|
||||||
~WindowInfo();
|
|
||||||
bool deleted;
|
|
||||||
bool added;
|
|
||||||
bool closed;
|
|
||||||
QTimeLine *timeLine;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
inline int GlideEffect::duration() const
|
||||||
|
{
|
||||||
|
return m_duration.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GlideEffect::RotationEdge GlideEffect::inRotationEdge() const
|
||||||
|
{
|
||||||
|
return m_inParams.edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline qreal GlideEffect::inRotationAngle() const
|
||||||
|
{
|
||||||
|
return m_inParams.angle.from;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline qreal GlideEffect::inDistance() const
|
||||||
|
{
|
||||||
|
return m_inParams.distance.from;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline qreal GlideEffect::inOpacity() const
|
||||||
|
{
|
||||||
|
return m_inParams.opacity.from;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GlideEffect::RotationEdge GlideEffect::outRotationEdge() const
|
||||||
|
{
|
||||||
|
return m_outParams.edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline qreal GlideEffect::outRotationAngle() const
|
||||||
|
{
|
||||||
|
return m_outParams.angle.to;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline qreal GlideEffect::outDistance() const
|
||||||
|
{
|
||||||
|
return m_outParams.distance.to;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline qreal GlideEffect::outOpacity() const
|
||||||
|
{
|
||||||
|
return m_outParams.opacity.to;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace KWin
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,11 +8,33 @@
|
||||||
<entry name="Duration" type="UInt">
|
<entry name="Duration" type="UInt">
|
||||||
<default>0</default>
|
<default>0</default>
|
||||||
</entry>
|
</entry>
|
||||||
<entry name="GlideEffect" type="Int">
|
<entry name="InRotationEdge" type="Int">
|
||||||
<default>0</default>
|
<default>0</default>
|
||||||
</entry>
|
</entry>
|
||||||
<entry name="GlideAngle" type="Int">
|
<entry name="InRotationAngle" type="Double">
|
||||||
<default>-90</default>
|
<default>3.0</default>
|
||||||
|
</entry>
|
||||||
|
<entry name="InDistance" type="Double">
|
||||||
|
<default>30.0</default>
|
||||||
|
</entry>
|
||||||
|
<entry name="InOpacity" type="Double">
|
||||||
|
<default>0.4</default>
|
||||||
|
<min>0.0</min>
|
||||||
|
<max>1.0</max>
|
||||||
|
</entry>
|
||||||
|
<entry name="OutRotationEdge" type="Int">
|
||||||
|
<default>2</default>
|
||||||
|
</entry>
|
||||||
|
<entry name="OutRotationAngle" type="Double">
|
||||||
|
<default>3.0</default>
|
||||||
|
</entry>
|
||||||
|
<entry name="OutDistance" type="Double">
|
||||||
|
<default>30.0</default>
|
||||||
|
</entry>
|
||||||
|
<entry name="OutOpacity" type="Double">
|
||||||
|
<default>0.0</default>
|
||||||
|
<min>0.0</min>
|
||||||
|
<max>1.0</max>
|
||||||
</entry>
|
</entry>
|
||||||
</group>
|
</group>
|
||||||
</kcfg>
|
</kcfg>
|
||||||
|
|
|
@ -55,5 +55,7 @@ void GlideEffectConfig::save()
|
||||||
QDBusConnection::sessionBus());
|
QDBusConnection::sessionBus());
|
||||||
interface.reconfigureEffect(QStringLiteral("glide"));
|
interface.reconfigureEffect(QStringLiteral("glide"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace KWin
|
} // namespace KWin
|
||||||
|
|
||||||
#include "glide_config.moc"
|
#include "glide_config.moc"
|
||||||
|
|
|
@ -32,10 +32,10 @@ class GlideEffectConfig : public KCModule
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GlideEffectConfig(QWidget *parent = 0, const QVariantList& args = QVariantList());
|
explicit GlideEffectConfig(QWidget *parent = nullptr, const QVariantList &args = QVariantList());
|
||||||
~GlideEffectConfig();
|
~GlideEffectConfig() override;
|
||||||
|
|
||||||
void save();
|
void save() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::Ui::GlideEffectConfig ui;
|
::Ui::GlideEffectConfig ui;
|
||||||
|
|
|
@ -6,159 +6,249 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>306</width>
|
<width>440</width>
|
||||||
<height>130</height>
|
<height>375</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="glideEffectLabel">
|
<layout class="QFormLayout" name="layout_Duration">
|
||||||
<property name="text">
|
<item row="0" column="0">
|
||||||
<string>Glide Effect:</string>
|
<widget class="QLabel" name="label_Duration">
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayoutGlideEffect">
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacerGlideEffect">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Fixed</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="inGlideEffectLabel">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>In</string>
|
<string>Duration:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="0" column="1">
|
||||||
<widget class="QSlider" name="kcfg_GlideEffect">
|
<widget class="QSpinBox" name="kcfg_Duration">
|
||||||
<property name="minimum">
|
<property name="sizePolicy">
|
||||||
<number>0</number>
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="specialValueText">
|
||||||
|
<string>Default</string>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> milliseconds</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>3</number>
|
<number>9999</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="singleStep">
|
<property name="singleStep">
|
||||||
<number>1</number>
|
<number>5</number>
|
||||||
</property>
|
|
||||||
<property name="pageStep">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="tickPosition">
|
|
||||||
<enum>QSlider::TicksBelow</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="outGlideEffectLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Out</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacerUnderGlideEffect">
|
<widget class="QGroupBox" name="groupBox_InAnimation">
|
||||||
<property name="orientation">
|
<property name="title">
|
||||||
<enum>Qt::Vertical</enum>
|
<string>Window Open Animation</string>
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="glideAngleLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Glide Angle:</string>
|
|
||||||
</property>
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_InRotationEdge">
|
||||||
|
<property name="text">
|
||||||
|
<string>Rotation edge:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="kcfg_InRotationEdge">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Top</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Right</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Bottom</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Left</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_InRotationAngle">
|
||||||
|
<property name="text">
|
||||||
|
<string>Rotation angle:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QSpinBox" name="kcfg_InRotationAngle">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-360</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>360</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_InDistance">
|
||||||
|
<property name="text">
|
||||||
|
<string>Distance:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QSpinBox" name="kcfg_InDistance">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-5000</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>5000</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayoutGlideAngle">
|
<widget class="QGroupBox" name="groupBox_OutAnimation">
|
||||||
<item>
|
<property name="title">
|
||||||
<spacer name="horizontalSpacerGlideAngle">
|
<string>Window Close Animation</string>
|
||||||
<property name="orientation">
|
</property>
|
||||||
<enum>Qt::Horizontal</enum>
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
</property>
|
<item row="0" column="0">
|
||||||
<property name="sizeType">
|
<widget class="QLabel" name="label_OutRotationEdge">
|
||||||
<enum>QSizePolicy::Fixed</enum>
|
<property name="text">
|
||||||
</property>
|
<string>Rotation edge:</string>
|
||||||
<property name="sizeHint" stdset="0">
|
</property>
|
||||||
<size>
|
</widget>
|
||||||
<width>20</width>
|
</item>
|
||||||
<height>20</height>
|
<item row="0" column="1">
|
||||||
</size>
|
<widget class="QComboBox" name="kcfg_OutRotationEdge">
|
||||||
</property>
|
<property name="sizePolicy">
|
||||||
</spacer>
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
</item>
|
<horstretch>0</horstretch>
|
||||||
<item>
|
<verstretch>0</verstretch>
|
||||||
<widget class="QLabel" name="glideAnglenegLabel">
|
</sizepolicy>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>-90</string>
|
<item>
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string>Top</string>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
</item>
|
||||||
<widget class="QSlider" name="kcfg_GlideAngle">
|
<item>
|
||||||
<property name="minimum">
|
<property name="text">
|
||||||
<number>-90</number>
|
<string>Right</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
</item>
|
||||||
<number>90</number>
|
<item>
|
||||||
</property>
|
<property name="text">
|
||||||
<property name="singleStep">
|
<string>Bottom</string>
|
||||||
<number>10</number>
|
</property>
|
||||||
</property>
|
</item>
|
||||||
<property name="pageStep">
|
<item>
|
||||||
<number>45</number>
|
<property name="text">
|
||||||
</property>
|
<string>Left</string>
|
||||||
<property name="orientation">
|
</property>
|
||||||
<enum>Qt::Horizontal</enum>
|
</item>
|
||||||
</property>
|
</widget>
|
||||||
<property name="tickPosition">
|
</item>
|
||||||
<enum>QSlider::TicksBelow</enum>
|
<item row="1" column="0">
|
||||||
</property>
|
<widget class="QLabel" name="label_OutRotationAngle">
|
||||||
</widget>
|
<property name="text">
|
||||||
</item>
|
<string>Rotation angle:</string>
|
||||||
<item>
|
</property>
|
||||||
<widget class="QLabel" name="glideAngleposLabel">
|
</widget>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>90</string>
|
<item row="2" column="0">
|
||||||
</property>
|
<widget class="QLabel" name="label_OutDistance">
|
||||||
</widget>
|
<property name="text">
|
||||||
</item>
|
<string>Distance:</string>
|
||||||
</layout>
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QSpinBox" name="kcfg_OutRotationAngle">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-360</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>360</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QSpinBox" name="kcfg_OutDistance">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-5000</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>5000</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacerUnderGlideAngle">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>0</width>
|
<width>20</width>
|
||||||
<height>0</height>
|
<height>40</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
|
|
Loading…
Reference in New Issue