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