2020-08-02 22:22:19 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-FileCopyrightText: 2007 Lubos Lunak <l.lunak@kde.org>
|
|
|
|
SPDX-FileCopyrightText: 2008 Lucas Murray <lmurray@undefinedfire.com>
|
|
|
|
SPDX-FileCopyrightText: 2009 Martin Gräßlin <mgraesslin@kde.org>
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#include "desktopgrid.h"
|
2012-09-14 12:34:40 +00:00
|
|
|
// KConfigSkeleton
|
|
|
|
#include "desktopgridconfig.h"
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2009-02-06 10:15:06 +00:00
|
|
|
#include "../presentwindows/presentwindows_proxy.h"
|
2014-04-03 09:04:28 +00:00
|
|
|
#include "../effect_builtins.h"
|
2009-02-06 10:15:06 +00:00
|
|
|
|
2013-08-14 19:13:12 +00:00
|
|
|
#include <QAction>
|
2013-09-04 14:33:51 +00:00
|
|
|
#include <QApplication>
|
2014-03-17 15:24:10 +00:00
|
|
|
#include <KGlobalAccel>
|
|
|
|
#include <KLocalizedString>
|
2007-04-29 17:35:43 +00:00
|
|
|
#include <netwm_def.h>
|
2008-02-02 20:54:19 +00:00
|
|
|
#include <QEvent>
|
|
|
|
#include <QMouseEvent>
|
2015-08-28 20:52:03 +00:00
|
|
|
#include <QTimer>
|
2018-06-05 10:52:57 +00:00
|
|
|
#include <QVector2D>
|
2020-01-22 13:10:47 +00:00
|
|
|
#include <QMatrix4x4>
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-01-22 13:10:47 +00:00
|
|
|
#include <QQuickItem>
|
|
|
|
#include <QQmlContext>
|
2020-04-29 15:18:41 +00:00
|
|
|
#include <KWaylandServer/surface_interface.h>
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
|
2019-07-09 19:19:26 +00:00
|
|
|
#include <cmath>
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
2009-02-14 14:49:46 +00:00
|
|
|
// WARNING, TODO: This effect relies on the desktop layout being EWMH-compliant.
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
DesktopGridEffect::DesktopGridEffect()
|
2011-01-30 14:34:42 +00:00
|
|
|
: activated(false)
|
2008-08-12 15:22:06 +00:00
|
|
|
, timeline()
|
2011-01-30 14:34:42 +00:00
|
|
|
, keyboardGrab(false)
|
|
|
|
, wasWindowMove(false)
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
, wasWindowCopy(false)
|
2011-01-30 14:34:42 +00:00
|
|
|
, wasDesktopMove(false)
|
2011-04-24 20:21:58 +00:00
|
|
|
, isValidMove(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
|
|
|
, windowMove(nullptr)
|
2008-08-12 15:22:06 +00:00
|
|
|
, windowMoveDiff()
|
2020-10-30 09:39:00 +00:00
|
|
|
, windowMoveElevateTimer(new QTimer(this))
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
, lastPresentTime(std::chrono::milliseconds::zero())
|
2008-08-12 15:22:06 +00:00
|
|
|
, gridSize()
|
2011-01-30 14:34:42 +00:00
|
|
|
, orientation(Qt::Horizontal)
|
|
|
|
, activeCell(1, 1)
|
2008-08-12 15:22:06 +00:00
|
|
|
, scale()
|
|
|
|
, unscaledBorder()
|
|
|
|
, scaledSize()
|
|
|
|
, scaledOffset()
|
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_proxy(nullptr)
|
2017-04-01 17:30:44 +00:00
|
|
|
, m_activateAction(new QAction(this))
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2016-12-02 19:27:43 +00:00
|
|
|
initConfig<DesktopGridConfig>();
|
2008-08-12 15:22:06 +00:00
|
|
|
// Load shortcuts
|
2017-04-01 17:30:44 +00:00
|
|
|
QAction* a = m_activateAction;
|
2013-12-10 10:45:33 +00:00
|
|
|
a->setObjectName(QStringLiteral("ShowDesktopGrid"));
|
2011-01-30 14:34:42 +00:00
|
|
|
a->setText(i18n("Show Desktop Grid"));
|
2013-08-14 19:13:12 +00:00
|
|
|
KGlobalAccel::self()->setDefaultShortcut(a, QList<QKeySequence>() << Qt::CTRL + Qt::Key_F8);
|
|
|
|
KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>() << Qt::CTRL + Qt::Key_F8);
|
|
|
|
shortcut = KGlobalAccel::self()->shortcut(a);
|
2013-07-10 10:26:50 +00:00
|
|
|
effects->registerGlobalShortcut(Qt::CTRL + Qt::Key_F8, a);
|
2017-03-18 10:00:30 +00:00
|
|
|
effects->registerTouchpadSwipeShortcut(SwipeDirection::Up, a);
|
2019-01-01 20:48:53 +00:00
|
|
|
connect(a, &QAction::triggered, this, &DesktopGridEffect::toggle);
|
2013-08-14 19:13:12 +00:00
|
|
|
connect(KGlobalAccel::self(), &KGlobalAccel::globalShortcutChanged, this, &DesktopGridEffect::globalShortcutChanged);
|
2019-01-01 20:48:53 +00:00
|
|
|
connect(effects, &EffectsHandler::windowAdded, this, &DesktopGridEffect::slotWindowAdded);
|
|
|
|
connect(effects, &EffectsHandler::windowClosed, this, &DesktopGridEffect::slotWindowClosed);
|
|
|
|
connect(effects, &EffectsHandler::windowDeleted, this, &DesktopGridEffect::slotWindowDeleted);
|
|
|
|
connect(effects, &EffectsHandler::numberDesktopsChanged, this, &DesktopGridEffect::slotNumberDesktopsChanged);
|
2020-02-11 17:03:48 +00:00
|
|
|
connect(effects, &EffectsHandler::windowFrameGeometryChanged, this, &DesktopGridEffect::slotWindowFrameGeometryChanged);
|
2014-03-26 17:03:54 +00:00
|
|
|
connect(effects, &EffectsHandler::numberScreensChanged, this, &DesktopGridEffect::setup);
|
2008-01-29 13:48:26 +00:00
|
|
|
|
2019-06-23 15:59:44 +00:00
|
|
|
connect(effects, &EffectsHandler::screenAboutToLock, this, [this]() {
|
|
|
|
setActive(false);
|
2020-10-30 09:39:00 +00:00
|
|
|
windowMoveElevateTimer->stop();
|
2019-06-23 15:59:44 +00:00
|
|
|
if (keyboardGrab) {
|
|
|
|
effects->ungrabKeyboard();
|
|
|
|
keyboardGrab = false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-10-30 09:39:00 +00:00
|
|
|
windowMoveElevateTimer->setInterval(QApplication::startDragTime());
|
|
|
|
windowMoveElevateTimer->setSingleShot(true);
|
|
|
|
connect(windowMoveElevateTimer, &QTimer::timeout, this, [this]() {
|
|
|
|
effects->setElevatedWindow(windowMove, true);
|
|
|
|
wasWindowMove = true;
|
|
|
|
});
|
|
|
|
|
2008-08-12 15:22:06 +00:00
|
|
|
// Load all other configuration details
|
2011-01-30 14:34:42 +00:00
|
|
|
reconfigure(ReconfigureAll);
|
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2008-10-02 09:27:32 +00:00
|
|
|
DesktopGridEffect::~DesktopGridEffect()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
}
|
2008-10-02 09:27:32 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DesktopGridEffect::reconfigure(ReconfigureFlags)
|
|
|
|
{
|
2014-03-25 15:29:03 +00:00
|
|
|
DesktopGridConfig::self()->read();
|
2008-08-12 15:22:06 +00:00
|
|
|
|
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
|
|
|
}
|
2009-03-29 12:57:20 +00:00
|
|
|
borderActivate.clear();
|
2012-09-14 12:34:40 +00:00
|
|
|
foreach (int i, DesktopGridConfig::borderActivate()) {
|
2011-01-30 14:34:42 +00:00
|
|
|
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
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2012-11-25 17:46:13 +00:00
|
|
|
// TODO: rename zoomDuration to duration
|
2012-09-14 12:34:40 +00:00
|
|
|
zoomDuration = animationTime(DesktopGridConfig::zoomDuration() != 0 ? DesktopGridConfig::zoomDuration() : 300);
|
2020-09-09 12:53:13 +00:00
|
|
|
timeline.setEasingCurve(QEasingCurve::InOutSine);
|
2011-01-30 14:34:42 +00:00
|
|
|
timeline.setDuration(zoomDuration);
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2012-09-14 12:34:40 +00:00
|
|
|
border = DesktopGridConfig::borderWidth();
|
|
|
|
desktopNameAlignment = Qt::Alignment(DesktopGridConfig::desktopNameAlignment());
|
|
|
|
layoutMode = DesktopGridConfig::layoutMode();
|
|
|
|
customLayoutRows = DesktopGridConfig::customLayoutRows();
|
2020-10-30 09:39:00 +00:00
|
|
|
clickBehavior = DesktopGridConfig::clickBehavior();
|
2017-04-01 17:30:44 +00:00
|
|
|
|
|
|
|
// deactivate and activate all touch border
|
|
|
|
const QVector<ElectricBorder> relevantBorders{ElectricLeft, ElectricTop, ElectricRight, ElectricBottom};
|
|
|
|
for (auto e : relevantBorders) {
|
|
|
|
effects->unregisterTouchBorder(e, m_activateAction);
|
|
|
|
}
|
|
|
|
const auto touchBorders = DesktopGridConfig::touchBorderActivate();
|
|
|
|
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), m_activateAction);
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-01-29 13:48:26 +00:00
|
|
|
|
2008-08-12 15:22:06 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Screen painting
|
|
|
|
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
void DesktopGridEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
// The animation code assumes that the time diff cannot be 0, let's work around it.
|
|
|
|
int time;
|
|
|
|
if (lastPresentTime.count()) {
|
|
|
|
time = std::max(1, int((presentTime - lastPresentTime).count()));
|
|
|
|
} else {
|
|
|
|
time = 1;
|
|
|
|
}
|
|
|
|
lastPresentTime = presentTime;
|
|
|
|
|
2011-03-14 21:50:05 +00:00
|
|
|
if (timeline.currentValue() != 0 || activated || (isUsingPresentWindows() && isMotionManagerMovingWindows())) {
|
2011-01-30 14:34:42 +00:00
|
|
|
if (activated)
|
2011-03-14 21:50:05 +00:00
|
|
|
timeline.setCurrentTime(timeline.currentTime() + time);
|
2007-04-29 17:35:43 +00:00
|
|
|
else
|
2011-03-14 21:50:05 +00:00
|
|
|
timeline.setCurrentTime(timeline.currentTime() - time);
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i < effects->numberOfDesktops(); i++) {
|
|
|
|
if (i == highlightedDesktop - 1)
|
2011-03-14 21:50:05 +00:00
|
|
|
hoverTimeline[i]->setCurrentTime(hoverTimeline[i]->currentTime() + time);
|
2008-08-12 15:22:06 +00:00
|
|
|
else
|
2011-03-14 21:50:05 +00:00
|
|
|
hoverTimeline[i]->setCurrentTime(hoverTimeline[i]->currentTime() - time);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (isUsingPresentWindows()) {
|
2009-11-15 12:38:26 +00:00
|
|
|
QList<WindowMotionManager>::iterator i;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (i = m_managers.begin(); i != m_managers.end(); ++i)
|
|
|
|
(*i).calculate(time);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
// PAINT_SCREEN_BACKGROUND_FIRST is needed because screen will be actually painted more than once,
|
|
|
|
// so with normal screen painting second screen paint would erase parts of the first paint
|
2011-03-14 21:50:05 +00:00
|
|
|
if (timeline.currentValue() != 0 || (isUsingPresentWindows() && isMotionManagerMovingWindows()))
|
2007-07-07 14:01:32 +00:00
|
|
|
data.mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
|
2011-03-14 21:50:05 +00:00
|
|
|
if (!activated && timeline.currentValue() == 0 && !(isUsingPresentWindows() && isMotionManagerMovingWindows()))
|
2007-04-29 17:35:43 +00:00
|
|
|
finish();
|
|
|
|
}
|
[effects/desktopgrid] Enable blur behind windows
Summary: Use the blur effect even when the desktop grid is used.
Test Plan: {F5828458}
Reviewers: davidedmundson, fredrik, #vdg, #kwin, graesslin, ngraham
Reviewed By: #vdg, #kwin, graesslin, ngraham
Subscribers: graesslin, kwin, #kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D12620
2018-05-01 14:13:14 +00:00
|
|
|
|
|
|
|
for (auto const &w : effects->stackingOrder()) {
|
|
|
|
w->setData(WindowForceBlurRole, QVariant(true));
|
|
|
|
}
|
|
|
|
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
effects->prePaintScreen(data, presentTime);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-10-29 22:04:15 +00:00
|
|
|
void DesktopGridEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-03-14 21:50:05 +00:00
|
|
|
if (timeline.currentValue() == 0 && !isUsingPresentWindows()) {
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->paintScreen(mask, region, data);
|
2007-04-29 17:35:43 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
for (int desktop = 1; desktop <= effects->numberOfDesktops(); desktop++) {
|
2007-04-29 17:35:43 +00:00
|
|
|
ScreenPaintData d = data;
|
2008-08-12 15:22:06 +00:00
|
|
|
paintingDesktop = desktop;
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->paintScreen(mask, region, d);
|
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
|
|
|
// paint the add desktop button
|
2020-01-22 13:10:47 +00:00
|
|
|
for (EffectQuickScene *view : m_desktopButtons) {
|
|
|
|
view->rootItem()->setOpacity(timeline.currentValue());
|
|
|
|
effects->renderEffectQuickView(view);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows() && windowMove && wasWindowMove) {
|
2009-11-15 14:12:34 +00:00
|
|
|
// the moving window has to be painted on top of all desktops
|
|
|
|
QPoint diff = cursorPos() - m_windowMoveStartPoint;
|
2011-01-30 14:34:42 +00:00
|
|
|
QRect geo = m_windowMoveGeometry.translated(diff);
|
[effects/desktopgrid] Specify screen projection matrix when drawing moving window
Summary:
Currently, when the user is moving a window in the desktop grid it is drawn from
the paintScreen function to ensure it appears above all other windows. However,
when drawing the window, the screenProjectionMatrix for the WindowPaintData structure
is never specified. Because of this, the window will not be visible if OpenGL
compositing along with Lanczos scaling are in use since its coordinates will never
be projected into screen-space (unless the window is maximized, in which case the
scaling code is bypassed).
BUG: 361371
BUG: 364509
FIXED-IN: 5.14.3
Test Plan:
Ensure OpenGL compositing is enabled and the scaling method is set to "Accurate" on
hardware supporting this option. Additionally, ensure the desktop grid effect is
active and is configured to use Present Windows. Open a window and ensure is it not
maximized. Click on the window and drag it around - its contents should remain visible
the entire time and follow the mouse.
Reviewers: #kwin, zzag, graesslin, davidedmundson
Reviewed By: #kwin, zzag, davidedmundson
Subscribers: broulik, davidedmundson, kwin, #kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D16430
2018-10-26 08:18:39 +00:00
|
|
|
WindowPaintData d(windowMove, data.projectionMatrix());
|
2012-05-28 10:00:31 +00:00
|
|
|
d *= QVector2D((qreal)geo.width() / (qreal)windowMove->width(), (qreal)geo.height() / (qreal)windowMove->height());
|
2013-03-15 14:51:36 +00:00
|
|
|
d += QPoint(geo.left() - windowMove->x(), geo.top() - windowMove->y());
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->drawWindow(windowMove, PAINT_WINDOW_TRANSFORMED | PAINT_WINDOW_LANCZOS, infiniteRegion(), d);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (desktopNameAlignment) {
|
|
|
|
for (int screen = 0; screen < effects->numScreens(); screen++) {
|
|
|
|
QRect screenGeom = effects->clientArea(ScreenArea, screen, 0);
|
2010-03-28 09:05:36 +00:00
|
|
|
int desktop = 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (EffectFrame * frame, desktopNames) {
|
|
|
|
QPointF posTL(scalePos(screenGeom.topLeft(), desktop, screen));
|
|
|
|
QPointF posBR(scalePos(screenGeom.bottomRight(), desktop, screen));
|
|
|
|
QRect textArea(posTL.x(), posTL.y(), posBR.x() - posTL.x(), posBR.y() - posTL.y());
|
|
|
|
textArea.adjust(textArea.width() / 10, textArea.height() / 10,
|
|
|
|
-textArea.width() / 10, -textArea.height() / 10);
|
2009-02-22 13:04:16 +00:00
|
|
|
int x, y;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (desktopNameAlignment & Qt::AlignLeft)
|
2009-02-22 13:04:16 +00:00
|
|
|
x = textArea.x();
|
2011-01-30 14:34:42 +00:00
|
|
|
else if (desktopNameAlignment & Qt::AlignRight)
|
2009-02-22 13:04:16 +00:00
|
|
|
x = textArea.right();
|
|
|
|
else
|
|
|
|
x = textArea.center().x();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (desktopNameAlignment & Qt::AlignTop)
|
2009-02-22 13:04:16 +00:00
|
|
|
y = textArea.y();
|
2011-01-30 14:34:42 +00:00
|
|
|
else if (desktopNameAlignment & Qt::AlignBottom)
|
2009-02-22 13:04:16 +00:00
|
|
|
y = textArea.bottom();
|
|
|
|
else
|
|
|
|
y = textArea.center().y();
|
2011-01-30 14:34:42 +00:00
|
|
|
frame->setPosition(QPoint(x, y));
|
2011-03-14 21:50:05 +00:00
|
|
|
frame->render(region, timeline.currentValue(), 0.7);
|
2010-03-28 09:05:36 +00:00
|
|
|
++desktop;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2008-08-12 15:22:06 +00:00
|
|
|
void DesktopGridEffect::postPaintScreen()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
bool resetLastPresentTime = true;
|
|
|
|
|
|
|
|
if (activated ? timeline.currentValue() != 1 : timeline.currentValue() != 0) {
|
2008-08-12 15:22:06 +00:00
|
|
|
effects->addRepaintFull(); // Repaint during zoom
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
resetLastPresentTime = false;
|
|
|
|
}
|
|
|
|
if (isUsingPresentWindows() && isMotionManagerMovingWindows()) {
|
2009-11-15 14:44:42 +00:00
|
|
|
effects->addRepaintFull();
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
resetLastPresentTime = false;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (activated) {
|
|
|
|
for (int i = 0; i < effects->numberOfDesktops(); i++) {
|
2011-03-14 21:50:05 +00:00
|
|
|
if (hoverTimeline[i]->currentValue() != 0.0 && hoverTimeline[i]->currentValue() != 1.0) {
|
2011-01-30 14:34:42 +00:00
|
|
|
// Repaint during soft highlighting
|
2008-08-12 15:22:06 +00:00
|
|
|
effects->addRepaintFull();
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
resetLastPresentTime = false;
|
2008-08-12 15:22:06 +00:00
|
|
|
break;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
[effects/desktopgrid] Enable blur behind windows
Summary: Use the blur effect even when the desktop grid is used.
Test Plan: {F5828458}
Reviewers: davidedmundson, fredrik, #vdg, #kwin, graesslin, ngraham
Reviewed By: #vdg, #kwin, graesslin, ngraham
Subscribers: graesslin, kwin, #kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D12620
2018-05-01 14:13:14 +00:00
|
|
|
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
if (resetLastPresentTime) {
|
|
|
|
lastPresentTime = std::chrono::milliseconds::zero();
|
|
|
|
}
|
|
|
|
|
[effects/desktopgrid] Enable blur behind windows
Summary: Use the blur effect even when the desktop grid is used.
Test Plan: {F5828458}
Reviewers: davidedmundson, fredrik, #vdg, #kwin, graesslin, ngraham
Reviewed By: #vdg, #kwin, graesslin, ngraham
Subscribers: graesslin, kwin, #kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D12620
2018-05-01 14:13:14 +00:00
|
|
|
for (auto &w : effects->stackingOrder()) {
|
2018-06-11 11:25:10 +00:00
|
|
|
w->setData(WindowForceBlurRole, QVariant());
|
[effects/desktopgrid] Enable blur behind windows
Summary: Use the blur effect even when the desktop grid is used.
Test Plan: {F5828458}
Reviewers: davidedmundson, fredrik, #vdg, #kwin, graesslin, ngraham
Reviewed By: #vdg, #kwin, graesslin, ngraham
Subscribers: graesslin, kwin, #kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D12620
2018-05-01 14:13:14 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->postPaintScreen();
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2008-08-12 15:22:06 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Window painting
|
2007-04-29 17:35:43 +00:00
|
|
|
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
void DesktopGridEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-03-14 21:50:05 +00:00
|
|
|
if (timeline.currentValue() != 0 || (isUsingPresentWindows() && isMotionManagerMovingWindows())) {
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w->isOnDesktop(paintingDesktop)) {
|
|
|
|
w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
|
|
|
|
if (w->isMinimized() && isUsingPresentWindows())
|
|
|
|
w->enablePainting(EffectWindow::PAINT_DISABLED_BY_MINIMIZE);
|
2008-08-12 15:22:06 +00:00
|
|
|
data.mask |= PAINT_WINDOW_TRANSFORMED;
|
|
|
|
|
|
|
|
// Split windows at screen edges
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int screen = 0; screen < effects->numScreens(); screen++) {
|
|
|
|
QRect screenGeom = effects->clientArea(ScreenArea, screen, 0);
|
|
|
|
if (w->x() < screenGeom.x())
|
|
|
|
data.quads = data.quads.splitAtX(screenGeom.x() - w->x());
|
|
|
|
if (w->x() + w->width() > screenGeom.x() + screenGeom.width())
|
|
|
|
data.quads = data.quads.splitAtX(screenGeom.x() + screenGeom.width() - w->x());
|
|
|
|
if (w->y() < screenGeom.y())
|
|
|
|
data.quads = data.quads.splitAtY(screenGeom.y() - w->y());
|
|
|
|
if (w->y() + w->height() > screenGeom.y() + screenGeom.height())
|
|
|
|
data.quads = data.quads.splitAtY(screenGeom.y() + screenGeom.height() - w->y());
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (windowMove && wasWindowMove && windowMove->findModal() == w)
|
|
|
|
w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
|
|
|
|
} else
|
|
|
|
w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
effects->prePaintWindow(w, data, presentTime);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DesktopGridEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data)
|
|
|
|
{
|
2011-03-14 21:50:05 +00:00
|
|
|
if (timeline.currentValue() != 0 || (isUsingPresentWindows() && isMotionManagerMovingWindows())) {
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
if (isUsingPresentWindows() && w == windowMove && wasWindowMove &&
|
|
|
|
((!wasWindowCopy && sourceDesktop == paintingDesktop) ||
|
|
|
|
(sourceDesktop != highlightedDesktop && highlightedDesktop == paintingDesktop))) {
|
2009-11-15 14:12:34 +00:00
|
|
|
return; // will be painted on top of all other windows
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-11-15 14:12:34 +00:00
|
|
|
|
2012-05-28 10:00:31 +00:00
|
|
|
qreal xScale = data.xScale();
|
|
|
|
qreal yScale = data.yScale();
|
2009-01-05 14:18:58 +00:00
|
|
|
|
2015-09-14 14:10:31 +00:00
|
|
|
data.multiplyBrightness(1.0 - (0.3 * (1.0 - hoverTimeline[paintingDesktop - 1]->currentValue())));
|
2009-11-15 12:38:26 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int screen = 0; screen < effects->numScreens(); screen++) {
|
|
|
|
QRect screenGeom = effects->clientArea(ScreenArea, screen, 0);
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2009-11-15 12:38:26 +00:00
|
|
|
QRectF transformedGeo = w->geometry();
|
2008-08-12 15:22:06 +00:00
|
|
|
// Display all quads on the same screen on the same pass
|
|
|
|
WindowQuadList screenQuads;
|
2009-11-15 12:38:26 +00:00
|
|
|
bool quadsAdded = false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
|
|
|
WindowMotionManager& manager = m_managers[(paintingDesktop-1)*(effects->numScreens())+screen ];
|
|
|
|
if (manager.isManaging(w)) {
|
|
|
|
foreach (const WindowQuad & quad, data.quads)
|
2015-09-14 17:34:25 +00:00
|
|
|
screenQuads.append(quad);
|
2011-01-30 14:34:42 +00:00
|
|
|
transformedGeo = manager.transformedGeometry(w);
|
2009-11-15 12:38:26 +00:00
|
|
|
quadsAdded = true;
|
2011-05-28 15:41:27 +00:00
|
|
|
if (!manager.areWindowsMoving() && timeline.currentValue() == 1.0)
|
2010-11-01 12:17:05 +00:00
|
|
|
mask |= PAINT_WINDOW_LANCZOS;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else if (w->screen() != screen)
|
2009-11-15 12:38:26 +00:00
|
|
|
quadsAdded = true; // we don't want parts of overlapping windows on the other screen
|
2015-09-14 18:33:20 +00:00
|
|
|
if (w->isDesktop())
|
|
|
|
quadsAdded = false;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (!quadsAdded) {
|
|
|
|
foreach (const WindowQuad & quad, data.quads) {
|
2009-11-15 12:38:26 +00:00
|
|
|
QRect quadRect(
|
|
|
|
w->x() + quad.left(), w->y() + quad.top(),
|
|
|
|
quad.right() - quad.left(), quad.bottom() - quad.top()
|
2011-01-30 14:34:42 +00:00
|
|
|
);
|
|
|
|
if (quadRect.intersects(screenGeom))
|
|
|
|
screenQuads.append(quad);
|
2008-08-12 15:22:06 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (screenQuads.isEmpty())
|
2008-08-12 15:22:06 +00:00
|
|
|
continue; // Nothing is being displayed, don't bother
|
|
|
|
WindowPaintData d = data;
|
|
|
|
d.quads = screenQuads;
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QPointF newPos = scalePos(transformedGeo.topLeft().toPoint(), paintingDesktop, screen);
|
2011-03-14 21:50:05 +00:00
|
|
|
double progress = timeline.currentValue();
|
2012-05-28 10:00:31 +00:00
|
|
|
d.setXScale(interpolate(1, xScale * scale[screen] * (float)transformedGeo.width() / (float)w->geometry().width(), progress));
|
|
|
|
d.setYScale(interpolate(1, yScale * scale[screen] * (float)transformedGeo.height() / (float)w->geometry().height(), progress));
|
2012-05-28 12:45:46 +00:00
|
|
|
d += QPoint(qRound(newPos.x() - w->x()), qRound(newPos.y() - w->y()));
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows() && (w->isDock() || w->isSkipSwitcher())) {
|
2009-11-15 16:35:36 +00:00
|
|
|
// fade out panels if present windows is used
|
2012-07-12 15:20:17 +00:00
|
|
|
d.multiplyOpacity((1.0 - timeline.currentValue()));
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (isUsingPresentWindows() && w->isMinimized()) {
|
2012-07-12 15:20:17 +00:00
|
|
|
d.multiplyOpacity(timeline.currentValue());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-11-15 16:35:36 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (effects->compositingType() == XRenderCompositing) {
|
|
|
|
// More exact clipping as XRender displays the entire window instead of just the quad
|
|
|
|
QPointF screenPosF = scalePos(screenGeom.topLeft(), paintingDesktop).toPoint();
|
2008-08-12 15:22:06 +00:00
|
|
|
QPoint screenPos(
|
2011-01-30 14:34:42 +00:00
|
|
|
qRound(screenPosF.x()),
|
|
|
|
qRound(screenPosF.y())
|
|
|
|
);
|
2008-08-12 15:22:06 +00:00
|
|
|
QSize screenSize(
|
2011-01-30 14:34:42 +00:00
|
|
|
qRound(interpolate(screenGeom.width(), scaledSize[screen].width(), progress)),
|
|
|
|
qRound(interpolate(screenGeom.height(), scaledSize[screen].height(), progress))
|
|
|
|
);
|
|
|
|
PaintClipper pc(effects->clientArea(ScreenArea, screen, 0) & QRect(screenPos, screenSize));
|
|
|
|
effects->paintWindow(w, mask, region, d);
|
|
|
|
} else {
|
2011-03-14 21:50:05 +00:00
|
|
|
if (w->isDesktop() && timeline.currentValue() == 1.0) {
|
2010-11-01 12:17:05 +00:00
|
|
|
// desktop windows are not in a motion manager and can always be rendered with
|
|
|
|
// lanczos sampling except for animations
|
|
|
|
mask |= PAINT_WINDOW_LANCZOS;
|
2008-08-12 15:22:06 +00:00
|
|
|
}
|
2011-06-26 12:51:19 +00:00
|
|
|
effects->paintWindow(w, mask, effects->clientArea(ScreenArea, screen, 0), d);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
} else
|
|
|
|
effects->paintWindow(w, mask, region, data);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2008-08-12 15:22:06 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// User interaction
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-02-25 21:06:02 +00:00
|
|
|
void DesktopGridEffect::slotWindowAdded(EffectWindow* w)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (!activated)
|
2009-11-15 12:38:26 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
2012-09-09 12:24:06 +00:00
|
|
|
if (!isRelevantWithPresentWindows(w))
|
2010-01-18 19:06:09 +00:00
|
|
|
return; // don't add
|
2015-09-14 14:40:31 +00:00
|
|
|
foreach (const int i, desktopList(w)) {
|
|
|
|
WindowMotionManager& manager = m_managers[ i*effects->numScreens()+w->screen()];
|
2011-01-30 14:34:42 +00:00
|
|
|
manager.manage(w);
|
|
|
|
m_proxy->calculateWindowTransformations(manager.managedWindows(), w->screen(), manager);
|
2009-11-15 12:38:26 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->addRepaintFull();
|
|
|
|
}
|
2009-11-15 12:38:26 +00:00
|
|
|
|
2011-02-27 08:25:45 +00:00
|
|
|
void DesktopGridEffect::slotWindowClosed(EffectWindow* w)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-03-14 21:50:05 +00:00
|
|
|
if (!activated && timeline.currentValue() == 0)
|
2009-11-15 12:38:26 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w == windowMove) {
|
|
|
|
effects->setElevatedWindow(windowMove, 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
|
|
|
windowMove = nullptr;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (isUsingPresentWindows()) {
|
2015-09-14 14:40:31 +00:00
|
|
|
foreach (const int i, desktopList(w)) {
|
|
|
|
WindowMotionManager& manager = m_managers[i*effects->numScreens()+w->screen()];
|
|
|
|
manager.unmanage(w);
|
|
|
|
m_proxy->calculateWindowTransformations(manager.managedWindows(), w->screen(), manager);
|
2009-11-15 12:38:26 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
effects->addRepaintFull();
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-02-27 09:47:42 +00:00
|
|
|
void DesktopGridEffect::slotWindowDeleted(EffectWindow* w)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-03-07 17:38:56 +00:00
|
|
|
if (w == windowMove)
|
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
|
|
|
windowMove = nullptr;
|
2015-11-10 21:44:22 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
|
|
|
for (QList<WindowMotionManager>::iterator it = m_managers.begin(),
|
|
|
|
end = m_managers.end(); it != end; ++it) {
|
|
|
|
it->unmanage(w);
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-10-19 18:34:19 +00:00
|
|
|
|
2020-02-11 17:03:48 +00:00
|
|
|
void DesktopGridEffect::slotWindowFrameGeometryChanged(EffectWindow* w, const QRect& old)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
Q_UNUSED(old)
|
|
|
|
if (!activated)
|
2010-03-14 16:18:57 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w == windowMove && wasWindowMove)
|
2010-03-14 16:18:57 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
2015-09-14 14:40:31 +00:00
|
|
|
foreach (const int i, desktopList(w)) {
|
|
|
|
WindowMotionManager& manager = m_managers[i*effects->numScreens()+w->screen()];
|
2010-03-14 16:18:57 +00:00
|
|
|
m_proxy->calculateWindowTransformations(manager.managedWindows(), w->screen(), manager);
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-14 16:18:57 +00:00
|
|
|
|
2013-04-24 14:51:04 +00:00
|
|
|
void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if ((e->type() != QEvent::MouseMove
|
|
|
|
&& e->type() != QEvent::MouseButtonPress
|
|
|
|
&& e->type() != QEvent::MouseButtonRelease)
|
2011-03-14 21:50:05 +00:00
|
|
|
|| timeline.currentValue() != 1) // Block user input during animations
|
2007-04-29 17:35:43 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
QMouseEvent* me = static_cast< QMouseEvent* >(e);
|
2015-09-14 08:57:02 +00:00
|
|
|
if (!(wasWindowMove || wasDesktopMove)) {
|
2020-01-22 13:10:47 +00:00
|
|
|
for (EffectQuickScene *view : m_desktopButtons) {
|
|
|
|
view->forwardMouseEvent(me);
|
|
|
|
if (e->isAccepted()) {
|
2015-09-14 08:57:02 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (e->type() == QEvent::MouseMove) {
|
|
|
|
int d = posToDesktop(me->pos());
|
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
|
|
|
if (windowMove != nullptr &&
|
2013-09-04 14:33:51 +00:00
|
|
|
(me->pos() - dragStartPos).manhattanLength() > QApplication::startDragDistance()) {
|
2011-01-30 14:34:42 +00:00
|
|
|
// Handle window moving
|
2020-10-30 09:39:00 +00:00
|
|
|
if (windowMoveElevateTimer->isActive()) { // Window started moving, but is not elevated yet!
|
|
|
|
windowMoveElevateTimer->stop();
|
|
|
|
effects->setElevatedWindow(windowMove, true);
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!wasWindowMove) { // Activate on move
|
2015-09-14 14:40:31 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
|
|
|
foreach (const int i, desktopList(windowMove)) {
|
2011-01-30 14:34:42 +00:00
|
|
|
WindowMotionManager& manager = m_managers[(i)*(effects->numScreens()) + windowMove->screen()];
|
2015-09-14 14:40:31 +00:00
|
|
|
if ((i + 1) == sourceDesktop) {
|
2011-01-30 14:34:42 +00:00
|
|
|
const QRectF transformedGeo = manager.transformedGeometry(windowMove);
|
2015-09-14 14:40:31 +00:00
|
|
|
const QPointF pos = scalePos(transformedGeo.topLeft().toPoint(), sourceDesktop, windowMove->screen());
|
2011-01-30 14:34:42 +00:00
|
|
|
const QSize size(scale[windowMove->screen()] *(float)transformedGeo.width(),
|
|
|
|
scale[windowMove->screen()] *(float)transformedGeo.height());
|
|
|
|
m_windowMoveGeometry = QRect(pos.toPoint(), size);
|
2010-01-01 11:04:27 +00:00
|
|
|
m_windowMoveStartPoint = me->pos();
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
manager.unmanage(windowMove);
|
|
|
|
if (EffectWindow* modal = windowMove->findModal()) {
|
|
|
|
if (manager.isManaging(modal))
|
|
|
|
manager.unmanage(modal);
|
|
|
|
}
|
|
|
|
m_proxy->calculateWindowTransformations(manager.managedWindows(), windowMove->screen(), manager);
|
2010-01-01 11:04:27 +00:00
|
|
|
}
|
2015-09-14 17:34:25 +00:00
|
|
|
wasWindowMove = true;
|
2009-11-15 14:53:33 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (windowMove->isMovable() && !isUsingPresentWindows()) {
|
2015-09-14 17:34:25 +00:00
|
|
|
wasWindowMove = true;
|
2011-01-30 14:34:42 +00:00
|
|
|
int screen = effects->screenNumber(me->pos());
|
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->moveWindow(windowMove, unscalePos(me->pos(), nullptr) + windowMoveDiff, true, 1.0 / scale[screen]);
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2015-09-14 17:34:25 +00:00
|
|
|
if (wasWindowMove) {
|
2019-02-18 12:58:30 +00:00
|
|
|
if (effects->waylandDisplay() && (me->modifiers() & Qt::ControlModifier)) {
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
wasWindowCopy = true;
|
|
|
|
effects->defineCursor(Qt::DragCopyCursor);
|
|
|
|
} else {
|
|
|
|
wasWindowCopy = false;
|
|
|
|
effects->defineCursor(Qt::ClosedHandCursor);
|
|
|
|
}
|
2015-09-14 17:34:25 +00:00
|
|
|
if (d != highlightedDesktop) {
|
2018-11-13 16:18:46 +00:00
|
|
|
auto desktops = windowMove->desktops();
|
|
|
|
if (!desktops.contains(d)) {
|
|
|
|
desktops.append(d);
|
|
|
|
}
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
if (highlightedDesktop != sourceDesktop || !wasWindowCopy) {
|
2018-11-13 16:18:46 +00:00
|
|
|
desktops.removeOne(highlightedDesktop);
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
}
|
2018-11-13 16:18:46 +00:00
|
|
|
effects->windowToDesktops(windowMove, desktops);
|
2015-09-14 17:34:25 +00:00
|
|
|
const int screen = effects->screenNumber(me->pos());
|
|
|
|
if (screen != windowMove->screen())
|
|
|
|
effects->windowToScreen(windowMove, screen);
|
|
|
|
}
|
|
|
|
effects->addRepaintFull();
|
2009-12-14 21:28:24 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
} else if ((me->buttons() & Qt::LeftButton) && !wasDesktopMove &&
|
2013-09-04 14:33:51 +00:00
|
|
|
(me->pos() - dragStartPos).manhattanLength() > QApplication::startDragDistance()) {
|
2011-01-30 14:34:42 +00:00
|
|
|
wasDesktopMove = true;
|
2013-04-24 14:51:04 +00:00
|
|
|
effects->defineCursor(Qt::ClosedHandCursor);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (d != highlightedDesktop) { // Highlight desktop
|
2011-04-24 20:21:58 +00:00
|
|
|
if ((me->buttons() & Qt::LeftButton) && isValidMove && !wasWindowMove && d <= effects->numberOfDesktops()) {
|
2009-08-25 14:34:40 +00:00
|
|
|
EffectWindowList windows = effects->stackingOrder();
|
2012-03-12 23:25:10 +00:00
|
|
|
EffectWindowList stack[3];
|
|
|
|
for (EffectWindowList::const_iterator it = windows.constBegin(),
|
|
|
|
end = windows.constEnd(); it != end; ++it) {
|
|
|
|
EffectWindow *w = const_cast<EffectWindow*>(*it); // we're not really touching it here but below
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w->isOnAllDesktops())
|
2009-08-25 14:34:40 +00:00
|
|
|
continue;
|
2012-03-12 23:25:10 +00:00
|
|
|
if (w->isOnDesktop(highlightedDesktop))
|
|
|
|
stack[0] << w;
|
|
|
|
if (w->isOnDesktop(d))
|
|
|
|
stack[1] << w;
|
|
|
|
if (w->isOnDesktop(m_originalMovingDesktop))
|
|
|
|
stack[2] << w;
|
|
|
|
}
|
|
|
|
const int desks[4] = {highlightedDesktop, d, m_originalMovingDesktop, highlightedDesktop};
|
|
|
|
for (int i = 0; i < 3; ++i ) {
|
|
|
|
if (desks[i] == desks[i+1])
|
|
|
|
continue;
|
|
|
|
foreach (EffectWindow *w, stack[i]) {
|
2018-11-13 16:18:46 +00:00
|
|
|
auto desktops = w->desktops();
|
|
|
|
desktops.removeOne(desks[i]);
|
|
|
|
desktops.append(desks[i+1]);
|
|
|
|
effects->windowToDesktops(w, desktops);
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
2012-03-12 23:25:10 +00:00
|
|
|
m_managers[(desks[i]-1)*(effects->numScreens()) + w->screen()].unmanage(w);
|
|
|
|
m_managers[(desks[i+1]-1)*(effects->numScreens()) + w->screen()].manage(w);
|
2009-11-15 12:38:26 +00:00
|
|
|
}
|
2009-08-25 14:34:40 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (isUsingPresentWindows()) {
|
|
|
|
for (int i = 0; i < effects->numScreens(); i++) {
|
2012-03-12 23:25:10 +00:00
|
|
|
for (int j = 0; j < 3; ++j) {
|
|
|
|
WindowMotionManager& manager = m_managers[(desks[j]-1)*(effects->numScreens()) + i ];
|
|
|
|
m_proxy->calculateWindowTransformations(manager.managedWindows(), i, manager);
|
|
|
|
}
|
2009-11-15 12:38:26 +00:00
|
|
|
}
|
|
|
|
effects->addRepaintFull();
|
2009-08-25 14:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
setHighlightedDesktop(d);
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (e->type() == QEvent::MouseButtonPress) {
|
|
|
|
if (me->buttons() == Qt::LeftButton) {
|
2011-04-24 20:21:58 +00:00
|
|
|
isValidMove = true;
|
2009-10-19 08:24:25 +00:00
|
|
|
dragStartPos = me->pos();
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
sourceDesktop = posToDesktop(me->pos());
|
|
|
|
bool isDesktop = (me->modifiers() & Qt::ShiftModifier);
|
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
|
|
|
EffectWindow* w = isDesktop ? nullptr : windowAt(me->pos());
|
|
|
|
if (w != nullptr)
|
2009-08-25 14:34:40 +00:00
|
|
|
isDesktop = w->isDesktop();
|
2012-03-12 23:25:10 +00:00
|
|
|
if (isDesktop)
|
|
|
|
m_originalMovingDesktop = posToDesktop(me->pos());
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
else
|
|
|
|
m_originalMovingDesktop = 0;
|
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
|
|
|
if (w != nullptr && !w->isDesktop() && (w->isMovable() || w->isMovableAcrossScreens() || isUsingPresentWindows())) {
|
2011-01-30 14:34:42 +00:00
|
|
|
// Prepare it for moving
|
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
|
|
|
windowMoveDiff = w->pos() - unscalePos(me->pos(), nullptr);
|
2008-08-12 15:22:06 +00:00
|
|
|
windowMove = w;
|
2020-10-30 09:39:00 +00:00
|
|
|
windowMoveElevateTimer->start();
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2020-09-01 05:14:58 +00:00
|
|
|
} else if ((me->buttons() == Qt::MiddleButton || me->buttons() == Qt::RightButton) && windowMove == nullptr) {
|
2011-01-30 14:34:42 +00:00
|
|
|
EffectWindow* w = windowAt(me->pos());
|
2016-11-04 08:28:06 +00:00
|
|
|
if (w && w->isDesktop()) {
|
|
|
|
w = nullptr;
|
|
|
|
}
|
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
|
|
|
if (w != nullptr) {
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
const int desktop = posToDesktop(me->pos());
|
2011-01-30 14:34:42 +00:00
|
|
|
if (w->isOnAllDesktops()) {
|
|
|
|
effects->windowToDesktop(w, desktop);
|
|
|
|
} else {
|
2015-09-14 14:40:31 +00:00
|
|
|
effects->windowToDesktop(w, NET::OnAllDesktops);
|
|
|
|
}
|
|
|
|
const bool isOnAllDesktops = w->isOnAllDesktops();
|
|
|
|
if (isUsingPresentWindows()) {
|
|
|
|
for (int i = 0; i < effects->numberOfDesktops(); i++) {
|
|
|
|
if (i != desktop - 1) {
|
|
|
|
WindowMotionManager& manager = m_managers[ i*effects->numScreens() + w->screen()];
|
|
|
|
if (isOnAllDesktops)
|
2011-01-30 14:34:42 +00:00
|
|
|
manager.manage(w);
|
2015-09-14 14:40:31 +00:00
|
|
|
else
|
|
|
|
manager.unmanage(w);
|
|
|
|
m_proxy->calculateWindowTransformations(manager.managedWindows(), w->screen(), manager);
|
2009-11-15 12:38:26 +00:00
|
|
|
}
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->addRepaintFull();
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (e->type() == QEvent::MouseButtonRelease && me->button() == Qt::LeftButton) {
|
2011-04-24 20:21:58 +00:00
|
|
|
isValidMove = false;
|
2020-10-30 09:39:00 +00:00
|
|
|
if (windowMove) {
|
|
|
|
if (windowMoveElevateTimer->isActive()) {
|
|
|
|
// no need to elevate window, it was just a click
|
|
|
|
windowMoveElevateTimer->stop();
|
|
|
|
}
|
|
|
|
if (clickBehavior == SwitchDesktopAndActivateWindow || wasWindowMove) {
|
|
|
|
// activate window if relevant config is set or window was moved
|
|
|
|
effects->activateWindow(windowMove);
|
|
|
|
}
|
|
|
|
}
|
2015-09-14 17:34:25 +00:00
|
|
|
if (wasWindowMove || wasDesktopMove) { // reset pointer
|
|
|
|
effects->defineCursor(Qt::PointingHandCursor);
|
|
|
|
} else { // click -> exit
|
2012-03-12 23:46:58 +00:00
|
|
|
const int desk = posToDesktop(me->pos());
|
|
|
|
if (desk > effects->numberOfDesktops())
|
|
|
|
return; // don't quit when missing desktop
|
|
|
|
setCurrentDesktop(desk);
|
2011-01-30 14:34:42 +00:00
|
|
|
setActive(false);
|
|
|
|
}
|
|
|
|
if (windowMove) {
|
2015-09-14 17:34:25 +00:00
|
|
|
if (wasWindowMove && isUsingPresentWindows()) {
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
const int targetDesktop = posToDesktop(cursorPos());
|
2015-09-14 17:34:25 +00:00
|
|
|
foreach (const int i, desktopList(windowMove)) {
|
|
|
|
WindowMotionManager& manager = m_managers[(i)*(effects->numScreens()) + windowMove->screen()];
|
|
|
|
manager.manage(windowMove);
|
|
|
|
if (EffectWindow* modal = windowMove->findModal())
|
|
|
|
manager.manage(modal);
|
|
|
|
if (i + 1 == targetDesktop) {
|
|
|
|
// for the desktop the window is dropped on, we use the current geometry
|
|
|
|
manager.setTransformedGeometry(windowMove, moveGeometryToDesktop(targetDesktop));
|
2009-11-15 14:53:33 +00:00
|
|
|
}
|
2015-09-14 17:34:25 +00:00
|
|
|
m_proxy->calculateWindowTransformations(manager.managedWindows(), windowMove->screen(), manager);
|
2009-11-15 14:12:34 +00:00
|
|
|
}
|
2015-09-14 17:34:25 +00:00
|
|
|
effects->addRepaintFull();
|
2008-11-19 07:46:01 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->setElevatedWindow(windowMove, 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
|
|
|
windowMove = nullptr;
|
2015-09-14 17:34:25 +00:00
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
wasWindowMove = false;
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
wasWindowCopy = false;
|
2009-08-25 14:34:40 +00:00
|
|
|
wasDesktopMove = false;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DesktopGridEffect::grabbedKeyboardEvent(QKeyEvent* e)
|
|
|
|
{
|
2011-03-14 21:50:05 +00:00
|
|
|
if (timeline.currentValue() != 1) // Block user input during animations
|
2010-08-28 08:43:12 +00:00
|
|
|
return;
|
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
|
|
|
if (windowMove != nullptr)
|
2010-08-28 14:13:26 +00:00
|
|
|
return;
|
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 (shortcut.contains(e->key() + e->modifiers())) {
|
2009-03-30 11:27:57 +00:00
|
|
|
toggle();
|
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-03-30 11:27:57 +00:00
|
|
|
|
2007-12-08 17:57:53 +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)
|
2007-12-08 17:57:53 +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)
|
2007-12-08 17:57:53 +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()) {
|
|
|
|
setHighlightedDesktop(desktop);
|
|
|
|
setCurrentDesktop(desktop);
|
|
|
|
setActive(false);
|
2007-11-20 16:17:08 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch(e->key()) {
|
|
|
|
// Wrap only on autorepeat
|
|
|
|
case Qt::Key_Left:
|
|
|
|
setHighlightedDesktop(desktopToLeft(highlightedDesktop, !e->isAutoRepeat()));
|
|
|
|
break;
|
|
|
|
case Qt::Key_Right:
|
|
|
|
setHighlightedDesktop(desktopToRight(highlightedDesktop, !e->isAutoRepeat()));
|
|
|
|
break;
|
|
|
|
case Qt::Key_Up:
|
|
|
|
setHighlightedDesktop(desktopUp(highlightedDesktop, !e->isAutoRepeat()));
|
|
|
|
break;
|
|
|
|
case Qt::Key_Down:
|
|
|
|
setHighlightedDesktop(desktopDown(highlightedDesktop, !e->isAutoRepeat()));
|
|
|
|
break;
|
|
|
|
case Qt::Key_Escape:
|
|
|
|
setActive(false);
|
|
|
|
return;
|
|
|
|
case Qt::Key_Enter:
|
|
|
|
case Qt::Key_Return:
|
|
|
|
case Qt::Key_Space:
|
|
|
|
setCurrentDesktop(highlightedDesktop);
|
|
|
|
setActive(false);
|
|
|
|
return;
|
|
|
|
case Qt::Key_Plus:
|
|
|
|
slotAddDesktop();
|
|
|
|
break;
|
|
|
|
case Qt::Key_Minus:
|
|
|
|
slotRemoveDesktop();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2007-11-20 16:17:08 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool DesktopGridEffect::borderActivated(ElectricBorder border)
|
|
|
|
{
|
|
|
|
if (!borderActivate.contains(border))
|
2008-01-29 13:48:26 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this)
|
2008-01-29 13:48:26 +00:00
|
|
|
return true;
|
2009-02-06 14:21:20 +00:00
|
|
|
toggle();
|
|
|
|
return true;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-01-29 13:48:26 +00:00
|
|
|
|
2008-08-12 15:22:06 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Helper functions
|
|
|
|
|
|
|
|
// Transform a point to its position on the scaled grid
|
2011-01-30 14:34:42 +00:00
|
|
|
QPointF DesktopGridEffect::scalePos(const QPoint& pos, int desktop, int screen) const
|
|
|
|
{
|
|
|
|
if (screen == -1)
|
|
|
|
screen = effects->screenNumber(pos);
|
|
|
|
QRect screenGeom = effects->clientArea(ScreenArea, screen, 0);
|
2008-08-12 15:22:06 +00:00
|
|
|
QPoint desktopCell;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (orientation == Qt::Horizontal) {
|
|
|
|
desktopCell.setX((desktop - 1) % gridSize.width() + 1);
|
|
|
|
desktopCell.setY((desktop - 1) / gridSize.width() + 1);
|
|
|
|
} else {
|
|
|
|
desktopCell.setX((desktop - 1) / gridSize.height() + 1);
|
|
|
|
desktopCell.setY((desktop - 1) % gridSize.height() + 1);
|
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2011-03-14 21:50:05 +00:00
|
|
|
double progress = timeline.currentValue();
|
2008-08-12 15:22:06 +00:00
|
|
|
QPointF point(
|
|
|
|
interpolate(
|
|
|
|
(
|
2011-01-30 14:34:42 +00:00
|
|
|
(screenGeom.width() + unscaledBorder[screen]) *(desktopCell.x() - 1)
|
|
|
|
- (screenGeom.width() + unscaledBorder[screen]) *(activeCell.x() - 1)
|
2008-08-12 15:22:06 +00:00
|
|
|
) + pos.x(),
|
|
|
|
(
|
2011-01-30 14:34:42 +00:00
|
|
|
(scaledSize[screen].width() + border) *(desktopCell.x() - 1)
|
2008-08-12 15:22:06 +00:00
|
|
|
+ scaledOffset[screen].x()
|
2011-01-30 14:34:42 +00:00
|
|
|
+ (pos.x() - screenGeom.x()) * scale[screen]
|
2008-08-12 15:22:06 +00:00
|
|
|
),
|
2011-01-30 14:34:42 +00:00
|
|
|
progress),
|
2008-08-12 15:22:06 +00:00
|
|
|
interpolate(
|
|
|
|
(
|
2011-01-30 14:34:42 +00:00
|
|
|
(screenGeom.height() + unscaledBorder[screen]) *(desktopCell.y() - 1)
|
|
|
|
- (screenGeom.height() + unscaledBorder[screen]) *(activeCell.y() - 1)
|
2008-08-12 15:22:06 +00:00
|
|
|
) + pos.y(),
|
|
|
|
(
|
2011-01-30 14:34:42 +00:00
|
|
|
(scaledSize[screen].height() + border) *(desktopCell.y() - 1)
|
2008-08-12 15:22:06 +00:00
|
|
|
+ scaledOffset[screen].y()
|
2011-01-30 14:34:42 +00:00
|
|
|
+ (pos.y() - screenGeom.y()) * scale[screen]
|
2008-08-12 15:22:06 +00:00
|
|
|
),
|
2011-01-30 14:34:42 +00:00
|
|
|
progress)
|
|
|
|
);
|
2008-08-12 15:22:06 +00:00
|
|
|
|
|
|
|
return point;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
|
|
|
// Detransform a point to its position on the full grid
|
|
|
|
// TODO: Doesn't correctly interpolate (Final position is correct though), don't forget to copy to posToDesktop()
|
2011-01-30 14:34:42 +00:00
|
|
|
QPoint DesktopGridEffect::unscalePos(const QPoint& pos, int* desktop) const
|
|
|
|
{
|
|
|
|
int screen = effects->screenNumber(pos);
|
|
|
|
QRect screenGeom = effects->clientArea(ScreenArea, screen, 0);
|
|
|
|
|
2011-03-14 21:50:05 +00:00
|
|
|
//double progress = timeline.currentValue();
|
2008-08-12 15:22:06 +00:00
|
|
|
double scaledX = /*interpolate(
|
|
|
|
( pos.x() - screenGeom.x() + unscaledBorder[screen] / 2.0 ) / ( screenGeom.width() + unscaledBorder[screen] ) + activeCell.x() - 1,*/
|
2011-01-30 14:34:42 +00:00
|
|
|
(pos.x() - scaledOffset[screen].x() + double(border) / 2.0) / (scaledSize[screen].width() + border)/*,
|
2008-08-12 15:22:06 +00:00
|
|
|
progress )*/;
|
|
|
|
double scaledY = /*interpolate(
|
|
|
|
( pos.y() - screenGeom.y() + unscaledBorder[screen] / 2.0 ) / ( screenGeom.height() + unscaledBorder[screen] ) + activeCell.y() - 1,*/
|
2011-01-30 14:34:42 +00:00
|
|
|
(pos.y() - scaledOffset[screen].y() + double(border) / 2.0) / (scaledSize[screen].height() + border)/*,
|
2008-08-12 15:22:06 +00:00
|
|
|
progress )*/;
|
2011-01-30 14:34:42 +00:00
|
|
|
int gx = qBound(0, int(scaledX), gridSize.width() - 1); // Zero-based
|
|
|
|
int gy = qBound(0, int(scaledY), gridSize.height() - 1);
|
2008-08-12 15:22:06 +00:00
|
|
|
scaledX -= gx;
|
|
|
|
scaledY -= gy;
|
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
|
|
|
if (desktop != nullptr) {
|
2011-01-30 14:34:42 +00:00
|
|
|
if (orientation == Qt::Horizontal)
|
2008-08-12 15:22:06 +00:00
|
|
|
*desktop = gy * gridSize.width() + gx + 1;
|
|
|
|
else
|
|
|
|
*desktop = gx * gridSize.height() + gy + 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
|
|
|
return QPoint(
|
2011-01-30 14:34:42 +00:00
|
|
|
qBound(
|
|
|
|
screenGeom.x(),
|
|
|
|
qRound(
|
|
|
|
scaledX * (screenGeom.width() + unscaledBorder[screen])
|
|
|
|
- unscaledBorder[screen] / 2.0
|
|
|
|
+ screenGeom.x()
|
|
|
|
),
|
|
|
|
screenGeom.right()
|
|
|
|
),
|
|
|
|
qBound(
|
|
|
|
screenGeom.y(),
|
|
|
|
qRound(
|
|
|
|
scaledY * (screenGeom.height() + unscaledBorder[screen])
|
|
|
|
- unscaledBorder[screen] / 2.0
|
|
|
|
+ screenGeom.y()
|
|
|
|
),
|
|
|
|
screenGeom.bottom()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
int DesktopGridEffect::posToDesktop(const QPoint& pos) const
|
|
|
|
{
|
|
|
|
// Copied from unscalePos()
|
|
|
|
int screen = effects->screenNumber(pos);
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2012-05-03 09:27:52 +00:00
|
|
|
double scaledX = (pos.x() - scaledOffset[screen].x() + double(border) / 2.0) / (scaledSize[screen].width() + border);
|
|
|
|
double scaledY = (pos.y() - scaledOffset[screen].y() + double(border) / 2.0) / (scaledSize[screen].height() + border);
|
2011-01-30 14:34:42 +00:00
|
|
|
int gx = qBound(0, int(scaledX), gridSize.width() - 1); // Zero-based
|
|
|
|
int gy = qBound(0, int(scaledY), gridSize.height() - 1);
|
|
|
|
if (orientation == Qt::Horizontal)
|
2008-08-12 15:22:06 +00:00
|
|
|
return gy * gridSize.width() + gx + 1;
|
|
|
|
return gx * gridSize.height() + gy + 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
EffectWindow* DesktopGridEffect::windowAt(QPoint pos) const
|
|
|
|
{
|
2008-08-12 15:22:06 +00:00
|
|
|
// Get stacking order top first
|
|
|
|
EffectWindowList windows = effects->stackingOrder();
|
|
|
|
EffectWindowList::Iterator begin = windows.begin();
|
|
|
|
EffectWindowList::Iterator end = windows.end();
|
|
|
|
--end;
|
2011-01-30 14:34:42 +00:00
|
|
|
while (begin < end)
|
|
|
|
qSwap(*begin++, *end--);
|
2008-08-12 15:22:06 +00:00
|
|
|
|
|
|
|
int desktop;
|
2011-01-30 14:34:42 +00:00
|
|
|
pos = unscalePos(pos, &desktop);
|
|
|
|
if (desktop > effects->numberOfDesktops())
|
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
|
|
|
return nullptr;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
|
|
|
const int screen = effects->screenNumber(pos);
|
2009-11-15 12:38:26 +00:00
|
|
|
EffectWindow *w =
|
2011-01-30 14:34:42 +00:00
|
|
|
m_managers.at((desktop - 1) * (effects->numScreens()) + screen).windowAtPoint(pos, false);
|
|
|
|
if (w)
|
2008-08-12 15:22:06 +00:00
|
|
|
return w;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (EffectWindow * w, windows) {
|
|
|
|
if (w->isOnDesktop(desktop) && w->isDesktop() && w->geometry().contains(pos))
|
2009-11-15 12:38:26 +00:00
|
|
|
return w;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
|
|
|
foreach (EffectWindow * w, windows) {
|
2018-07-11 12:40:28 +00:00
|
|
|
if (w->isOnDesktop(desktop) && w->isOnCurrentActivity() && !w->isMinimized() && w->geometry().contains(pos))
|
2009-11-15 12:38:26 +00:00
|
|
|
return w;
|
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
}
|
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
|
|
|
return nullptr;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DesktopGridEffect::setCurrentDesktop(int desktop)
|
|
|
|
{
|
|
|
|
if (orientation == Qt::Horizontal) {
|
|
|
|
activeCell.setX((desktop - 1) % gridSize.width() + 1);
|
|
|
|
activeCell.setY((desktop - 1) / gridSize.width() + 1);
|
|
|
|
} else {
|
|
|
|
activeCell.setX((desktop - 1) / gridSize.height() + 1);
|
|
|
|
activeCell.setY((desktop - 1) % gridSize.height() + 1);
|
2008-08-12 15:22:06 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (effects->currentDesktop() != desktop)
|
|
|
|
effects->setCurrentDesktop(desktop);
|
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DesktopGridEffect::setHighlightedDesktop(int d)
|
|
|
|
{
|
|
|
|
if (d == highlightedDesktop || d <= 0 || d > effects->numberOfDesktops())
|
2008-08-12 15:22:06 +00:00
|
|
|
return;
|
2013-11-16 15:37:22 +00:00
|
|
|
if (highlightedDesktop > 0 && highlightedDesktop <= hoverTimeline.count())
|
|
|
|
hoverTimeline[highlightedDesktop-1]->setCurrentTime(qMin(hoverTimeline[highlightedDesktop-1]->currentTime(),
|
|
|
|
hoverTimeline[highlightedDesktop-1]->duration()));
|
2008-08-12 15:22:06 +00:00
|
|
|
highlightedDesktop = d;
|
2013-11-16 15:37:22 +00:00
|
|
|
if (highlightedDesktop <= hoverTimeline.count())
|
|
|
|
hoverTimeline[highlightedDesktop-1]->setCurrentTime(qMax(hoverTimeline[highlightedDesktop-1]->currentTime(), 0));
|
2008-08-12 15:22:06 +00:00
|
|
|
effects->addRepaintFull();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
int DesktopGridEffect::desktopToRight(int desktop, bool wrap) const
|
|
|
|
{
|
|
|
|
// Copied from Workspace::desktopToRight()
|
2008-12-13 09:20:02 +00:00
|
|
|
int dt = desktop - 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (orientation == Qt::Vertical) {
|
2008-12-13 09:20:02 +00:00
|
|
|
dt += gridSize.height();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (dt >= effects->numberOfDesktops()) {
|
|
|
|
if (wrap)
|
2008-12-13 09:20:02 +00:00
|
|
|
dt -= effects->numberOfDesktops();
|
|
|
|
else
|
|
|
|
return desktop;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
|
|
|
int d = (dt % gridSize.width()) + 1;
|
|
|
|
if (d >= gridSize.width()) {
|
|
|
|
if (wrap)
|
2008-12-13 09:20:02 +00:00
|
|
|
d -= gridSize.width();
|
|
|
|
else
|
|
|
|
return desktop;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
dt = dt - (dt % gridSize.width()) + d;
|
2008-12-13 09:20:02 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return dt + 1;
|
|
|
|
}
|
2008-12-13 09:20:02 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
int DesktopGridEffect::desktopToLeft(int desktop, bool wrap) const
|
|
|
|
{
|
|
|
|
// Copied from Workspace::desktopToLeft()
|
2008-12-13 09:20:02 +00:00
|
|
|
int dt = desktop - 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (orientation == Qt::Vertical) {
|
2008-12-13 09:20:02 +00:00
|
|
|
dt -= gridSize.height();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (dt < 0) {
|
|
|
|
if (wrap)
|
2008-12-13 09:20:02 +00:00
|
|
|
dt += effects->numberOfDesktops();
|
|
|
|
else
|
|
|
|
return desktop;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
|
|
|
int d = (dt % gridSize.width()) - 1;
|
|
|
|
if (d < 0) {
|
|
|
|
if (wrap)
|
2008-12-13 09:20:02 +00:00
|
|
|
d += gridSize.width();
|
|
|
|
else
|
|
|
|
return desktop;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
dt = dt - (dt % gridSize.width()) + d;
|
2008-12-13 09:20:02 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return dt + 1;
|
|
|
|
}
|
2008-12-13 09:20:02 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
int DesktopGridEffect::desktopUp(int desktop, bool wrap) const
|
|
|
|
{
|
|
|
|
// Copied from Workspace::desktopUp()
|
2008-12-13 09:20:02 +00:00
|
|
|
int dt = desktop - 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (orientation == Qt::Horizontal) {
|
2008-12-13 09:20:02 +00:00
|
|
|
dt -= gridSize.width();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (dt < 0) {
|
|
|
|
if (wrap)
|
2008-12-13 09:20:02 +00:00
|
|
|
dt += effects->numberOfDesktops();
|
|
|
|
else
|
|
|
|
return desktop;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
|
|
|
int d = (dt % gridSize.height()) - 1;
|
|
|
|
if (d < 0) {
|
|
|
|
if (wrap)
|
2008-12-13 09:20:02 +00:00
|
|
|
d += gridSize.height();
|
|
|
|
else
|
|
|
|
return desktop;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
dt = dt - (dt % gridSize.height()) + d;
|
2008-12-13 09:20:02 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return dt + 1;
|
|
|
|
}
|
2008-12-13 09:20:02 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
int DesktopGridEffect::desktopDown(int desktop, bool wrap) const
|
|
|
|
{
|
|
|
|
// Copied from Workspace::desktopDown()
|
2008-12-13 09:20:02 +00:00
|
|
|
int dt = desktop - 1;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (orientation == Qt::Horizontal) {
|
2008-12-13 09:20:02 +00:00
|
|
|
dt += gridSize.width();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (dt >= effects->numberOfDesktops()) {
|
|
|
|
if (wrap)
|
2008-12-13 09:20:02 +00:00
|
|
|
dt -= effects->numberOfDesktops();
|
|
|
|
else
|
|
|
|
return desktop;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
|
|
|
int d = (dt % gridSize.height()) + 1;
|
|
|
|
if (d >= gridSize.height()) {
|
|
|
|
if (wrap)
|
2008-12-13 09:20:02 +00:00
|
|
|
d -= gridSize.height();
|
|
|
|
else
|
|
|
|
return desktop;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
dt = dt - (dt % gridSize.height()) + d;
|
2008-12-13 09:20:02 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return dt + 1;
|
|
|
|
}
|
2008-12-13 09:20:02 +00:00
|
|
|
|
2008-08-12 15:22:06 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Activation
|
|
|
|
|
|
|
|
void DesktopGridEffect::toggle()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
setActive(!activated);
|
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DesktopGridEffect::setActive(bool active)
|
|
|
|
{
|
|
|
|
if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this)
|
2008-08-12 15:22:06 +00:00
|
|
|
return; // Only one fullscreen effect at a time thanks
|
2011-01-30 14:34:42 +00:00
|
|
|
if (active && isMotionManagerMovingWindows())
|
2010-01-18 18:45:42 +00:00
|
|
|
return; // Still moving windows from last usage - don't activate
|
2011-01-30 14:34:42 +00:00
|
|
|
if (activated == active)
|
2008-08-12 15:22:06 +00:00
|
|
|
return; // Already in that state
|
|
|
|
|
|
|
|
activated = active;
|
2015-02-18 01:09:00 +00:00
|
|
|
if (activated) {
|
|
|
|
effects->setShowingDesktop(false);
|
|
|
|
if (timeline.currentValue() == 0)
|
|
|
|
setup();
|
|
|
|
} else {
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
2009-11-15 12:38:26 +00:00
|
|
|
QList<WindowMotionManager>::iterator it;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (it = m_managers.begin(); it != m_managers.end(); ++it) {
|
|
|
|
foreach (EffectWindow * w, (*it).managedWindows()) {
|
|
|
|
(*it).moveWindow(w, w->geometry());
|
2009-11-15 12:38:26 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2015-08-28 20:52:03 +00:00
|
|
|
QTimer::singleShot(zoomDuration + 1, this,
|
|
|
|
[this] {
|
|
|
|
if (activated)
|
|
|
|
return;
|
2020-01-22 13:10:47 +00:00
|
|
|
for (EffectQuickScene *view : m_desktopButtons) {
|
2015-08-28 20:52:03 +00:00
|
|
|
view->hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2011-01-30 14:34:42 +00:00
|
|
|
setHighlightedDesktop(effects->currentDesktop()); // Ensure selected desktop is highlighted
|
2008-08-12 15:22:06 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->addRepaintFull();
|
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
|
|
|
void DesktopGridEffect::setup()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2014-03-26 17:03:54 +00:00
|
|
|
if (!isActive())
|
|
|
|
return;
|
|
|
|
if (!keyboardGrab) {
|
|
|
|
keyboardGrab = effects->grabKeyboard(this);
|
|
|
|
effects->startMouseInterception(this, Qt::PointingHandCursor);
|
|
|
|
effects->setActiveFullScreenEffect(this);
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
setHighlightedDesktop(effects->currentDesktop());
|
2008-08-12 15:22:06 +00:00
|
|
|
|
|
|
|
// Soft highlighting
|
2011-03-14 21:50:05 +00:00
|
|
|
qDeleteAll(hoverTimeline);
|
2008-08-12 15:22:06 +00:00
|
|
|
hoverTimeline.clear();
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i < effects->numberOfDesktops(); i++) {
|
2012-11-25 18:00:31 +00:00
|
|
|
QTimeLine *newTimeline = new QTimeLine(zoomDuration, this);
|
2020-09-09 12:53:13 +00:00
|
|
|
newTimeline->setEasingCurve(QEasingCurve::InOutSine);
|
2011-01-30 14:34:42 +00:00
|
|
|
hoverTimeline.append(newTimeline);
|
|
|
|
}
|
2011-03-14 21:50:05 +00:00
|
|
|
hoverTimeline[effects->currentDesktop() - 1]->setCurrentTime(hoverTimeline[effects->currentDesktop() - 1]->duration());
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2009-02-22 13:04:16 +00:00
|
|
|
// Create desktop name textures if enabled
|
2011-01-30 14:34:42 +00:00
|
|
|
if (desktopNameAlignment) {
|
2009-02-22 13:04:16 +00:00
|
|
|
QFont font;
|
2011-01-30 14:34:42 +00:00
|
|
|
font.setBold(true);
|
|
|
|
font.setPointSize(12);
|
|
|
|
for (int i = 0; i < effects->numberOfDesktops(); i++) {
|
|
|
|
EffectFrame* frame = effects->effectFrame(EffectFrameUnstyled, false);
|
|
|
|
frame->setFont(font);
|
|
|
|
frame->setText(effects->desktopName(i + 1));
|
|
|
|
frame->setAlignment(desktopNameAlignment);
|
|
|
|
desktopNames.append(frame);
|
2009-02-22 13:04:16 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
setupGrid();
|
2011-01-30 14:34:42 +00:00
|
|
|
setCurrentDesktop(effects->currentDesktop());
|
2009-02-22 13:04:16 +00:00
|
|
|
|
2010-03-28 09:05:36 +00:00
|
|
|
// setup the motion managers
|
2020-10-30 09:39:00 +00:00
|
|
|
if (clickBehavior == SwitchDesktopAndActivateWindow)
|
2014-04-03 09:04:28 +00:00
|
|
|
m_proxy = static_cast<PresentWindowsEffectProxy*>(effects->getProxy(BuiltInEffects::nameForEffect(BuiltInEffect::PresentWindows)));
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
2015-08-28 05:50:20 +00:00
|
|
|
m_proxy->reCreateGrids(); // revalidation on multiscreen, bug #351724
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 1; i <= effects->numberOfDesktops(); i++) {
|
|
|
|
for (int j = 0; j < effects->numScreens(); j++) {
|
2010-03-28 09:05:36 +00:00
|
|
|
WindowMotionManager manager;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (EffectWindow * w, effects->stackingOrder()) {
|
2012-09-09 12:24:06 +00:00
|
|
|
if (w->isOnDesktop(i) && w->screen() == j &&isRelevantWithPresentWindows(w)) {
|
2011-01-30 14:34:42 +00:00
|
|
|
manager.manage(w);
|
2010-03-28 09:05:36 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
m_proxy->calculateWindowTransformations(manager.managedWindows(), j, manager);
|
|
|
|
m_managers.append(manager);
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2015-05-06 21:18:39 +00:00
|
|
|
|
2020-01-22 13:10:47 +00:00
|
|
|
auto it = m_desktopButtons.begin();
|
2015-09-14 08:19:16 +00:00
|
|
|
const int n = DesktopGridConfig::showAddRemove() ? effects->numScreens() : 0;
|
|
|
|
for (int i = 0; i < n; ++i) {
|
2020-01-22 13:10:47 +00:00
|
|
|
EffectQuickScene *view;
|
|
|
|
QSize size;
|
|
|
|
if (it == m_desktopButtons.end()) {
|
|
|
|
view = new EffectQuickScene(this);
|
|
|
|
|
|
|
|
connect(view, &EffectQuickView::repaintNeeded, this, []() {
|
|
|
|
effects->addRepaintFull();
|
|
|
|
});
|
|
|
|
|
|
|
|
view->rootContext()->setContextProperty("effects", effects);
|
|
|
|
view->setSource(QUrl(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/effects/desktopgrid/main.qml"))));
|
|
|
|
|
|
|
|
QQuickItem *rootItem = view->rootItem();
|
|
|
|
if (!rootItem) {
|
|
|
|
delete view;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_desktopButtons.append(view);
|
|
|
|
it = m_desktopButtons.end(); // changed through insert!
|
|
|
|
|
|
|
|
size = QSize(rootItem->implicitWidth(), rootItem->implicitHeight());
|
2015-05-06 21:18:39 +00:00
|
|
|
} else {
|
2015-09-14 08:57:02 +00:00
|
|
|
view = *it;
|
2015-05-06 21:18:39 +00:00
|
|
|
++it;
|
2020-01-22 13:10:47 +00:00
|
|
|
size = view->size();
|
2015-05-06 21:18:39 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
const QRect screenRect = effects->clientArea(FullScreenArea, i, 1);
|
2015-06-20 23:23:25 +00:00
|
|
|
view->show(); // pseudo show must happen before geometry changes
|
2020-01-22 13:10:47 +00:00
|
|
|
const QPoint position(screenRect.right() - border/3 - size.width(),
|
|
|
|
screenRect.bottom() - border/3 - size.height());
|
|
|
|
view->setGeometry(QRect(position, size));
|
2015-05-06 21:18:39 +00:00
|
|
|
}
|
2020-01-22 13:10:47 +00:00
|
|
|
while (it != m_desktopButtons.end()) {
|
2015-09-14 08:57:02 +00:00
|
|
|
(*it)->deleteLater();
|
2020-01-22 13:10:47 +00:00
|
|
|
it = m_desktopButtons.erase(it);
|
2010-03-28 09:05:36 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
|
|
|
void DesktopGridEffect::setupGrid()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2008-08-12 15:22:06 +00:00
|
|
|
// We need these variables for every paint so lets cache them
|
2008-09-04 14:37:07 +00:00
|
|
|
int x, y;
|
|
|
|
int numDesktops = effects->numberOfDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
switch(layoutMode) {
|
|
|
|
default:
|
|
|
|
case LayoutPager:
|
|
|
|
orientation = Qt::Horizontal;
|
|
|
|
gridSize = effects->desktopGridSize();
|
|
|
|
// sanity check: pager may report incorrect size in case of one desktop
|
|
|
|
if (numDesktops == 1) {
|
|
|
|
gridSize = QSize(1, 1);
|
2008-08-12 15:22:06 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
break;
|
|
|
|
case LayoutAutomatic:
|
|
|
|
y = sqrt(float(numDesktops)) + 0.5;
|
|
|
|
x = float(numDesktops) / float(y) + 0.5;
|
|
|
|
if (x * y < numDesktops)
|
|
|
|
x++;
|
|
|
|
orientation = Qt::Horizontal;
|
|
|
|
gridSize.setWidth(x);
|
|
|
|
gridSize.setHeight(y);
|
|
|
|
break;
|
|
|
|
case LayoutCustom:
|
|
|
|
orientation = Qt::Horizontal;
|
|
|
|
gridSize.setWidth(ceil(effects->numberOfDesktops() / double(customLayoutRows)));
|
|
|
|
gridSize.setHeight(customLayoutRows);
|
|
|
|
break;
|
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
scale.clear();
|
|
|
|
unscaledBorder.clear();
|
|
|
|
scaledSize.clear();
|
|
|
|
scaledOffset.clear();
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i < effects->numScreens(); i++) {
|
|
|
|
QRect geom = effects->clientArea(ScreenArea, i, 0);
|
2008-08-12 15:22:06 +00:00
|
|
|
double sScale;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (gridSize.width() > gridSize.height())
|
|
|
|
sScale = (geom.width() - border * (gridSize.width() + 1)) / double(geom.width() * gridSize.width());
|
2008-08-12 15:22:06 +00:00
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
sScale = (geom.height() - border * (gridSize.height() + 1)) / double(geom.height() * gridSize.height());
|
2008-08-12 15:22:06 +00:00
|
|
|
double sBorder = border / sScale;
|
|
|
|
QSizeF size(
|
2011-01-30 14:34:42 +00:00
|
|
|
double(geom.width()) * sScale,
|
|
|
|
double(geom.height()) * sScale
|
|
|
|
);
|
2008-08-12 15:22:06 +00:00
|
|
|
QPointF offset(
|
2011-01-30 14:34:42 +00:00
|
|
|
geom.x() + (geom.width() - size.width() * gridSize.width() - border *(gridSize.width() - 1)) / 2.0,
|
|
|
|
geom.y() + (geom.height() - size.height() * gridSize.height() - border *(gridSize.height() - 1)) / 2.0
|
|
|
|
);
|
|
|
|
scale.append(sScale);
|
|
|
|
unscaledBorder.append(sBorder);
|
|
|
|
scaledSize.append(size);
|
|
|
|
scaledOffset.append(offset);
|
2008-08-12 15:22:06 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
|
|
|
void DesktopGridEffect::finish()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (desktopNameAlignment) {
|
2010-03-28 09:05:36 +00:00
|
|
|
qDeleteAll(desktopNames);
|
|
|
|
desktopNames.clear();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-22 13:04:16 +00:00
|
|
|
|
2020-10-30 09:39:00 +00:00
|
|
|
windowMoveElevateTimer->stop();
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (keyboardGrab)
|
2008-08-12 15:22:06 +00:00
|
|
|
effects->ungrabKeyboard();
|
|
|
|
keyboardGrab = false;
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
lastPresentTime = std::chrono::milliseconds::zero();
|
2013-04-24 14:51:04 +00:00
|
|
|
effects->stopMouseInterception(this);
|
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);
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
|
|
|
while (!m_managers.isEmpty()) {
|
2009-11-15 12:38:26 +00:00
|
|
|
m_managers.first().unmanageAll();
|
|
|
|
m_managers.removeFirst();
|
|
|
|
}
|
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_proxy = nullptr;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
}
|
2008-08-12 15:22:06 +00:00
|
|
|
|
2013-08-14 19:13:12 +00:00
|
|
|
void DesktopGridEffect::globalShortcutChanged(QAction *action, const QKeySequence& seq)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-09-09 07:02:19 +00:00
|
|
|
if (action->objectName() != QStringLiteral("ShowDesktopGrid")) {
|
|
|
|
return;
|
|
|
|
}
|
2013-08-14 19:13:12 +00:00
|
|
|
shortcut.clear();
|
|
|
|
shortcut.append(seq);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-03-30 11:27:57 +00:00
|
|
|
|
2011-08-27 09:21:31 +00:00
|
|
|
bool DesktopGridEffect::isMotionManagerMovingWindows() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (isUsingPresentWindows()) {
|
2011-08-27 09:21:31 +00:00
|
|
|
QList<WindowMotionManager>::const_iterator it;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (it = m_managers.begin(); it != m_managers.end(); ++it) {
|
|
|
|
if ((*it).areWindowsMoving())
|
2009-11-15 12:38:26 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return false;
|
|
|
|
}
|
2009-11-15 12:38:26 +00:00
|
|
|
|
|
|
|
bool DesktopGridEffect::isUsingPresentWindows() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
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
|
|
|
return (m_proxy != nullptr);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-11-15 12:38:26 +00:00
|
|
|
|
2010-03-18 09:27:01 +00:00
|
|
|
// transforms the geometry of the moved window to a geometry on the desktop
|
|
|
|
// internal method only used when a window is dropped onto a desktop
|
2011-01-30 14:34:42 +00:00
|
|
|
QRectF DesktopGridEffect::moveGeometryToDesktop(int desktop) const
|
|
|
|
{
|
|
|
|
QPointF point = unscalePos(m_windowMoveGeometry.topLeft() + cursorPos() - m_windowMoveStartPoint);
|
|
|
|
const double scaleFactor = scale[ windowMove->screen()];
|
|
|
|
if (posToDesktop(m_windowMoveGeometry.topLeft() + cursorPos() - m_windowMoveStartPoint) != desktop) {
|
2010-03-18 09:27:01 +00:00
|
|
|
// topLeft is not on the desktop - check other corners
|
|
|
|
// if all corners are not on the desktop the window is bigger than the desktop - no matter what it will look strange
|
2011-01-30 14:34:42 +00:00
|
|
|
if (posToDesktop(m_windowMoveGeometry.topRight() + cursorPos() - m_windowMoveStartPoint) == desktop) {
|
|
|
|
point = unscalePos(m_windowMoveGeometry.topRight() + cursorPos() - m_windowMoveStartPoint) -
|
|
|
|
QPointF(m_windowMoveGeometry.width(), 0) / scaleFactor;
|
|
|
|
} else if (posToDesktop(m_windowMoveGeometry.bottomLeft() + cursorPos() - m_windowMoveStartPoint) == desktop) {
|
|
|
|
point = unscalePos(m_windowMoveGeometry.bottomLeft() + cursorPos() - m_windowMoveStartPoint) -
|
|
|
|
QPointF(0, m_windowMoveGeometry.height()) / scaleFactor;
|
|
|
|
} else if (posToDesktop(m_windowMoveGeometry.bottomRight() + cursorPos() - m_windowMoveStartPoint) == desktop) {
|
|
|
|
point = unscalePos(m_windowMoveGeometry.bottomRight() + cursorPos() - m_windowMoveStartPoint) -
|
|
|
|
QPointF(m_windowMoveGeometry.width(), m_windowMoveGeometry.height()) / scaleFactor;
|
2010-03-18 09:27:01 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return QRectF(point, m_windowMoveGeometry.size() / scaleFactor);
|
|
|
|
}
|
2010-03-18 09:27:01 +00:00
|
|
|
|
2010-03-28 09:05:36 +00:00
|
|
|
void DesktopGridEffect::slotAddDesktop()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
effects->setNumberOfDesktops(effects->numberOfDesktops() + 1);
|
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
|
|
|
void DesktopGridEffect::slotRemoveDesktop()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
effects->setNumberOfDesktops(effects->numberOfDesktops() - 1);
|
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
2012-11-16 07:23:47 +00:00
|
|
|
void DesktopGridEffect::slotNumberDesktopsChanged(uint old)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (!activated)
|
2010-03-28 09:05:36 +00:00
|
|
|
return;
|
2013-01-08 10:04:07 +00:00
|
|
|
const uint desktop = effects->numberOfDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (old < desktop)
|
|
|
|
desktopsAdded(old);
|
|
|
|
else
|
|
|
|
desktopsRemoved(old);
|
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DesktopGridEffect::desktopsAdded(int old)
|
|
|
|
{
|
2010-03-28 09:05:36 +00:00
|
|
|
const int desktop = effects->numberOfDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = old; i <= effects->numberOfDesktops(); i++) {
|
2010-03-28 09:05:36 +00:00
|
|
|
// add a timeline for the new desktop
|
2012-11-25 18:00:31 +00:00
|
|
|
QTimeLine *newTimeline = new QTimeLine(zoomDuration, this);
|
2020-09-09 12:53:13 +00:00
|
|
|
newTimeline->setEasingCurve(QEasingCurve::InOutSine);
|
2011-01-30 14:34:42 +00:00
|
|
|
hoverTimeline.append(newTimeline);
|
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
|
|
|
// Create desktop name textures if enabled
|
2011-01-30 14:34:42 +00:00
|
|
|
if (desktopNameAlignment) {
|
2010-03-28 09:05:36 +00:00
|
|
|
QFont font;
|
2011-01-30 14:34:42 +00:00
|
|
|
font.setBold(true);
|
|
|
|
font.setPointSize(12);
|
|
|
|
for (int i = old; i < desktop; i++) {
|
|
|
|
EffectFrame* frame = effects->effectFrame(EffectFrameUnstyled, false);
|
|
|
|
frame->setFont(font);
|
|
|
|
frame->setText(effects->desktopName(i + 1));
|
|
|
|
frame->setAlignment(desktopNameAlignment);
|
|
|
|
desktopNames.append(frame);
|
2010-03-28 09:05:36 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
2012-09-09 12:24:06 +00:00
|
|
|
for (int i = old+1; i <= effects->numberOfDesktops(); ++i) {
|
|
|
|
for (int j = 0; j < effects->numScreens(); ++j) {
|
2010-03-28 09:05:36 +00:00
|
|
|
WindowMotionManager manager;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (EffectWindow * w, effects->stackingOrder()) {
|
2012-09-09 12:24:06 +00:00
|
|
|
if (w->isOnDesktop(i) && w->screen() == j &&isRelevantWithPresentWindows(w)) {
|
2011-01-30 14:34:42 +00:00
|
|
|
manager.manage(w);
|
2010-03-28 09:05:36 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
m_proxy->calculateWindowTransformations(manager.managedWindows(), j, manager);
|
|
|
|
m_managers.append(manager);
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
|
|
|
setupGrid();
|
|
|
|
|
|
|
|
// and repaint
|
|
|
|
effects->addRepaintFull();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DesktopGridEffect::desktopsRemoved(int old)
|
|
|
|
{
|
2010-03-28 09:05:36 +00:00
|
|
|
const int desktop = effects->numberOfDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = desktop; i < old; i++) {
|
2011-03-14 21:50:05 +00:00
|
|
|
delete hoverTimeline.takeLast();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (desktopNameAlignment) {
|
2010-03-28 09:05:36 +00:00
|
|
|
delete desktopNames.last();
|
|
|
|
desktopNames.removeLast();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (isUsingPresentWindows()) {
|
|
|
|
for (int j = 0; j < effects->numScreens(); ++j) {
|
2010-03-28 09:05:36 +00:00
|
|
|
WindowMotionManager& manager = m_managers.last();
|
|
|
|
manager.unmanageAll();
|
|
|
|
m_managers.removeLast();
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
// add removed windows to the last desktop
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isUsingPresentWindows()) {
|
|
|
|
for (int j = 0; j < effects->numScreens(); ++j) {
|
|
|
|
WindowMotionManager& manager = m_managers[(desktop-1)*(effects->numScreens())+j ];
|
|
|
|
foreach (EffectWindow * w, effects->stackingOrder()) {
|
2012-09-09 12:24:06 +00:00
|
|
|
if (manager.isManaging(w))
|
|
|
|
continue;
|
|
|
|
if (w->isOnDesktop(desktop) && w->screen() == j && isRelevantWithPresentWindows(w)) {
|
2011-01-30 14:34:42 +00:00
|
|
|
manager.manage(w);
|
2010-03-28 09:05:36 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
m_proxy->calculateWindowTransformations(manager.managedWindows(), j, manager);
|
2010-03-28 09:05:36 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:05:36 +00:00
|
|
|
|
|
|
|
setupGrid();
|
|
|
|
|
|
|
|
// and repaint
|
|
|
|
effects->addRepaintFull();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
//TODO: kill this function? or at least keep a consistent numeration with desktops starting from 1
|
2015-09-14 14:40:31 +00:00
|
|
|
QVector<int> DesktopGridEffect::desktopList(const EffectWindow *w) const
|
|
|
|
{
|
|
|
|
if (w->isOnAllDesktops()) {
|
|
|
|
static QVector<int> allDesktops;
|
|
|
|
if (allDesktops.count() != effects->numberOfDesktops()) {
|
|
|
|
allDesktops.resize(effects->numberOfDesktops());
|
|
|
|
for (int i = 0; i < effects->numberOfDesktops(); ++i)
|
|
|
|
allDesktops[i] = i;
|
|
|
|
}
|
|
|
|
return allDesktops;
|
|
|
|
}
|
|
|
|
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
QVector<int> desks;
|
|
|
|
desks.resize(w->desktops().count());
|
|
|
|
int i = 0;
|
|
|
|
for (const int desk : w->desktops()) {
|
|
|
|
desks[i++] = desk-1;
|
2015-09-14 14:40:31 +00:00
|
|
|
}
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
return desks;
|
2015-09-14 14:40:31 +00:00
|
|
|
}
|
|
|
|
|
2011-08-27 09:21:31 +00:00
|
|
|
bool DesktopGridEffect::isActive() const
|
|
|
|
{
|
2015-11-20 10:17:16 +00:00
|
|
|
return (timeline.currentValue() != 0 || activated || (isUsingPresentWindows() && isMotionManagerMovingWindows())) && !effects->isScreenLocked();
|
2011-08-27 09:21:31 +00:00
|
|
|
}
|
|
|
|
|
2012-09-09 12:24:06 +00:00
|
|
|
bool DesktopGridEffect::isRelevantWithPresentWindows(EffectWindow *w) const
|
|
|
|
{
|
2018-10-29 12:29:47 +00:00
|
|
|
if (w->isSpecialWindow() || w->isUtility()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (w->isSkipSwitcher()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (w->isDeleted()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!w->acceptsFocus()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!w->isOnCurrentActivity()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2012-09-09 12:24:06 +00:00
|
|
|
}
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
} // namespace
|
|
|
|
|