| 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 | |