KWin
Loading...
Searching...
No Matches
placementtracker.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9#include "placementtracker.h"
10#include "core/output.h"
11#include "window.h"
12#include "workspace.h"
13
14namespace KWin
15{
16
21
22PlacementTracker::WindowData PlacementTracker::dataForWindow(Window *window) const
23{
24 return WindowData{
25 .outputUuid = window->moveResizeOutput()->uuid(),
26 .geometry = window->moveResizeGeometry(),
27 .maximize = window->requestedMaximizeMode(),
28 .quickTile = window->quickTileMode(),
29 .geometryRestore = window->geometryRestore(),
30 .fullscreen = window->isFullScreen(),
31 .fullscreenGeometryRestore = window->fullscreenGeometryRestore(),
32 .interactiveMoveResizeCount = window->interactiveMoveResizeCount(),
33 };
34}
35
37{
38 if (window->isUnmanaged() || window->isAppletPopup() || window->isSpecialWindow()) {
39 return;
40 }
41 connect(window, &Window::frameGeometryChanged, this, [this, window]() {
42 saveGeometry(window);
43 });
44 connect(window, &Window::maximizedChanged, this, [this, window]() {
45 saveMaximize(window);
46 });
47 connect(window, &Window::quickTileModeChanged, this, [this, window]() {
48 saveQuickTile(window);
49 });
50 connect(window, &Window::fullScreenChanged, this, [this, window]() {
51 saveFullscreen(window);
52 });
53 connect(window, &Window::interactiveMoveResizeFinished, this, [this, window]() {
54 saveInteractionCounter(window);
55 });
56 WindowData data = dataForWindow(window);
57 m_data[m_currentKey][window] = data;
58 m_savedWindows.push_back(window);
59}
60
62{
63 if (m_savedWindows.contains(window)) {
64 disconnect(window, nullptr, this, nullptr);
65 for (auto &dataMap : m_data) {
66 dataMap.remove(window);
67 }
68 m_savedWindows.removeOne(window);
69 }
70}
71
72void PlacementTracker::restore(const QString &key)
73{
74 if (key == m_currentKey) {
75 return;
76 }
77 auto &dataMap = m_data[key];
78 auto &oldDataMap = m_data[m_currentKey];
79 const auto outputs = m_workspace->outputs();
80
81 inhibit();
82 for (const auto window : std::as_const(m_savedWindows)) {
83 const auto it = dataMap.find(window);
84 if (it != dataMap.end()) {
85 const WindowData &newData = it.value();
86
87 // don't touch windows where the user intentionally changed their state
88 bool restore = window->interactiveMoveResizeCount() == newData.interactiveMoveResizeCount
89 && window->requestedMaximizeMode() == newData.maximize
90 && window->quickTileMode() == newData.quickTile
91 && window->isFullScreen() == newData.fullscreen;
92 if (!restore) {
93 // the logic above can have false negatives if PlacementTracker changed the window state
94 // to prevent that, also restore if the window still has the same state from that
95 if (const auto it = m_lastRestoreData.find(window); it != m_lastRestoreData.end()) {
96 restore = window->interactiveMoveResizeCount() == it->interactiveMoveResizeCount
97 && window->requestedMaximizeMode() == it->maximize
98 && window->quickTileMode() == it->quickTile
99 && window->isFullScreen() == it->fullscreen
100 && window->moveResizeOutput()->uuid() == it->outputUuid;
101 }
102 }
103 if (!restore) {
104 // restore anyways if the output the window was on got removed
105 if (const auto oldData = oldDataMap.find(window); oldData != oldDataMap.end()) {
106 restore = std::none_of(outputs.begin(), outputs.end(), [&oldData](const auto output) {
107 return output->uuid() == oldData->outputUuid;
108 });
109 }
110 }
111 if (restore) {
112 window->setFullScreen(false);
114 window->setMaximize(false, false);
115 if (newData.quickTile || newData.maximize) {
116 window->moveResize(newData.geometryRestore);
117 window->setQuickTileMode(newData.quickTile, true);
118 window->setMaximize(newData.maximize & MaximizeMode::MaximizeVertical, newData.maximize & MaximizeMode::MaximizeHorizontal);
119 }
120 if (newData.fullscreen) {
121 window->moveResize(newData.fullscreenGeometryRestore);
122 window->setFullScreen(newData.fullscreen);
123 }
124 if (newData.quickTile || newData.maximize || newData.fullscreen) {
125 // restore geometry isn't necessarily on the output the window was, so explicitly restore it
126 const auto outputIt = std::find_if(outputs.begin(), outputs.end(), [&newData](const auto output) {
127 return output->uuid() == newData.outputUuid;
128 });
129 if (outputIt != outputs.end()) {
130 window->sendToOutput(*outputIt);
131 }
132 } else {
133 window->moveResize(newData.geometry);
134 }
135 m_lastRestoreData[window] = dataForWindow(window);
136 }
137 }
138 // ensure data in current map is always up to date
139 dataMap[window] = dataForWindow(window);
140 }
141 uninhibit();
142 m_currentKey = key;
143}
144
145void PlacementTracker::init(const QString &key)
146{
147 m_currentKey = key;
148}
149
150void PlacementTracker::saveGeometry(Window *window)
151{
152 if (m_inhibitCount == 0) {
153 auto &data = m_data[m_currentKey][window];
154 data.geometry = window->moveResizeGeometry();
155 data.outputUuid = window->moveResizeOutput()->uuid();
156 }
157}
158
159void PlacementTracker::saveInteractionCounter(Window *window)
160{
161 if (m_inhibitCount == 0) {
162 m_data[m_currentKey][window].interactiveMoveResizeCount = window->interactiveMoveResizeCount();
163 }
164}
165
166void PlacementTracker::saveMaximize(Window *window)
167{
168 if (m_inhibitCount == 0) {
169 auto &data = m_data[m_currentKey][window];
170 data.maximize = window->maximizeMode();
171 data.geometryRestore = window->geometryRestore();
172 }
173}
174
175void PlacementTracker::saveQuickTile(Window *window)
176{
177 if (m_inhibitCount == 0) {
178 auto &data = m_data[m_currentKey][window];
179 data.quickTile = window->quickTileMode();
180 data.geometryRestore = window->geometryRestore();
181 }
182}
183
184void PlacementTracker::saveFullscreen(Window *window)
185{
186 if (m_inhibitCount == 0) {
187 auto &data = m_data[m_currentKey][window];
188 data.fullscreen = window->isFullScreen();
189 data.fullscreenGeometryRestore = window->fullscreenGeometryRestore();
190 }
191}
192
194{
195 m_inhibitCount++;
196}
197
199{
200 Q_ASSERT(m_inhibitCount > 0);
201 m_inhibitCount--;
202}
203}
204
205#include "moc_placementtracker.cpp"
QUuid uuid() const
Definition output.cpp:364
void add(Window *window)
void remove(Window *window)
void restore(const QString &key)
void init(const QString &key)
PlacementTracker(Workspace *workspace)
void maximizedChanged()
void moveResize(const QRectF &rect)
Definition window.cpp:3323
QRectF fullscreenGeometryRestore() const
Definition window.cpp:3908
virtual void setFullScreen(bool set)
Definition window.cpp:3952
void fullScreenChanged()
virtual bool isFullScreen() const
Definition window.cpp:3935
uint32_t interactiveMoveResizeCount() const
Definition window.cpp:4167
void setQuickTileMode(QuickTileMode mode, bool keyboard=false)
Definition window.cpp:3411
virtual bool isUnmanaged() const
Definition window.cpp:307
void interactiveMoveResizeFinished()
void sendToOutput(Output *output)
Definition window.cpp:3622
bool isAppletPopup() const
Definition window.h:1987
virtual MaximizeMode requestedMaximizeMode() const
Definition window.cpp:3999
QuickTileMode quickTileMode() const
Definition window.h:1096
void quickTileModeChanged()
Output * moveResizeOutput() const
Definition window.cpp:3297
QRectF moveResizeGeometry() const
Definition window.cpp:3286
QRectF geometryRestore() const
Definition window.cpp:4007
void frameGeometryChanged(const QRectF &oldGeometry)
bool isSpecialWindow() const
Definition window.cpp:702
Q_INVOKABLE void setMaximize(bool vertically, bool horizontally)
Definition window.cpp:1172
QList< Output * > outputs() const
Definition workspace.h:762
@ MaximizeVertical
The window is maximized vertically.
Definition common.h:76
@ MaximizeHorizontal
Definition common.h:77
Workspace * workspace()
Definition workspace.h:830