diff --git a/daemon/powerdevilbrightnesslogic.h b/daemon/powerdevilbrightnesslogic.h
index 9ffdd02..3f4da27 100644
--- a/daemon/powerdevilbrightnesslogic.h
+++ b/daemon/powerdevilbrightnesslogic.h
@@ -146,7 +146,7 @@ public:
* @param step Brightness step, from 0 to steps
* @return Brightness value that corresponds to the given step
*/
- int stepToValue(int step) const;
+ virtual int stepToValue(int step) const;
/**
* Convert raw brightness value to brightness step
@@ -154,7 +154,7 @@ public:
* @param value Brightness value, from 0 to valueMax
* @return Brightness step that is nearest to the given brightness value
*/
- int valueToStep(int value) const;
+ virtual int valueToStep(int value) const;
protected:
@@ -171,9 +171,8 @@ protected:
* @param valueMax the maximum brightness value for which we want to calculate the number of steps
* @return the optimal maximum step number
*/
- virtual int calculateSteps(int valueMax) const = 0;
+ virtual int calculateSteps(int valueMax) = 0;
-private:
int m_value = -1;
int m_valueMax = -1;
int m_steps = -1;
diff --git a/daemon/powerdevilkeyboardbrightnesslogic.cpp b/daemon/powerdevilkeyboardbrightnesslogic.cpp
index c1f5dbf..939b1ea 100644
--- a/daemon/powerdevilkeyboardbrightnesslogic.cpp
+++ b/daemon/powerdevilkeyboardbrightnesslogic.cpp
@@ -24,7 +24,7 @@
namespace PowerDevil
{
-int KeyboardBrightnessLogic::calculateSteps(int maxValue) const
+int KeyboardBrightnessLogic::calculateSteps(int maxValue)
{
// We assume that a generally good number of steps for keyboard brightness is about 5.
diff --git a/daemon/powerdevilkeyboardbrightnesslogic.h b/daemon/powerdevilkeyboardbrightnesslogic.h
index 0ae630f..c378792 100644
--- a/daemon/powerdevilkeyboardbrightnesslogic.h
+++ b/daemon/powerdevilkeyboardbrightnesslogic.h
@@ -29,7 +29,7 @@ class KeyboardBrightnessLogic : public BrightnessLogic
{
protected:
- int calculateSteps(int valueMax) const override;
+ int calculateSteps(int valueMax) override;
};
diff --git a/daemon/powerdevilscreenbrightnesslogic.cpp b/daemon/powerdevilscreenbrightnesslogic.cpp
index 66e2a96..f9b926a 100644
--- a/daemon/powerdevilscreenbrightnesslogic.cpp
+++ b/daemon/powerdevilscreenbrightnesslogic.cpp
@@ -30,48 +30,95 @@ int ScreenBrightnessLogic::toggled() const
return -1;
}
-int ScreenBrightnessLogic::calculateSteps(int maxValue) const
+int ScreenBrightnessLogic::increased() const
{
- // We assume that the preferred number of steps for screen brightness is 20, but we don't want more.
-
- if (maxValue <= 20) {
- // Too few steps, return the number of actual steps.
- // Those would be uniform, but not round in some cases.
- return maxValue;
+ if (m_value == m_valueMax) {
+ return m_valueMax; // we are at the maximum already
}
- if (maxValue >= 100 || maxValue % 20 == 0 || (maxValue >= 80 && maxValue % 4 == 0)) {
- // In this case all 20 steps are perfect.
- return 20;
+ int step = valueToStep(m_value) + 1;
+
+ return stepToValue(step);
+}
+
+int ScreenBrightnessLogic::decreased() const
+{
+ int step = valueToStep(m_value);
+
+ if ((m_value == 0)||(step == 0)) {
+ return 0; // we are at the minimum already
}
+ step -= 1;
- // At this point we have maxValue in the range 21-79 which probably is a rare case.
+ return stepToValue(step);
+}
- if (maxValue >= 34 || maxValue == 32 || maxValue == 28) {
- // In this case all 20 steps are matched +-1%, which is fine.
- return 20;
+int ScreenBrightnessLogic::stepToValue(int step) const
+{
+ // This is the easy part
+ if (step >= m_steps) return m_valueMax;
+ if (step <= 0) return 0;
+ return m_steptab[step];
+}
+
+int ScreenBrightnessLogic::valueToStep(int value) const
+{
+ int step;
+ if (value >= m_valueMax) return m_steps;
+ if (value <= 0) return 0;
+ for (step = 1; step < m_steps; step++) {
+ // for very sparse steppings, endv can end up at value, thus <=
+ int endv = (m_steptab[step+1] + m_steptab[step]) / 2;
+ if (value <= endv) return step;
}
+ return m_steps;
+}
- // At this point we have maxValue in the range 21-33.
- // Trying to make 20 steps from here will make them not uniform.
- if (maxValue % 5 == 0) {
- // For maxValue == 30 there are 10 even and round steps.
- // For maxValue == 25 steps are shown as
- // 0% 12% 20% 32% 40% 52% 60% 72% 80% 92% 100%, which is also fine.
- return 10;
+int ScreenBrightnessLogic::calculateSteps(int maxValue)
+{
+ // F'ck uniformity of percentage steps. We want useful.
+ // Up to 20 steps is fine, tho.
+ // What i mean by useful is that the behaviour of values on lots of hardware is not linear,
+ // because the human visual system is not linear, and the use-cases are not linear.
+ // The use cases that matter being basically either in a dark room, or in the sunshine.
+ // Basically any implementation that works for those will also be fine for "office"
+ // -- i mean, as long as we have some middle-of-the range points.
+
+ if (maxValue <= 20) {
+ // So few steps that we can provide each step directly. Easy.
+ for (int i = 0; i <= maxValue; i++) m_steptab[i] = i;
+ return maxValue;
}
- // Trying hard to find an uniform steps set
- for (int steps = 9; steps <= 14; steps++) {
- if (maxValue % steps == 0) {
- return steps;
+ m_steptab[0] = 0;
+ // First step is the lowest (non-zero) value that averages to atleast 1 %.
+ for (int v = 1; v < maxValue; v++) {
+ int p = (percentage(v) + 0.5);
+ if (p >= 1) {
+ m_steptab[1] = v;
+ break;
}
}
- // 4 different maxValue values left: 21, 23, 29, 31.
- // Those produce +-2% on 10 steps, there is nothing better we can do here.
- return 10;
+ // We need each point to evaluate to a different percentage value.
+ // These are crudely mapped from exponential-ish curve to the
+ // integer percentage space and finessed by hand to look nicer.
+ // Note: the lower end here can be unrepresentable if maxValue < 100.
+ // Thus we eliminate the duplicates.
+
+ const int basetab[14] = { 2,3,4,5,6,7,8,10,15,20,25,40,50,75 };
+ int stepout = 2;
+ for (int i = 0; i < 14; i++) {
+ float vf = (basetab[i] * maxValue) / 100.0f;
+ int v = vf + 0.5f;
+ if (m_steptab[stepout-1] == v) {
+ continue;
+ }
+ m_steptab[stepout++] = v;
+ }
+ m_steptab[stepout] = maxValue;
+ return stepout;
}
};
diff --git a/daemon/powerdevilscreenbrightnesslogic.h b/daemon/powerdevilscreenbrightnesslogic.h
index ce71e6b..1ed4254 100644
--- a/daemon/powerdevilscreenbrightnesslogic.h
+++ b/daemon/powerdevilscreenbrightnesslogic.h
@@ -31,9 +31,16 @@ class ScreenBrightnessLogic : public BrightnessLogic
public:
int toggled() const override;
-protected:
- int calculateSteps(int valueMax) const override;
+ int increased() const override;
+ int decreased() const override;
+
+ int stepToValue(int step) const override;
+ int valueToStep(int value) const override;
+protected:
+ int calculateSteps(int valueMax) override;
+ // Fencepost: there's actually 21 steps going 0,5,10,...,95,100
+ int m_steptab[21];
};
}