1 /*
2 Copyright (C) 2016 P.L. Lucas <selairi@gmail.com>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "xrandrbrightness.h"
20 #include "brightnesswatcher.h"
21
22 #include <QDebug>
23 #include <QTimer>
24 #include <LXQt/SingleApplication>
25 #include <QCommandLineParser>
26 #include <QMessageBox>
27 #include "brightnesssettings.h"
28
29 #include <iostream>
30
31 enum CommandLineParseResult {
32 CommandLineOk,
33 CommandLineError,
34 CommandLineVersionRequested,
35 CommandLineHelpRequested
36 };
37
38 enum UiMode {
39 GUI,
40 TUI
41 };
42
43 struct BrightnessConfigData {
44 BrightnessConfigData();
45
46 UiMode mode;
47 bool increaseBrightness;
48 bool decreaseBrightness;
49 bool setBrightness;
50 float brightnessValue;
51 bool resetGamma;
52 };
53
BrightnessConfigData()54 BrightnessConfigData::BrightnessConfigData()
55 : mode(UiMode::GUI),
56 increaseBrightness(false),
57 decreaseBrightness(false),
58 setBrightness(false),
59 brightnessValue(0.0f),
60 resetGamma(false)
61 {
62 }
63
parseCommandLine(QCommandLineParser * parser,BrightnessConfigData * config,QString * errorMessage)64 static CommandLineParseResult parseCommandLine(QCommandLineParser *parser, BrightnessConfigData *config, QString *errorMessage)
65 {
66 parser->setApplicationDescription(QStringLiteral("LXQt Config Brightness"));
67 QCommandLineOption increaseOption(QStringList() << QStringLiteral("i") << QStringLiteral("increase"),
68 QObject::tr("Increase brightness."));
69 QCommandLineOption decreaseOption(QStringList() << QStringLiteral("d") << QStringLiteral("decrease"),
70 QObject::tr("Decrease brightness."));
71 QCommandLineOption setOption(QStringList() << QStringLiteral("s") << QStringLiteral("set"),
72 QObject::tr("Set brightness from 1 to 100."), QStringLiteral("brightness"));
73 QCommandLineOption resetGammaOption(QStringList() << QStringLiteral("r") << QStringLiteral("reset"),
74 QObject::tr("Reset gamma to default value."));
75 QCommandLineOption helpOption = parser->addHelpOption();
76 QCommandLineOption versionOption = parser->addVersionOption();
77 parser->addOption(increaseOption);
78 parser->addOption(decreaseOption);
79 parser->addOption(setOption);
80 parser->addOption(resetGammaOption);
81
82 const QStringList args = QCoreApplication::arguments();
83 if (args.size() <= 1) { // no arguments given. GUI mode
84 config->mode = UiMode::GUI;
85 return CommandLineOk;
86 } else {
87 config->mode = UiMode::TUI;
88 }
89
90 if (!parser->parse(QCoreApplication::arguments())) {
91 *errorMessage = parser->errorText();
92 return CommandLineError;
93 }
94
95 if (parser->isSet(versionOption))
96 return CommandLineVersionRequested;
97
98 if (parser->isSet(helpOption))
99 return CommandLineHelpRequested;
100
101 const bool isIncreaseSet = parser->isSet(increaseOption);
102 const bool isDecreaseSet = parser->isSet(decreaseOption);
103
104 const bool isSetBrightnessSet = parser->isSet(setOption);
105 float brightnessValue = 0.0f;
106 if (isSetBrightnessSet)
107 brightnessValue = parser->value(setOption).toFloat();
108
109 const bool isResetGammaSet = parser->isSet(resetGammaOption);
110
111 if ((isIncreaseSet || isDecreaseSet) && isSetBrightnessSet) {
112 *errorMessage = QObject::tr("%1: Can't use increase/decrease and set in conjunction").arg(QCoreApplication::applicationName());
113 return CommandLineError;
114 }
115
116 if (isIncreaseSet && isDecreaseSet) {
117 *errorMessage = QObject::tr("%1: Can't use increase and decrease options in conjunction").arg(QCoreApplication::applicationName());
118 return CommandLineError;
119 }
120
121 config->increaseBrightness = isIncreaseSet;
122 config->decreaseBrightness = isDecreaseSet;
123 config->setBrightness = isSetBrightnessSet;
124 config->brightnessValue = brightnessValue;
125 config->resetGamma = isResetGammaSet;
126
127 return CommandLineOk;
128 }
129
main(int argn,char * argv[])130 int main(int argn, char* argv[])
131 {
132 LXQt::SingleApplication app(argn, argv);
133 app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
134
135 const QString VERINFO = QStringLiteral(LXQT_CONFIG_VERSION
136 "\nliblxqt " LXQT_VERSION
137 "\nQt " QT_VERSION_STR);
138 app.setApplicationVersion(VERINFO);
139
140 // Command line options
141 QCommandLineParser parser;
142
143 BrightnessConfigData config;
144 QString errorMessage;
145
146 switch(parseCommandLine(&parser, &config, &errorMessage)) {
147 case CommandLineOk:
148 break;
149 case CommandLineError:
150 std::cerr << qPrintable(errorMessage);
151 std::cerr << "\n\n";
152 std::cerr << qPrintable(parser.helpText());
153 return EXIT_FAILURE;
154 case CommandLineVersionRequested:
155 parser.showVersion();
156 Q_UNREACHABLE();
157 case CommandLineHelpRequested:
158 parser.showHelp();
159 Q_UNREACHABLE();
160 }
161
162 if (config.mode == UiMode::GUI) {
163 BrightnessSettings brightnessSettings;
164 brightnessSettings.setWindowIcon(QIcon(QLatin1String(ICON_DIR) + QStringLiteral("/brightnesssettings.svg")));
165 brightnessSettings.show();
166 return app.exec();
167 }
168
169 // TUi mode
170 float sign = (config.decreaseBrightness) ? -1.0f : 1.0f;
171 float brightnessValue = qMin( qMax(config.brightnessValue, 0.0f), 100.0f ) / 100.0f;
172
173 // Checks if backlight driver is available
174 LXQt::Backlight *mBacklight = new LXQt::Backlight(&app);
175 if (mBacklight->isBacklightAvailable() && !config.resetGamma) { // Use backlight driver
176 BrightnessWatcher *brightnessWatcher = new BrightnessWatcher(&app);
177
178 // Qt::QueuedConnection needed. The event loop isn't running, yet.
179 QObject::connect(mBacklight, &LXQt::Backlight::backlightChanged,
180 brightnessWatcher, &BrightnessWatcher::changed, Qt::QueuedConnection);
181
182 if (config.setBrightness)
183 sign = 0.0f;
184
185 const int currentBacklight = mBacklight->getBacklight();
186 const int maxBacklight = mBacklight->getMaxBacklight();
187 int backlight = ( currentBacklight + sign*(maxBacklight/50 + 1) )*qAbs(sign) + brightnessValue*maxBacklight;
188
189 mBacklight->setBacklight(backlight);
190
191 // Timeout for situations where LXQtBacklight::setBacklight() doesn't
192 // produce a changed signal.
193 // QTimer::singleShot() doesn't allow to choose the type of connection.
194 // Qt::QueuedConnection needed. The event loop isn't running, yet.
195 QTimer *timeout = new QTimer(&app);
196 QObject::connect(timeout, &QTimer::timeout, &app, LXQt::SingleApplication::quit, Qt::QueuedConnection);
197 timeout->setSingleShot(true);
198 timeout->setInterval(2000);
199 timeout->start();
200 } else { // Use XRandr driver
201 XRandrBrightness *brightness = new XRandrBrightness();
202 const QList<MonitorInfo> monitors = brightness->getMonitorsInfo();
203 QList<MonitorInfo> monitorsChanged;
204 for(MonitorInfo monitor : monitors)
205 {
206 if(config.resetGamma)
207 {
208 monitor.setBrightness(1.0f);
209 monitorsChanged.append(monitor);
210 continue;
211 }
212
213 if(monitor.isBacklightSupported() )
214 {
215 long backlight = ( monitor.backlight() + sign*(monitor.backlightMax()/50 + 1) )*qAbs(sign) + brightnessValue*monitor.backlightMax();
216 if(backlight<monitor.backlightMax() && backlight>0)
217 {
218 monitor.setBacklight(backlight);
219 monitorsChanged.append(monitor);
220 }
221 }
222 else
223 {
224 float brightness = (monitor.brightness() + 0.1f *sign)*qAbs(sign) + brightnessValue * 2.0f;
225 if(brightness < 2.0f && brightness > 0.0f)
226 {
227 monitor.setBrightness(brightness);
228 monitorsChanged.append(monitor);
229 }
230 }
231 }
232 brightness->setMonitorsSettings(monitorsChanged);
233 delete brightness;
234 return 0;
235 }
236
237 // We need to start the event loop. Otherwise the signal/slot mechanism
238 // won't work.
239 return app.exec();
240 }
241