~ubuntu-branches/ubuntu/gutsy/kdebase-workspace/gutsy-backports

« back to all changes in this revision

Viewing changes to kcontrol/input/mouse.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2007-09-05 20:45:14 UTC
  • Revision ID: james.westby@ubuntu.com-20070905204514-632hhspl0nvrc84i
Tags: upstream-3.93.0
ImportĀ upstreamĀ versionĀ 3.93.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * mouse.cpp
 
3
 *
 
4
 * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca
 
5
 *
 
6
 * Layout management, enhancements:
 
7
 * Copyright (c) 1999 Dirk A. Mueller <dmuell@gmx.net>
 
8
 *
 
9
 * SC/DC/AutoSelect/ChangeCursor:
 
10
 * Copyright (c) 2000 David Faure <faure@kde.org>
 
11
 *
 
12
 * Double click interval, drag time & dist
 
13
 * Copyright (c) 2000 Bernd Gehrmann
 
14
 *
 
15
 * Large cursor support
 
16
 * Visual activation TODO: speed
 
17
 * Copyright (c) 2000 Rik Hemsley <rik@kde.org>
 
18
 *
 
19
 * White cursor support
 
20
 * TODO: give user the option to choose a certain cursor font
 
21
 * -> Theming
 
22
 *
 
23
 * General/Advanced tabs
 
24
 * Copyright (c) 2000 Brad Hughes <bhughes@trolltech.com>
 
25
 *
 
26
 * redesign for KDE 2.2
 
27
 * Copyright (c) 2001 Ralf Nolden <nolden@kde.org>
 
28
 *
 
29
 * Logitech mouse support
 
30
 * Copyright (C) 2004 Brad Hards <bradh@frogmouth.net>
 
31
 *
 
32
 * Requires the Qt widget libraries, available at no cost at
 
33
 * http://www.troll.no/
 
34
 *
 
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.
 
39
 *
 
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.
 
44
 *
 
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.
 
48
 */
 
49
 
 
50
#include <QLayout>
 
51
#include <QCheckBox>
 
52
#undef Below
 
53
#undef Above
 
54
#include <QSlider>
 
55
#include <QWhatsThis>
 
56
#include <QTabWidget>
 
57
#include <QRadioButton>
 
58
 
 
59
#include <ktoolinvocation.h>
 
60
#include <klocale.h>
 
61
#include <kdialog.h>
 
62
#include <kconfig.h>
 
63
#include <kstandarddirs.h>
 
64
#include <kdebug.h>
 
65
#include <kaboutdata.h>
 
66
#include <KPluginFactory>
 
67
#include <KPluginLoader>
 
68
 
 
69
#include <config-workspace.h>
 
70
 
 
71
#include "mouse.h"
 
72
 
 
73
#include <X11/X.h>
 
74
#include <X11/Xlib.h>
 
75
#include <X11/Xutil.h>
 
76
#include <kglobalsettings.h>
 
77
#include <QX11Info>
 
78
 
 
79
#undef Below
 
80
 
 
81
 
 
82
K_PLUGIN_FACTORY(MouseConfigFactory,
 
83
        registerPlugin<MouseConfig>(); // mouse
 
84
        )
 
85
K_EXPORT_PLUGIN(MouseConfigFactory("kcminput"))
 
86
 
 
87
MouseConfig::MouseConfig(QWidget *parent, const QVariantList &args)
 
88
  : KCModule(MouseConfigFactory::componentData(), parent, args)
 
89
{
 
90
 
 
91
 
 
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."));
 
96
 
 
97
    QString wtstr;
 
98
 
 
99
    QBoxLayout *top = new QVBoxLayout(this);
 
100
    top->setMargin(0);
 
101
    top->setSpacing(KDialog::spacingHint());
 
102
 
 
103
    tabwidget = new QTabWidget(this);
 
104
    top->addWidget(tabwidget);
 
105
 
 
106
    tab1 = new KMouseDlg(this);
 
107
    Q3ButtonGroup *group = new Q3ButtonGroup( tab1 );
 
108
    group->setExclusive( true );
 
109
    group->hide();
 
110
    group->insert( tab1->singleClick );
 
111
    group->insert( tab1->doubleClick );
 
112
 
 
113
    tabwidget->addTab(tab1, i18n("&General"));
 
114
 
 
115
    connect(tab1->handedBox, SIGNAL(clicked(int)), this, SLOT(changed()));
 
116
    connect(tab1->handedBox, SIGNAL(clicked(int)), this, SLOT(slotHandedChanged(int)));
 
117
 
 
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 );
 
125
 
 
126
    connect(tab1->doubleClick, SIGNAL(clicked()), SLOT(changed()));
 
127
 
 
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 );
 
135
 
 
136
    wtstr = i18n("Activates and opens a file or folder with a single click.");
 
137
    tab1->singleClick->setWhatsThis( wtstr );
 
138
 
 
139
 
 
140
    connect(tab1->cbAutoSelect, SIGNAL(clicked()), this, SLOT(changed()));
 
141
 
 
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 );
 
147
 
 
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 );
 
154
 
 
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 );
 
159
 
 
160
    wtstr = i18n("Show feedback when clicking an icon");
 
161
    tab1->cbVisualActivate->setWhatsThis( wtstr );
 
162
 
 
163
    connect(tab1->slAutoSelect, SIGNAL(valueChanged(int)), this, SLOT(changed()));
 
164
    connect(tab1->cbVisualActivate, SIGNAL(clicked()), this, SLOT(changed()));
 
165
 
 
166
    connect(tab1->cb_pointershape, SIGNAL(clicked()), this, SLOT(changed()));
 
167
 
 
168
    connect(tab1->singleClick, SIGNAL(clicked()), this, SLOT(changed()));
 
169
    connect(tab1->singleClick, SIGNAL(clicked()), this, SLOT(slotClick()));
 
170
 
 
171
    connect( tab1->doubleClick, SIGNAL( clicked() ), this, SLOT( slotClick() ) );
 
172
    connect( tab1->cbAutoSelect, SIGNAL( clicked() ), this, SLOT( slotClick() ) );
 
173
 
 
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 )
 
177
    {
 
178
      tab1->cbScrollPolarity->setEnabled( true );
 
179
      tab1->cbScrollPolarity->show();
 
180
    }
 
181
    else
 
182
    {
 
183
      tab1->cbScrollPolarity->setEnabled( false );
 
184
      tab1->cbScrollPolarity->hide();
 
185
    }
 
186
    connect(tab1->cbScrollPolarity, SIGNAL(clicked()), this, SLOT(changed()));
 
187
    connect(tab1->cbScrollPolarity, SIGNAL(clicked()), this, SLOT(slotScrollPolarityChanged()));
 
188
 
 
189
    // Cursor theme tab
 
190
    themetab = new ThemePage(this);
 
191
    connect(themetab, SIGNAL(changed(bool)), SLOT(changed()));
 
192
    tabwidget->addTab(themetab, i18n("&Cursor Theme"));
 
193
 
 
194
    // Advanced tab
 
195
    tab2 = new QWidget(0);
 
196
    tab2->setObjectName("Advanced Tab");
 
197
    tabwidget->addTab(tab2, i18n("Advanced"));
 
198
 
 
199
    QBoxLayout *lay = new QVBoxLayout(tab2);
 
200
    lay->setMargin(KDialog::marginHint());
 
201
    lay->setSpacing(KDialog::spacingHint());
 
202
 
 
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()));
 
208
 
 
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 );
 
220
 
 
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());
 
229
 
 
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 );
 
240
 
 
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()));
 
250
 
 
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 );
 
258
 
 
259
    lay->addSpacing(15);
 
260
 
 
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()));
 
268
 
 
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 );
 
273
 
 
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());
 
282
 
 
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 );
 
287
 
 
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());
 
296
 
 
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);
 
299
    lay->addStretch();
 
300
 
 
301
{
 
302
  QWidget *mouse = new QWidget(this);
 
303
  mouse->setObjectName("Mouse Navigation");
 
304
  tabwidget->addTab(mouse, i18n("Mouse Navigation"));
 
305
 
 
306
  QBoxLayout *vbox = new QVBoxLayout(mouse);
 
307
  vbox->setMargin(KDialog::marginHint());
 
308
  vbox->setSpacing(KDialog::spacingHint());
 
309
 
 
310
  QVBoxLayout *vvbox = new QVBoxLayout();
 
311
  vbox->addItem( vvbox );
 
312
  vvbox->setSpacing(KDialog::spacingHint());
 
313
 
 
314
  mouseKeys = new QCheckBox(i18n("&Move pointer with keyboard (using the num pad)"), mouse);
 
315
  vvbox->addWidget(mouseKeys);
 
316
 
 
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);
 
326
 
 
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);
 
336
 
 
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);
 
346
 
 
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);
 
356
 
 
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);
 
365
 
 
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()));
 
373
 
 
374
  vbox->addStretch();
 
375
}
 
376
 
 
377
  settings = new MouseSettings;
 
378
 
 
379
  // This part is for handling features on Logitech USB mice.
 
380
  // It only works if libusb is available.
 
381
#ifdef HAVE_LIBUSB
 
382
 
 
383
  struct device_table {
 
384
      int idVendor;
 
385
      int idProduct;
 
386
      QString Model;
 
387
      QString Name;
 
388
      int flags;
 
389
  } 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 }
 
408
  };
 
409
 
 
410
  usb_init();
 
411
  usb_find_busses();
 
412
  usb_find_devices();
 
413
 
 
414
  struct usb_bus *bus;
 
415
  struct usb_device *dev;
 
416
 
 
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 );
 
426
              }
 
427
      }
 
428
  }
 
429
 
 
430
#endif
 
431
 
 
432
  load();
 
433
 
 
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 );
 
445
}
 
446
 
 
447
void MouseConfig::checkAccess()
 
448
{
 
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());
 
454
}
 
455
 
 
456
 
 
457
MouseConfig::~MouseConfig()
 
458
{
 
459
    delete settings;
 
460
}
 
461
 
 
462
double MouseConfig::getAccel()
 
463
{
 
464
  return accel->value();
 
465
}
 
466
 
 
467
void MouseConfig::setAccel(double val)
 
468
{
 
469
  accel->setValue(val);
 
470
}
 
471
 
 
472
int MouseConfig::getThreshold()
 
473
{
 
474
  return thresh->value();
 
475
}
 
476
 
 
477
void MouseConfig::setThreshold(int val)
 
478
{
 
479
  thresh->setValue(val);
 
480
}
 
481
 
 
482
 
 
483
int MouseConfig::getHandedness()
 
484
{
 
485
  if (tab1->rightHanded->isChecked())
 
486
    return RIGHT_HANDED;
 
487
  else
 
488
    return LEFT_HANDED;
 
489
}
 
490
 
 
491
void MouseConfig::setHandedness(int val)
 
492
{
 
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"));
 
498
  }
 
499
  else{
 
500
    tab1->leftHanded->setChecked(true);
 
501
    tab1->mousePix->setPixmap(KStandardDirs::locate("data", "kcminput/pics/mouse_lh.png"));
 
502
  }
 
503
}
 
504
 
 
505
void MouseConfig::load()
 
506
{
 
507
  KConfig config( "kcminputrc" );
 
508
  settings->load(&config);
 
509
 
 
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 );
 
515
 
 
516
  setAccel(settings->accelRate);
 
517
  setThreshold(settings->thresholdMove);
 
518
  setHandedness(settings->handed);
 
519
 
 
520
  doubleClickInterval->setValue(settings->doubleClickInterval);
 
521
  dragStartTime->setValue(settings->dragStartTime);
 
522
  dragStartDist->setValue(settings->dragStartDist);
 
523
  wheelScrollLines->setValue(settings->wheelScrollLines);
 
524
 
 
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 );
 
531
  else
 
532
     tab1->slAutoSelect->setValue( settings->autoSelectDelay );
 
533
  tab1->cbVisualActivate->setChecked( settings->visualActivate );
 
534
  slotClick();
 
535
 
 
536
 
 
537
  KConfig ac("kaccessrc");
 
538
 
 
539
  KConfigGroup group = ac.group("Mouse");
 
540
  mouseKeys->setChecked(group.readEntry("MouseKeys", false));
 
541
  mk_delay->setValue(group.readEntry("MKDelay", 160));
 
542
 
 
543
  int interval = group.readEntry("MKInterval", 5);
 
544
  mk_interval->setValue(interval);
 
545
 
 
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);
 
550
 
 
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)
 
557
     max_speed = 2000;
 
558
  max_speed = group.readEntry("MK-MaxSpeed", int(max_speed));
 
559
  mk_max_speed->setValue(max_speed);
 
560
 
 
561
  mk_curve->setValue(group.readEntry("MKCurve", 0));
 
562
 
 
563
  themetab->load();
 
564
 
 
565
  checkAccess();
 
566
  changed();
 
567
}
 
568
 
 
569
void MouseConfig::save()
 
570
{
 
571
  settings->accelRate = getAccel();
 
572
  settings->thresholdMove = getThreshold();
 
573
  settings->handed = getHandedness();
 
574
 
 
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();
 
585
 
 
586
  settings->apply();
 
587
  KConfig config( "kcminputrc" );
 
588
  settings->save(&config);
 
589
 
 
590
  KConfig ac("kaccessrc");
 
591
 
 
592
  KConfigGroup group = ac.group("Mouse");
 
593
 
 
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());
 
605
  group.sync();
 
606
  group.writeEntry("MKCurve", mk_curve->value());
 
607
 
 
608
  themetab->save();
 
609
 
 
610
  // restart kaccess
 
611
  KToolInvocation::startServiceByDesktopName("kaccess");
 
612
 
 
613
  KCModule::changed(false);
 
614
 
 
615
}
 
616
 
 
617
void MouseConfig::defaults()
 
618
{
 
619
    setThreshold(2);
 
620
    setAccel(2);
 
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);
 
633
    slotClick();
 
634
 
 
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);
 
641
 
 
642
  checkAccess();
 
643
 
 
644
  changed();
 
645
}
 
646
 
 
647
void MouseConfig::slotClick()
 
648
{
 
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 );
 
657
 
 
658
}
 
659
 
 
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"));
 
664
  else
 
665
    tab1->mousePix->setPixmap(KStandardDirs::locate("data", "kcminput/pics/mouse_lh.png"));
 
666
  settings->m_handedNeedsApply = true;
 
667
}
 
668
 
 
669
void MouseSettings::load(KConfig *config)
 
670
{
 
671
  int accel_num, accel_den, threshold;
 
672
  double accel;
 
673
  XGetPointerControl( QX11Info::display(),
 
674
              &accel_num, &accel_den, &threshold );
 
675
  accel = float(accel_num) / float(accel_den);
 
676
 
 
677
  // get settings from X server
 
678
  int h = RIGHT_HANDED;
 
679
  unsigned char map[20];
 
680
  num_buttons = XGetPointerMapping(QX11Info::display(), map, 20);
 
681
 
 
682
  handedEnabled = true;
 
683
 
 
684
  // ## keep this in sync with KGlobalSettings::mouseSettings
 
685
  if( num_buttons == 1 )
 
686
  {
 
687
      /* disable button remapping */
 
688
      handedEnabled = false;
 
689
  }
 
690
  else if( num_buttons == 2 )
 
691
  {
 
692
      if ( (int)map[0] == 1 && (int)map[1] == 2 )
 
693
        h = RIGHT_HANDED;
 
694
      else if ( (int)map[0] == 2 && (int)map[1] == 1 )
 
695
        h = LEFT_HANDED;
 
696
      else
 
697
        /* custom button setup: disable button remapping */
 
698
        handedEnabled = false;
 
699
  }
 
700
  else
 
701
  {
 
702
      middle_button = (int)map[1];
 
703
      if ( (int)map[0] == 1 && (int)map[2] == 3 )
 
704
    h = RIGHT_HANDED;
 
705
      else if ( (int)map[0] == 3 && (int)map[2] == 1 )
 
706
    h = LEFT_HANDED;
 
707
      else
 
708
    {
 
709
      /* custom button setup: disable button remapping */
 
710
      handedEnabled = false;
 
711
    }
 
712
  }
 
713
 
 
714
  KConfigGroup group = config->group("Mouse");
 
715
  double a = group.readEntry("Acceleration",-1);
 
716
  if (a == -1)
 
717
    accelRate = accel;
 
718
  else
 
719
    accelRate = a;
 
720
 
 
721
  int t = group.readEntry("Threshold",-1);
 
722
  if (t == -1)
 
723
    thresholdMove = threshold;
 
724
  else
 
725
    thresholdMove = t;
 
726
 
 
727
  QString key = group.readEntry("MouseButtonMapping");
 
728
  if (key == "RightHanded")
 
729
    handed = RIGHT_HANDED;
 
730
  else if (key == "LeftHanded")
 
731
    handed = LEFT_HANDED;
 
732
#ifdef __GNUC__
 
733
#warning was key == NULL how was this working? is key.isNull() what the coder meant?
 
734
#endif
 
735
  else if (key.isNull())
 
736
    handed = h;
 
737
  reverseScrollPolarity = group.readEntry( "ReverseScrollPolarity", false);
 
738
  m_handedNeedsApply = false;
 
739
 
 
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);
 
746
 
 
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);
 
751
}
 
752
 
 
753
void MouseConfig::slotThreshChanged(int value)
 
754
{
 
755
  thresh->setSuffix(i18np(" pixel", " pixels", value));
 
756
}
 
757
 
 
758
void MouseConfig::slotDragStartDistChanged(int value)
 
759
{
 
760
  dragStartDist->setSuffix(i18np(" pixel", " pixels", value));
 
761
}
 
762
 
 
763
void MouseConfig::slotWheelScrollLinesChanged(int value)
 
764
{
 
765
  wheelScrollLines->setSuffix(i18np(" line", " lines", value));
 
766
}
 
767
 
 
768
void MouseSettings::apply(bool force)
 
769
{
 
770
  XChangePointerControl( QX11Info::display(),
 
771
                         true, true, int(qRound(accelRate*10)), 10, thresholdMove);
 
772
 
 
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 )
 
778
      {
 
779
          map[0] = (unsigned char) 1;
 
780
      }
 
781
      else if( num_buttons == 2 )
 
782
      {
 
783
          if (handed == RIGHT_HANDED)
 
784
          {
 
785
              map[0] = (unsigned char) 1;
 
786
              map[1] = (unsigned char) 3;
 
787
          }
 
788
          else
 
789
          {
 
790
              map[0] = (unsigned char) 3;
 
791
              map[1] = (unsigned char) 1;
 
792
          }
 
793
      }
 
794
      else // 3 buttons and more
 
795
      {
 
796
          if (handed == RIGHT_HANDED)
 
797
          {
 
798
              map[0] = (unsigned char) 1;
 
799
              map[1] = (unsigned char) middle_button;
 
800
              map[2] = (unsigned char) 3;
 
801
          }
 
802
          else
 
803
          {
 
804
              map[0] = (unsigned char) 3;
 
805
              map[1] = (unsigned char) middle_button;
 
806
              map[2] = (unsigned char) 1;
 
807
          }
 
808
          if( num_buttons >= 5 )
 
809
          {
 
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.
 
814
              int pos;
 
815
              for( pos = 0; pos < num_buttons; ++pos )
 
816
                  if( map[pos] == 4 || map[pos] == 5 )
 
817
                      break;
 
818
              if( pos < num_buttons - 1 )
 
819
              {
 
820
                  map[pos] = reverseScrollPolarity ? (unsigned char) 5 : (unsigned char) 4;
 
821
                  map[pos+1] = reverseScrollPolarity ? (unsigned char) 4 : (unsigned char) 5;
 
822
              }
 
823
          }
 
824
      }
 
825
      int retval;
 
826
      if (remap)
 
827
          while ((retval=XSetPointerMapping(QX11Info::display(), map,
 
828
                                            num_buttons)) == MappingBusy)
 
829
              /* keep trying until the pointer is free */
 
830
          { };
 
831
      m_handedNeedsApply = false;
 
832
  }
 
833
 
 
834
  // This iterates through the various Logitech mice, if we have support.
 
835
  #ifdef HAVE_LIBUSB
 
836
  LogitechMouse *logitechMouse;
 
837
  Q_FOREACH( logitechMouse, logitechMouseList ) {
 
838
      logitechMouse->applyChanges();
 
839
  }
 
840
  #endif
 
841
}
 
842
 
 
843
void MouseSettings::save(KConfig *config)
 
844
{
 
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"));
 
850
  else
 
851
      group.writeEntry("MouseButtonMapping",QString("LeftHanded"));
 
852
  group.writeEntry( "ReverseScrollPolarity", reverseScrollPolarity );
 
853
 
 
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.
 
864
#ifdef HAVE_LIBUSB
 
865
  LogitechMouse *logitechMouse;
 
866
  Q_FOREACH( logitechMouse, logitechMouseList ) {
 
867
      logitechMouse->save(config);
 
868
  }
 
869
#endif
 
870
  config->sync();
 
871
  KGlobalSettings::self()->emitChange(KGlobalSettings::SettingsChanged, KGlobalSettings::SETTINGS_MOUSE);
 
872
}
 
873
 
 
874
void MouseConfig::slotScrollPolarityChanged()
 
875
{
 
876
  settings->m_handedNeedsApply = true;
 
877
}
 
878
 
 
879
#include "mouse.moc"