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 | |
12 | class KWindowStateSaverPrivate |
13 | { |
14 | public: |
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 | |
24 | void 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 saveSize = [q, this]() { |
34 | KWindowConfig::saveWindowSize(window, config&: configGroup); |
35 | if (!timerId) { |
36 | timerId = q->startTimer(time: std::chrono::seconds(30)); |
37 | } |
38 | }; |
39 | const auto savePosition = [q, this]() { |
40 | KWindowConfig::saveWindowPosition(window, config&: configGroup); |
41 | if (!timerId) { |
42 | timerId = q->startTimer(time: std::chrono::seconds(30)); |
43 | } |
44 | }; |
45 | |
46 | QObject::connect(sender: window, signal: &QWindow::windowStateChanged, context: q, slot: saveSize); |
47 | QObject::connect(sender: window, signal: &QWindow::widthChanged, context: q, slot: saveSize); |
48 | QObject::connect(sender: window, signal: &QWindow::heightChanged, context: q, slot: saveSize); |
49 | QObject::connect(sender: window, signal: &QWindow::xChanged, context: q, slot: savePosition); |
50 | QObject::connect(sender: window, signal: &QWindow::yChanged, context: q, slot: savePosition); |
51 | } |
52 | |
53 | void KWindowStateSaverPrivate::initWidget(QObject *widget, KWindowStateSaver *q) |
54 | { |
55 | if (!window && windowHandleCallback) { |
56 | window = windowHandleCallback(); |
57 | } |
58 | if (window) { |
59 | init(q); |
60 | } else { |
61 | widget->installEventFilter(filterObj: q); |
62 | } |
63 | } |
64 | |
65 | KWindowStateSaver::KWindowStateSaver(QWindow *window, const KConfigGroup &configGroup) |
66 | : QObject(window) |
67 | , d(new KWindowStateSaverPrivate) |
68 | { |
69 | Q_ASSERT(window); |
70 | d->window = window; |
71 | d->configGroup = configGroup; |
72 | d->init(q: this); |
73 | } |
74 | |
75 | KWindowStateSaver::KWindowStateSaver(QWindow *window, const QString &configGroupName) |
76 | : QObject(window) |
77 | , d(new KWindowStateSaverPrivate) |
78 | { |
79 | Q_ASSERT(window); |
80 | d->window = window; |
81 | d->configGroup = KConfigGroup(KSharedConfig::openStateConfig(), configGroupName); |
82 | d->init(q: this); |
83 | } |
84 | |
85 | KWindowStateSaver::~KWindowStateSaver() |
86 | { |
87 | delete d; |
88 | } |
89 | |
90 | void KWindowStateSaver::timerEvent(QTimerEvent *event) |
91 | { |
92 | killTimer(id: event->timerId()); |
93 | d->configGroup.sync(); |
94 | d->timerId = 0; |
95 | } |
96 | |
97 | bool KWindowStateSaver::eventFilter(QObject *watched, QEvent *event) |
98 | { |
99 | // QEvent::PlatformSurface would give us a valid window, but if there are |
100 | // initial resizings (explicitly or via layout constraints) those would then |
101 | // already overwrite our restored values. So wait until all that is done |
102 | // and only restore afterwards. |
103 | if (event->type() == QEvent::ShowToParent && !d->window) { |
104 | watched->removeEventFilter(obj: this); |
105 | d->window = d->windowHandleCallback(); |
106 | d->init(q: this); |
107 | } |
108 | |
109 | return QObject::eventFilter(watched, event); |
110 | } |
111 | |
112 | void KWindowStateSaver::initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const KConfigGroup &configGroup) |
113 | { |
114 | d = new KWindowStateSaverPrivate; |
115 | d->windowHandleCallback = windowHandleCallback; |
116 | d->configGroup = configGroup; |
117 | d->initWidget(widget, q: this); |
118 | } |
119 | |
120 | void KWindowStateSaver::initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const QString &configGroupName) |
121 | { |
122 | d = new KWindowStateSaverPrivate; |
123 | d->windowHandleCallback = windowHandleCallback; |
124 | d->configGroup = KConfigGroup(KSharedConfig::openStateConfig(), configGroupName); |
125 | d->initWidget(widget, q: this); |
126 | } |
127 | |
128 | #include "moc_kwindowstatesaver.cpp" |
129 | |