KWin
Loading...
Searching...
No Matches
overvieweffect.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "overvieweffect.h"
9#include "overviewconfig.h"
10
11#include <KGlobalAccel>
12#include <KLocalizedString>
13
14#include <QAction>
15#include <QDebug>
16#include <QQuickItem>
17#include <QTimer>
18
19namespace KWin
20{
21
23 // manages the transition between inactive -> overview
24 : m_overviewState(new EffectTogglableState(this))
25 // manages the transition between overview -> grid
26 , m_transitionState(new EffectTogglableState(this))
27 // manages the transition betwee inactive -> overview
28 , m_gridState(new EffectTogglableState(this))
29 , m_border(new EffectTogglableTouchBorder(m_overviewState))
30 , m_shutdownTimer(new QTimer(this))
31{
32 auto gesture = new EffectTogglableGesture(m_overviewState);
33 gesture->addTouchpadSwipeGesture(SwipeDirection::Up, 4);
34 gesture->addTouchscreenSwipeGesture(SwipeDirection::Up, 3);
35
36 auto transitionGesture = new EffectTogglableGesture(m_transitionState);
37 transitionGesture->addTouchpadSwipeGesture(SwipeDirection::Up, 4);
38 transitionGesture->addTouchscreenSwipeGesture(SwipeDirection::Up, 3);
39 m_transitionState->stop();
40
41 auto gridGesture = new EffectTogglableGesture(m_gridState);
42 gridGesture->addTouchpadSwipeGesture(SwipeDirection::Down, 4);
43 gridGesture->addTouchscreenSwipeGesture(SwipeDirection::Down, 3);
44
47
48 connect(m_overviewState, &EffectTogglableState::statusChanged, this, [this](EffectTogglableState::Status status) {
50 m_searchText = QString();
51 setRunning(true);
52 m_gridState->stop();
53 }
55 m_transitionState->deactivate();
56 }
58 m_transitionState->stop();
59 }
61 m_gridState->deactivate();
62 deactivate();
63 }
64 });
65
66 connect(m_transitionState, &EffectTogglableState::statusChanged, this, [this](EffectTogglableState::Status status) {
68 m_overviewState->stop();
69 }
71 m_overviewState->activate();
72 }
74 m_gridState->activate();
75 }
77 m_gridState->stop();
78 }
79 });
80
81 connect(m_gridState, &EffectTogglableState::statusChanged, this, [this](EffectTogglableState::Status status) {
83 m_searchText = QString();
84 setRunning(true);
85 m_overviewState->stop();
86 }
88 m_overviewState->deactivate();
89 deactivate();
90 }
92 m_transitionState->activate();
93 }
95 m_transitionState->stop();
96 }
97 });
98
101
104
105 connect(effects, &EffectsHandler::desktopChanging, this, [this](VirtualDesktop *old, QPointF desktopOffset, EffectWindow *with) {
106 m_desktopOffset = desktopOffset;
107 Q_EMIT desktopOffsetChanged();
108 });
109 connect(effects, &EffectsHandler::desktopChanged, this, [this](VirtualDesktop *old, VirtualDesktop *current, EffectWindow *with) {
110 m_desktopOffset = QPointF(0, 0);
111 Q_EMIT desktopOffsetChanged();
112 });
113 connect(effects, &EffectsHandler::desktopChangingCancelled, this, [this]() {
114 m_desktopOffset = QPointF(0, 0);
115 Q_EMIT desktopOffsetChanged();
116 });
117
118 m_shutdownTimer->setSingleShot(true);
119 connect(m_shutdownTimer, &QTimer::timeout, this, &OverviewEffect::realDeactivate);
120
121 auto cycleAction = new QAction(this);
122 connect(cycleAction, &QAction::triggered, this, &OverviewEffect::cycle);
123 cycleAction->setObjectName(QStringLiteral("Cycle Overview"));
124 cycleAction->setText(i18nc("@action Grid View and Overview are the name of KWin effects", "Cycle through Overview and Grid View"));
125 KGlobalAccel::self()->setDefaultShortcut(cycleAction, {});
126 KGlobalAccel::self()->setShortcut(cycleAction, {});
127 m_cycleShortcut = KGlobalAccel::self()->shortcut(cycleAction);
128
129 auto reverseCycleAction = new QAction(this);
130 connect(reverseCycleAction, &QAction::triggered, this, &OverviewEffect::reverseCycle);
131 reverseCycleAction->setObjectName(QStringLiteral("Cycle Overview Opposite"));
132 reverseCycleAction->setText(i18nc("@action Grid View and Overview are the name of KWin effects", "Cycle through Grid View and Overview"));
133 KGlobalAccel::self()->setDefaultShortcut(reverseCycleAction, {});
134 KGlobalAccel::self()->setShortcut(reverseCycleAction, {});
135 m_reverseCycleShortcut = KGlobalAccel::self()->shortcut(reverseCycleAction);
136
137 const QKeySequence defaultOverviewShortcut = Qt::META | Qt::Key_W;
138 auto overviewAction = m_overviewState->toggleAction();
139 overviewAction->setObjectName(QStringLiteral("Overview"));
140 overviewAction->setText(i18nc("@action Overview is the name of a Kwin effect", "Toggle Overview"));
141 KGlobalAccel::self()->setDefaultShortcut(overviewAction, {defaultOverviewShortcut});
142 KGlobalAccel::self()->setShortcut(overviewAction, {defaultOverviewShortcut});
143 m_overviewShortcut = KGlobalAccel::self()->shortcut(overviewAction);
144
145 const QKeySequence defaultGridShortcut = Qt::META | Qt::Key_G;
146 auto gridAction = m_gridState->toggleAction();
147 gridAction->setObjectName(QStringLiteral("Grid View"));
148 gridAction->setText(i18nc("@action Grid view is the name of a Kwin effect", "Toggle Grid View"));
149 KGlobalAccel::self()->setDefaultShortcut(gridAction, {defaultGridShortcut});
150 KGlobalAccel::self()->setShortcut(gridAction, {defaultGridShortcut});
151 m_overviewShortcut = KGlobalAccel::self()->shortcut(gridAction);
152
153 connect(effects, &EffectsHandler::screenAboutToLock, this, &OverviewEffect::realDeactivate);
154
155 OverviewConfig::instance(effects->config());
157
158 auto delegate = new QQmlComponent(effects->qmlEngine());
159 connect(delegate, &QQmlComponent::statusChanged, this, [delegate]() {
160 if (delegate->isError()) {
161 qWarning() << "Failed to load overview:" << delegate->errorString();
162 }
163 });
164 delegate->loadUrl(QUrl(QStringLiteral("qrc:/overview/qml/main.qml")), QQmlComponent::Asynchronous);
166}
167
171
172void OverviewEffect::reconfigure(ReconfigureFlags)
173{
174 OverviewConfig::self()->read();
175 setLayout(OverviewConfig::layoutMode());
177 setFilterWindows(OverviewConfig::filterWindows());
178
179 for (const ElectricBorder &border : std::as_const(m_borderActivate)) {
180 effects->unreserveElectricBorder(border, this);
181 }
182
183 m_borderActivate.clear();
184
185 const QList<int> activateBorders = OverviewConfig::borderActivate();
186 for (const int &border : activateBorders) {
187 m_borderActivate.append(ElectricBorder(border));
189 }
190
191 m_border->setBorders(OverviewConfig::touchBorderActivate());
192}
193
195{
196 return m_animationDuration;
197}
198
200{
201 if (m_animationDuration != duration) {
202 m_animationDuration = duration;
204 }
205}
206
208{
209 return m_filterWindows;
210}
211
212void OverviewEffect::setFilterWindows(bool filterWindows)
213{
214 if (m_filterWindows != filterWindows) {
215 m_filterWindows = filterWindows;
216 Q_EMIT filterWindowsChanged();
217 }
218}
219
221{
222 return m_overviewState->partialActivationFactor();
223}
224
226{
227 return m_overviewState->inProgress();
228}
229
231{
232 return m_transitionState->partialActivationFactor();
233}
234
236{
237 return m_transitionState->inProgress();
238}
239
241{
242 return m_gridState->partialActivationFactor();
243}
244
246{
247 return m_gridState->inProgress();
248}
249
251{
252 return m_desktopOffset;
253}
254
256{
257 return m_layout;
258}
259
261{
262 return OverviewConfig::ignoreMinimized();
263}
264
266{
267 return OverviewConfig::organizedGrid();
268}
269
271{
272 if (m_layout != layout) {
273 m_layout = layout;
274 Q_EMIT layoutChanged();
275 }
276}
277
279{
280 return 70;
281}
282
284{
285 if (m_borderActivate.contains(border)) {
286 cycle();
287 return true;
288 }
289 return false;
290}
291
293{
294 if (effects->isScreenLocked()) {
295 return;
296 }
297
298 m_overviewState->activate();
299}
300
302{
303 const auto screens = effects->screens();
304 m_shutdownTimer->start(animationDuration());
305 m_overviewState->deactivate();
306}
307
308void OverviewEffect::realDeactivate()
309{
310 if (m_overviewState->status() == EffectTogglableState::Status::Inactive) {
311 setRunning(false);
312 }
313}
314
315void OverviewEffect::cycle()
316{
317 if (m_overviewState->status() == EffectTogglableState::Status::Inactive) {
318 m_overviewState->activate();
319 } else if (m_transitionState->status() == EffectTogglableState::Status::Inactive) {
320 m_transitionState->activate();
321 } else if (m_gridState->status() == EffectTogglableState::Status::Active) {
322 m_overviewState->deactivate();
323 }
324}
325
326void OverviewEffect::reverseCycle()
327{
328 if (m_overviewState->status() == EffectTogglableState::Status::Active) {
329 m_overviewState->deactivate();
330 } else if (m_transitionState->status() == EffectTogglableState::Status::Active) {
331 m_transitionState->deactivate();
332 } else if (m_gridState->status() == EffectTogglableState::Status::Inactive) {
333 m_gridState->activate();
334 }
335}
336
338{
339 if (m_cycleShortcut.contains(keyEvent->key() | keyEvent->modifiers())) {
340 if (keyEvent->type() == QEvent::KeyPress) {
341 cycle();
342 }
343 return;
344 }
345 if (m_reverseCycleShortcut.contains(keyEvent->key() | keyEvent->modifiers())) {
346 if (keyEvent->type() == QEvent::KeyPress) {
347 reverseCycle();
348 }
349 return;
350 }
351 if (m_overviewShortcut.contains(keyEvent->key() | keyEvent->modifiers())) {
352 if (keyEvent->type() == QEvent::KeyPress) {
353 m_overviewState->toggleAction();
354 }
355 return;
356 }
357 if (m_gridShortcut.contains(keyEvent->key() | keyEvent->modifiers())) {
358 if (keyEvent->type() == QEvent::KeyPress) {
359 m_gridState->toggleAction();
360 }
361 return;
362 }
364}
365
367{
368 QList<EffectWindow *> fromList;
369 QList<EffectWindow *> toList;
370 for (auto *w : effects->stackingOrder()) {
371 if (!w->isNormalWindow() || !w->isOnCurrentActivity()) {
372 continue;
373 }
374 if (w->isOnDesktop(from)) {
375 fromList << w;
376 } else if (w->isOnDesktop(to)) {
377 toList << w;
378 }
379 }
380 for (auto *w : fromList) {
381 effects->windowToDesktops(w, {to});
382 }
383 for (auto *w : toList) {
384 effects->windowToDesktops(w, {from});
385 }
386}
387
388} // namespace KWin
389
390#include "moc_overvieweffect.cpp"
void statusChanged(Status status)
void setBorders(const QList< int > &borders)
Representation of a window used by/for Effect classes.
Q_SCRIPTABLE void windowToDesktops(KWin::EffectWindow *w, const QList< KWin::VirtualDesktop * > &desktops)
void desktopChanging(KWin::VirtualDesktop *currentDesktop, QPointF offset, KWin::EffectWindow *with)
QQmlEngine * qmlEngine() const
QList< EffectWindow * > stackingOrder
void reserveElectricBorder(ElectricBorder border, Effect *effect)
QList< Output * > screens() const
void desktopChanged(KWin::VirtualDesktop *oldDesktop, KWin::VirtualDesktop *newDesktop, KWin::EffectWindow *with)
void unreserveElectricBorder(ElectricBorder border, Effect *effect)
void desktopChangingCancelled()
KSharedConfigPtr config() const
qreal overviewPartialActivationFactor
void overviewPartialActivationFactorChanged()
qreal transitionPartialActivationFactor
void setLayout(int layout)
void gridGestureInProgressChanged()
void transitionPartialActivationFactorChanged()
Q_INVOKABLE void swapDesktops(KWin::VirtualDesktop *from, KWin::VirtualDesktop *to)
void animationDurationChanged()
void reconfigure(ReconfigureFlags flags) override
void grabbedKeyboardEvent(QKeyEvent *keyEvent) override
bool borderActivated(ElectricBorder border) override
void setFilterWindows(bool filterWindows)
int requestedEffectChainPosition() const override
void transitionGestureInProgressChanged()
void gridPartialActivationFactorChanged()
void overviewGestureInProgressChanged()
void setAnimationDuration(int duration)
QQmlComponent * delegate
Definition quickeffect.h:79
void setDelegate(QQmlComponent *delegate)
void grabbedKeyboardEvent(QKeyEvent *keyEvent) override
void setRunning(bool running)
static double animationTime(const KConfigGroup &cfg, const QString &key, int defaultTime)
Definition effect.cpp:483
@ ReconfigureAll
Definition effect.h:601
ElectricBorder
Definition globals.h:60
EffectsHandler * effects