4
* Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca
6
* Layout management, enhancements:
7
* Copyright (c) 1999 Dirk A. Mueller <dmuell@gmx.net>
9
* SC/DC/AutoSelect/ChangeCursor:
10
* Copyright (c) 2000 David Faure <faure@kde.org>
12
* Double click interval, drag time & dist
13
* Copyright (c) 2000 Bernd Gehrmann
15
* Large cursor support
16
* Visual activation TODO: speed
17
* Copyright (c) 2000 Rik Hemsley <rik@kde.org>
19
* White cursor support
20
* TODO: give user the option to choose a certain cursor font
23
* General/Advanced tabs
24
* Copyright (c) 2000 Brad Hughes <bhughes@trolltech.com>
26
* redesign for KDE 2.2
27
* Copyright (c) 2001 Ralf Nolden <nolden@kde.org>
29
* Logitech mouse support
30
* Copyright (C) 2004 Brad Hards <bradh@frogmouth.net>
32
* Requires the Qt widget libraries, available at no cost at
33
* http://www.troll.no/
35
* This program is free software; you can redistribute it and/or modify
36
* it under the terms of the GNU General Public License as published by
37
* the Free Software Foundation; either version 2 of the License, or
38
* (at your option) any later version.
40
* This program is distributed in the hope that it will be useful,
41
* but WITHOUT ANY WARRANTY; without even the implied warranty of
42
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43
* GNU General Public License for more details.
45
* You should have received a copy of the GNU General Public License
46
* along with this program; if not, write to the Free Software
47
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
57
#include <QRadioButton>
59
#include <ktoolinvocation.h>
63
#include <kstandarddirs.h>
65
#include <kaboutdata.h>
66
#include <KPluginFactory>
67
#include <KPluginLoader>
69
#include <config-workspace.h>
75
#include <X11/Xutil.h>
76
#include <kglobalsettings.h>
82
K_PLUGIN_FACTORY(MouseConfigFactory,
83
registerPlugin<MouseConfig>(); // mouse
85
K_EXPORT_PLUGIN(MouseConfigFactory("kcminput"))
87
MouseConfig::MouseConfig(QWidget *parent, const QVariantList &args)
88
: KCModule(MouseConfigFactory::componentData(), parent, args)
92
setQuickHelp( i18n("<h1>Mouse</h1> This module allows you to choose various"
93
" options for the way in which your pointing device works. Your"
94
" pointing device may be a mouse, trackball, or some other hardware"
95
" that performs a similar function."));
99
QBoxLayout *top = new QVBoxLayout(this);
101
top->setSpacing(KDialog::spacingHint());
103
tabwidget = new QTabWidget(this);
104
top->addWidget(tabwidget);
106
tab1 = new KMouseDlg(this);
107
Q3ButtonGroup *group = new Q3ButtonGroup( tab1 );
108
group->setExclusive( true );
110
group->insert( tab1->singleClick );
111
group->insert( tab1->doubleClick );
113
tabwidget->addTab(tab1, i18n("&General"));
115
connect(tab1->handedBox, SIGNAL(clicked(int)), this, SLOT(changed()));
116
connect(tab1->handedBox, SIGNAL(clicked(int)), this, SLOT(slotHandedChanged(int)));
118
wtstr = i18n("If you are left-handed, you may prefer to swap the"
119
" functions of the left and right buttons on your pointing device"
120
" by choosing the 'left-handed' option. If your pointing device"
121
" has more than two buttons, only those that function as the"
122
" left and right buttons are affected. For example, if you have"
123
" a three-button mouse, the middle button is unaffected.");
124
tab1->handedBox->setWhatsThis( wtstr );
126
connect(tab1->doubleClick, SIGNAL(clicked()), SLOT(changed()));
128
wtstr = i18n("The default behavior in KDE is to select and activate"
129
" icons with a single click of the left button on your pointing"
130
" device. This behavior is consistent with what you would expect"
131
" when you click links in most web browsers. If you would prefer"
132
" to select with a single click, and activate with a double click,"
133
" check this option.");
134
tab1->doubleClick->setWhatsThis( wtstr );
136
wtstr = i18n("Activates and opens a file or folder with a single click.");
137
tab1->singleClick->setWhatsThis( wtstr );
140
connect(tab1->cbAutoSelect, SIGNAL(clicked()), this, SLOT(changed()));
142
wtstr = i18n("If you check this option, pausing the mouse pointer"
143
" over an icon on the screen will automatically select that icon."
144
" This may be useful when single clicks activate icons, and you"
145
" want only to select the icon without activating it.");
146
tab1->cbAutoSelect->setWhatsThis( wtstr );
148
// slAutoSelect = new QSlider(0, 2000, 10, 0, QSlider::Horizontal, tab1);
149
tab1->slAutoSelect->setSingleStep( 125 );
150
tab1->slAutoSelect->setPageStep( 125 );
151
tab1->slAutoSelect->setTickPosition( QSlider::TicksBelow );
152
tab1->slAutoSelect->setTickInterval( 250 );
153
tab1->slAutoSelect->setTracking( true );
155
wtstr = i18n("If you have checked the option to automatically select"
156
" icons, this slider allows you to select how long the mouse pointer"
157
" must be paused over the icon before it is selected.");
158
tab1->slAutoSelect->setWhatsThis( wtstr );
160
wtstr = i18n("Show feedback when clicking an icon");
161
tab1->cbVisualActivate->setWhatsThis( wtstr );
163
connect(tab1->slAutoSelect, SIGNAL(valueChanged(int)), this, SLOT(changed()));
164
connect(tab1->cbVisualActivate, SIGNAL(clicked()), this, SLOT(changed()));
166
connect(tab1->cb_pointershape, SIGNAL(clicked()), this, SLOT(changed()));
168
connect(tab1->singleClick, SIGNAL(clicked()), this, SLOT(changed()));
169
connect(tab1->singleClick, SIGNAL(clicked()), this, SLOT(slotClick()));
171
connect( tab1->doubleClick, SIGNAL( clicked() ), this, SLOT( slotClick() ) );
172
connect( tab1->cbAutoSelect, SIGNAL( clicked() ), this, SLOT( slotClick() ) );
174
// Only allow setting reversing scroll polarity if we have scroll buttons
175
unsigned char map[20];
176
if ( XGetPointerMapping(QX11Info::display(), map, 20) >= 5 )
178
tab1->cbScrollPolarity->setEnabled( true );
179
tab1->cbScrollPolarity->show();
183
tab1->cbScrollPolarity->setEnabled( false );
184
tab1->cbScrollPolarity->hide();
186
connect(tab1->cbScrollPolarity, SIGNAL(clicked()), this, SLOT(changed()));
187
connect(tab1->cbScrollPolarity, SIGNAL(clicked()), this, SLOT(slotScrollPolarityChanged()));
190
themetab = new ThemePage(this);
191
connect(themetab, SIGNAL(changed(bool)), SLOT(changed()));
192
tabwidget->addTab(themetab, i18n("&Cursor Theme"));
195
tab2 = new QWidget(0);
196
tab2->setObjectName("Advanced Tab");
197
tabwidget->addTab(tab2, i18n("Advanced"));
199
QBoxLayout *lay = new QVBoxLayout(tab2);
200
lay->setMargin(KDialog::marginHint());
201
lay->setSpacing(KDialog::spacingHint());
203
accel = new KDoubleNumInput(0.1, 20, 2, tab2, 0.1, 1);
204
accel->setLabel(i18n("Pointer acceleration:"));
205
accel->setSuffix("x");
206
lay->addWidget(accel);
207
connect(accel, SIGNAL(valueChanged(double)), this, SLOT(changed()));
209
wtstr = i18n("<p>This option allows you to change the relationship"
210
" between the distance that the mouse pointer moves on the"
211
" screen and the relative movement of the physical device"
212
" itself (which may be a mouse, trackball, or some other"
213
" pointing device.)</p><p>"
214
" A high value for the acceleration will lead to large"
215
" movements of the mouse pointer on the screen even when"
216
" you only make a small movement with the physical device."
217
" Selecting very high values may result in the mouse pointer"
218
" flying across the screen, making it hard to control.</p>");
219
accel->setWhatsThis( wtstr );
221
thresh = new KIntNumInput(accel, 20, tab2);
222
thresh->setLabel(i18n("Pointer threshold:"));
223
thresh->setRange(0,20,1);
224
thresh->setSteps(1,1);
225
lay->addWidget(thresh);
226
connect(thresh, SIGNAL(valueChanged(int)), this, SLOT(changed()));
227
connect(thresh, SIGNAL(valueChanged(int)), this, SLOT(slotThreshChanged(int)));
228
slotThreshChanged(thresh->value());
230
wtstr = i18n("<p>The threshold is the smallest distance that the"
231
" mouse pointer must move on the screen before acceleration"
232
" has any effect. If the movement is smaller than the threshold,"
233
" the mouse pointer moves as if the acceleration was set to 1X;</p><p>"
234
" thus, when you make small movements with the physical device,"
235
" there is no acceleration at all, giving you a greater degree"
236
" of control over the mouse pointer. With larger movements of"
237
" the physical device, you can move the mouse pointer"
238
" rapidly to different areas on the screen.</p>");
239
thresh->setWhatsThis( wtstr );
241
// It would be nice if the user had a test field.
242
// Selecting such values in milliseconds is not intuitive
243
doubleClickInterval = new KIntNumInput(thresh, 2000, tab2);
244
doubleClickInterval->setLabel(i18n("Double click interval:"));
245
doubleClickInterval->setRange(0, 2000, 100);
246
doubleClickInterval->setSuffix(i18n(" msec"));
247
doubleClickInterval->setSteps(100, 100);
248
lay->addWidget(doubleClickInterval);
249
connect(doubleClickInterval, SIGNAL(valueChanged(int)), this, SLOT(changed()));
251
wtstr = i18n("The double click interval is the maximal time"
252
" (in milliseconds) between two mouse clicks which"
253
" turns them into a double click. If the second"
254
" click happens later than this time interval after"
255
" the first click, they are recognized as two"
256
" separate clicks.");
257
doubleClickInterval->setWhatsThis( wtstr );
261
dragStartTime = new KIntNumInput(doubleClickInterval, 2000, tab2);
262
dragStartTime->setLabel(i18n("Drag start time:"));
263
dragStartTime->setRange(0, 2000, 100);
264
dragStartTime->setSuffix(i18n(" msec"));
265
dragStartTime->setSteps(100, 100);
266
lay->addWidget(dragStartTime);
267
connect(dragStartTime, SIGNAL(valueChanged(int)), this, SLOT(changed()));
269
wtstr = i18n("If you click with the mouse (e.g. in a multi-line"
270
" editor) and begin to move the mouse within the"
271
" drag start time, a drag operation will be initiated.");
272
dragStartTime->setWhatsThis( wtstr );
274
dragStartDist = new KIntNumInput(dragStartTime, 20, tab2);
275
dragStartDist->setLabel(i18n("Drag start distance:"));
276
dragStartDist->setRange(1, 20, 1);
277
dragStartDist->setSteps(1,1);
278
lay->addWidget(dragStartDist);
279
connect(dragStartDist, SIGNAL(valueChanged(int)), this, SLOT(changed()));
280
connect(dragStartDist, SIGNAL(valueChanged(int)), this, SLOT(slotDragStartDistChanged(int)));
281
slotDragStartDistChanged(dragStartDist->value());
283
wtstr = i18n("If you click with the mouse and begin to move the"
284
" mouse at least the drag start distance, a drag"
285
" operation will be initiated.");
286
dragStartDist->setWhatsThis( wtstr );
288
wheelScrollLines = new KIntNumInput(dragStartDist, 3, tab2);
289
wheelScrollLines->setLabel(i18n("Mouse wheel scrolls by:"));
290
wheelScrollLines->setRange(1, 12, 1);
291
wheelScrollLines->setSteps(1,1);
292
lay->addWidget(wheelScrollLines);
293
connect(wheelScrollLines, SIGNAL(valueChanged(int)), this, SLOT(changed()));
294
connect(wheelScrollLines, SIGNAL(valueChanged(int)), SLOT(slotWheelScrollLinesChanged(int)));
295
slotWheelScrollLinesChanged(wheelScrollLines->value());
297
wtstr = i18n("If you use the wheel of a mouse, this value determines the number of lines to scroll for each wheel movement. Note that if this number exceeds the number of visible lines, it will be ignored and the wheel movement will be handled as a page up/down movement.");
298
wheelScrollLines->setWhatsThis(wtstr);
302
QWidget *mouse = new QWidget(this);
303
mouse->setObjectName("Mouse Navigation");
304
tabwidget->addTab(mouse, i18n("Mouse Navigation"));
306
QBoxLayout *vbox = new QVBoxLayout(mouse);
307
vbox->setMargin(KDialog::marginHint());
308
vbox->setSpacing(KDialog::spacingHint());
310
QVBoxLayout *vvbox = new QVBoxLayout();
311
vbox->addItem( vvbox );
312
vvbox->setSpacing(KDialog::spacingHint());
314
mouseKeys = new QCheckBox(i18n("&Move pointer with keyboard (using the num pad)"), mouse);
315
vvbox->addWidget(mouseKeys);
317
QBoxLayout *hbox = new QHBoxLayout();
318
vvbox->addItem( hbox );
319
hbox->setSpacing(KDialog::spacingHint());
320
hbox->addSpacing(24);
321
mk_delay = new KIntNumInput(mouse);
322
mk_delay->setLabel(i18n("&Acceleration delay:"), Qt::AlignVCenter);
323
mk_delay->setSuffix(i18n(" msec"));
324
mk_delay->setRange(1, 1000, 50);
325
hbox->addWidget(mk_delay);
327
hbox = new QHBoxLayout();
328
vvbox->addItem(hbox);
329
hbox->setSpacing(KDialog::spacingHint());
330
hbox->addSpacing(24);
331
mk_interval = new KIntNumInput(mk_delay, 0, mouse);
332
mk_interval->setLabel(i18n("R&epeat interval:"), Qt::AlignVCenter);
333
mk_interval->setSuffix(i18n(" msec"));
334
mk_interval->setRange(1, 1000, 10);
335
hbox->addWidget(mk_interval);
337
hbox = new QHBoxLayout();
338
vvbox->addItem(hbox);
339
hbox->setSpacing(KDialog::spacingHint());
340
hbox->addSpacing(24);
341
mk_time_to_max = new KIntNumInput(mk_interval, 0, mouse);
342
mk_time_to_max->setLabel(i18n("Acceleration &time:"), Qt::AlignVCenter);
343
mk_time_to_max->setRange(100, 10000, 200);
344
mk_time_to_max->setSuffix(i18n(" msec"));
345
hbox->addWidget(mk_time_to_max);
347
hbox = new QHBoxLayout();
348
vvbox->addItem(hbox);
349
hbox->setSpacing(KDialog::spacingHint());
350
hbox->addSpacing(24);
351
mk_max_speed = new KIntNumInput(mk_time_to_max, 0, mouse);
352
mk_max_speed->setLabel(i18n("Ma&ximum speed:"), Qt::AlignVCenter);
353
mk_max_speed->setRange(1, 2000, 20);
354
mk_max_speed->setSuffix(i18n(" pixel/sec"));
355
hbox->addWidget(mk_max_speed);
357
hbox = new QHBoxLayout();
358
vvbox->addItem(hbox);
359
hbox->setSpacing(KDialog::spacingHint());
360
hbox->addSpacing(24);
361
mk_curve = new KIntNumInput(mk_max_speed, 0, mouse);
362
mk_curve->setLabel(i18n("Acceleration &profile:"), Qt::AlignVCenter);
363
mk_curve->setRange(-1000, 1000, 100);
364
hbox->addWidget(mk_curve);
366
connect(mouseKeys, SIGNAL(clicked()), this, SLOT(checkAccess()));
367
connect(mouseKeys, SIGNAL(clicked()), this, SLOT(changed()));
368
connect(mk_delay, SIGNAL(valueChanged(int)), this, SLOT(changed()));
369
connect(mk_interval, SIGNAL(valueChanged(int)), this, SLOT(changed()));
370
connect(mk_time_to_max, SIGNAL(valueChanged(int)), this, SLOT(changed()));
371
connect(mk_max_speed, SIGNAL(valueChanged(int)), this, SLOT(changed()));
372
connect(mk_curve, SIGNAL(valueChanged(int)), this, SLOT(changed()));
377
settings = new MouseSettings;
379
// This part is for handling features on Logitech USB mice.
380
// It only works if libusb is available.
383
struct device_table {
390
{ VENDOR_LOGITECH, 0xC00E, "M-BJ58", "Wheel Mouse Optical", HAS_RES },
391
{ VENDOR_LOGITECH, 0xC00F, "M-BJ79", "MouseMan Traveler", HAS_RES },
392
{ VENDOR_LOGITECH, 0xC012, "M-BL63B", "MouseMan Dual Optical", HAS_RES },
393
{ VENDOR_LOGITECH, 0xC01B, "M-BP86", "MX310 Optical Mouse", HAS_RES },
394
{ VENDOR_LOGITECH, 0xC01D, "M-BS81A", "MX510 Optical Mouse", HAS_RES | HAS_SS | HAS_SSR },
395
{ VENDOR_LOGITECH, 0xC024, "M-BP82", "MX300 Optical Mouse", HAS_RES },
396
{ VENDOR_LOGITECH, 0xC025, "M-BP81A", "MX500 Optical Mouse", HAS_RES | HAS_SS | HAS_SSR },
397
{ VENDOR_LOGITECH, 0xC031, "M-UT58A", "iFeel Mouse (silver)", HAS_RES },
398
{ VENDOR_LOGITECH, 0xC501, "C-BA4-MSE", "Mouse Receiver", HAS_CSR },
399
{ VENDOR_LOGITECH, 0xC502, "C-UA3-DUAL", "Dual Receiver", HAS_CSR | USE_CH2},
400
{ VENDOR_LOGITECH, 0xC504, "C-BD9-DUAL", "Cordless Freedom Optical", HAS_CSR | USE_CH2 },
401
{ VENDOR_LOGITECH, 0xC505, "C-BG17-DUAL", "Cordless Elite Duo", HAS_SS | HAS_SSR | HAS_CSR | USE_CH2},
402
{ VENDOR_LOGITECH, 0xC506, "C-BF16-MSE", "MX700 Optical Mouse", HAS_SS | HAS_CSR },
403
{ VENDOR_LOGITECH, 0xC508, "C-BA4-MSE", "Cordless Optical TrackMan", HAS_SS | HAS_CSR },
404
{ VENDOR_LOGITECH, 0xC50B, "967300-0403", "Cordless MX Duo Receiver", HAS_SS|HAS_CSR },
405
{ VENDOR_LOGITECH, 0xC50E, "M-RAG97", "MX1000 Laser Mouse", HAS_SS | HAS_CSR },
406
{ VENDOR_LOGITECH, 0xC702, "C-UF15", "Receiver for Cordless Presenter", HAS_CSR },
407
{ 0, 0, QString(), QString(), 0 }
415
struct usb_device *dev;
417
for (bus = usb_busses; bus; bus = bus->next) {
418
for (dev = bus->devices; dev; dev = dev->next) {
419
for (int n = 0; device_table[n].idVendor; n++)
420
if ( (device_table[n].idVendor == dev->descriptor.idVendor) &&
421
(device_table[n].idProduct == dev->descriptor.idProduct) ) {
422
// OK, we have a device that appears to be one of the ones we support
423
LogitechMouse *mouse = new LogitechMouse( dev, device_table[n].flags, this, device_table[n].Name.toLatin1() );
424
settings->logitechMouseList.append(mouse);
425
tabwidget->addTab( (QWidget*)mouse, device_table[n].Name );
434
KAboutData* about = new KAboutData("kcmmouse", 0, ki18n("Mouse"), 0, KLocalizedString(),
435
KAboutData::License_GPL, ki18n("(c) 1997 - 2005 Mouse developers"));
436
about->addAuthor(ki18n("Patrick Dowler"));
437
about->addAuthor(ki18n("Dirk A. Mueller"));
438
about->addAuthor(ki18n("David Faure"));
439
about->addAuthor(ki18n("Bernd Gehrmann"));
440
about->addAuthor(ki18n("Rik Hemsley"));
441
about->addAuthor(ki18n("Brad Hughes"));
442
about->addAuthor(ki18n("Ralf Nolden"));
443
about->addAuthor(ki18n("Brad Hards"));
444
setAboutData( about );
447
void MouseConfig::checkAccess()
449
mk_delay->setEnabled(mouseKeys->isChecked());
450
mk_interval->setEnabled(mouseKeys->isChecked());
451
mk_time_to_max->setEnabled(mouseKeys->isChecked());
452
mk_max_speed->setEnabled(mouseKeys->isChecked());
453
mk_curve->setEnabled(mouseKeys->isChecked());
457
MouseConfig::~MouseConfig()
462
double MouseConfig::getAccel()
464
return accel->value();
467
void MouseConfig::setAccel(double val)
469
accel->setValue(val);
472
int MouseConfig::getThreshold()
474
return thresh->value();
477
void MouseConfig::setThreshold(int val)
479
thresh->setValue(val);
483
int MouseConfig::getHandedness()
485
if (tab1->rightHanded->isChecked())
491
void MouseConfig::setHandedness(int val)
493
tab1->rightHanded->setChecked(false);
494
tab1->leftHanded->setChecked(false);
495
if (val == RIGHT_HANDED){
496
tab1->rightHanded->setChecked(true);
497
tab1->mousePix->setPixmap(KStandardDirs::locate("data", "kcminput/pics/mouse_rh.png"));
500
tab1->leftHanded->setChecked(true);
501
tab1->mousePix->setPixmap(KStandardDirs::locate("data", "kcminput/pics/mouse_lh.png"));
505
void MouseConfig::load()
507
KConfig config( "kcminputrc" );
508
settings->load(&config);
510
tab1->rightHanded->setEnabled(settings->handedEnabled);
511
tab1->leftHanded->setEnabled(settings->handedEnabled);
512
if ( tab1->cbScrollPolarity->isEnabled() )
513
tab1->cbScrollPolarity->setEnabled(settings->handedEnabled);
514
tab1->cbScrollPolarity->setChecked( settings->reverseScrollPolarity );
516
setAccel(settings->accelRate);
517
setThreshold(settings->thresholdMove);
518
setHandedness(settings->handed);
520
doubleClickInterval->setValue(settings->doubleClickInterval);
521
dragStartTime->setValue(settings->dragStartTime);
522
dragStartDist->setValue(settings->dragStartDist);
523
wheelScrollLines->setValue(settings->wheelScrollLines);
525
tab1->singleClick->setChecked( settings->singleClick );
526
tab1->doubleClick->setChecked(!settings->singleClick);
527
tab1->cb_pointershape->setChecked(settings->changeCursor);
528
tab1->cbAutoSelect->setChecked( settings->autoSelectDelay >= 0 );
529
if ( settings->autoSelectDelay < 0 )
530
tab1->slAutoSelect->setValue( 0 );
532
tab1->slAutoSelect->setValue( settings->autoSelectDelay );
533
tab1->cbVisualActivate->setChecked( settings->visualActivate );
537
KConfig ac("kaccessrc");
539
KConfigGroup group = ac.group("Mouse");
540
mouseKeys->setChecked(group.readEntry("MouseKeys", false));
541
mk_delay->setValue(group.readEntry("MKDelay", 160));
543
int interval = group.readEntry("MKInterval", 5);
544
mk_interval->setValue(interval);
546
// Default time to reach maximum speed: 5000 msec
547
int time_to_max = group.readEntry("MKTimeToMax", (5000+interval/2)/interval);
548
time_to_max = group.readEntry("MK-TimeToMax", time_to_max*interval);
549
mk_time_to_max->setValue(time_to_max);
551
// Default maximum speed: 1000 pixels/sec
552
// (The old default maximum speed from KDE <= 3.4
553
// (100000 pixels/sec) was way too fast)
554
long max_speed = group.readEntry("MKMaxSpeed", interval);
555
max_speed = max_speed * 1000 / interval;
556
if (max_speed > 2000)
558
max_speed = group.readEntry("MK-MaxSpeed", int(max_speed));
559
mk_max_speed->setValue(max_speed);
561
mk_curve->setValue(group.readEntry("MKCurve", 0));
569
void MouseConfig::save()
571
settings->accelRate = getAccel();
572
settings->thresholdMove = getThreshold();
573
settings->handed = getHandedness();
575
settings->doubleClickInterval = doubleClickInterval->value();
576
settings->dragStartTime = dragStartTime->value();
577
settings->dragStartDist = dragStartDist->value();
578
settings->wheelScrollLines = wheelScrollLines->value();
579
settings->singleClick = !tab1->doubleClick->isChecked();
580
settings->autoSelectDelay = tab1->cbAutoSelect->isChecked()? tab1->slAutoSelect->value():-1;
581
settings->visualActivate = tab1->cbVisualActivate->isChecked();
582
// settings->changeCursor = tab1->singleClick->isChecked();
583
settings->changeCursor = tab1->cb_pointershape->isChecked();
584
settings->reverseScrollPolarity = tab1->cbScrollPolarity->isChecked();
587
KConfig config( "kcminputrc" );
588
settings->save(&config);
590
KConfig ac("kaccessrc");
592
KConfigGroup group = ac.group("Mouse");
594
int interval = mk_interval->value();
595
group.writeEntry("MouseKeys", mouseKeys->isChecked());
596
group.writeEntry("MKDelay", mk_delay->value());
597
group.writeEntry("MKInterval", interval);
598
group.writeEntry("MK-TimeToMax", mk_time_to_max->value());
599
group.writeEntry("MKTimeToMax",
600
(mk_time_to_max->value() + interval/2)/interval);
601
group.writeEntry("MK-MaxSpeed", mk_max_speed->value());
602
group.writeEntry("MKMaxSpeed",
603
(mk_max_speed->value()*interval + 500)/1000);
604
group.writeEntry("MKCurve", mk_curve->value());
606
group.writeEntry("MKCurve", mk_curve->value());
611
KToolInvocation::startServiceByDesktopName("kaccess");
613
KCModule::changed(false);
617
void MouseConfig::defaults()
621
setHandedness(RIGHT_HANDED);
622
tab1->cbScrollPolarity->setChecked( false );
623
doubleClickInterval->setValue(400);
624
dragStartTime->setValue(500);
625
dragStartDist->setValue(4);
626
wheelScrollLines->setValue(3);
627
tab1->doubleClick->setChecked( !KDE_DEFAULT_SINGLECLICK );
628
tab1->cbAutoSelect->setChecked( KDE_DEFAULT_AUTOSELECTDELAY != -1 );
629
tab1->slAutoSelect->setValue( KDE_DEFAULT_AUTOSELECTDELAY == -1 ? 50 : KDE_DEFAULT_AUTOSELECTDELAY );
630
tab1->singleClick->setChecked( KDE_DEFAULT_SINGLECLICK );
631
tab1->cbVisualActivate->setChecked( KDE_DEFAULT_VISUAL_ACTIVATE );
632
tab1->cb_pointershape->setChecked(KDE_DEFAULT_CHANGECURSOR);
635
mouseKeys->setChecked(false);
636
mk_delay->setValue(160);
637
mk_interval->setValue(5);
638
mk_time_to_max->setValue(5000);
639
mk_max_speed->setValue(1000);
640
mk_curve->setValue(0);
647
void MouseConfig::slotClick()
649
// Autoselect has a meaning only in single-click mode
650
tab1->cbAutoSelect->setEnabled(!tab1->doubleClick->isChecked() || tab1->singleClick->isChecked());
651
// Delay has a meaning only for autoselect
652
bool bDelay = tab1->cbAutoSelect->isChecked() && ! tab1->doubleClick->isChecked();
653
tab1->slAutoSelect->setEnabled( bDelay );
654
tab1->lDelay->setEnabled( bDelay );
655
tab1->lb_short->setEnabled( bDelay );
656
tab1->lb_long->setEnabled( bDelay );
660
/** No descriptions */
661
void MouseConfig::slotHandedChanged(int val){
662
if(val==RIGHT_HANDED)
663
tab1->mousePix->setPixmap(KStandardDirs::locate("data", "kcminput/pics/mouse_rh.png"));
665
tab1->mousePix->setPixmap(KStandardDirs::locate("data", "kcminput/pics/mouse_lh.png"));
666
settings->m_handedNeedsApply = true;
669
void MouseSettings::load(KConfig *config)
671
int accel_num, accel_den, threshold;
673
XGetPointerControl( QX11Info::display(),
674
&accel_num, &accel_den, &threshold );
675
accel = float(accel_num) / float(accel_den);
677
// get settings from X server
678
int h = RIGHT_HANDED;
679
unsigned char map[20];
680
num_buttons = XGetPointerMapping(QX11Info::display(), map, 20);
682
handedEnabled = true;
684
// ## keep this in sync with KGlobalSettings::mouseSettings
685
if( num_buttons == 1 )
687
/* disable button remapping */
688
handedEnabled = false;
690
else if( num_buttons == 2 )
692
if ( (int)map[0] == 1 && (int)map[1] == 2 )
694
else if ( (int)map[0] == 2 && (int)map[1] == 1 )
697
/* custom button setup: disable button remapping */
698
handedEnabled = false;
702
middle_button = (int)map[1];
703
if ( (int)map[0] == 1 && (int)map[2] == 3 )
705
else if ( (int)map[0] == 3 && (int)map[2] == 1 )
709
/* custom button setup: disable button remapping */
710
handedEnabled = false;
714
KConfigGroup group = config->group("Mouse");
715
double a = group.readEntry("Acceleration",-1);
721
int t = group.readEntry("Threshold",-1);
723
thresholdMove = threshold;
727
QString key = group.readEntry("MouseButtonMapping");
728
if (key == "RightHanded")
729
handed = RIGHT_HANDED;
730
else if (key == "LeftHanded")
731
handed = LEFT_HANDED;
733
#warning was key == NULL how was this working? is key.isNull() what the coder meant?
735
else if (key.isNull())
737
reverseScrollPolarity = group.readEntry( "ReverseScrollPolarity", false);
738
m_handedNeedsApply = false;
740
// SC/DC/AutoSelect/ChangeCursor
741
group = config->group("KDE");
742
doubleClickInterval = group.readEntry("DoubleClickInterval", 400);
743
dragStartTime = group.readEntry("StartDragTime", 500);
744
dragStartDist = group.readEntry("StartDragDist", 4);
745
wheelScrollLines = group.readEntry("WheelScrollLines", 3);
747
singleClick = group.readEntry("SingleClick", KDE_DEFAULT_SINGLECLICK);
748
autoSelectDelay = group.readEntry("AutoSelectDelay", KDE_DEFAULT_AUTOSELECTDELAY);
749
visualActivate = group.readEntry("VisualActivate", KDE_DEFAULT_VISUAL_ACTIVATE);
750
changeCursor = group.readEntry("ChangeCursor", KDE_DEFAULT_CHANGECURSOR);
753
void MouseConfig::slotThreshChanged(int value)
755
thresh->setSuffix(i18np(" pixel", " pixels", value));
758
void MouseConfig::slotDragStartDistChanged(int value)
760
dragStartDist->setSuffix(i18np(" pixel", " pixels", value));
763
void MouseConfig::slotWheelScrollLinesChanged(int value)
765
wheelScrollLines->setSuffix(i18np(" line", " lines", value));
768
void MouseSettings::apply(bool force)
770
XChangePointerControl( QX11Info::display(),
771
true, true, int(qRound(accelRate*10)), 10, thresholdMove);
773
unsigned char map[20];
774
num_buttons = XGetPointerMapping(QX11Info::display(), map, 20);
775
int remap=(num_buttons>=1);
776
if (handedEnabled && (m_handedNeedsApply || force)) {
777
if( num_buttons == 1 )
779
map[0] = (unsigned char) 1;
781
else if( num_buttons == 2 )
783
if (handed == RIGHT_HANDED)
785
map[0] = (unsigned char) 1;
786
map[1] = (unsigned char) 3;
790
map[0] = (unsigned char) 3;
791
map[1] = (unsigned char) 1;
794
else // 3 buttons and more
796
if (handed == RIGHT_HANDED)
798
map[0] = (unsigned char) 1;
799
map[1] = (unsigned char) middle_button;
800
map[2] = (unsigned char) 3;
804
map[0] = (unsigned char) 3;
805
map[1] = (unsigned char) middle_button;
806
map[2] = (unsigned char) 1;
808
if( num_buttons >= 5 )
810
// Apps seem to expect logical buttons 4,5 are the vertical wheel.
811
// With mice with more than 3 buttons (not including wheel) the physical
812
// buttons mapped to logical 4,5 may not be physical 4,5 , so keep
813
// this mapping, only possibly reversing them.
815
for( pos = 0; pos < num_buttons; ++pos )
816
if( map[pos] == 4 || map[pos] == 5 )
818
if( pos < num_buttons - 1 )
820
map[pos] = reverseScrollPolarity ? (unsigned char) 5 : (unsigned char) 4;
821
map[pos+1] = reverseScrollPolarity ? (unsigned char) 4 : (unsigned char) 5;
827
while ((retval=XSetPointerMapping(QX11Info::display(), map,
828
num_buttons)) == MappingBusy)
829
/* keep trying until the pointer is free */
831
m_handedNeedsApply = false;
834
// This iterates through the various Logitech mice, if we have support.
836
LogitechMouse *logitechMouse;
837
Q_FOREACH( logitechMouse, logitechMouseList ) {
838
logitechMouse->applyChanges();
843
void MouseSettings::save(KConfig *config)
845
KConfigGroup group = config->group("Mouse");
846
group.writeEntry("Acceleration",accelRate);
847
group.writeEntry("Threshold",thresholdMove);
848
if (handed == RIGHT_HANDED)
849
group.writeEntry("MouseButtonMapping",QString("RightHanded"));
851
group.writeEntry("MouseButtonMapping",QString("LeftHanded"));
852
group.writeEntry( "ReverseScrollPolarity", reverseScrollPolarity );
854
group = config->group("KDE");
855
group.writeEntry("DoubleClickInterval", doubleClickInterval, KConfigBase::Persistent|KConfigBase::Global);
856
group.writeEntry("StartDragTime", dragStartTime, KConfigBase::Persistent|KConfigBase::Global);
857
group.writeEntry("StartDragDist", dragStartDist, KConfigBase::Persistent|KConfigBase::Global);
858
group.writeEntry("WheelScrollLines", wheelScrollLines, KConfigBase::Persistent|KConfigBase::Global);
859
group.writeEntry("SingleClick", singleClick, KConfigBase::Persistent|KConfigBase::Global);
860
group.writeEntry("AutoSelectDelay", autoSelectDelay, KConfigBase::Persistent|KConfigBase::Global);
861
group.writeEntry("VisualActivate", visualActivate, KConfigBase::Persistent|KConfigBase::Global);
862
group.writeEntry("ChangeCursor", changeCursor,KConfigBase::Persistent|KConfigBase::Global);
863
// This iterates through the various Logitech mice, if we have support.
865
LogitechMouse *logitechMouse;
866
Q_FOREACH( logitechMouse, logitechMouseList ) {
867
logitechMouse->save(config);
871
KGlobalSettings::self()->emitChange(KGlobalSettings::SettingsChanged, KGlobalSettings::SETTINGS_MOUSE);
874
void MouseConfig::slotScrollPolarityChanged()
876
settings->m_handedNeedsApply = true;