| 1 | /* |
| 2 | SPDX-FileCopyrightText: 2015 Martin Gräßlin <[email protected]> |
| 3 | |
| 4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
| 5 | */ |
| 6 | #include "dpms.h" |
| 7 | #include "event_queue.h" |
| 8 | #include "output.h" |
| 9 | #include "wayland_pointer_p.h" |
| 10 | |
| 11 | #include <wayland-client-protocol.h> |
| 12 | #include <wayland-dpms-client-protocol.h> |
| 13 | |
| 14 | namespace KWayland |
| 15 | { |
| 16 | namespace Client |
| 17 | { |
| 18 | class Q_DECL_HIDDEN DpmsManager::Private |
| 19 | { |
| 20 | public: |
| 21 | WaylandPointer<org_kde_kwin_dpms_manager, org_kde_kwin_dpms_manager_destroy> manager; |
| 22 | EventQueue *queue = nullptr; |
| 23 | }; |
| 24 | |
| 25 | DpmsManager::DpmsManager(QObject *parent) |
| 26 | : QObject(parent) |
| 27 | , d(new Private) |
| 28 | { |
| 29 | } |
| 30 | |
| 31 | DpmsManager::~DpmsManager() |
| 32 | { |
| 33 | release(); |
| 34 | } |
| 35 | |
| 36 | void DpmsManager::release() |
| 37 | { |
| 38 | d->manager.release(); |
| 39 | } |
| 40 | |
| 41 | void DpmsManager::destroy() |
| 42 | { |
| 43 | d->manager.destroy(); |
| 44 | } |
| 45 | |
| 46 | bool DpmsManager::isValid() const |
| 47 | { |
| 48 | return d->manager.isValid(); |
| 49 | } |
| 50 | |
| 51 | void DpmsManager::setup(org_kde_kwin_dpms_manager *manager) |
| 52 | { |
| 53 | Q_ASSERT(manager); |
| 54 | Q_ASSERT(!d->manager.isValid()); |
| 55 | d->manager.setup(pointer: manager); |
| 56 | } |
| 57 | |
| 58 | EventQueue *DpmsManager::eventQueue() |
| 59 | { |
| 60 | return d->queue; |
| 61 | } |
| 62 | |
| 63 | void DpmsManager::setEventQueue(EventQueue *queue) |
| 64 | { |
| 65 | d->queue = queue; |
| 66 | } |
| 67 | |
| 68 | Dpms *DpmsManager::getDpms(Output *output, QObject *parent) |
| 69 | { |
| 70 | Q_ASSERT(isValid()); |
| 71 | Q_ASSERT(output); |
| 72 | Dpms *dpms = new Dpms(output, parent); |
| 73 | auto w = org_kde_kwin_dpms_manager_get(org_kde_kwin_dpms_manager: d->manager, output: *output); |
| 74 | if (d->queue) { |
| 75 | d->queue->addProxy(proxy: w); |
| 76 | } |
| 77 | dpms->setup(w); |
| 78 | return dpms; |
| 79 | } |
| 80 | |
| 81 | DpmsManager::operator org_kde_kwin_dpms_manager *() const |
| 82 | { |
| 83 | return d->manager; |
| 84 | } |
| 85 | |
| 86 | DpmsManager::operator org_kde_kwin_dpms_manager *() |
| 87 | { |
| 88 | return d->manager; |
| 89 | } |
| 90 | |
| 91 | class Q_DECL_HIDDEN Dpms::Private |
| 92 | { |
| 93 | public: |
| 94 | explicit Private(const QPointer<Output> &output, Dpms *q); |
| 95 | void setup(org_kde_kwin_dpms *d); |
| 96 | |
| 97 | WaylandPointer<org_kde_kwin_dpms, org_kde_kwin_dpms_release> dpms; |
| 98 | struct Data { |
| 99 | bool supported = false; |
| 100 | Mode mode = Mode::On; |
| 101 | bool supportedChanged = false; |
| 102 | bool modeChanged = false; |
| 103 | }; |
| 104 | Data current; |
| 105 | Data pending; |
| 106 | QPointer<Output> output; |
| 107 | |
| 108 | private: |
| 109 | static void supportedCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms, uint32_t supported); |
| 110 | static void modeCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms, uint32_t mode); |
| 111 | static void doneCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms); |
| 112 | static const struct org_kde_kwin_dpms_listener s_listener; |
| 113 | |
| 114 | Dpms *q; |
| 115 | }; |
| 116 | |
| 117 | #ifndef K_DOXYGEN |
| 118 | const org_kde_kwin_dpms_listener Dpms::Private::s_listener = {.supported: supportedCallback, .mode: modeCallback, .done: doneCallback}; |
| 119 | #endif |
| 120 | |
| 121 | void Dpms::Private::supportedCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms, uint32_t supported) |
| 122 | { |
| 123 | Q_UNUSED(org_kde_kwin_dpms) |
| 124 | Private *p = reinterpret_cast<Private *>(data); |
| 125 | p->pending.supported = supported == 0 ? false : true; |
| 126 | p->pending.supportedChanged = true; |
| 127 | } |
| 128 | |
| 129 | void Dpms::Private::modeCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms, uint32_t mode) |
| 130 | { |
| 131 | Q_UNUSED(org_kde_kwin_dpms) |
| 132 | Mode m; |
| 133 | switch (mode) { |
| 134 | case ORG_KDE_KWIN_DPMS_MODE_ON: |
| 135 | m = Mode::On; |
| 136 | break; |
| 137 | case ORG_KDE_KWIN_DPMS_MODE_STANDBY: |
| 138 | m = Mode::Standby; |
| 139 | break; |
| 140 | case ORG_KDE_KWIN_DPMS_MODE_SUSPEND: |
| 141 | m = Mode::Suspend; |
| 142 | break; |
| 143 | case ORG_KDE_KWIN_DPMS_MODE_OFF: |
| 144 | m = Mode::Off; |
| 145 | break; |
| 146 | default: |
| 147 | return; |
| 148 | } |
| 149 | Private *p = reinterpret_cast<Private *>(data); |
| 150 | p->pending.mode = m; |
| 151 | p->pending.modeChanged = true; |
| 152 | } |
| 153 | |
| 154 | void Dpms::Private::doneCallback(void *data, org_kde_kwin_dpms *org_kde_kwin_dpms) |
| 155 | { |
| 156 | Q_UNUSED(org_kde_kwin_dpms) |
| 157 | Private *p = reinterpret_cast<Private *>(data); |
| 158 | const bool supportedChanged = p->pending.supportedChanged && p->pending.supported != p->current.supported; |
| 159 | const bool modeChanged = p->pending.modeChanged && p->pending.mode != p->current.mode; |
| 160 | if (supportedChanged) { |
| 161 | p->current.supported = p->pending.supported; |
| 162 | Q_EMIT p->q->supportedChanged(); |
| 163 | } |
| 164 | if (modeChanged) { |
| 165 | p->current.mode = p->pending.mode; |
| 166 | Q_EMIT p->q->modeChanged(); |
| 167 | } |
| 168 | p->pending = Data(); |
| 169 | } |
| 170 | |
| 171 | Dpms::Private::Private(const QPointer<Output> &output, Dpms *q) |
| 172 | : output(output) |
| 173 | , q(q) |
| 174 | { |
| 175 | } |
| 176 | |
| 177 | void Dpms::Private::setup(org_kde_kwin_dpms *d) |
| 178 | { |
| 179 | Q_ASSERT(d); |
| 180 | Q_ASSERT(!dpms.isValid()); |
| 181 | dpms.setup(pointer: d); |
| 182 | org_kde_kwin_dpms_add_listener(org_kde_kwin_dpms: dpms, listener: &s_listener, data: this); |
| 183 | } |
| 184 | |
| 185 | Dpms::Dpms(const QPointer<Output> &o, QObject *parent) |
| 186 | : QObject(parent) |
| 187 | , d(new Private(o, this)) |
| 188 | { |
| 189 | } |
| 190 | |
| 191 | Dpms::~Dpms() |
| 192 | { |
| 193 | release(); |
| 194 | } |
| 195 | |
| 196 | void Dpms::destroy() |
| 197 | { |
| 198 | d->dpms.destroy(); |
| 199 | } |
| 200 | |
| 201 | void Dpms::release() |
| 202 | { |
| 203 | d->dpms.release(); |
| 204 | } |
| 205 | |
| 206 | bool Dpms::isValid() const |
| 207 | { |
| 208 | return d->dpms.isValid(); |
| 209 | } |
| 210 | |
| 211 | void Dpms::setup(org_kde_kwin_dpms *dpms) |
| 212 | { |
| 213 | d->setup(dpms); |
| 214 | } |
| 215 | |
| 216 | bool Dpms::isSupported() const |
| 217 | { |
| 218 | return d->current.supported; |
| 219 | } |
| 220 | |
| 221 | Dpms::Mode Dpms::mode() const |
| 222 | { |
| 223 | return d->current.mode; |
| 224 | } |
| 225 | |
| 226 | void Dpms::requestMode(Dpms::Mode mode) |
| 227 | { |
| 228 | uint32_t wlMode; |
| 229 | switch (mode) { |
| 230 | case Mode::On: |
| 231 | wlMode = ORG_KDE_KWIN_DPMS_MODE_ON; |
| 232 | break; |
| 233 | case Mode::Standby: |
| 234 | wlMode = ORG_KDE_KWIN_DPMS_MODE_STANDBY; |
| 235 | break; |
| 236 | case Mode::Suspend: |
| 237 | wlMode = ORG_KDE_KWIN_DPMS_MODE_SUSPEND; |
| 238 | break; |
| 239 | case Mode::Off: |
| 240 | wlMode = ORG_KDE_KWIN_DPMS_MODE_OFF; |
| 241 | break; |
| 242 | default: |
| 243 | Q_UNREACHABLE(); |
| 244 | } |
| 245 | org_kde_kwin_dpms_set(org_kde_kwin_dpms: d->dpms, mode: wlMode); |
| 246 | } |
| 247 | |
| 248 | QPointer<Output> Dpms::output() const |
| 249 | { |
| 250 | return d->output; |
| 251 | } |
| 252 | |
| 253 | Dpms::operator org_kde_kwin_dpms *() |
| 254 | { |
| 255 | return d->dpms; |
| 256 | } |
| 257 | |
| 258 | Dpms::operator org_kde_kwin_dpms *() const |
| 259 | { |
| 260 | return d->dpms; |
| 261 | } |
| 262 | |
| 263 | } |
| 264 | } |
| 265 | |
| 266 | #include "moc_dpms.cpp" |
| 267 | |