File: screenbrightnesscontroller.h

package info (click to toggle)
powerdevil 4%3A6.5.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 10,680 kB
  • sloc: cpp: 13,284; xml: 1,911; python: 1,204; sh: 19; makefile: 10
file content (239 lines) | stat: -rw-r--r-- 9,471 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*  This file is part of the KDE project
    SPDX-FileCopyrightText: 2006 Kevin Ottens <ervin@kde.org>
    SPDX-FileCopyrightText: 2008-2010 Dario Freddi <drf@kde.org>
    SPDX-FileCopyrightText: 2010 Alejandro Fiestas <alex@eyeos.org>
    SPDX-FileCopyrightText: 2015 Kai Uwe Broulik <kde@privat.broulik.de>
    SPDX-FileCopyrightText: 2024 Jakob Petsovits <jpetso@petsovits.com>

    SPDX-License-Identifier: LGPL-2.0-only

*/

#pragma once

#include <KScreen/Types>

#include <QHash>
#include <QObject>
#include <QStringList>

#include <optional>
#include <unordered_map>

#include <powerdevilcore_export.h>

#include "displaybrightness.h"
#include "displaymatch.h"
#include "powerdevilscreenbrightnesslogic.h"

class ExternalBrightnessController;

class POWERDEVILCORE_EXPORT ScreenBrightnessController : public QObject
{
    Q_OBJECT

public:
    enum BrightnessStepSize {
        RegularStepSize,
        SmallStepSize,
    };

    /// This hint will be ignored by ScreenBrightnessController itself, but forwarded to any
    /// signals emitted by the corresponding brightness setter call.
    enum IndicatorHint {
        ShowIndicator = 0,
        SuppressIndicator = 1,
    };

    explicit ScreenBrightnessController();
    ~ScreenBrightnessController() override;

    /**
     * Actively look for connected displays.
     *
     * This will emit detectionFinished signal once all candidates were checked, and after initial
     * detection, displayAdded/displayRemoved can be emitted whenever a change in display
     * connections is observed.
     */
    void detectDisplays();
    bool isSupported() const;

    /**
     * A list of string identifiers for displays that support brightness operations.
     *
     * Note that a displayId is not necessarily stable across reboots and hotplugging events.
     * The same display may receive a different displayId when it is removed and later re-added.
     */
    QStringList displayIds() const;

    /**
     * A filtered list of string identifiers for displays that support brightness operations.
     *
     * Like `displayIds()`, but the list is narrowed down by a DisplayFilter.
     */
    QStringList displayIds(const DisplayFilter &) const;

    /**
     * A human-readable name for this display.
     */
    QString label(const QString &label) const;

    /**
     * Returns true if the display is part of the system (e.g. laptop panel),
     * false if external (e.g. monitor, drawing tablet) or unknown.
     */
    bool isInternal(const QString &displayId) const;

    int knownSafeMinBrightness(const QString &displayId) const;
    int minBrightness(const QString &displayId) const;
    int maxBrightness(const QString &displayId) const;
    int brightness(const QString &displayId) const;

    /**
     * Set display brightness for this @p displayId to the given @p value.
     *
     * The @p value will be clamped to the range within minBrightness(@p displayId) and
     * maxBrightness(@p displayId). @p sourceClientName and @p sourceClientContext are passed to
     * the `brightnessChanged` signal that is emitted when a change has indeed happened.
     *
     * @see brightnessChanged
     */
    void setBrightness(const QString &displayId,
                       int value,
                       const QString &sourceClientName,
                       const QString &sourceClientContext,
                       IndicatorHint hint = SuppressIndicator);

    /**
     * Adjust display brightness for this @p displayId by a @p delta between -1.0 and 1.0.
     *
     * The @p delta will be converted to and clamped to the valid brightness range for this display.
     *  @p sourceClientName and @p sourceClientContext are passed to the `brightnessChanged` signal
     * that is emitted for each display when a change has indeed happened.
     *
     * @see brightnessChanged
     */
    void adjustBrightnessRatio(const QString &displayId, double delta, const QString &sourceClientName, const QString &sourceClientContext, IndicatorHint hint);

    /**
     * Adjust display brightness for a predetermined set of displays by a @p delta between -1.0 and 1.0.
     *
     * The @p delta will be converted to and clamped to the valid brightness range for each
     * affected display. @p sourceClientName and @p sourceClientContext are passed to the
     * `brightnessChanged` signal that is emitted for each display when a change has indeed happened.
     *
     * @see brightnessChanged
     */
    void adjustBrightnessRatio(double delta, const QString &sourceClientName, const QString &sourceClientContext, IndicatorHint hint = SuppressIndicator);

    /**
     * Adjust display brightness for a predetermined set of displays by a step up or down the
     * brightness scale.
     *
     * The direction and size of each step are specified by @p step. The exact behavior of step
     * movement and the set of affected displays are an implementation detail that may change
     * over time. @p sourceClientName and @p sourceClientContext are passed to the
     * `brightnessChanged` signal that is emitted when a change has indeed happened.
     *
     * @see brightnessChanged
     */
    void adjustBrightnessStep(PowerDevil::BrightnessLogic::StepAdjustmentAction adjustment,
                              const QString &sourceClientName,
                              const QString &sourceClientContext,
                              IndicatorHint hint = SuppressIndicator);

    int brightnessSteps(const QString &displayId) const;

    /**
     * Add, modify or remove a brightness limit for dimming, with a @p ratio between 0.0 and 1.0.
     *
     * Several limits can be set independently, distinguished by their @p dimmingId.
     * The lowest one will apply. Setting the @p ratio to 1.0 will remove this limit.
     *
     * Setting a dimming limit will have the same visible effect as calling setBrightness()
     * for all affected displays with the brightness value multiplied by @p ratio. However,
     * unlike setBrightness(), this function will not affect the value returned by brightness().
     * Subsequent setBrightness() calls will apply the same multiplier.
     *
     * By default, all currently connected displays are affected. Optional display id filter
     * parameters may be added in the future.
     *
     * Newly connected displays will remain at full brightness (i.e ratio of 1.0) until another
     * call of this function affects them. Displays which were previously dimmed and are
     * re-recognized after reconnection will be restored to the current applicable limit.
     */
    void setDimmingRatio(const QString &dimmingId, double ratio);

    KScreen::OutputPtr tryMatchKScreenOutput(const QString &displayId) const;

    // legacy API without displayId parameter, kept for backward compatibility
    QStringList legacyDisplayIds() const;
    int knownSafeMinBrightness() const;
    int minBrightness() const;
    int maxBrightness() const;
    int brightness() const;
    void setBrightness(int value, IndicatorHint hint = SuppressIndicator);
    int brightnessSteps() const;

Q_SIGNALS:
    void detectionFinished();
    void displayIdsChanged(const QStringList &displayIds);
    void displayAdded(const QString &displayId);
    void displayRemoved(const QString &displayId);
    void brightnessChanged(const QString &displayId,
                           const PowerDevil::BrightnessLogic::BrightnessInfo &,
                           const QString &sourceClientName,
                           const QString &sourceClientContext,
                           IndicatorHint);

    // legacy API without displayId parameter, kept for backward compatibility.
    // include legacy prefix to avoid function overload errors when used in connect()
    void legacyDisplayIdsChanged(const QStringList &);
    void legacyBrightnessInfoChanged(const PowerDevil::BrightnessLogic::BrightnessInfo &, IndicatorHint);

private Q_SLOTS:
    void onDisplayDestroyed(QObject *);
    void onDetectorDisplaysChanged();
    void onExternalBrightnessChangeObserved(DisplayBrightness *display, int value);

private:
    int brightnessMultiplied(int value, double multiplier, int min) const;
    double dimmingRatioForDisplay(const QString &displayId);

private:
    struct DisplayInfo {
        DisplayBrightness *display = nullptr;
        DisplayBrightnessDetector *detector = nullptr;
        PowerDevil::ScreenBrightnessLogic brightnessLogic = {};
        DisplayMatch match;
        double dimmingRatio = 1.0;
        double trackingError = 0.0;
        bool zombie = false;
    };
    QStringList m_sortedDisplayIds;
    QStringList m_legacyDisplayIds;
    std::unordered_map<QString, DisplayInfo> m_displaysById;

    struct DetectorInfo {
        DisplayBrightnessDetector *detector = nullptr;
        const char *debugName = nullptr;
        const char *displayIdPrefix = nullptr;
    };
    QList<DetectorInfo> m_detectors;
    int m_finishedDetectingCount = 0;
    std::unique_ptr<ExternalBrightnessController> m_externalBrightnessController;

    struct RememberedDisplayState {
        int brightness;
        int minBrightness = 0;
        std::optional<double> latestActiveDimmingRatio;
    };
    std::map<DisplayMatch, RememberedDisplayState> m_rememberedDisplayState;

    struct DimmingLimit {
        double ratio = 1.0;
    };
    std::unordered_map<QString, DimmingLimit> m_dimmingLimits;

    KScreen::ConfigPtr m_kscreenConfig = nullptr;
};