Add functions to save and restore window positions on non-Wayland platforms

These functions allow an application to save and restore the positions
of its windows. Positions are stored on a per-screen-arrangement basis.

For example with a single screen connected, the config file would have
entries like this in it:

eDP-1 XPosition=140
eDP-1 YPosition=340

When a second screen is connected, the following gets saved:

eDP-1 HDMI-1 XPosition=3878
eDP-1 HDMI-1 YPosition=29

This ensures that each separate screen arrangement can have its own
saved window position, which is handy for the use case where you have a
laptop that you plug into an external screen some of the time. It also
allows the position to get restored to the correct screen when there are
multiple screens.

This is a necessary first step to getting KDE apps to save their window
positions on X11 The next step would be calling the new functions from
KXMLGui and Kirigami apps, and then porting all apps that manually invoke
KWindowConfig::saveWindowSize() and KWindowConfig::restoreWindowSize()
to also invoke KWindowConfig::saveWindowPosition() and
KWindowConfig::restoreWindowPosition() in the same places.

The functions only work on X11 or other non-Wayland platforms. On
Wayland, the compositor has sole dominion over window positioning so a
compositor-specific solution much be adopted instead, such as
https://bugs.kde.org/show_bug.cgi?id=15329.

CCBUG: 415150
wilder
Nate Graham 6 years ago
parent 3e5e2ea59e
commit 1434257972
  1. 58
      src/gui/kwindowconfig.cpp
  2. 27
      src/gui/kwindowconfig.h

@ -7,6 +7,7 @@
#include "kwindowconfig.h"
#include <QGuiApplication>
#include <QScreen>
#include <QWindow>
@ -71,3 +72,60 @@ void KWindowConfig::restoreWindowSize(QWindow *window, const KConfigGroup &confi
window->setWindowState(Qt::WindowMaximized);
}
}
void KWindowConfig::saveWindowPosition(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options)
{
// On Wayland, the compositor is solely responsible for window positioning,
// So this needs to be a no-op
if (!window || QGuiApplication::platformName() == QStringLiteral("wayland")) {
return;
}
// Prepend the names of all connected screens so that we save the position
// on a per-screen-arrangement basis, since people often like to have
// windows positioned differently depending on their screen arrangements
QStringList names;
const auto screens = QGuiApplication::screens();
names.reserve(screens.length());
for (auto screen : screens) {
names << screen->name();
}
const QString allScreens = names.join(QStringLiteral(" "));
config.writeEntry(allScreens + QStringLiteral(" XPosition"), window->x(), options);
config.writeEntry(allScreens + QStringLiteral(" YPosition"), window->y(), options);
}
void KWindowConfig::restoreWindowPosition(QWindow *window, const KConfigGroup &config)
{
// On Wayland, the compositor is solely responsible for window positioning,
// So this needs to be a no-op
if (!window || QGuiApplication::platformName() == QStringLiteral("wayland")) {
return;
}
const QRect desk = window->screen()->geometry();
const bool isMaximized = config.readEntry(QStringLiteral("Window-Maximized %1x%2").arg(desk.height()).arg(desk.width()), false);
// Don't need to restore position if the window was maximized
if (isMaximized) {
window->setWindowState(Qt::WindowMaximized);
return;
}
QStringList names;
const auto screens = QGuiApplication::screens();
names.reserve(screens.length());
for (auto screen : screens) {
names << screen->name();
}
const QString allScreens = names.join(QStringLiteral(" "));
const int xPos = config.readEntry(allScreens + QStringLiteral(" XPosition"), -1);
const int yPos = config.readEntry(allScreens + QStringLiteral(" YPosition"), -1);
if (xPos == -1 || yPos == -1) {
return;
}
window->setX(xPos);
window->setY(yPos);
}

@ -55,6 +55,33 @@ KCONFIGGUI_EXPORT void saveWindowSize(const QWindow *window, KConfigGroup &confi
* @since 5.0.
*/
KCONFIGGUI_EXPORT void restoreWindowSize(QWindow *window, const KConfigGroup &config);
/**
* Saves the window's position either to the global or application config file.
* This function has no effect on Wayland, where the compositor is responsible
* for window positioning.
*
* @note the group must be set before calling
*
* @param window The window whose position to save.
* @param config The config group to read from.
* @param options passed to KConfigGroup::writeEntry()
* @since 5.74
*/
KCONFIGGUI_EXPORT void saveWindowPosition(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options = KConfigGroup::Normal);
/**
* Restores the window's position from the configuration.
* This function has no effect on Wayland, where the compositor is responsible
* for window positioning.
*
* @note the group must be set before calling
*
* @param window The window whose position to restore.
* @param config The config group to read from.
* @since 5.74
*/
KCONFIGGUI_EXPORT void restoreWindowPosition(QWindow *window, const KConfigGroup &config);
}
#endif // KWINDOWCONFIG_H

Loading…
Cancel
Save