1 /*
2     SPDX-FileCopyrightText: 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca>
3     SPDX-FileCopyrightText: 1999 Dirk A. Mueller <dmuell@gmx.net>
4     SPDX-FileCopyrightText: 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
5     SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org>
6     SPDX-FileCopyrightText: 2000 Bernd Gehrmann
7     SPDX-FileCopyrightText: 2000 Rik Hemsley <rik@kde.org>
8     SPDX-FileCopyrightText: 2000 Brad Hughes <bhughes@trolltech.com>
9     SPDX-FileCopyrightText: 2004 Brad Hards <bradh@frogmouth.net>
10     SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
11 
12     SPDX-License-Identifier: GPL-2.0-or-later
13 */
14 #include "xlib_config.h"
15 
16 #include "../configcontainer.h"
17 #include "backends/x11/x11_evdev_backend.h"
18 
19 #include "../../../migrationlib/kdelibs4config.h"
20 
21 #include <KLocalizedString>
22 #include <KToolInvocation>
23 //#include <KConfig>
24 #include <KAboutData>
25 #include <KPluginFactory>
26 
27 #include <QCheckBox>
28 #include <QDoubleSpinBox>
29 #include <QFormLayout>
30 #include <QSpinBox>
31 #include <QStandardPaths>
32 #include <QTabWidget>
33 #include <QWhatsThis>
34 
35 #include <KConfig>
36 #include <KConfigGroup>
37 
XlibConfig(ConfigContainer * parent,InputBackend * backend)38 XlibConfig::XlibConfig(ConfigContainer *parent, InputBackend *backend)
39     : ConfigPlugin(parent)
40     , m_backend(dynamic_cast<X11EvdevBackend *>(backend))
41 {
42     setupUi(this);
43 
44     handedGroup->setId(rightHanded, static_cast<int>(Handed::Right));
45     handedGroup->setId(leftHanded, static_cast<int>(Handed::Left));
46 
47     connect(handedGroup, SIGNAL(buttonClicked(int)), m_parent, SLOT(changed()));
48     connect(handedGroup, SIGNAL(buttonClicked(int)), this, SLOT(slotHandedChanged(int)));
49 
50     connect(cbScrollPolarity, SIGNAL(clicked()), m_parent, SLOT(changed()));
51     connect(cbScrollPolarity, SIGNAL(clicked()), this, SLOT(slotScrollPolarityChanged()));
52 
53     connect(accel, SIGNAL(valueChanged(double)), m_parent, SLOT(changed()));
54     connect(thresh, SIGNAL(valueChanged(int)), m_parent, SLOT(changed()));
55     connect(thresh, SIGNAL(valueChanged(int)), this, SLOT(slotThreshChanged(int)));
56     slotThreshChanged(thresh->value());
57 
58     // It would be nice if the user had a test field.
59     // Selecting such values in milliseconds is not intuitive
60     connect(doubleClickInterval, SIGNAL(valueChanged(int)), m_parent, SLOT(changed()));
61 
62     connect(dragStartTime, SIGNAL(valueChanged(int)), m_parent, SLOT(changed()));
63 
64     connect(dragStartDist, SIGNAL(valueChanged(int)), m_parent, SLOT(changed()));
65     connect(dragStartDist, SIGNAL(valueChanged(int)), this, SLOT(slotDragStartDistChanged(int)));
66     slotDragStartDistChanged(dragStartDist->value());
67 
68     connect(wheelScrollLines, SIGNAL(valueChanged(int)), m_parent, SLOT(changed()));
69     connect(wheelScrollLines, SIGNAL(valueChanged(int)), SLOT(slotWheelScrollLinesChanged(int)));
70     slotWheelScrollLinesChanged(wheelScrollLines->value());
71 
72     connect(mouseKeys, SIGNAL(clicked()), this, SLOT(checkAccess()));
73     connect(mouseKeys, SIGNAL(clicked()), m_parent, SLOT(changed()));
74     connect(mk_delay, SIGNAL(valueChanged(int)), m_parent, SLOT(changed()));
75     connect(mk_interval, SIGNAL(valueChanged(int)), m_parent, SLOT(changed()));
76     connect(mk_time_to_max, SIGNAL(valueChanged(int)), m_parent, SLOT(changed()));
77     connect(mk_max_speed, SIGNAL(valueChanged(int)), m_parent, SLOT(changed()));
78     connect(mk_curve, SIGNAL(valueChanged(int)), m_parent, SLOT(changed()));
79 
80     KAboutData *about = new KAboutData(QStringLiteral("kcmmouse"),
81                                        i18n("Mouse"),
82                                        QStringLiteral("1.0"),
83                                        QString(),
84                                        KAboutLicense::GPL,
85                                        i18n("(c) 1997 - 2018 Mouse developers"));
86     about->addAuthor(i18n("Patrick Dowler"));
87     about->addAuthor(i18n("Dirk A. Mueller"));
88     about->addAuthor(i18n("David Faure"));
89     about->addAuthor(i18n("Bernd Gehrmann"));
90     about->addAuthor(i18n("Rik Hemsley"));
91     about->addAuthor(i18n("Brad Hughes"));
92     about->addAuthor(i18n("Brad Hards"));
93     about->addAuthor(i18n("Roman Gilg"));
94     m_parent->setAboutData(about);
95 }
96 
checkAccess()97 void XlibConfig::checkAccess()
98 {
99     mk_delay->setEnabled(mouseKeys->isChecked());
100     mk_interval->setEnabled(mouseKeys->isChecked());
101     mk_time_to_max->setEnabled(mouseKeys->isChecked());
102     mk_max_speed->setEnabled(mouseKeys->isChecked());
103     mk_curve->setEnabled(mouseKeys->isChecked());
104 }
105 
getAccel()106 double XlibConfig::getAccel()
107 {
108     return accel->value();
109 }
110 
setAccel(double val)111 void XlibConfig::setAccel(double val)
112 {
113     accel->setValue(val);
114 }
115 
getThreshold()116 int XlibConfig::getThreshold()
117 {
118     return thresh->value();
119 }
120 
setThreshold(int val)121 void XlibConfig::setThreshold(int val)
122 {
123     thresh->setValue(val);
124 }
125 
getHandedness()126 Handed XlibConfig::getHandedness()
127 {
128     if (rightHanded->isChecked())
129         return Handed::Right;
130     else
131         return Handed::Left;
132 }
133 
setHandedness(Handed val)134 void XlibConfig::setHandedness(Handed val)
135 {
136     rightHanded->setChecked(false);
137     leftHanded->setChecked(false);
138     if (val == Handed::Right) {
139         rightHanded->setChecked(true);
140         mousePix->setPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kcmmouse/pics/mouse_rh.png"));
141     } else {
142         leftHanded->setChecked(true);
143         mousePix->setPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kcmmouse/pics/mouse_lh.png"));
144     }
145     m_backend->settings()->handedNeedsApply = true;
146 }
147 
load()148 void XlibConfig::load()
149 {
150     EvdevSettings *settings = m_backend->settings();
151 
152     m_parent->kcmLoad();
153     m_backend->load();
154 
155     // Only allow setting reversing scroll polarity if we have scroll buttons
156     if (m_backend) {
157         if (m_backend->supportScrollPolarity()) {
158             cbScrollPolarity->setEnabled(true);
159             cbScrollPolarity->show();
160         } else {
161             cbScrollPolarity->setEnabled(false);
162             cbScrollPolarity->hide();
163         }
164     }
165 
166     rightHanded->setEnabled(settings->handedEnabled);
167     leftHanded->setEnabled(settings->handedEnabled);
168     if (cbScrollPolarity->isEnabled())
169         cbScrollPolarity->setEnabled(settings->handedEnabled);
170     cbScrollPolarity->setChecked(settings->reverseScrollPolarity);
171 
172     setAccel(settings->accelRate);
173     setThreshold(settings->thresholdMove);
174     setHandedness(settings->handed);
175 
176     doubleClickInterval->setValue(settings->doubleClickInterval);
177     dragStartTime->setValue(settings->dragStartTime);
178     dragStartDist->setValue(settings->dragStartDist);
179     wheelScrollLines->setValue(settings->wheelScrollLines);
180 
181     KConfig ac("kaccessrc");
182 
183     KConfigGroup group = ac.group("Mouse");
184     mouseKeys->setChecked(group.readEntry("MouseKeys", false));
185     mk_delay->setValue(group.readEntry("MKDelay", 160));
186 
187     int interval = group.readEntry("MKInterval", 5);
188     mk_interval->setValue(interval);
189 
190     // Default time to reach maximum speed: 5000 msec
191     int time_to_max = group.readEntry("MKTimeToMax", (5000 + interval / 2) / interval);
192     time_to_max = group.readEntry("MK-TimeToMax", time_to_max * interval);
193     mk_time_to_max->setValue(time_to_max);
194 
195     // Default maximum speed: 1000 pixels/sec
196     //     (The old default maximum speed from KDE <= 3.4
197     //     (100000 pixels/sec) was way too fast)
198     long max_speed = group.readEntry("MKMaxSpeed", interval);
199     max_speed = max_speed * 1000 / interval;
200     if (max_speed > 2000)
201         max_speed = 2000;
202     max_speed = group.readEntry("MK-MaxSpeed", int(max_speed));
203     mk_max_speed->setValue(max_speed);
204 
205     mk_curve->setValue(group.readEntry("MKCurve", 0));
206 
207     checkAccess();
208     Q_EMIT m_parent->changed(false);
209 }
210 
save()211 void XlibConfig::save()
212 {
213     EvdevSettings *settings = m_backend->settings();
214 
215     settings->accelRate = getAccel();
216     settings->thresholdMove = getThreshold();
217     settings->handed = getHandedness();
218 
219     settings->doubleClickInterval = doubleClickInterval->value();
220     settings->dragStartTime = dragStartTime->value();
221     settings->dragStartDist = dragStartDist->value();
222     settings->wheelScrollLines = wheelScrollLines->value();
223     settings->reverseScrollPolarity = cbScrollPolarity->isChecked();
224 
225     m_backend->apply();
226     settings->save();
227 
228     KConfig ac("kaccessrc");
229 
230     KConfigGroup group = ac.group("Mouse");
231 
232     int interval = mk_interval->value();
233     group.writeEntry("MouseKeys", mouseKeys->isChecked());
234     group.writeEntry("MKDelay", mk_delay->value());
235     group.writeEntry("MKInterval", interval);
236     group.writeEntry("MK-TimeToMax", mk_time_to_max->value());
237     group.writeEntry("MKTimeToMax", (mk_time_to_max->value() + interval / 2) / interval);
238     group.writeEntry("MK-MaxSpeed", mk_max_speed->value());
239     group.writeEntry("MKMaxSpeed", (mk_max_speed->value() * interval + 500) / 1000);
240     group.writeEntry("MKCurve", mk_curve->value());
241     group.sync();
242 
243     // restart kaccess
244     KToolInvocation::startServiceByDesktopName("kaccess");
245 
246     Q_EMIT m_parent->changed(false);
247 }
248 
defaults()249 void XlibConfig::defaults()
250 {
251     setThreshold(2);
252     setAccel(2);
253     setHandedness(Handed::Right);
254     cbScrollPolarity->setChecked(false);
255     doubleClickInterval->setValue(400);
256     dragStartTime->setValue(500);
257     dragStartDist->setValue(4);
258     wheelScrollLines->setValue(3);
259 
260     mouseKeys->setChecked(false);
261     mk_delay->setValue(160);
262     mk_interval->setValue(5);
263     mk_time_to_max->setValue(5000);
264     mk_max_speed->setValue(1000);
265     mk_curve->setValue(0);
266 
267     checkAccess();
268     m_parent->kcmDefaults();
269 
270     Q_EMIT m_parent->changed(true);
271 }
272 
273 /** No descriptions */
slotHandedChanged(int val)274 void XlibConfig::slotHandedChanged(int val)
275 {
276     if (val == static_cast<int>(Handed::Right))
277         mousePix->setPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kcmmouse/pics/mouse_rh.png"));
278     else
279         mousePix->setPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kcmmouse/pics/mouse_lh.png"));
280     m_backend->settings()->handedNeedsApply = true;
281 }
282 
slotThreshChanged(int value)283 void XlibConfig::slotThreshChanged(int value)
284 {
285     thresh->setSuffix(i18np(" pixel", " pixels", value));
286 }
287 
slotDragStartDistChanged(int value)288 void XlibConfig::slotDragStartDistChanged(int value)
289 {
290     dragStartDist->setSuffix(i18np(" pixel", " pixels", value));
291 }
292 
slotWheelScrollLinesChanged(int value)293 void XlibConfig::slotWheelScrollLinesChanged(int value)
294 {
295     wheelScrollLines->setSuffix(i18np(" line", " lines", value));
296 }
297 
slotScrollPolarityChanged()298 void XlibConfig::slotScrollPolarityChanged()
299 {
300     m_backend->settings()->handedNeedsApply = true;
301 }
302