1/*
2 SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
3 SPDX-License-Identifier: LGPL-2.0-or-later
4*/
5
6#include "kwindowstatesaver.h"
7#include "ksharedconfig.h"
8#include "kwindowconfig.h"
9
10#include <QWindow>
11
12class KWindowStateSaverPrivate
13{
14public:
15 QWindow *window = nullptr;
16 KConfigGroup configGroup;
17 std::function<QWindow *()> windowHandleCallback;
18 int timerId = 0;
19
20 void init(KWindowStateSaver *q);
21 void initWidget(QObject *widget, KWindowStateSaver *q);
22};
23
24void KWindowStateSaverPrivate::init(KWindowStateSaver *q)
25{
26 if (!window) {
27 return;
28 }
29
30 KWindowConfig::restoreWindowSize(window, config: configGroup);
31 KWindowConfig::restoreWindowPosition(window, config: configGroup);
32
33 const auto deferredSave = [q, this]() {
34 if (!timerId) {
35 timerId = q->startTimer(interval: 250);
36 }
37 };
38 QObject::connect(sender: window, signal: &QWindow::widthChanged, context: q, slot: deferredSave);
39 QObject::connect(sender: window, signal: &QWindow::heightChanged, context: q, slot: deferredSave);
40 QObject::connect(sender: window, signal: &QWindow::xChanged, context: q, slot: deferredSave);
41 QObject::connect(sender: window, signal: &QWindow::yChanged, context: q, slot: deferredSave);
42}
43
44void KWindowStateSaverPrivate::initWidget(QObject *widget, KWindowStateSaver *q)
45{
46 if (!window && windowHandleCallback) {
47 window = windowHandleCallback();
48 }
49 if (window) {
50 init(q);
51 } else {
52 widget->installEventFilter(filterObj: q);
53 }
54}
55
56KWindowStateSaver::KWindowStateSaver(QWindow *window, const KConfigGroup &configGroup)
57 : QObject(window)
58 , d(new KWindowStateSaverPrivate)
59{
60 Q_ASSERT(window);
61 d->window = window;
62 d->configGroup = configGroup;
63 d->init(q: this);
64}
65
66KWindowStateSaver::KWindowStateSaver(QWindow *window, const QString &configGroupName)
67 : QObject(window)
68 , d(new KWindowStateSaverPrivate)
69{
70 Q_ASSERT(window);
71 d->window = window;
72 d->configGroup = KConfigGroup(KSharedConfig::openStateConfig(), configGroupName);
73 d->init(q: this);
74}
75
76KWindowStateSaver::~KWindowStateSaver()
77{
78 delete d;
79}
80
81void KWindowStateSaver::timerEvent(QTimerEvent *event)
82{
83 killTimer(id: event->timerId());
84 KWindowConfig::saveWindowPosition(window: d->window, config&: d->configGroup);
85 KWindowConfig::saveWindowSize(window: d->window, config&: d->configGroup);
86 d->timerId = 0;
87}
88
89bool KWindowStateSaver::eventFilter(QObject *watched, QEvent *event)
90{
91 // QEvent::PlatformSurface would give us a valid window, but if there are
92 // intial resizings (explicitly or via layout constraints) those would then
93 // already overwrite our restored values. So wait until all that is done
94 // and only restore afterwards.
95 if (event->type() == QEvent::ShowToParent && !d->window) {
96 watched->removeEventFilter(obj: this);
97 d->window = d->windowHandleCallback();
98 d->init(q: this);
99 }
100
101 return QObject::eventFilter(watched, event);
102}
103
104void KWindowStateSaver::initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const KConfigGroup &configGroup)
105{
106 d = new KWindowStateSaverPrivate;
107 d->windowHandleCallback = windowHandleCallback;
108 d->configGroup = configGroup;
109 d->initWidget(widget, q: this);
110}
111
112void KWindowStateSaver::initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const QString &configGroupName)
113{
114 d = new KWindowStateSaverPrivate;
115 d->windowHandleCallback = windowHandleCallback;
116 d->configGroup = KConfigGroup(KSharedConfig::openStateConfig(), configGroupName);
117 d->initWidget(widget, q: this);
118}
119
120#include "moc_kwindowstatesaver.cpp"
121

source code of kconfig/src/gui/kwindowstatesaver.cpp