KConfig

kwindowconfig.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2012 Benjamin Port <benjamin.port@ben2367.fr>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#include "kwindowconfig.h"
9#include "ksharedconfig.h"
10
11#include <QGuiApplication>
12#include <QScreen>
13#include <QWindow>
14
15static const char s_initialSizePropertyName[] = "_kconfig_initial_size";
16static const char s_initialScreenSizePropertyName[] = "_kconfig_initial_screen_size";
17
18// Convenience function to get a space-separated list of all connected screens
19static QString allConnectedScreens()
20{
21 QStringList names;
22 const auto screens = QGuiApplication::screens();
23 names.reserve(screens.length());
24 for (auto screen : screens) {
25 names << screen->name();
26 }
27 // A string including the connector names is used in the config file key for
28 // storing per-screen-arrangement size and position data, which means we
29 // need this string to be consistent for the same screen arrangement. But
30 // connector order is non-deterministic. We need to sort the list to keep a
31 // consistent order and avoid losing multi-screen size and position data.
32 names.sort();
33 return names.join(QLatin1Char(' '));
34}
35
36// Convenience function to return screen by its name from window screen siblings
37// returns current window screen if not found
38static QScreen *findScreenByName(const QWindow *window, const QString screenName)
39{
40 if (screenName == window->screen()->name()) {
41 return window->screen();
42 }
43 for (QScreen *s : window->screen()->virtualSiblings()) {
44 if (s->name() == screenName) {
45 return s;
46 }
47 }
48 return window->screen();
49}
50
51// Convenience function to get an appropriate config file key under which to
52// save window size, position, or maximization information.
53static QString configFileString(const QString &key)
54{
55 QString returnString;
56 const int numberOfScreens = QGuiApplication::screens().length();
57
58 if (numberOfScreens == 1) {
59 // For single-screen setups, we save data on a per-resolution basis.
60 const QRect screenGeometry = QGuiApplication::primaryScreen()->geometry();
61 returnString = QStringLiteral("%1x%2 screen: %3").arg(QString::number(screenGeometry.width()), QString::number(screenGeometry.height()), key);
62 } else {
63 // For multi-screen setups, we save data based on the number of screens.
64 // Distinguishing individual screens based on their names is unreliable
65 // due to name strings being inherently volatile.
66 returnString = QStringLiteral("%1 screens: %2").arg(QString::number(numberOfScreens), key);
67 }
68 return returnString;
69}
70
71// Convenience function for "window is maximized" string
72static QString screenMaximizedString()
73{
74 return configFileString(QStringLiteral("Window-Maximized"));
75}
76// Convenience function for window width string
77static QString windowWidthString()
78{
79 return configFileString(QStringLiteral("Width"));
80}
81// Convenience function for window height string
82static QString windowHeightString()
83{
84 return configFileString(QStringLiteral("Height"));
85}
86// Convenience function for window X position string
87static QString windowXPositionString()
88{
89 return configFileString(QStringLiteral("XPosition"));
90}
91// Convenience function for window Y position string
92static QString windowYPositionString()
93{
94 return configFileString(QStringLiteral("YPosition"));
95}
96static QString windowScreenPositionString()
97{
98 return QStringLiteral("%1").arg(allConnectedScreens());
99}
100
102{
103 // QWindow::screen() shouldn't return null, but it sometimes does due to bugs.
104 if (!window || !window->screen()) {
105 return;
106 }
107 const QScreen *screen = window->screen();
108
109 const QSize sizeToSave = window->size();
110 const bool isMaximized = window->windowState() & Qt::WindowMaximized;
111
112 // Save size only if window is not maximized
113 if (!isMaximized) {
114 const QSize defaultSize(window->property(s_initialSizePropertyName).toSize());
115 const QSize defaultScreenSize(window->property(s_initialScreenSizePropertyName).toSize());
116 const bool sizeValid = defaultSize.isValid() && defaultScreenSize.isValid();
117 if (!sizeValid || (defaultSize != sizeToSave || defaultScreenSize != screen->geometry().size())) {
118 config.writeEntry(windowWidthString(), sizeToSave.width(), options);
119 config.writeEntry(windowHeightString(), sizeToSave.height(), options);
120 // Don't keep the maximized string in the file since the window is
121 // no longer maximized at this point
122 config.deleteEntry(screenMaximizedString());
123 }
124 // Revert width and height to default if they are same as defaults
125 else {
126 config.revertToDefault(windowWidthString());
127 config.revertToDefault(windowHeightString());
128 }
129 }
130 if ((isMaximized == false) && !config.hasDefault(screenMaximizedString())) {
131 config.revertToDefault(screenMaximizedString());
132 } else {
133 config.writeEntry(screenMaximizedString(), isMaximized, options);
134 }
135}
136
138{
139 return config.hasKey(windowWidthString()) || config.hasKey(windowHeightString()) || config.hasKey(screenMaximizedString());
140}
141
143{
144 if (!window) {
145 return;
146 }
147
148 const QString screenName = config.readEntry(windowScreenPositionString(), window->screen()->name());
149
150 const int width = config.readEntry(windowWidthString(), -1);
151 const int height = config.readEntry(windowHeightString(), -1);
152 const bool isMaximized = config.readEntry(configFileString(QStringLiteral("Window-Maximized")), false);
153
154 // Check default size
155 const QSize defaultSize(window->property(s_initialSizePropertyName).toSize());
156 const QSize defaultScreenSize(window->property(s_initialScreenSizePropertyName).toSize());
157 if (!defaultSize.isValid() || !defaultScreenSize.isValid()) {
158 const QScreen *screen = findScreenByName(window, screenName);
159 window->setProperty(s_initialSizePropertyName, window->size());
160 window->setProperty(s_initialScreenSizePropertyName, screen->geometry().size());
161 }
162
163 if (width > 0 && height > 0) {
164 window->resize(width, height);
165 }
166
167 if (isMaximized) {
169 }
170}
171
173{
174 // On Wayland, the compositor is solely responsible for window positioning,
175 // So this needs to be a no-op
176 if (!window || QGuiApplication::platformName() == QLatin1String{"wayland"}) {
177 return;
178 }
179
180 // If the window is maximized, saving the position will only serve to mis-position
181 // it once de-maximized, so let's not do that
182 if (window->windowState() & Qt::WindowMaximized) {
183 return;
184 }
185
186 config.writeEntry(windowXPositionString(), window->x(), options);
187 config.writeEntry(windowYPositionString(), window->y(), options);
188 config.writeEntry(windowScreenPositionString(), window->screen()->name(), options);
189}
190
192{
193 // Window position save/restore features outside of the compositor are not
194 // supported on Wayland
195 if (QGuiApplication::platformName() == QLatin1String{"wayland"}) {
196 return false;
197 }
198
199 return config.hasKey(windowXPositionString()) || config.hasKey(windowYPositionString()) || config.hasKey(windowScreenPositionString());
200}
201
203{
204 // On Wayland, the compositor is solely responsible for window positioning,
205 // So this needs to be a no-op
206 if (!window || QGuiApplication::platformName() == QLatin1String{"wayland"}) {
207 return;
208 }
209
210 const bool isMaximized = config.readEntry(configFileString(QStringLiteral("Window-Maximized")), false);
211
212 // Don't need to restore position if the window was maximized
213 if (isMaximized) {
215 return;
216 }
217
218 // Move window to proper screen
219 const QScreen *screen = window->screen();
220 const QString screenName = config.readEntry(windowScreenPositionString(), screen->name());
221 if (screenName != screen->name()) {
222 QScreen *screenConf = findScreenByName(window, screenName);
223 window->setScreen(screenConf);
224 restoreWindowScreenPosition(window, screenConf, config);
225 return;
226 }
227 restoreWindowScreenPosition(window, screen, config);
228}
229
231{
232 Q_UNUSED(screen);
233 const int xPos = config.readEntry(windowXPositionString(), -1);
234 const int yPos = config.readEntry(windowYPositionString(), -1);
235
236 if (xPos == -1 || yPos == -1) {
237 return;
238 }
239
240 window->setX(xPos);
241 window->setY(yPos);
242}
A class for one specific group in a KConfig object.
T readEntry(const QString &key, const T &aDefault) const
Reads the value of an entry specified by pKey in the current group.
bool hasDefault(const QString &key) const
Whether a default is specified for an entry in either the system wide configuration file or the globa...
bool hasKey(const QString &key) const
Checks whether the key has an entry in this group.
void revertToDefault(const QString &key, WriteConfigFlags pFlag=WriteConfigFlags())
Reverts an entry to the default settings.
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
Writes a value to the configuration object.
void deleteEntry(const QString &pKey, WriteConfigFlags pFlags=Normal)
Deletes the entry specified by pKey in the current group.
QWidget * window(QObject *job)
KCONFIGGUI_EXPORT void saveWindowSize(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options=KConfigGroup::Normal)
Saves the window's size dependent on the screen dimension either to the global or application config ...
KCONFIGGUI_EXPORT bool hasSavedWindowSize(KConfigGroup &config)
Returns whether a given KConfig group has any saved window size data.
KCONFIGGUI_EXPORT void restoreWindowScreenPosition(QWindow *window, const QScreen *screen, const KConfigGroup &config)
Restores the window's position on provided screen from the configuration.
KCONFIGGUI_EXPORT bool hasSavedWindowPosition(KConfigGroup &config)
Returns whether a given KConfig group has any saved window position data.
KCONFIGGUI_EXPORT void saveWindowPosition(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options=KConfigGroup::Normal)
Saves the window's position either to the global or application config file.
KCONFIGGUI_EXPORT void restoreWindowSize(QWindow *window, const KConfigGroup &config)
Restores the dialog's size from the configuration according to the screen size.
KCONFIGGUI_EXPORT void restoreWindowPosition(QWindow *window, const KConfigGroup &config)
Restores the window's screen position from the configuration and calls restoreWindowScreenPosition.
QList< QScreen * > screens()
void reserve(qsizetype size)
QVariant property(const char *name) const const
bool setProperty(const char *name, QVariant &&value)
int height() const const
int width() const const
QList< QScreen * > virtualSiblings() const const
int height() const const
bool isValid() const const
int width() const const
QString arg(Args &&... args) const const
qsizetype length() const const
QString number(double n, char format, int precision)
QString join(QChar separator) const const
void sort(Qt::CaseSensitivity cs)
WindowMaximized
QSize toSize() const const
QScreen * screen() const const
void setScreen(QScreen *screen)
void setWindowState(Qt::WindowStates windowState)
Qt::WindowStates windowState() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:18:27 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.