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 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 | |
44 | void 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 | |
56 | KWindowStateSaver::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 | |
66 | KWindowStateSaver::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 | |
76 | KWindowStateSaver::~KWindowStateSaver() |
77 | { |
78 | delete d; |
79 | } |
80 | |
81 | void 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 | |
89 | bool 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 | |
104 | void 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 | |
112 | void 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 | |