Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "placementtracker.h"
|
||||
#include "core/output.h"
|
||||
#include "window.h"
|
||||
#include "workspace.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
PlacementTracker::PlacementTracker(Workspace *workspace)
|
||||
: m_workspace(workspace)
|
||||
{
|
||||
}
|
||||
|
||||
PlacementTracker::WindowData PlacementTracker::dataForWindow(Window *window) const
|
||||
{
|
||||
return WindowData{
|
||||
.outputUuid = window->moveResizeOutput()->uuid(),
|
||||
.geometry = window->moveResizeGeometry(),
|
||||
.maximize = window->requestedMaximizeMode(),
|
||||
.quickTile = window->requestedQuickTileMode(),
|
||||
.geometryRestore = window->geometryRestore(),
|
||||
.fullscreen = window->isRequestedFullScreen(),
|
||||
.fullscreenGeometryRestore = window->fullscreenGeometryRestore(),
|
||||
.interactiveMoveResizeCount = window->interactiveMoveResizeCount(),
|
||||
};
|
||||
}
|
||||
|
||||
void PlacementTracker::add(Window *window)
|
||||
{
|
||||
if (window->isUnmanaged() || window->isAppletPopup() || window->isSpecialWindow()) {
|
||||
return;
|
||||
}
|
||||
connect(window, &Window::frameGeometryChanged, this, [this, window]() {
|
||||
saveGeometry(window);
|
||||
});
|
||||
connect(window, &Window::maximizedChanged, this, [this, window]() {
|
||||
saveMaximize(window);
|
||||
});
|
||||
connect(window, &Window::quickTileModeChanged, this, [this, window]() {
|
||||
saveQuickTile(window);
|
||||
});
|
||||
connect(window, &Window::fullScreenChanged, this, [this, window]() {
|
||||
saveFullscreen(window);
|
||||
});
|
||||
connect(window, &Window::interactiveMoveResizeFinished, this, [this, window]() {
|
||||
saveInteractionCounter(window);
|
||||
});
|
||||
connect(window, &Window::maximizeGeometryRestoreChanged, this, [this, window]() {
|
||||
saveMaximizeGeometryRestore(window);
|
||||
});
|
||||
connect(window, &Window::fullscreenGeometryRestoreChanged, this, [this, window]() {
|
||||
saveFullscreenGeometryRestore(window);
|
||||
});
|
||||
WindowData data = dataForWindow(window);
|
||||
m_data[m_currentKey][window] = data;
|
||||
m_savedWindows.push_back(window);
|
||||
}
|
||||
|
||||
void PlacementTracker::remove(Window *window)
|
||||
{
|
||||
if (m_savedWindows.contains(window)) {
|
||||
disconnect(window, nullptr, this, nullptr);
|
||||
for (auto &dataMap : m_data) {
|
||||
dataMap.remove(window);
|
||||
}
|
||||
m_savedWindows.removeOne(window);
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementTracker::restore(const QString &key)
|
||||
{
|
||||
if (key == m_currentKey) {
|
||||
return;
|
||||
}
|
||||
auto &dataMap = m_data[key];
|
||||
auto &oldDataMap = m_data[m_currentKey];
|
||||
const auto outputs = m_workspace->outputs();
|
||||
|
||||
inhibit();
|
||||
for (const auto window : std::as_const(m_savedWindows)) {
|
||||
const auto it = dataMap.find(window);
|
||||
if (it != dataMap.end()) {
|
||||
const WindowData &newData = it.value();
|
||||
|
||||
// don't touch windows where the user intentionally changed their state
|
||||
bool restore = window->interactiveMoveResizeCount() == newData.interactiveMoveResizeCount
|
||||
&& window->requestedMaximizeMode() == newData.maximize
|
||||
&& window->requestedQuickTileMode() == newData.quickTile
|
||||
&& window->isFullScreen() == newData.fullscreen;
|
||||
if (!restore) {
|
||||
// the logic above can have false negatives if PlacementTracker changed the window state
|
||||
// to prevent that, also restore if the window still has the same state from that
|
||||
if (const auto it = m_lastRestoreData.find(window); it != m_lastRestoreData.end()) {
|
||||
restore = window->interactiveMoveResizeCount() == it->interactiveMoveResizeCount
|
||||
&& window->requestedMaximizeMode() == it->maximize
|
||||
&& window->requestedQuickTileMode() == it->quickTile
|
||||
&& window->isFullScreen() == it->fullscreen
|
||||
&& window->moveResizeOutput()->uuid() == it->outputUuid;
|
||||
}
|
||||
}
|
||||
if (!restore) {
|
||||
// restore anyways if the output the window was on got removed
|
||||
if (const auto oldData = oldDataMap.find(window); oldData != oldDataMap.end()) {
|
||||
restore = std::none_of(outputs.begin(), outputs.end(), [&oldData](const auto output) {
|
||||
return output->uuid() == oldData->outputUuid;
|
||||
});
|
||||
}
|
||||
}
|
||||
if (restore) {
|
||||
window->setQuickTileMode(newData.quickTile, newData.geometry.center());
|
||||
window->setMaximize(newData.maximize & MaximizeMode::MaximizeVertical, newData.maximize & MaximizeMode::MaximizeHorizontal);
|
||||
window->setFullScreen(newData.fullscreen);
|
||||
window->moveResize(newData.geometry);
|
||||
window->setGeometryRestore(newData.geometryRestore);
|
||||
window->setFullscreenGeometryRestore(newData.fullscreenGeometryRestore);
|
||||
m_lastRestoreData[window] = dataForWindow(window);
|
||||
}
|
||||
}
|
||||
// ensure data in current map is always up to date
|
||||
dataMap[window] = dataForWindow(window);
|
||||
}
|
||||
uninhibit();
|
||||
m_currentKey = key;
|
||||
}
|
||||
|
||||
void PlacementTracker::init(const QString &key)
|
||||
{
|
||||
m_currentKey = key;
|
||||
}
|
||||
|
||||
void PlacementTracker::saveGeometry(Window *window)
|
||||
{
|
||||
if (m_inhibitCount == 0) {
|
||||
auto &data = m_data[m_currentKey][window];
|
||||
data.geometry = window->moveResizeGeometry();
|
||||
data.outputUuid = window->moveResizeOutput()->uuid();
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementTracker::saveInteractionCounter(Window *window)
|
||||
{
|
||||
if (m_inhibitCount == 0) {
|
||||
m_data[m_currentKey][window].interactiveMoveResizeCount = window->interactiveMoveResizeCount();
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementTracker::saveMaximize(Window *window)
|
||||
{
|
||||
if (m_inhibitCount == 0) {
|
||||
auto &data = m_data[m_currentKey][window];
|
||||
data.maximize = window->maximizeMode();
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementTracker::saveQuickTile(Window *window)
|
||||
{
|
||||
if (m_inhibitCount == 0) {
|
||||
auto &data = m_data[m_currentKey][window];
|
||||
data.quickTile = window->quickTileMode();
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementTracker::saveFullscreen(Window *window)
|
||||
{
|
||||
if (m_inhibitCount == 0) {
|
||||
auto &data = m_data[m_currentKey][window];
|
||||
data.fullscreen = window->isFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementTracker::saveMaximizeGeometryRestore(Window *window)
|
||||
{
|
||||
if (m_inhibitCount == 0) {
|
||||
auto &data = m_data[m_currentKey][window];
|
||||
data.geometryRestore = window->geometryRestore();
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementTracker::saveFullscreenGeometryRestore(Window *window)
|
||||
{
|
||||
if (m_inhibitCount == 0) {
|
||||
auto &data = m_data[m_currentKey][window];
|
||||
data.fullscreenGeometryRestore = window->fullscreenGeometryRestore();
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementTracker::inhibit()
|
||||
{
|
||||
m_inhibitCount++;
|
||||
}
|
||||
|
||||
void PlacementTracker::uninhibit()
|
||||
{
|
||||
Q_ASSERT(m_inhibitCount > 0);
|
||||
m_inhibitCount--;
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_placementtracker.cpp"
|
||||
Reference in New Issue
Block a user