File indexing completed on 2024-04-28 05:30:17

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2017 Martin Flöser <mgraesslin@kde.org>
0006     SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 #include "idle_inhibition.h"
0011 #include "input.h"
0012 #include "virtualdesktops.h"
0013 #include "wayland/surface.h"
0014 #include "window.h"
0015 #include "workspace.h"
0016 
0017 #include <algorithm>
0018 #include <functional>
0019 
0020 namespace KWin
0021 {
0022 
0023 IdleInhibition::IdleInhibition(QObject *parent)
0024     : QObject(parent)
0025 {
0026     // Workspace is created after the wayland server is initialized.
0027     connect(kwinApp(), &Application::workspaceCreated, this, &IdleInhibition::slotWorkspaceCreated);
0028 }
0029 
0030 IdleInhibition::~IdleInhibition() = default;
0031 
0032 void IdleInhibition::registerClient(Window *client)
0033 {
0034     if (!client->surface()) {
0035         return;
0036     }
0037 
0038     auto updateInhibit = [this, client] {
0039         update(client);
0040     };
0041 
0042     m_connections[client] = connect(client->surface(), &SurfaceInterface::inhibitsIdleChanged, this, updateInhibit);
0043     connect(client, &Window::desktopsChanged, this, updateInhibit);
0044     connect(client, &Window::minimizedChanged, this, updateInhibit);
0045     connect(client, &Window::windowHidden, this, updateInhibit);
0046     connect(client, &Window::windowShown, this, updateInhibit);
0047     connect(client, &Window::closed, this, [this, client]() {
0048         uninhibit(client);
0049         auto it = m_connections.find(client);
0050         if (it != m_connections.end()) {
0051             disconnect(it.value());
0052             m_connections.erase(it);
0053         }
0054     });
0055 
0056     updateInhibit();
0057 }
0058 
0059 void IdleInhibition::inhibit(Window *client)
0060 {
0061     input()->addIdleInhibitor(client);
0062     // TODO: notify powerdevil?
0063 }
0064 
0065 void IdleInhibition::uninhibit(Window *client)
0066 {
0067     input()->removeIdleInhibitor(client);
0068 }
0069 
0070 void IdleInhibition::update(Window *client)
0071 {
0072     if (client->isInternal() || client->isUnmanaged()) {
0073         return;
0074     }
0075 
0076     // TODO: Don't honor the idle inhibitor object if the shell client is not
0077     // on the current activity (currently, activities are not supported).
0078     const bool visible = client->isShown() && client->isOnCurrentDesktop();
0079     if (visible && client->surface() && client->surface()->inhibitsIdle()) {
0080         inhibit(client);
0081     } else {
0082         uninhibit(client);
0083     }
0084 }
0085 
0086 void IdleInhibition::slotWorkspaceCreated()
0087 {
0088     connect(workspace(), &Workspace::windowAdded, this, &IdleInhibition::registerClient);
0089     connect(workspace(), &Workspace::currentDesktopChanged, this, &IdleInhibition::slotDesktopChanged);
0090 }
0091 
0092 void IdleInhibition::slotDesktopChanged()
0093 {
0094     workspace()->forEachWindow([this](Window *c) {
0095         update(c);
0096     });
0097 }
0098 
0099 }
0100 
0101 #include "moc_idle_inhibition.cpp"