summaryrefslogtreecommitdiffstats
path: root/kcontrol/input
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/input')
-rw-r--r--kcontrol/input/AUTHORS7
-rw-r--r--kcontrol/input/ChangeLog11
-rw-r--r--kcontrol/input/Makefile.am47
-rw-r--r--kcontrol/input/configure.in.bot5
-rw-r--r--kcontrol/input/configure.in.in26
-rwxr-xr-xkcontrol/input/consoleUserPerms42
-rw-r--r--kcontrol/input/core/Makefile.am7
-rw-r--r--kcontrol/input/core/bitmaps.h146
-rw-r--r--kcontrol/input/core/themepage.cpp212
-rw-r--r--kcontrol/input/core/themepage.h55
-rw-r--r--kcontrol/input/cursor_large.bdf4447
-rw-r--r--kcontrol/input/cursor_large_black.pcf.gzbin0 -> 3636 bytes
-rw-r--r--kcontrol/input/cursor_large_white.pcf.gzbin0 -> 3784 bytes
-rw-r--r--kcontrol/input/cursor_small_white.pcf.gzbin0 -> 3770 bytes
-rw-r--r--kcontrol/input/kapplymousetheme.cpp92
-rw-r--r--kcontrol/input/kmousedlg.ui378
-rw-r--r--kcontrol/input/logitechmouse.cpp417
-rw-r--r--kcontrol/input/logitechmouse.h102
-rw-r--r--kcontrol/input/logitechmouse.usermap35
-rw-r--r--kcontrol/input/logitechmouse_base.ui153
-rw-r--r--kcontrol/input/main.cpp96
-rw-r--r--kcontrol/input/mouse.cpp838
-rw-r--r--kcontrol/input/mouse.desktop242
-rw-r--r--kcontrol/input/mouse.h156
-rw-r--r--kcontrol/input/mouse_cursor_theme.upd5
-rw-r--r--kcontrol/input/pics/Makefile.am3
-rw-r--r--kcontrol/input/pics/mouse_lh.pngbin0 -> 12981 bytes
-rw-r--r--kcontrol/input/pics/mouse_lh.svgzbin0 -> 4814 bytes
-rw-r--r--kcontrol/input/pics/mouse_rh.pngbin0 -> 13053 bytes
-rw-r--r--kcontrol/input/pics/mouse_rh.svgzbin0 -> 4709 bytes
-rw-r--r--kcontrol/input/xcursor/Makefile.am7
-rw-r--r--kcontrol/input/xcursor/previewwidget.cpp353
-rw-r--r--kcontrol/input/xcursor/previewwidget.h47
-rw-r--r--kcontrol/input/xcursor/themepage.cpp637
-rw-r--r--kcontrol/input/xcursor/themepage.h76
35 files changed, 8642 insertions, 0 deletions
diff --git a/kcontrol/input/AUTHORS b/kcontrol/input/AUTHORS
new file mode 100644
index 000000000..525df4d20
--- /dev/null
+++ b/kcontrol/input/AUTHORS
@@ -0,0 +1,7 @@
+Mouse & Keyboard Configuration Modules:
+
+ Pat Dowler (dowler@pt1B1106.FSH.UVic.CA)
+
+Conversion to kcontrol applet:
+
+ Matthias Hoelzer (hoelzer@physik.uni-wuerzburg.de) \ No newline at end of file
diff --git a/kcontrol/input/ChangeLog b/kcontrol/input/ChangeLog
new file mode 100644
index 000000000..2d9b8d545
--- /dev/null
+++ b/kcontrol/input/ChangeLog
@@ -0,0 +1,11 @@
+2002-07-01 Fabian Wolf <fabianw@gmx.net>
+ * added option to select a white cursor
+
+2000-03-14 David Faure <faure@kde.org>
+
+ * mouse.cpp: Added global settings for SC/DC/AutoSelect/ChangeCursor
+ * mousedefaults.h: New file, to store default values
+
+1998-11-30 Alex Zepeda <garbanzo@hooked.net>
+
+ * Makefile.am: Move all the icons into pics/ && pics/mini/
diff --git a/kcontrol/input/Makefile.am b/kcontrol/input/Makefile.am
new file mode 100644
index 000000000..7a852aa3e
--- /dev/null
+++ b/kcontrol/input/Makefile.am
@@ -0,0 +1,47 @@
+if have_xcursor
+THEMEPAGE_SUBDIR = xcursor
+THEMEPAGE_INCLUDES = -I$(srcdir)/xcursor
+THEMEPAGE_LIB = xcursor/libthemepage.la
+else
+THEMEPAGE_SUBDIR = core
+THEMEPAGE_INCLUDES = -I$(srcdir)/core
+THEMEPAGE_LIB = core/libthemepage.la
+endif
+
+SUBDIRS = $(THEMEPAGE_SUBDIR) pics
+
+AM_CPPFLAGS = $(USB_CFLAGS) $(THEMEPAGE_INCLUDES) $(all_includes)
+
+bin_PROGRAMS = kapplymousetheme
+
+kapplymousetheme_SOURCES = kapplymousetheme.cpp
+kapplymousetheme_LDFLAGS = $(all_libraries)
+kapplymousetheme_LDADD = $(LIB_XCURSOR) $(LIB_X11)
+
+kde_module_LTLIBRARIES = kcm_input.la
+
+kcm_input_la_SOURCES = mouse.cpp kmousedlg.ui main.cpp logitechmouse.cpp logitechmouse_base.ui
+kcm_input_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined
+kcm_input_la_LIBADD = $(THEMEPAGE_LIB) $(XTESTLIB) $(LIB_KIO) $(LIB_XCURSOR) $(USB_LIBS)
+
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp */*.cpp -o $(podir)/kcminput.pot
+
+xdg_apps_DATA = mouse.desktop
+
+fontdir = $(kde_datadir)/kcminput
+font_DATA = cursor_large_black.pcf.gz cursor_large_white.pcf.gz cursor_small_white.pcf.gz
+EXTRA_DIST = $(font_DATA)
+
+update_DATA = mouse_cursor_theme.upd
+
+updatedir = $(kde_datadir)/kconf_update
+
+install-data-hook:
+ $(mkinstalldirs) $(DESTDIR)$(datadir)/fonts/override
+ -mkfontdir $(DESTDIR)$(datadir)/fonts/override
+##I'd like to install this automatically, but it only works on Linux, and I don't want to break things...
+## $(INSTALL_DATA) $(srcdir)/consoleUserPerms $(DESTDIR)/etc/hotplug/usb/consoleUserPerms
+## $(INSTALL_DATA) $(srcdir)/logitechmouse.usermap $(DESTDIR)/etc/hotplug/usb/logitechmouse.usermap
diff --git a/kcontrol/input/configure.in.bot b/kcontrol/input/configure.in.bot
new file mode 100644
index 000000000..08bf95ca5
--- /dev/null
+++ b/kcontrol/input/configure.in.bot
@@ -0,0 +1,5 @@
+if test "x$with_libusb" = xcheck && test "x$have_libusb" = xno; then
+ echo ""
+ echo "Logitech mouse support is disabled. Provide libusb to enable it."
+ echo ""
+fi
diff --git a/kcontrol/input/configure.in.in b/kcontrol/input/configure.in.in
new file mode 100644
index 000000000..0d656e2dc
--- /dev/null
+++ b/kcontrol/input/configure.in.in
@@ -0,0 +1,26 @@
+AC_ARG_WITH(libusb,
+ [AC_HELP_STRING(--with-libusb,
+ [enable control of some mouse models through libusb @<:@default=check@:>@])],
+ [], with_libusb=check)
+
+USB_LIBS=
+USB_CFLAGS=
+have_libusb=no
+if test "x$with_libusb" != xno; then
+ AC_PATH_PROG(LIBUSBCONFIG,libusb-config,no)
+ if test $LIBUSBCONFIG != "no"; then
+ USB_LIBS="$($LIBUSBCONFIG --libs)"
+ USB_CFLAGS="$($LIBUSBCONFIG --cflags)"
+
+ AC_CHECK_LIB(usb,main,
+ [have_libusb=yes
+ AC_DEFINE(HAVE_LIBUSB, 1, [Defined if you have libusb])],
+ [], [$USB_LIBS]
+ )
+ fi
+ if test "x$with_libusb" != xcheck && test "x$have_libusb" = xno; then
+ AC_MSG_ERROR([--with-libusb was given, but test for libusb failed])
+ fi
+fi
+AC_SUBST(USB_LIBS)
+AC_SUBST(USB_CFLAGS)
diff --git a/kcontrol/input/consoleUserPerms b/kcontrol/input/consoleUserPerms
new file mode 100755
index 000000000..015df642f
--- /dev/null
+++ b/kcontrol/input/consoleUserPerms
@@ -0,0 +1,42 @@
+#!/bin/bash
+#
+# /etc/hotplug/usb/consoleUserPerms
+#
+# Sets up newly plugged in USB device so that the user who owns
+# the console according to pam_console can access it from user space
+#
+# Note that for this script to work, you'll need all of the following:
+# a) a line in the file /etc/hotplug/usb.usermap or another usermap file
+# in /etc/hotplug/usb/ that corresponds to the device you are using.
+# b) a setup using pam_console creates the respective lock files
+# containing the name of the respective user. You can check for that
+# by executing "echo `cat /var/{run,lock}/console.lock`" and
+# verifying the appropriate user is mentioned somewhere there.
+# c) a Linux kernel supporting hotplug and usbdevfs
+# d) the hotplug package (http://linux-hotplug.sourceforge.net/)
+#
+# In the usermap file, the first field "usb module" should be named
+# "consoleUserPerms" to invoke this script.
+#
+
+if [ "${ACTION}" = "add" ] && [ -f "${DEVICE}" ]
+then
+ # New code, using lock files instead of copying /dev/console permissions
+ # This also works with non-kdm logins (e.g. on a virtual terminal)
+ # Idea and code from Nalin Dahyabhai <nalin@redhat.com>
+ if [ -f /var/run/console.lock ]
+ then
+ CONSOLEOWNER=`cat /var/run/console.lock`
+ elif [ -f /var/lock/console.lock ]
+ then
+ CONSOLEOWNER=`cat /var/lock/console.lock`
+ else
+ CONSOLEOWNER=
+ fi
+ if [ -n "$CONSOLEOWNER" ]
+ then
+ chmod 0000 "${DEVICE}"
+ chown "$CONSOLEOWNER" "${DEVICE}"
+ chmod 0600 "${DEVICE}"
+ fi
+fi
diff --git a/kcontrol/input/core/Makefile.am b/kcontrol/input/core/Makefile.am
new file mode 100644
index 000000000..3c73ba8b0
--- /dev/null
+++ b/kcontrol/input/core/Makefile.am
@@ -0,0 +1,7 @@
+AM_CPPFLAGS = $(all_includes)
+
+noinst_LTLIBRARIES = libthemepage.la
+libthemepage_la_SOURCES = themepage.cpp
+METASOURCES = AUTO
+noinst_HEADERS = themepage.h bitmaps.h
+
diff --git a/kcontrol/input/core/bitmaps.h b/kcontrol/input/core/bitmaps.h
new file mode 100644
index 000000000..9f44c3d5d
--- /dev/null
+++ b/kcontrol/input/core/bitmaps.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2003 Fredrik Höglund <fredrik@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __BITMAPS_H
+#define __BITMAPS_H
+
+
+static const char* const arrow_large_black_xpm[] = {
+"24 24 3 1",
+"# c None",
+"a c #000000",
+". c #ffffff",
+"#####..#################",
+"#####.a.################",
+"#####.aa.###############",
+"#####.aaa.##############",
+"#####.aaaa.#############",
+"#####.aaaaa.############",
+"#####.aaaaaa.###########",
+"#####.aaaaaaa.##########",
+"#####.aaaaaaaa.#########",
+"#####.aaaaaaaaa.########",
+"#####.aaaaaaaaaa.#######",
+"#####.aaaaaaaaaaa.######",
+"#####.aaaaaaaaaaaa.#####",
+"#####.aaaaaaaa....######",
+"#####.aaaaaaa.##########",
+"#####.aaa.aaaa.#########",
+"#####.aa.#.aaa.#########",
+"#####.a.##.aaaa.########",
+"#####..####.aaa.########",
+"###########.aaaa.#######",
+"############.aaa.#######",
+"############.aaa.#######",
+"#############...########",
+"########################"};
+
+
+static const char* const arrow_small_black_xpm[]={
+"24 24 3 1",
+"# c None",
+"a c #000000",
+". c #ffffff",
+"########################",
+"########################",
+"########################",
+"########################",
+"#######..###############",
+"#######.a.##############",
+"#######.aa.#############",
+"#######.aaa.############",
+"#######.aaaa.###########",
+"#######.aaaaa.##########",
+"#######.aaaaaa.#########",
+"#######.aaaaaaa.########",
+"#######.aaaaaaaa.#######",
+"#######.aaaaa....#######",
+"#######.aa.aa.##########",
+"#######.a.#.aa.#########",
+"#######..##.aa.#########",
+"############.aa.########",
+"############.aa.########",
+"#############..#########",
+"########################",
+"########################",
+"########################",
+"########################"};
+
+
+static const char* const arrow_large_white_xpm[] = {
+"24 24 3 1",
+"# c None",
+"a c #ffffff",
+". c #000000",
+"#####..#################",
+"#####.a.################",
+"#####.aa.###############",
+"#####.aaa.##############",
+"#####.aaaa.#############",
+"#####.aaaaa.############",
+"#####.aaaaaa.###########",
+"#####.aaaaaaa.##########",
+"#####.aaaaaaaa.#########",
+"#####.aaaaaaaaa.########",
+"#####.aaaaaaaaaa.#######",
+"#####.aaaaaaaaaaa.######",
+"#####.aaaaaaaaaaaa.#####",
+"#####.aaaaaaaa....######",
+"#####.aaaaaaa.##########",
+"#####.aaa.aaaa.#########",
+"#####.aa.#.aaa.#########",
+"#####.a.##.aaaa.########",
+"#####..####.aaa.########",
+"###########.aaaa.#######",
+"############.aaa.#######",
+"############.aaa.#######",
+"#############...########",
+"########################"};
+
+
+static const char* const arrow_small_white_xpm[]={
+"24 24 3 1",
+"# c None",
+"a c #ffffff",
+". c #000000",
+"########################",
+"########################",
+"########################",
+"########################",
+"#######..###############",
+"#######.a.##############",
+"#######.aa.#############",
+"#######.aaa.############",
+"#######.aaaa.###########",
+"#######.aaaaa.##########",
+"#######.aaaaaa.#########",
+"#######.aaaaaaa.########",
+"#######.aaaaaaaa.#######",
+"#######.aaaaa....#######",
+"#######.aa.aa.##########",
+"#######.a.#.aa.#########",
+"#######..##.aa.#########",
+"############.aa.########",
+"############.aa.########",
+"#############..#########",
+"########################",
+"########################",
+"########################",
+"########################"};
+
+#endif
diff --git a/kcontrol/input/core/themepage.cpp b/kcontrol/input/core/themepage.cpp
new file mode 100644
index 000000000..d83b28cb7
--- /dev/null
+++ b/kcontrol/input/core/themepage.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2003 Fredrik Höglund <fredrik@kde.org>
+ *
+ * Based on the large cursor code written by Rik Hemsley,
+ * Copyright (c) 2000 Rik Hemsley <rik@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+#include <kprocess.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <klistview.h>
+#include <kdialog.h>
+
+#include <qlayout.h>
+#include <qdir.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qlabel.h>
+
+#include "themepage.h"
+#include "themepage.moc"
+
+#include "bitmaps.h"
+
+
+namespace {
+ // Listview columns
+ enum Columns { NameColumn = 0, DescColumn, /* hidden */ DirColumn };
+}
+
+
+ThemePage::ThemePage( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ QBoxLayout *layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setMargin( KDialog::marginHint() );
+ layout->setSpacing( KDialog::spacingHint() );
+
+ new QLabel( i18n("Select the cursor theme you want to use:"), this );
+
+ // Create the theme list view
+ listview = new KListView( this );
+ listview->setFullWidth( true );
+ listview->setAllColumnsShowFocus( true );
+ listview->addColumn( i18n("Name") );
+ listview->addColumn( i18n("Description") );
+
+ connect( listview, SIGNAL(selectionChanged(QListViewItem*)),
+ SLOT(selectionChanged(QListViewItem*)) );
+
+ insertThemes();
+}
+
+
+ThemePage::~ThemePage()
+{
+}
+
+
+void ThemePage::selectionChanged( QListViewItem *item )
+{
+ selectedTheme = item->text( DirColumn );
+ emit changed( selectedTheme != currentTheme );
+}
+
+
+void ThemePage::save()
+{
+ if ( currentTheme == selectedTheme )
+ return;
+
+ bool whiteCursor = selectedTheme.right( 5 ) == "White";
+ bool largeCursor = selectedTheme.left( 5 ) == "Large";
+
+ KConfig c( "kcminputrc" );
+ c.setGroup( "Mouse" );
+ c.writeEntry( "LargeCursor", largeCursor );
+ c.writeEntry( "WhiteCursor", whiteCursor );
+
+ currentTheme = selectedTheme;
+
+ fixCursorFile();
+
+ KMessageBox::information( this, i18n("You have to restart KDE for these "
+ "changes to take effect."), i18n("Cursor Settings Changed"),
+ "CursorSettingsChanged" );
+}
+
+void ThemePage::load()
+{
+ load( false );
+}
+
+void ThemePage::load( bool useDefaults )
+{
+ bool largeCursor, whiteCursor;
+
+ KConfig c( "kcminputrc" );
+
+ c.setReadDefaults( useDefaults );
+
+ c.setGroup( "Mouse" );
+ largeCursor = c.readBoolEntry( "LargeCursor", false );
+ whiteCursor = c.readBoolEntry( "WhiteCursor", false );
+
+ if ( largeCursor )
+ currentTheme = whiteCursor ? "LargeWhite" : "LargeBlack";
+ else
+ currentTheme = whiteCursor ? "SmallWhite" : "SmallBlack";
+
+ selectedTheme = currentTheme;
+ QListViewItem *item = listview->findItem( currentTheme, DirColumn );
+ item->setSelected( true );
+}
+
+
+void ThemePage::defaults()
+{
+ load( true );
+}
+
+
+void ThemePage::insertThemes()
+{
+ KListViewItem *item;
+
+ item = new KListViewItem( listview, i18n("Small black"),
+ i18n("Small black cursors"), "SmallBlack" );
+ item->setPixmap( 0, QPixmap( arrow_small_black_xpm ) );
+ listview->insertItem( item );
+
+ item = new KListViewItem( listview, i18n("Large black"),
+ i18n("Large black cursors"), "LargeBlack" );
+ item->setPixmap( 0, QPixmap( arrow_large_black_xpm ) );
+ listview->insertItem( item );
+
+ item = new KListViewItem( listview, i18n("Small white"),
+ i18n("Small white cursors"), "SmallWhite" );
+ item->setPixmap( 0, QPixmap( arrow_small_white_xpm ) );
+ listview->insertItem( item );
+
+ item = new KListViewItem( listview, i18n("Large white"),
+ i18n("Large white cursors"), "LargeWhite" );
+ item->setPixmap( 0, QPixmap( arrow_large_white_xpm ) );
+ listview->insertItem( item );
+}
+
+
+void ThemePage::fixCursorFile()
+{
+ // Make sure we have the 'font' resource dir registered and can find the
+ // override dir.
+ //
+ // Next, if the user wants large cursors, copy the font
+ // cursor_large.pcf.gz to (localkdedir)/share/fonts/override/cursor.pcf.gz.
+ // Else remove the font cursor.pcf.gz from (localkdedir)/share/fonts/override.
+ //
+ // Run mkfontdir to update fonts.dir in that dir.
+
+ KGlobal::dirs()->addResourceType( "font", "share/fonts/" );
+ KIO::mkdir( KURL::fromPathOrURL(QDir::homeDirPath() + "/.fonts/kde-override") );
+ QString overrideDir = QDir::homeDirPath() + "/.fonts/kde-override/";
+
+ KURL installedFont;
+ installedFont.setPath( overrideDir + "cursor.pcf.gz" );
+
+ if ( currentTheme == "SmallBlack" )
+ KIO::NetAccess::del( installedFont, this );
+ else {
+ KURL source;
+
+ if ( currentTheme == "LargeBlack" )
+ source.setPath( locate("data", "kcminput/cursor_large_black.pcf.gz") );
+ else if ( currentTheme == "LargeWhite" )
+ source.setPath( locate("data", "kcminput/cursor_large_white.pcf.gz") );
+ else if ( currentTheme == "SmallWhite" )
+ source.setPath( locate("data", "kcminput/cursor_small_white.pcf.gz") );
+
+ KIO::NetAccess::file_copy( source, installedFont, -1, true );
+ }
+
+ QString cmd = KGlobal::dirs()->findExe( "mkfontdir" );
+ if ( !cmd.isEmpty() )
+ {
+ KProcess p;
+ p << cmd << overrideDir;
+ p.start(KProcess::Block);
+ }
+}
+
+// vim: set noet ts=4 sw=4:
diff --git a/kcontrol/input/core/themepage.h b/kcontrol/input/core/themepage.h
new file mode 100644
index 000000000..491c11f75
--- /dev/null
+++ b/kcontrol/input/core/themepage.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2003 Fredrik Höglund <fredrik@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __THEMEPAGE_H
+#define __THEMEPAGE_H
+
+class KListView;
+class QListViewItem;
+
+class ThemePage : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ ThemePage( QWidget* parent = 0, const char* name = 0 );
+ ~ThemePage();
+
+ // Called by the KCM
+ void save();
+ void load();
+ void load( bool useDefaults );
+ void defaults();
+
+ signals:
+ void changed( bool );
+
+ private slots:
+ void selectionChanged( QListViewItem * );
+
+ private:
+ void insertThemes();
+ void fixCursorFile();
+
+ KListView *listview;
+ QString currentTheme, selectedTheme;
+};
+
+#endif // __THEMEPAGE_H
+
+// vim: set noet ts=4 sw=4:
diff --git a/kcontrol/input/cursor_large.bdf b/kcontrol/input/cursor_large.bdf
new file mode 100644
index 000000000..241189286
--- /dev/null
+++ b/kcontrol/input/cursor_large.bdf
@@ -0,0 +1,4447 @@
+STARTFONT 2.1
+FONT cursor
+SIZE 47 78 78
+FONTBOUNDINGBOX 45 42 -21 -23
+STARTPROPERTIES 13
+COPYRIGHT "(C) 2000 Rik Hemsley <rik@kde.org>"
+POINT_SIZE 470
+FONT "cursor"
+WEIGHT 10
+RESOLUTION 107
+RESOLUTION_X 78
+RESOLUTION_Y 78
+X_HEIGHT -1
+QUAD_WIDTH 20
+DEFAULT_CHAR 0
+FONT_ASCENT 23
+FONT_DESCENT 24
+_XMBDFED_INFO "Edited with xmbdfed 4.3."
+ENDPROPERTIES
+CHARS 154
+STARTCHAR D
+ENCODING 0
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 1
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR C002
+ENCODING 2
+SWIDTH 1139 0
+DWIDTH 58 0
+BBX 12 21 -10 -22
+BITMAP
+0010
+0030
+0070
+00F0
+01F0
+03F0
+07F0
+0FF0
+1FF0
+3FF0
+7FF0
+FFF0
+0FF0
+07F0
+0F70
+0E30
+1E10
+1C00
+3C00
+3800
+3800
+ENDCHAR
+STARTCHAR C003
+ENCODING 3
+SWIDTH 1414 0
+DWIDTH 72 0
+BBX 14 23 -11 -23
+BITMAP
+000C
+001C
+003C
+007C
+00FC
+01FC
+03FC
+07FC
+0FFC
+1FFC
+3FFC
+7FFC
+FFFC
+7FFC
+07FC
+0FFC
+0FBC
+1F9C
+1F0C
+3F00
+3E00
+3E00
+1C00
+ENDCHAR
+STARTCHAR C004
+ENCODING 4
+SWIDTH 137 0
+DWIDTH 7 0
+BBX 11 15 -4 -2
+BITMAP
+FFE0
+FFE0
+FFE0
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+FFE0
+7FC0
+3F80
+1F00
+0E00
+0400
+ENDCHAR
+STARTCHAR C004
+ENCODING 5
+SWIDTH 176 0
+DWIDTH 9 0
+BBX 15 17 -6 -3
+BITMAP
+3FF8
+7FFC
+7FFC
+7FFC
+3FF8
+07C0
+07C0
+07C0
+07C0
+FFFE
+7FFC
+3FF8
+1FF0
+0FE0
+07C0
+0380
+0100
+ENDCHAR
+STARTCHAR C004
+ENCODING 6
+SWIDTH 137 0
+DWIDTH 7 0
+BBX 11 15 -4 -16
+BITMAP
+0400
+0E00
+1F00
+3F80
+7FC0
+FFE0
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+FFE0
+FFE0
+FFE0
+ENDCHAR
+STARTCHAR C004
+ENCODING 7
+SWIDTH 176 0
+DWIDTH 9 0
+BBX 15 17 -6 -17
+BITMAP
+0100
+0380
+07C0
+0FE0
+1FF0
+3FF8
+7FFC
+FFFE
+07C0
+07C0
+07C0
+07C0
+3FF8
+7FFC
+7FFC
+7FFC
+3FF8
+ENDCHAR
+STARTCHAR D
+ENCODING 8
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 9
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 10
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 11
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR C014
+ENCODING 12
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 21 21 0 -3
+BITMAP
+E00000
+E00000
+E00000
+E00100
+E00380
+E087C0
+E0CF80
+E0FF00
+E0FE00
+E0FC00
+E0FC00
+E0FE00
+E0FF00
+E00000
+E00000
+E00000
+E00000
+E00000
+FFFFF8
+FFFFF8
+FFFFF8
+ENDCHAR
+STARTCHAR C014
+ENCODING 13
+SWIDTH 432 0
+DWIDTH 22 0
+BBX 23 23 -1 -4
+BITMAP
+700000
+F80000
+F80000
+F80080
+F881C0
+F8C3E0
+F8E7F0
+F8FFE0
+F8FFC0
+F8FF80
+F8FF00
+F8FF00
+F8FF80
+F8FFC0
+F8FFE0
+F80000
+F80000
+F80000
+FFFFFC
+FFFFFE
+FFFFFE
+FFFFFE
+FFFFFC
+ENDCHAR
+STARTCHAR C014
+ENCODING 14
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 21 21 -18 -3
+BITMAP
+000038
+000038
+000038
+040038
+0E0038
+1F0838
+0F9838
+07F838
+03F838
+01F838
+01F838
+03F838
+07F838
+000038
+000038
+000038
+000038
+000038
+FFFFF8
+FFFFF8
+FFFFF8
+ENDCHAR
+STARTCHAR C014
+ENCODING 15
+SWIDTH 432 0
+DWIDTH 22 0
+BBX 23 23 -19 -4
+BITMAP
+00001C
+00003E
+00003E
+02003E
+07023E
+0F863E
+1FCE3E
+0FFE3E
+07FE3E
+03FE3E
+01FE3E
+01FE3E
+03FE3E
+07FE3E
+0FFE3E
+00003E
+00003E
+00003E
+7FFFFE
+FFFFFE
+FFFFFE
+FFFFFE
+7FFFFE
+ENDCHAR
+STARTCHAR C020
+ENCODING 16
+SWIDTH 216 0
+DWIDTH 11 0
+BBX 19 20 -8 -3
+BITMAP
+00E000
+00E000
+00E000
+00E000
+00E000
+00E000
+00E000
+0FFE00
+07FC00
+03F800
+01F000
+00E000
+004000
+000000
+000000
+000000
+000000
+FFFFE0
+FFFFE0
+FFFFE0
+ENDCHAR
+STARTCHAR C020
+ENCODING 17
+SWIDTH 235 0
+DWIDTH 12 0
+BBX 21 22 -9 -4
+BITMAP
+007000
+00F800
+00F800
+00F800
+00F800
+00F800
+00F800
+1FFFC0
+0FFF80
+07FF00
+03FE00
+01FC00
+00F800
+007000
+002000
+000000
+000000
+7FFFF0
+FFFFF8
+FFFFF8
+FFFFF8
+7FFFF0
+ENDCHAR
+STARTCHAR D
+ENCODING 18
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 19
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 20
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 21
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR C026
+ENCODING 22
+SWIDTH 137 0
+DWIDTH 7 0
+BBX 11 20 -4 -21
+BITMAP
+0400
+0400
+0E00
+0E00
+1F00
+1F00
+3F80
+3F80
+7FC0
+7FC0
+FFE0
+CE60
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0400
+ENDCHAR
+STARTCHAR C026
+ENCODING 23
+SWIDTH 157 0
+DWIDTH 8 0
+BBX 13 22 -5 -22
+BITMAP
+0200
+0700
+0700
+0F80
+0F80
+1FC0
+1FC0
+3FE0
+3FE0
+7FF0
+7FF0
+FFF8
+FFF8
+6FB0
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+0700
+0200
+ENDCHAR
+STARTCHAR D
+ENCODING 24
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 25
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 26
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 27
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 28
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 29
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 30
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 24 23 -10 -13
+BITMAP
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+002800
+FFC7FF
+FF83FF
+FFC7FF
+002800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 31
+SWIDTH 294 0
+DWIDTH 15 0
+BBX 26 25 -11 -14
+BITMAP
+001C0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+7FF7FF80
+FFE3FFC0
+FFC1FFC0
+FFE3FFC0
+7FF7FF80
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+001C0000
+ENDCHAR
+STARTCHAR D
+ENCODING 32
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 33
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 24 23 -10 -13
+BITMAP
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+002800
+FFC7FF
+FF83FF
+FFC7FF
+002800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 294 0
+DWIDTH 15 0
+BBX 26 25 -11 -14
+BITMAP
+001C0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+7FF7FF80
+FFE3FFC0
+FFC1FFC0
+FFE3FFC0
+7FF7FF80
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+001C0000
+ENDCHAR
+STARTCHAR D
+ENCODING 36
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 37
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 38
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 39
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 40
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 41
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 15 23 -6 -13
+BITMAP
+0100
+0380
+07C0
+0FE0
+1FF0
+3FF8
+7BBC
+F39E
+638C
+0380
+0380
+0380
+0380
+0380
+E38C
+F39E
+7BBC
+3FF8
+1FF0
+0FE0
+07C0
+0380
+0100
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 196 0
+DWIDTH 10 0
+BBX 17 25 -7 -14
+BITMAP
+008000
+01C000
+03E000
+07F000
+0FF800
+1FFC00
+3FFE00
+7FFF00
+FFFF80
+7BEF00
+33E600
+03E000
+03E000
+03E000
+33E600
+7BEF00
+FFFF80
+7FFF00
+3FFE00
+1FFC00
+0FF800
+07F000
+03E000
+01C000
+008000
+ENDCHAR
+STARTCHAR C002
+ENCODING 44
+SWIDTH 1139 0
+DWIDTH 58 0
+BBX 12 21 -10 -22
+BITMAP
+0010
+0030
+0070
+00F0
+01F0
+03F0
+07F0
+0FF0
+1FF0
+3FF0
+7FF0
+FFF0
+0FF0
+07F0
+0F70
+0E30
+1E10
+1C00
+3C00
+3800
+3800
+ENDCHAR
+STARTCHAR C003
+ENCODING 45
+SWIDTH 1414 0
+DWIDTH 72 0
+BBX 14 23 -11 -23
+BITMAP
+000C
+001C
+003C
+007C
+00FC
+01FC
+03FC
+07FC
+0FFC
+1FFC
+3FFC
+7FFC
+FFFC
+7FFC
+07FC
+0FFC
+0FBC
+1F9C
+1F0C
+3F00
+3E00
+3E00
+1C00
+ENDCHAR
+STARTCHAR C002
+ENCODING 46
+SWIDTH 1139 0
+DWIDTH 58 0
+BBX 12 21 -10 -22
+BITMAP
+0010
+0030
+0070
+00F0
+01F0
+03F0
+07F0
+0FF0
+1FF0
+3FF0
+7FF0
+FFF0
+0FF0
+07F0
+0F70
+0E30
+1E10
+1C00
+3C00
+3800
+3800
+ENDCHAR
+STARTCHAR C003
+ENCODING 47
+SWIDTH 1414 0
+DWIDTH 72 0
+BBX 14 23 -11 -23
+BITMAP
+000C
+001C
+003C
+007C
+00FC
+01FC
+03FC
+07FC
+0FFC
+1FFC
+3FFC
+7FFC
+FFFC
+7FFC
+07FC
+0FFC
+0FBC
+1F9C
+1F0C
+3F00
+3E00
+3E00
+1C00
+ENDCHAR
+STARTCHAR D
+ENCODING 48
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 49
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 21 23 -9 -13
+BITMAP
+00F800
+C3FE00
+E7FF80
+FFC3C0
+DF00E0
+CE0060
+C60020
+C30000
+FF8000
+FF8000
+000000
+000000
+000000
+000FF8
+000FF8
+000618
+200318
+300398
+3C07D8
+1E1FF8
+0FFF38
+03FE18
+00F800
+ENDCHAR
+STARTCHAR 2
+ENCODING 51
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 21 23 -9 -13
+BITMAP
+00F800
+C3FE00
+E7FF80
+FFC3C0
+FF00E0
+FE0060
+FE0020
+FF0000
+FF8000
+FF8000
+000000
+000000
+000000
+000FF8
+000FF8
+0007F8
+2003F8
+3003F8
+3C07F8
+1E1FF8
+0FFF38
+03FE18
+00F800
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 27 27 -12 -15
+BITMAP
+00040000
+000E0000
+001F0000
+003F8000
+007FC000
+007FC000
+000E0000
+000E0000
+000E0000
+0C0E0600
+1C0E0700
+3C0E0780
+7FFFFFC0
+FFFFFFE0
+7FFFFFC0
+3C0E0780
+1C0E0700
+0C0E0600
+000E0000
+000E0000
+000E0000
+007FC000
+007FC000
+003F8000
+001F0000
+000E0000
+00040000
+ENDCHAR
+STARTCHAR 4
+ENCODING 53
+SWIDTH 314 0
+DWIDTH 16 0
+BBX 29 29 -13 -16
+BITMAP
+00020000
+00070000
+000F8000
+001FC000
+003FE000
+007FF000
+007FF000
+003FE000
+000F8000
+060F8300
+0F0F8780
+1F0F87C0
+3FFFFFE0
+7FFFFFF0
+FFFFFFF8
+7FFFFFF0
+3FFFFFE0
+1F0F87C0
+0F0F8780
+060F8300
+000F8000
+003FE000
+007FF000
+007FF000
+003FE000
+001FC000
+000F8000
+00070000
+00020000
+ENDCHAR
+STARTCHAR D
+ENCODING 54
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 55
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 56
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 57
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR less
+ENCODING 58
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 23 21 -21 -21
+BITMAP
+001FFC
+00FFFE
+01E006
+0307FC
+060FF8
+0C0060
+0C07C0
+0C0FC0
+0C0060
+1E07C0
+330FC0
+6180C0
+C0C780
+C06F00
+603C00
+318C00
+199800
+0C3000
+066000
+03C000
+018000
+ENDCHAR
+STARTCHAR equal
+ENCODING 59
+SWIDTH 432 0
+DWIDTH 22 0
+BBX 23 21 -21 -21
+BITMAP
+001FFC
+00FFFE
+01FFFE
+03FFFC
+07FFF8
+0FFFE0
+0FFFC0
+0FFFC0
+0FFFE0
+1FFFC0
+3FFFC0
+7FFFC0
+FFFF80
+FFFF00
+7FFC00
+3FFC00
+1FF800
+0FF000
+07E000
+03C000
+018000
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 962 0
+DWIDTH 49 0
+BBX 23 21 1 -21
+BITMAP
+7FF000
+FFFE00
+C00F00
+7FC180
+3FE0C0
+0C0060
+07C060
+07E060
+0C0060
+07C0F0
+07E198
+06030C
+03C606
+01EC06
+00780C
+006318
+003330
+001860
+000CC0
+000780
+000300
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 923 0
+DWIDTH 47 0
+BBX 23 21 1 -21
+BITMAP
+7FF000
+FFFE00
+FFFF00
+7FFF80
+3FFFC0
+0FFFE0
+07FFE0
+07FFE0
+0FFFE0
+07FFF0
+07FFF8
+07FFFC
+03FFFE
+01FFFE
+007FFC
+007FF8
+003FF0
+001FE0
+000FC0
+000780
+000300
+ENDCHAR
+STARTCHAR D
+ENCODING 62
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 63
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 64
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 65
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 66
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 67
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR C020
+ENCODING 70
+SWIDTH 216 0
+DWIDTH 11 0
+BBX 20 19 0 -11
+BITMAP
+E00000
+E00000
+E00000
+E00000
+E00800
+E01800
+E03800
+E07800
+E0FFF0
+E1FFF0
+E0FFF0
+E07800
+E03800
+E01800
+E00800
+E00000
+E00000
+E00000
+E00000
+ENDCHAR
+STARTCHAR C020
+ENCODING 71
+SWIDTH 235 0
+DWIDTH 12 0
+BBX 22 21 -1 -12
+BITMAP
+700000
+F80000
+F80000
+F80200
+F80600
+F80E00
+F81E00
+F83E00
+F87FF8
+F8FFFC
+F9FFFC
+F8FFFC
+F87FF8
+F83E00
+F81E00
+F80E00
+F80600
+F80200
+F80000
+F80000
+700000
+ENDCHAR
+STARTCHAR D
+ENCODING 72
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 73
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 74
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 75
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 76
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 77
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 78
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 79
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 80
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 81
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 82
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 83
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 84
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 85
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+D800
+CC00
+CC00
+6600
+6600
+3300
+3300
+1980
+1980
+0CC0
+0CC0
+0660
+0660
+03F0
+0330
+01F0
+00E0
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FC00
+7E00
+7E00
+3F00
+3F00
+1F80
+1F80
+0FC0
+0FC0
+07E0
+07E0
+03F0
+03F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 353 0
+DWIDTH 18 0
+BBX 17 17 1 -2
+BITMAP
+003F80
+007F00
+00FC00
+01F000
+03C000
+07FE00
+01FC00
+03F000
+07C000
+0F0000
+1FF000
+07E000
+0F8000
+1E0000
+380000
+600000
+800000
+ENDCHAR
+STARTCHAR X
+ENCODING 89
+SWIDTH 392 0
+DWIDTH 20 0
+BBX 20 19 0 -3
+BITMAP
+001FF0
+003FE0
+007FC0
+00FF80
+01FE00
+03FFC0
+07FF80
+0FFF00
+03FE00
+07F800
+0FFE00
+1FFC00
+3FF800
+0FF000
+0FC000
+3F0000
+7C0000
+F00000
+C00000
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 15 15 -6 -9
+BITMAP
+0380
+0380
+0380
+0380
+0380
+0380
+FFFE
+FFFE
+FFFE
+0380
+0380
+0380
+0380
+0380
+0380
+ENDCHAR
+STARTCHAR Z
+ENCODING 91
+SWIDTH 196 0
+DWIDTH 10 0
+BBX 17 17 -7 -10
+BITMAP
+01C000
+03E000
+03E000
+03E000
+03E000
+03E000
+7FFF00
+FFFF80
+FFFF80
+FFFF80
+7FFF00
+03E000
+03E000
+03E000
+03E000
+03E000
+01C000
+ENDCHAR
+STARTCHAR D
+ENCODING 92
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 93
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR C002
+ENCODING 94
+SWIDTH 1139 0
+DWIDTH 58 0
+BBX 12 21 -10 -22
+BITMAP
+0010
+0030
+0070
+00F0
+01F0
+03F0
+07F0
+0FF0
+1FF0
+3FF0
+7FF0
+FFF0
+0FF0
+07F0
+0F70
+0E30
+1E10
+1C00
+3C00
+3800
+3800
+ENDCHAR
+STARTCHAR C003
+ENCODING 95
+SWIDTH 1414 0
+DWIDTH 72 0
+BBX 14 23 -11 -23
+BITMAP
+000C
+001C
+003C
+007C
+00FC
+01FC
+03FC
+07FC
+0FFC
+1FFC
+3FFC
+7FFC
+FFFC
+7FFC
+07FC
+0FFC
+0FBC
+1F9C
+1F0C
+3F00
+3E00
+3E00
+1C00
+ENDCHAR
+STARTCHAR C020
+ENCODING 96
+SWIDTH 216 0
+DWIDTH 11 0
+BBX 20 19 -17 -11
+BITMAP
+000070
+000070
+000070
+000070
+010070
+018070
+01C070
+01E070
+FFF070
+FFF870
+FFF070
+01E070
+01C070
+018070
+010070
+000070
+000070
+000070
+000070
+ENDCHAR
+STARTCHAR C020
+ENCODING 97
+SWIDTH 235 0
+DWIDTH 12 0
+BBX 22 21 -18 -12
+BITMAP
+000038
+00007C
+00007C
+01007C
+01807C
+01C07C
+01E07C
+01F07C
+7FF87C
+FFFC7C
+FFFE7C
+FFFC7C
+7FF87C
+01F07C
+01E07C
+01C07C
+01807C
+01007C
+00007C
+00007C
+000038
+ENDCHAR
+STARTCHAR D
+ENCODING 98
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 99
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 100
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 101
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 102
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 103
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 104
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 105
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 157 0
+DWIDTH 8 0
+BBX 13 20 -5 -2
+BITMAP
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+FFF8
+7FF0
+3FE0
+1FC0
+0F80
+0700
+0200
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 176 0
+DWIDTH 9 0
+BBX 15 22 -6 -3
+BITMAP
+06C0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+7FFC
+FFFE
+7FFC
+3FF8
+1FF0
+0FE0
+07C0
+0380
+0100
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 25 13 -12 -7
+BITMAP
+02002000
+06003000
+0E003800
+1E003C00
+3FFFFE00
+7FFFFF00
+FE003F80
+7FFFFF00
+3FFFFE00
+1E003C00
+0E003800
+06003000
+02002000
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 274 0
+DWIDTH 14 0
+BBX 27 15 -13 -8
+BITMAP
+01001000
+03803800
+07803C00
+0F803E00
+1FFFFF00
+3FFFFF80
+7FFFFFC0
+FFFFFFE0
+7FFFFFC0
+3FFFFF80
+1FFFFF00
+0F803E00
+07803C00
+03803800
+01001000
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 412 0
+DWIDTH 21 0
+BBX 20 13 1 -8
+BITMAP
+020000
+060000
+0E0000
+1E0000
+3FFFF0
+7FFFF0
+FE0000
+7FFFF0
+3FFFF0
+1E0000
+0E0000
+060000
+020000
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 432 0
+DWIDTH 22 0
+BBX 22 15 0 -9
+BITMAP
+010000
+038000
+078000
+0F8000
+1FFFF8
+3FFFFC
+7FFFFC
+FFFFF8
+7FFFFC
+3FFFFC
+1FFFF8
+0F8000
+078000
+038000
+010000
+ENDCHAR
+STARTCHAR n
+ENCODING 112
+SWIDTH 412 0
+DWIDTH 21 0
+BBX 20 13 -18 -8
+BITMAP
+000400
+000600
+000700
+000780
+FFFFC0
+FFFFE0
+0007F0
+FFFFE0
+FFFFC0
+000780
+000700
+000600
+000400
+ENDCHAR
+STARTCHAR o
+ENCODING 113
+SWIDTH 432 0
+DWIDTH 22 0
+BBX 22 15 -19 -9
+BITMAP
+000200
+000700
+000780
+0007C0
+7FFFE0
+FFFFF0
+FFFFF8
+7FFFFC
+FFFFF8
+FFFFF0
+7FFFE0
+0007C0
+000780
+000700
+000200
+ENDCHAR
+STARTCHAR j
+ENCODING 114
+SWIDTH 157 0
+DWIDTH 8 0
+BBX 13 20 -5 -21
+BITMAP
+0200
+0700
+0F80
+1FC0
+3FE0
+7FF0
+FFF8
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+ENDCHAR
+STARTCHAR k
+ENCODING 115
+SWIDTH 176 0
+DWIDTH 9 0
+BBX 15 22 -6 -22
+BITMAP
+0100
+0380
+07C0
+0FE0
+1FF0
+3FF8
+7FFC
+FFFE
+7FFC
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+06C0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 137 0
+DWIDTH 7 0
+BBX 13 25 -5 -14
+BITMAP
+0200
+0700
+0F80
+1FC0
+3FE0
+7FF0
+FFF8
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+0D80
+FFF8
+7FF0
+3FE0
+1FC0
+0F80
+0700
+0200
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 157 0
+DWIDTH 8 0
+BBX 15 27 -6 -15
+BITMAP
+0100
+0380
+07C0
+0FE0
+1FF0
+3FF8
+7FFC
+FFFE
+7FFC
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+0FE0
+7FFC
+FFFE
+7FFC
+3FF8
+1FF0
+0FE0
+07C0
+0380
+0100
+ENDCHAR
+STARTCHAR D
+ENCODING 118
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 119
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 120
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 121
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 122
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 123
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 39 0
+DWIDTH 2 0
+BBX 15 26 -13 -22
+BITMAP
+000A
+0054
+00A0
+0000
+1CAA
+1D54
+1C00
+1C20
+3E14
+7F0A
+FF80
+C180
+C180
+C180
+C180
+C180
+C180
+C180
+FF80
+FF80
+FF80
+FF80
+C180
+FF80
+FF80
+FF80
+ENDCHAR
+STARTCHAR bar
+ENCODING 125
+SWIDTH 39 0
+DWIDTH 2 0
+BBX 15 26 -13 -22
+BITMAP
+000E
+007C
+00E0
+0000
+1CFE
+1DFE
+1C00
+1C60
+3E3C
+7F0E
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+FF80
+ENDCHAR
+STARTCHAR D
+ENCODING 126
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 127
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 128
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 129
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 130
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 24 23 -10 -13
+BITMAP
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+002800
+FFC7FF
+FF83FF
+FFC7FF
+002800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+003800
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 131
+SWIDTH 294 0
+DWIDTH 15 0
+BBX 26 25 -11 -14
+BITMAP
+001C0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+7FF7FF80
+FFE3FFC0
+FFC1FFC0
+FFE3FFC0
+7FF7FF80
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+003E0000
+001C0000
+ENDCHAR
+STARTCHAR D
+ENCODING 132
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 133
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR C014
+ENCODING 134
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 21 21 0 -21
+BITMAP
+FFFFF8
+FFFFF8
+FFFFF8
+E00000
+E00000
+E00000
+E00000
+E00000
+E0FF00
+E0FE00
+E0FC00
+E0FC00
+E0FE00
+E0FF00
+E0CF80
+E087C0
+E00380
+E00100
+E00000
+E00000
+E00000
+ENDCHAR
+STARTCHAR C014
+ENCODING 135
+SWIDTH 432 0
+DWIDTH 22 0
+BBX 23 23 -1 -22
+BITMAP
+FFFFFC
+FFFFFE
+FFFFFE
+FFFFFE
+FFFFFC
+F80000
+F80000
+F80000
+F8FFE0
+F8FFC0
+F8FF80
+F8FF00
+F8FF00
+F8FF80
+F8FFC0
+F8FFE0
+F8E7F0
+F8C3E0
+F881C0
+F80080
+F80000
+F80000
+700000
+ENDCHAR
+STARTCHAR C014
+ENCODING 136
+SWIDTH 510 0
+DWIDTH 26 0
+BBX 21 21 -18 -21
+BITMAP
+FFFFF8
+FFFFF8
+FFFFF8
+000038
+000038
+000038
+000038
+000038
+07F838
+03F838
+01F838
+01F838
+03F838
+07F838
+0F9838
+1F0838
+0E0038
+040038
+000038
+000038
+000038
+ENDCHAR
+STARTCHAR C014
+ENCODING 137
+SWIDTH 432 0
+DWIDTH 22 0
+BBX 23 23 -19 -22
+BITMAP
+7FFFFE
+FFFFFE
+FFFFFE
+FFFFFE
+7FFFFE
+00003E
+00003E
+00003E
+0FFE3E
+07FE3E
+03FE3E
+01FE3E
+01FE3E
+03FE3E
+07FE3E
+0FFE3E
+1FCE3E
+0F863E
+07023E
+02003E
+00003E
+00003E
+00001C
+ENDCHAR
+STARTCHAR C020
+ENCODING 138
+SWIDTH 216 0
+DWIDTH 11 0
+BBX 19 20 -8 -20
+BITMAP
+FFFFE0
+FFFFE0
+FFFFE0
+000000
+000000
+000000
+000000
+004000
+00E000
+01F000
+03F800
+07FC00
+0FFE00
+00E000
+00E000
+00E000
+00E000
+00E000
+00E000
+00E000
+ENDCHAR
+STARTCHAR C020
+ENCODING 139
+SWIDTH 235 0
+DWIDTH 12 0
+BBX 21 22 -9 -21
+BITMAP
+7FFFF0
+FFFFF8
+FFFFF8
+FFFFF8
+7FFFF0
+000000
+000000
+002000
+007000
+00F800
+01FC00
+03FE00
+07FF00
+0FFF80
+1FFFC0
+00F800
+00F800
+00F800
+00F800
+00F800
+00F800
+007000
+ENDCHAR
+STARTCHAR D
+ENCODING 140
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 141
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 142
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 143
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 144
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 145
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 146
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 147
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR D
+ENCODING 148
+SWIDTH 255 0
+DWIDTH 13 0
+BBX 12 21 1 -22
+BITMAP
+8000
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FF00
+FE00
+EF00
+C700
+8780
+0380
+03C0
+01C0
+01C0
+ENDCHAR
+STARTCHAR E
+ENCODING 149
+SWIDTH 530 0
+DWIDTH 27 0
+BBX 14 23 0 -23
+BITMAP
+C000
+E000
+F000
+F800
+FC00
+FE00
+FF00
+FF80
+FFC0
+FFE0
+FFF0
+FFF8
+FFFC
+FFF8
+FF80
+FFC0
+F7C0
+E7E0
+C3E0
+03F0
+01F0
+01F0
+00E0
+ENDCHAR
+STARTCHAR C226
+ENCODING 150
+SWIDTH 235 0
+DWIDTH 12 0
+BBX 23 37 -10 -20
+BITMAP
+007C00
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+03FF80
+0FFFE0
+1F01F0
+3C0078
+383838
+70381C
+70381C
+60380C
+E0380E
+E0380E
+E0380E
+E03C0E
+E01E0E
+600F0C
+70079C
+70031C
+380038
+3C0078
+1F01F0
+0FFFE0
+03FF80
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+007C00
+ENDCHAR
+STARTCHAR C226
+ENCODING 151
+SWIDTH 235 0
+DWIDTH 12 0
+BBX 23 37 -10 -20
+BITMAP
+007C00
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+03FF80
+0FFFE0
+1FFFF0
+3FFFF8
+3FFFF8
+7FFFFC
+7FFFFC
+7FFFFC
+FFFFFE
+FFFFFE
+FFFFFE
+FFFFFE
+FFFFFE
+7FFFFC
+7FFFFC
+7FFFFC
+3FFFF8
+3FFFF8
+1FFFF0
+0FFFE0
+03FF80
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+00FE00
+007C00
+ENDCHAR
+STARTCHAR C230
+ENCODING 152
+SWIDTH 373 0
+DWIDTH 19 0
+BBX 11 21 -4 -12
+BITMAP
+FBE0
+FFE0
+1F00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+0E00
+1F00
+FFE0
+FBE0
+ENDCHAR
+STARTCHAR C231
+ENCODING 153
+SWIDTH 157 0
+DWIDTH 8 0
+BBX 13 23 -5 -13
+BITMAP
+7DF0
+FFF8
+FFF8
+7FF0
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+0F80
+7FF0
+FFF8
+FFF8
+7DF0
+ENDCHAR
+ENDFONT
diff --git a/kcontrol/input/cursor_large_black.pcf.gz b/kcontrol/input/cursor_large_black.pcf.gz
new file mode 100644
index 000000000..900a1dd58
--- /dev/null
+++ b/kcontrol/input/cursor_large_black.pcf.gz
Binary files differ
diff --git a/kcontrol/input/cursor_large_white.pcf.gz b/kcontrol/input/cursor_large_white.pcf.gz
new file mode 100644
index 000000000..83935e1de
--- /dev/null
+++ b/kcontrol/input/cursor_large_white.pcf.gz
Binary files differ
diff --git a/kcontrol/input/cursor_small_white.pcf.gz b/kcontrol/input/cursor_small_white.pcf.gz
new file mode 100644
index 000000000..694cf5bfc
--- /dev/null
+++ b/kcontrol/input/cursor_small_white.pcf.gz
Binary files differ
diff --git a/kcontrol/input/kapplymousetheme.cpp b/kcontrol/input/kapplymousetheme.cpp
new file mode 100644
index 000000000..99d6d1077
--- /dev/null
+++ b/kcontrol/input/kapplymousetheme.cpp
@@ -0,0 +1,92 @@
+/*
+ * main.cpp
+ *
+ * Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
+ * Copyright (c) 2005 Lubos Lunak <l.lunak@kde.org>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <X11/Xlib.h>
+
+#ifdef HAVE_XCURSOR
+# include <X11/Xcursor/Xcursor.h>
+#endif
+
+static Display* dpy;
+static Display* qt_xdisplay() { return dpy; }\
+static Window qt_xrootwin() { return DefaultRootWindow( dpy ); }
+
+bool isEmpty( const char* str )
+ {
+ if( str == NULL )
+ return true;
+ while( isspace( *str ))
+ ++str;
+ return *str == '\0';
+ }
+
+int main( int argc, char* argv[] )
+ {
+ if( argc != 3 )
+ return 1;
+ dpy = XOpenDisplay( NULL );
+ if( dpy == NULL )
+ return 2;
+ int ret = 0;
+#ifdef HAVE_XCURSOR
+ const char* theme = argv[ 1 ];
+ const char* size = argv[ 2 ];
+
+ // Note: If you update this code, update kapplymousetheme as well.
+
+ // use a default value for theme only if it's not configured at all, not even in X resources
+ if( isEmpty( theme )
+ && isEmpty( XGetDefault( qt_xdisplay(), "Xcursor", "theme" ))
+ && isEmpty( XcursorGetTheme( qt_xdisplay())))
+ {
+ theme = "default";
+ ret = 10; // means to switch to default
+ }
+
+ // Apply the KDE cursor theme to ourselves
+ if( !isEmpty( theme ))
+ XcursorSetTheme(qt_xdisplay(), theme );
+
+ if (!isEmpty( size ))
+ XcursorSetDefaultSize(qt_xdisplay(), atoi( size ));
+
+ // Load the default cursor from the theme and apply it to the root window.
+ Cursor handle = XcursorLibraryLoadCursor(qt_xdisplay(), "left_ptr");
+ XDefineCursor(qt_xdisplay(), qt_xrootwin(), handle);
+ XFreeCursor(qt_xdisplay(), handle); // Don't leak the cursor
+
+#else
+ ( void ) qt_xdisplay();
+ ( void ) qt_xrootwin();
+ ( void ) argv;
+#endif
+ XCloseDisplay( dpy );
+ return ret;
+ }
diff --git a/kcontrol/input/kmousedlg.ui b/kcontrol/input/kmousedlg.ui
new file mode 100644
index 000000000..01ba9966f
--- /dev/null
+++ b/kcontrol/input/kmousedlg.ui
@@ -0,0 +1,378 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KMouseDlg</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KMouseDlg</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>568</width>
+ <height>434</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>handedBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>Button Order</string>
+ </property>
+ <property name="exclusive">
+ <bool>true</bool>
+ </property>
+ <property name="radioButtonExclusive">
+ <bool>true</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="2">
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>Spacer53</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>rightHanded</cstring>
+ </property>
+ <property name="text">
+ <string>Righ&amp;t handed</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>leftHanded</cstring>
+ </property>
+ <property name="text">
+ <string>Le&amp;ft handed</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1" rowspan="3" colspan="1">
+ <property name="name">
+ <cstring>mousePix</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>115</height>
+ </size>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>cbScrollPolarity</cstring>
+ </property>
+ <property name="text">
+ <string>Re&amp;verse scroll direction</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Change the direction of scrolling for the mouse wheel or the 4th and 5th mouse buttons.</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Icons</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>doubleClick</cstring>
+ </property>
+ <property name="text">
+ <string>Dou&amp;ble-click to open files and folders (select icons on first click)</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="Line" row="5" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>Line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="6" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>cbVisualActivate</cstring>
+ </property>
+ <property name="text">
+ <string>Visual f&amp;eedback on activation</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>cb_pointershape</cstring>
+ </property>
+ <property name="text">
+ <string>Cha&amp;nge pointer shape over icons</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>cbAutoSelect</cstring>
+ </property>
+ <property name="text">
+ <string>A&amp;utomatically select icons</string>
+ </property>
+ </widget>
+ <spacer row="2" column="0" rowspan="3" colspan="1">
+ <property name="name">
+ <cstring>Spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>60</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget" row="4" column="2">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>lb_short</cstring>
+ </property>
+ <property name="text">
+ <string>Short</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>slAutoSelect</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>250</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maxValue">
+ <number>2000</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <spacer row="0" column="3" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>Spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>230</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lDelay</cstring>
+ </property>
+ <property name="text">
+ <string>Dela&amp;y:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>slAutoSelect</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="2">
+ <property name="name">
+ <cstring>lb_long</cstring>
+ </property>
+ <property name="text">
+ <string>Long</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="hAlign" stdset="0">
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="4" column="1">
+ <property name="name">
+ <cstring>Spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QRadioButton" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>singleClick</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Single-click to open files and folders</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>singleClick</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>cb_pointershape</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>singleClick</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>cbAutoSelect</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>cbAutoSelect</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>slAutoSelect</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>rightHanded</tabstop>
+ <tabstop>leftHanded</tabstop>
+ <tabstop>singleClick</tabstop>
+ <tabstop>cb_pointershape</tabstop>
+ <tabstop>cbAutoSelect</tabstop>
+ <tabstop>slAutoSelect</tabstop>
+ <tabstop>doubleClick</tabstop>
+ <tabstop>cbVisualActivate</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+</UI>
diff --git a/kcontrol/input/logitechmouse.cpp b/kcontrol/input/logitechmouse.cpp
new file mode 100644
index 000000000..1b8132a7e
--- /dev/null
+++ b/kcontrol/input/logitechmouse.cpp
@@ -0,0 +1,417 @@
+/*
+ * logitechmouse.cpp
+ *
+ * Copyright (C) 2004 Brad Hards <bradh@frogmouth.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <qdialog.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qprogressbar.h>
+#include <qtimer.h>
+
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include <config.h>
+
+#ifdef HAVE_LIBUSB
+#include <usb.h>
+
+#include "logitechmouse.h"
+
+LogitechMouse::LogitechMouse( struct usb_device *usbDev, int mouseCapabilityFlags, QWidget* parent, const char* name )
+ : LogitechMouseBase( parent, name, 0 )
+{
+ if ( !name )
+ setName( "LogitechMouse" );
+
+ cordlessNameLabel->setText( i18n("Mouse type: %1").arg( this->name() ) );
+
+ m_mouseCapabilityFlags = mouseCapabilityFlags;
+
+ m_usbDeviceHandle = usb_open( usbDev );
+
+ if ( 0 == m_usbDeviceHandle ) {
+ kdWarning() << "Error opening usbfs file: " << usb_strerror() << endl;
+ return;
+ }
+
+ if ( mouseCapabilityFlags & USE_CH2 ) {
+ m_useSecondChannel = 0x0100;
+ } else {
+ m_useSecondChannel = 0x0000;
+ }
+
+ permissionProblemText->hide();
+
+ if ( mouseCapabilityFlags & HAS_RES ) {
+ updateResolution();
+ resolutionSelector->setEnabled( TRUE );
+
+ connect( button400cpi, SIGNAL( clicked() ), parent, SLOT( changed() ) );
+ connect( button800cpi, SIGNAL( clicked() ), parent, SLOT( changed() ) );
+
+ if ( 4 == resolution() ) {
+ button800cpi->setChecked( TRUE );
+ } else if ( 3 == resolution() ) {
+ button400cpi->setChecked( TRUE );
+ } else {
+ // it must have failed, try to help out
+ resolutionSelector->setEnabled(FALSE);
+ permissionProblemText->show();
+ }
+ }
+
+ if ( mouseCapabilityFlags & HAS_CSR ) {
+
+ initCordlessStatusReporting();
+
+ // Do a name
+ cordlessNameLabel->setText( i18n("Mouse type: %1").arg( cordlessName() ) );
+ cordlessNameLabel->setEnabled( TRUE );
+
+ // Display the battery power level - the level gets updated in updateGUI()
+ batteryBox->setEnabled( TRUE );
+
+ // Channel
+ channelSelector->setEnabled( TRUE );
+ // if the channel is changed, we need to turn off the timer, otherwise it
+ // just resets the button to reflect the current status. The timer is
+ // started again when we applyChanges()
+ connect( channel1, SIGNAL( clicked() ), this, SLOT( stopTimerForNow() ) );
+ connect( channel1, SIGNAL( clicked() ), parent, SLOT( changed() ) );
+ if ( isDualChannelCapable() ) {
+ channel2->setEnabled( TRUE );
+ connect( channel2, SIGNAL( clicked() ), this, SLOT( stopTimerForNow() ) );
+ connect( channel2, SIGNAL( clicked() ), parent, SLOT( changed() ) );
+ }
+
+ updateGUI();
+ }
+
+}
+
+LogitechMouse::~LogitechMouse()
+{
+ usb_close( m_usbDeviceHandle );
+}
+
+void LogitechMouse::initCordlessStatusReporting()
+{
+ updateCordlessStatus();
+ doUpdate = new QTimer( this ); // will be automatically deleted
+ connect( doUpdate, SIGNAL( timeout() ), this, SLOT( updateGUI() ) );
+ doUpdate->start( 20000 );
+}
+
+void LogitechMouse::updateCordlessStatus()
+{
+ QByteArray status(8);
+
+ int result = usb_control_msg( m_usbDeviceHandle,
+ USB_TYPE_VENDOR | USB_ENDPOINT_IN,0x09,
+ (0x0003 | m_useSecondChannel),
+ (0x0000 | m_useSecondChannel),
+ status.data(),
+ 0x0008,
+ 1000);
+
+ if (0 > result) {
+ // We probably have a permission problem
+ channelSelector->setEnabled( FALSE );
+ batteryBox->setEnabled( FALSE );
+ cordlessNameLabel->hide();
+ permissionProblemText->show();
+ } else {
+ // kdDebug() << "P6 (connect status): " << (status[0] & 0xFF) << endl;
+ if ( status[0] & 0x20 ) { // mouse is talking
+ m_connectStatus = ( status[0] & 0x80 );
+ m_mousePowerup = ( status[0] & 0x40 );
+ m_receiverUnlock = ( status[0] & 0x10 );
+ m_waitLock = ( status[0] & 0x08 );
+ }
+
+ // kdDebug() << "P0 (receiver type): " << (status[1] & 0xFF) << endl;
+ /*
+ 0x38 = pid C501
+ 0x39 = pid C502
+ 0x3B = pid C504
+ 0x3C = pid C508
+ 0x3D = pid C506
+ 0x3E = pid C505
+ */
+
+ m_cordlessNameIndex = (status[2] & 0xFF);
+
+ m_batteryLevel = (status[3] & 0x07 );
+ if ( status[3] & 0x08 ) {
+ m_channel = 2;
+ } else {
+ m_channel = 1;
+ }
+
+ m_cordlessSecurity = ( ( status[4] ) & ( status[5] << 8 ) );
+
+ m_caseShape = ( status[6] & 0x7F );
+
+ // kdDebug() << "PB1 (device Capabilities): " << (status[7] & 0xFF) << endl;
+ m_numberOfButtons = 2 + ( status[7] & 0x07 ); // 9 means something more than 8
+ m_twoChannelCapable = ( status[7] & 0x40 );
+ m_verticalRoller = ( status[7] & 0x08 );
+ m_horizontalRoller = ( status[7] & 0x10 );
+ m_has800cpi = ( status[7] & 0x20 );
+ }
+
+}
+
+void LogitechMouse::updateGUI()
+{
+ updateCordlessStatus();
+
+ batteryBar->setProgress( batteryLevel() );
+
+ if ( isDualChannelCapable() ) {
+ if ( 2 == channel() ) {
+ channel2->setChecked( TRUE );
+ } else if ( 1 == channel() ) {
+ channel1->setChecked( TRUE );
+ } // else it might have failed - we don't do anything
+ }
+}
+
+void LogitechMouse::stopTimerForNow()
+{
+ doUpdate->stop();
+}
+
+void LogitechMouse::applyChanges()
+{
+ if ( m_mouseCapabilityFlags & HAS_RES ) {
+ if ( ( resolution() == 4 ) && ( button400cpi->isChecked() ) ) {
+ // then we are in 800cpi mode, but want 400cpi
+ setLogitechTo400();
+ } else if ( ( resolution() == 3 ) && (button800cpi->isChecked() ) ) {
+ // then we are in 400 cpi mode, but want 800 cpi
+ setLogitechTo800();
+ }
+ }
+
+ if ( isDualChannelCapable() ) {
+ if ( ( channel() == 2 ) && ( channel1->isChecked() ) ) {
+ // we are on channel 2, but want channel 1
+ setChannel1();
+ KMessageBox::information(this, i18n("RF channel 1 has been set. Please press Connect button on mouse to re-establish link"), i18n("Press Connect Button") );
+ } else if ( ( channel() == 1 ) && ( channel2->isChecked() ) ) {
+ // we are on channel 1, but want channel 2
+ setChannel2();
+ KMessageBox::information(this, i18n("RF channel 2 has been set. Please press Connect button on mouse to re-establish link"), i18n("Press Connect Button") );
+ }
+
+ initCordlessStatusReporting();
+ }
+}
+
+void LogitechMouse::save(KConfig * /*config*/)
+{
+ kdDebug() << "Logitech mouse settings not saved - not implemented yet" << endl;
+}
+
+Q_UINT8 LogitechMouse::resolution()
+{
+ // kdDebug() << "resolution: " << m_resolution << endl;
+ if ( 0 == m_resolution ) {
+ updateResolution();
+ }
+ return m_resolution;
+}
+
+void LogitechMouse::updateResolution()
+{
+ char resolution;
+
+ int result = usb_control_msg( m_usbDeviceHandle,
+ USB_TYPE_VENDOR | USB_ENDPOINT_IN,
+ 0x01,
+ 0x000E,
+ 0x0000,
+ &resolution,
+ 0x0001,
+ 100);
+
+ // kdDebug() << "resolution is: " << resolution << endl;
+ if (0 > result) {
+ kdWarning() << "Error getting resolution from device : " << usb_strerror() << endl;
+ m_resolution = 0;
+ } else {
+ m_resolution = resolution;
+ }
+}
+
+void LogitechMouse::setLogitechTo800()
+{
+ int result = usb_control_msg( m_usbDeviceHandle,
+ USB_TYPE_VENDOR,
+ 0x02,
+ 0x000E,
+ 4,
+ NULL,
+ 0x0000,
+ 100);
+ if (0 > result) {
+ kdWarning() << "Error setting resolution on device: " << usb_strerror() << endl;
+ }
+}
+
+void LogitechMouse::setLogitechTo400()
+{
+ int result = usb_control_msg( m_usbDeviceHandle,
+ USB_TYPE_VENDOR,
+ 0x02,
+ 0x000E,
+ 3,
+ NULL,
+ 0x0000,
+ 100);
+ if (0 > result) {
+ kdWarning() << "Error setting resolution on device: " << usb_strerror() << endl;
+ }
+}
+
+Q_UINT8 LogitechMouse::batteryLevel()
+{
+ return m_batteryLevel;
+}
+
+
+Q_UINT8 LogitechMouse::channel()
+{
+ return m_channel;
+}
+
+bool LogitechMouse::isDualChannelCapable()
+{
+ return m_twoChannelCapable;
+}
+
+void LogitechMouse::setChannel1()
+{
+ int result = usb_control_msg( m_usbDeviceHandle,
+ USB_TYPE_VENDOR,
+ 0x02,
+ (0x0008 | m_useSecondChannel),
+ (0x0000 | m_useSecondChannel),
+ NULL,
+ 0x0000,
+ 1000);
+
+ if (0 > result) {
+ kdWarning() << "Error setting mouse to channel 1 : " << usb_strerror() << endl;
+ }
+
+}
+
+void LogitechMouse::setChannel2()
+{
+ int result = usb_control_msg( m_usbDeviceHandle,
+ USB_TYPE_VENDOR,
+ 0x02,
+ (0x0008 | m_useSecondChannel),
+ (0x0001 | m_useSecondChannel),
+ NULL,
+ 0x0000,
+ 1000);
+
+ if (0 > result) {
+ kdWarning() << "Error setting mouse to channel 2 : " << usb_strerror() << endl;
+ }
+
+}
+
+QString LogitechMouse::cordlessName()
+{
+ switch ( m_cordlessNameIndex ) {
+ case 0x00:
+ return i18n( "none" );
+ break;
+ case 0x04:
+ return i18n( "Cordless Mouse" );
+ break;
+ case 0x05:
+ return i18n( "Cordless Wheel Mouse" );
+ break;
+ case 0x06:
+ return i18n( "Cordless MouseMan Wheel" );
+ break;
+ case 0x07:
+ return i18n( "Cordless Wheel Mouse" );
+ break;
+ case 0x08:
+ return i18n( "Cordless Wheel Mouse" );
+ break;
+ case 0x09:
+ return i18n( "Cordless TrackMan Wheel" );
+ break;
+ case 0x0A:
+ return i18n( "TrackMan Live" );
+ break;
+ case 0x0C:
+ return i18n( "Cordless TrackMan FX" );
+ break;
+ case 0x0D:
+ return i18n( "Cordless MouseMan Optical" );
+ break;
+ case 0x0E:
+ return i18n( "Cordless Optical Mouse" );
+ break;
+ case 0x0F:
+ return i18n( "Cordless Mouse" );
+ break;
+ case 0x12:
+ return i18n( "Cordless MouseMan Optical (2ch)" );
+ break;
+ case 0x13:
+ return i18n( "Cordless Optical Mouse (2ch)" );
+ break;
+ case 0x14:
+ return i18n( "Cordless Mouse (2ch)" );
+ break;
+ case 0x82:
+ return i18n( "Cordless Optical TrackMan" );
+ break;
+ case 0x8A:
+ return i18n( "MX700 Cordless Optical Mouse" );
+ break;
+ case 0x8B:
+ return i18n( "MX700 Cordless Optical Mouse (2ch)" );
+ break;
+ default:
+ return i18n( "Unknown mouse");
+ }
+}
+
+#include "logitechmouse.moc"
+
+#endif
+
diff --git a/kcontrol/input/logitechmouse.h b/kcontrol/input/logitechmouse.h
new file mode 100644
index 000000000..8c7ef06d3
--- /dev/null
+++ b/kcontrol/input/logitechmouse.h
@@ -0,0 +1,102 @@
+/*
+ * logitechmouse.h
+ *
+ * Copyright (C) 2004 Brad Hards <bradh@frogmouth.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef __LOGITECHMOUSE_H__
+#define __LOGITECHMOUSE_H__
+
+#include <qdialog.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+
+#include <kconfig.h>
+
+#include <config.h>
+
+#include "logitechmouse_base.h"
+
+#include <usb.h>
+
+#define VENDOR_LOGITECH 0x046D
+#define HAS_RES 0x01 /* mouse supports variable resolution */
+#define HAS_SS 0x02 /* mouse supports smart scroll control */
+#define HAS_CSR 0x04 /* mouse supports cordless status reporting and control */
+#define HAS_SSR 0x08 /* mouse supports smart scroll reporting */
+#define USE_CH2 0x10 /* mouse needs to use the second channel */
+
+
+class LogitechMouse : public LogitechMouseBase
+{
+ Q_OBJECT
+
+public:
+ LogitechMouse( struct usb_device *usbDev, int mouseCapabilityFlags, QWidget* parent = 0, const char* name = 0 );
+ ~LogitechMouse();
+ void applyChanges();
+ void save(KConfig *config);
+
+protected slots:
+ void setChannel1();
+ void setChannel2();
+ void updateGUI();
+ void stopTimerForNow();
+
+private:
+ void initCordlessStatusReporting();
+ void updateCordlessStatus();
+
+ void setLogitechTo400();
+ void setLogitechTo800();
+
+ QString cordlessName();
+ Q_UINT8 resolution();
+ void updateResolution();
+ Q_UINT8 batteryLevel();
+ Q_UINT8 channel();
+ bool isDualChannelCapable();
+
+ QTimer *doUpdate;
+
+ struct usb_dev_handle *m_usbDeviceHandle;
+ bool m_connectStatus; // true if the CONNECT button on the mouse is pressed
+ bool m_mousePowerup; // true if we are doing "just out of the box" auto-locking
+ bool m_receiverUnlock; // true if mouse has been disconnected by a long press
+ // of the receiver's CONNECT button
+ bool m_waitLock; // true if receiver searching for new mouse because the
+ // CONNECT button on the receiver was pressed
+ Q_UINT8 m_batteryLevel;
+ Q_UINT8 m_channel;
+ Q_UINT8 m_cordlessNameIndex; // this gets convered into a QString in cordlessName()
+ Q_UINT16 m_cordlessSecurity;
+ Q_UINT16 m_useSecondChannel;
+ Q_UINT8 m_caseShape;
+ Q_UINT8 m_numberOfButtons;
+ Q_UINT8 m_resolution;
+ bool m_twoChannelCapable; // true if the mouse supports dual channels
+ bool m_verticalRoller; // true if the mouse has a vertical roller (wheel)
+ bool m_horizontalRoller; // true if the mouse has a horizontal roller (wheel)
+ bool m_has800cpi; // true if the mouse does 800cpi resolution
+ int m_mouseCapabilityFlags;
+};
+
+#endif
+
diff --git a/kcontrol/input/logitechmouse.usermap b/kcontrol/input/logitechmouse.usermap
new file mode 100644
index 000000000..65da520c5
--- /dev/null
+++ b/kcontrol/input/logitechmouse.usermap
@@ -0,0 +1,35 @@
+# script match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info
+# Wheel Mouse Optical
+consoleUserPerms 0x0003 0x046d 0xc00e 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# MouseMan Traveler
+consoleUserPerms 0x0003 0x046d 0xc00f 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# MouseMan Dual Optical
+consoleUserPerms 0x0003 0x046d 0xc012 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# MX310 Optical Mouse
+consoleUserPerms 0x0003 0x046d 0xc01b 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# MX510 Optical Mouse
+consoleUserPerms 0x0003 0x046d 0xc01d 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# MX300 Optical Mouse
+consoleUserPerms 0x0003 0x046d 0xc024 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# MX500 Optical Mouse
+consoleUserPerms 0x0003 0x046d 0xc025 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# iFeel Mouse
+consoleUserPerms 0x0003 0x046d 0xc031 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# Mouse Receiver
+consoleUserPerms 0x0003 0x046d 0xc501 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# Dual Receiver
+consoleUserPerms 0x0003 0x046d 0xc502 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# Cordless Freedom Optical
+consoleUserPerms 0x0003 0x046d 0xc504 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# Cordless Elite Duo
+consoleUserPerms 0x0003 0x046d 0xc505 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# MX700 Optical Mouse
+consoleUserPerms 0x0003 0x046d 0xc506 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# Cordless Optical Trackman
+consoleUserPerms 0x0003 0x046d 0xc508 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# Cordless MX Duo Receiver
+consoleUserPerms 0x0003 0x046d 0xc50b 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# MX100 Laser Mouse
+consoleUserPerms 0x0003 0x046d 0xc50e 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+# Receiver for Cordless Presenter
+consoleUserPerms 0x0003 0x046d 0xc702 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
diff --git a/kcontrol/input/logitechmouse_base.ui b/kcontrol/input/logitechmouse_base.ui
new file mode 100644
index 000000000..5c9c1cd9a
--- /dev/null
+++ b/kcontrol/input/logitechmouse_base.ui
@@ -0,0 +1,153 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>LogitechMouseBase</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>LogitechMouseBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>458</width>
+ <height>383</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>cordlessNameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Cordless Name</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>permissionProblemText</cstring>
+ </property>
+ <property name="text">
+ <string>You have a Logitech Mouse connected, and libusb was found at compile time, but it was not possible to access this mouse. This is probably caused by a permissions problem - you should consult the manual on how to fix this.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QButtonGroup" row="1" column="0">
+ <property name="name">
+ <cstring>resolutionSelector</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="title">
+ <string>Sensor Resolution</string>
+ </property>
+ <property name="radioButtonExclusive">
+ <bool>true</bool>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>button400cpi</cstring>
+ </property>
+ <property name="text">
+ <string>400 counts per inch</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>button800cpi</cstring>
+ </property>
+ <property name="text">
+ <string>800 counts per inch</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>1</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox" row="2" column="0">
+ <property name="name">
+ <cstring>batteryBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="title">
+ <string>Battery Level</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QProgressBar">
+ <property name="name">
+ <cstring>batteryBar</cstring>
+ </property>
+ <property name="totalSteps">
+ <number>7</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QButtonGroup" row="3" column="0">
+ <property name="name">
+ <cstring>channelSelector</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="title">
+ <string>RF Channel</string>
+ </property>
+ <property name="exclusive">
+ <bool>true</bool>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>channel1</cstring>
+ </property>
+ <property name="text">
+ <string>Channel 1</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>3</number>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>channel2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Channel 2</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>3</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kcontrol/input/main.cpp b/kcontrol/input/main.cpp
new file mode 100644
index 000000000..f0a464adc
--- /dev/null
+++ b/kcontrol/input/main.cpp
@@ -0,0 +1,96 @@
+/*
+ * main.cpp
+ *
+ * Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <klocale.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <dcopref.h>
+#include <qfile.h>
+
+#include <X11/Xlib.h>
+
+#ifdef HAVE_XCURSOR
+# include <X11/Xcursor/Xcursor.h>
+#endif
+
+#include "mouse.h"
+
+extern "C"
+{
+ KDE_EXPORT KCModule *create_mouse(QWidget *parent, const char *)
+ {
+ return new MouseConfig(parent, "kcminput");
+ }
+
+ KDE_EXPORT void init_mouse()
+ {
+ KConfig *config = new KConfig("kcminputrc", true, false); // Read-only, no globals
+ MouseSettings settings;
+ settings.load(config);
+ settings.apply(true); // force
+
+#ifdef HAVE_XCURSOR
+ config->setGroup("Mouse");
+ QCString theme = QFile::encodeName(config->readEntry("cursorTheme", QString()));
+ QCString size = config->readEntry("cursorSize", QString()).local8Bit();
+
+ // Note: If you update this code, update kapplymousetheme as well.
+
+ // use a default value for theme only if it's not configured at all, not even in X resources
+ if( theme.isEmpty()
+ && QCString( XGetDefault( qt_xdisplay(), "Xcursor", "theme" )).isEmpty()
+ && QCString( XcursorGetTheme( qt_xdisplay())).isEmpty())
+ {
+ theme = "default";
+ }
+
+ // Apply the KDE cursor theme to ourselves
+ if( !theme.isEmpty())
+ XcursorSetTheme(qt_xdisplay(), theme.data());
+
+ if (!size.isEmpty())
+ XcursorSetDefaultSize(qt_xdisplay(), size.toUInt());
+
+ // Load the default cursor from the theme and apply it to the root window.
+ Cursor handle = XcursorLibraryLoadCursor(qt_xdisplay(), "left_ptr");
+ XDefineCursor(qt_xdisplay(), qt_xrootwin(), handle);
+ XFreeCursor(qt_xdisplay(), handle); // Don't leak the cursor
+
+ // Tell klauncher to set the XCURSOR_THEME and XCURSOR_SIZE environment
+ // variables when launching applications.
+ DCOPRef klauncher("klauncher");
+ if( !theme.isEmpty())
+ klauncher.send("setLaunchEnv", QCString("XCURSOR_THEME"), theme);
+ if( !size.isEmpty())
+ klauncher.send("setLaunchEnv", QCString("XCURSOR_SIZE"), size);
+#endif
+
+ delete config;
+ }
+}
+
+
diff --git a/kcontrol/input/mouse.cpp b/kcontrol/input/mouse.cpp
new file mode 100644
index 000000000..56e737135
--- /dev/null
+++ b/kcontrol/input/mouse.cpp
@@ -0,0 +1,838 @@
+/*
+ * mouse.cpp
+ *
+ * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca
+ *
+ * Layout management, enhancements:
+ * Copyright (c) 1999 Dirk A. Mueller <dmuell@gmx.net>
+ *
+ * SC/DC/AutoSelect/ChangeCursor:
+ * Copyright (c) 2000 David Faure <faure@kde.org>
+ *
+ * Double click interval, drag time & dist
+ * Copyright (c) 2000 Bernd Gehrmann
+ *
+ * Large cursor support
+ * Visual activation TODO: speed
+ * Copyright (c) 2000 Rik Hemsley <rik@kde.org>
+ *
+ * White cursor support
+ * TODO: give user the option to choose a certain cursor font
+ * -> Theming
+ *
+ * General/Advanced tabs
+ * Copyright (c) 2000 Brad Hughes <bhughes@trolltech.com>
+ *
+ * redesign for KDE 2.2
+ * Copyright (c) 2001 Ralf Nolden <nolden@kde.org>
+ *
+ * Logitech mouse support
+ * Copyright (C) 2004 Brad Hards <bradh@frogmouth.net>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#undef Below
+#undef Above
+#include <qslider.h>
+#include <qwhatsthis.h>
+#include <qtabwidget.h>
+#include <qradiobutton.h>
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kaboutdata.h>
+
+#include <config.h>
+
+#include "mouse.h"
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <kipc.h>
+
+#undef Below
+
+MouseConfig::MouseConfig (QWidget * parent, const char *name)
+ : KCModule(parent, name)
+{
+
+
+ setQuickHelp( i18n("<h1>Mouse</h1> This module allows you to choose various"
+ " options for the way in which your pointing device works. Your"
+ " pointing device may be a mouse, trackball, or some other hardware"
+ " that performs a similar function."));
+
+ QString wtstr;
+
+ QBoxLayout *top = new QVBoxLayout(this, 0, KDialog::spacingHint());
+
+ tabwidget = new QTabWidget(this);
+ top->addWidget(tabwidget);
+
+ tab1 = new KMouseDlg(this);
+ QButtonGroup *group = new QButtonGroup( tab1 );
+ group->setExclusive( true );
+ group->hide();
+ group->insert( tab1->singleClick );
+ group->insert( tab1->doubleClick );
+
+ tabwidget->addTab(tab1, i18n("&General"));
+
+ connect(tab1->handedBox, SIGNAL(clicked(int)), this, SLOT(changed()));
+ connect(tab1->handedBox, SIGNAL(clicked(int)), this, SLOT(slotHandedChanged(int)));
+
+ wtstr = i18n("If you are left-handed, you may prefer to swap the"
+ " functions of the left and right buttons on your pointing device"
+ " by choosing the 'left-handed' option. If your pointing device"
+ " has more than two buttons, only those that function as the"
+ " left and right buttons are affected. For example, if you have"
+ " a three-button mouse, the middle button is unaffected.");
+ QWhatsThis::add( tab1->handedBox, wtstr );
+
+ connect(tab1->doubleClick, SIGNAL(clicked()), SLOT(changed()));
+
+ wtstr = i18n("The default behavior in KDE is to select and activate"
+ " icons with a single click of the left button on your pointing"
+ " device. This behavior is consistent with what you would expect"
+ " when you click links in most web browsers. If you would prefer"
+ " to select with a single click, and activate with a double click,"
+ " check this option.");
+ QWhatsThis::add( tab1->doubleClick, wtstr );
+
+ wtstr = i18n("Activates and opens a file or folder with a single click.");
+ QWhatsThis::add( tab1->singleClick, wtstr );
+
+
+ connect(tab1->cbAutoSelect, SIGNAL(clicked()), this, SLOT(changed()));
+
+ wtstr = i18n("If you check this option, pausing the mouse pointer"
+ " over an icon on the screen will automatically select that icon."
+ " This may be useful when single clicks activate icons, and you"
+ " want only to select the icon without activating it.");
+ QWhatsThis::add( tab1->cbAutoSelect, wtstr );
+
+// slAutoSelect = new QSlider(0, 2000, 10, 0, QSlider::Horizontal, tab1);
+ tab1->slAutoSelect->setSteps( 125, 125 );
+ tab1->slAutoSelect->setTickmarks( QSlider::Below );
+ tab1->slAutoSelect->setTickInterval( 250 );
+ tab1->slAutoSelect->setTracking( true );
+
+ wtstr = i18n("If you have checked the option to automatically select"
+ " icons, this slider allows you to select how long the mouse pointer"
+ " must be paused over the icon before it is selected.");
+ QWhatsThis::add( tab1->slAutoSelect, wtstr );
+
+ wtstr = i18n("Show feedback when clicking an icon");
+ QWhatsThis::add( tab1->cbVisualActivate, wtstr );
+
+ connect(tab1->slAutoSelect, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(tab1->cbVisualActivate, SIGNAL(clicked()), this, SLOT(changed()));
+
+ connect(tab1->cb_pointershape, SIGNAL(clicked()), this, SLOT(changed()));
+
+ connect(tab1->singleClick, SIGNAL(clicked()), this, SLOT(changed()));
+ connect(tab1->singleClick, SIGNAL(clicked()), this, SLOT(slotClick()));
+
+ connect( tab1->doubleClick, SIGNAL( clicked() ), this, SLOT( slotClick() ) );
+ connect( tab1->cbAutoSelect, SIGNAL( clicked() ), this, SLOT( slotClick() ) );
+
+ // Only allow setting reversing scroll polarity if we have scroll buttons
+ unsigned char map[20];
+ if ( XGetPointerMapping(kapp->getDisplay(), map, 20) >= 5 )
+ {
+ tab1->cbScrollPolarity->setEnabled( true );
+ tab1->cbScrollPolarity->show();
+ }
+ else
+ {
+ tab1->cbScrollPolarity->setEnabled( false );
+ tab1->cbScrollPolarity->hide();
+ }
+ connect(tab1->cbScrollPolarity, SIGNAL(clicked()), this, SLOT(changed()));
+ connect(tab1->cbScrollPolarity, SIGNAL(clicked()), this, SLOT(slotScrollPolarityChanged()));
+
+ // Cursor theme tab
+ themetab = new ThemePage(this);
+ connect(themetab, SIGNAL(changed(bool)), SLOT(changed()));
+ tabwidget->addTab(themetab, i18n("&Cursor Theme"));
+
+ // Advanced tab
+ tab2 = new QWidget(0, "Advanced Tab");
+ tabwidget->addTab(tab2, i18n("Advanced"));
+
+ QBoxLayout *lay = new QVBoxLayout(tab2, KDialog::marginHint(),
+ KDialog::spacingHint());
+
+ accel = new KDoubleNumInput(1, 20, 2, 0.1, 1, tab2);
+ accel->setLabel(i18n("Pointer acceleration:"));
+ accel->setSuffix("x");
+ lay->addWidget(accel);
+ connect(accel, SIGNAL(valueChanged(double)), this, SLOT(changed()));
+
+ wtstr = i18n("This option allows you to change the relationship"
+ " between the distance that the mouse pointer moves on the"
+ " screen and the relative movement of the physical device"
+ " itself (which may be a mouse, trackball, or some other"
+ " pointing device.)<p>"
+ " A high value for the acceleration will lead to large"
+ " movements of the mouse pointer on the screen even when"
+ " you only make a small movement with the physical device."
+ " Selecting very high values may result in the mouse pointer"
+ " flying across the screen, making it hard to control.");
+ QWhatsThis::add( accel, wtstr );
+
+ thresh = new KIntNumInput(accel, 20, tab2);
+ thresh->setLabel(i18n("Pointer threshold:"));
+ thresh->setRange(0,20,1);
+ thresh->setSteps(1,1);
+ lay->addWidget(thresh);
+ connect(thresh, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(thresh, SIGNAL(valueChanged(int)), this, SLOT(slotThreshChanged(int)));
+ slotThreshChanged(thresh->value());
+
+ wtstr = i18n("The threshold is the smallest distance that the"
+ " mouse pointer must move on the screen before acceleration"
+ " has any effect. If the movement is smaller than the threshold,"
+ " the mouse pointer moves as if the acceleration was set to 1X;<p>"
+ " thus, when you make small movements with the physical device,"
+ " there is no acceleration at all, giving you a greater degree"
+ " of control over the mouse pointer. With larger movements of"
+ " the physical device, you can move the mouse pointer"
+ " rapidly to different areas on the screen.");
+ QWhatsThis::add( thresh, wtstr );
+
+ // It would be nice if the user had a test field.
+ // Selecting such values in milliseconds is not intuitive
+ doubleClickInterval = new KIntNumInput(thresh, 2000, tab2);
+ doubleClickInterval->setLabel(i18n("Double click interval:"));
+ doubleClickInterval->setRange(0, 2000, 100);
+ doubleClickInterval->setSuffix(i18n(" msec"));
+ doubleClickInterval->setSteps(100, 100);
+ lay->addWidget(doubleClickInterval);
+ connect(doubleClickInterval, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+
+ wtstr = i18n("The double click interval is the maximal time"
+ " (in milliseconds) between two mouse clicks which"
+ " turns them into a double click. If the second"
+ " click happens later than this time interval after"
+ " the first click, they are recognized as two"
+ " separate clicks.");
+ QWhatsThis::add( doubleClickInterval, wtstr );
+
+ lay->addSpacing(15);
+
+ dragStartTime = new KIntNumInput(doubleClickInterval, 2000, tab2);
+ dragStartTime->setLabel(i18n("Drag start time:"));
+ dragStartTime->setRange(0, 2000, 100);
+ dragStartTime->setSuffix(i18n(" msec"));
+ dragStartTime->setSteps(100, 100);
+ lay->addWidget(dragStartTime);
+ connect(dragStartTime, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+
+ wtstr = i18n("If you click with the mouse (e.g. in a multi-line"
+ " editor) and begin to move the mouse within the"
+ " drag start time, a drag operation will be initiated.");
+ QWhatsThis::add( dragStartTime, wtstr );
+
+ dragStartDist = new KIntNumInput(dragStartTime, 20, tab2);
+ dragStartDist->setLabel(i18n("Drag start distance:"));
+ dragStartDist->setRange(1, 20, 1);
+ dragStartDist->setSteps(1,1);
+ lay->addWidget(dragStartDist);
+ connect(dragStartDist, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(dragStartDist, SIGNAL(valueChanged(int)), this, SLOT(slotDragStartDistChanged(int)));
+ slotDragStartDistChanged(dragStartDist->value());
+
+ wtstr = i18n("If you click with the mouse and begin to move the"
+ " mouse at least the drag start distance, a drag"
+ " operation will be initiated.");
+ QWhatsThis::add( dragStartDist, wtstr);
+
+ wheelScrollLines = new KIntNumInput(dragStartDist, 3, tab2);
+ wheelScrollLines->setLabel(i18n("Mouse wheel scrolls by:"));
+ wheelScrollLines->setRange(1, 12, 1);
+ wheelScrollLines->setSteps(1,1);
+ lay->addWidget(wheelScrollLines);
+ connect(wheelScrollLines, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(wheelScrollLines, SIGNAL(valueChanged(int)), SLOT(slotWheelScrollLinesChanged(int)));
+ slotWheelScrollLinesChanged(wheelScrollLines->value());
+
+ 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.");
+ QWhatsThis::add( wheelScrollLines, wtstr);
+ lay->addStretch();
+
+{
+ QWidget *mouse = new QWidget(this, "Mouse Navigation");
+ tabwidget->addTab(mouse, i18n("Mouse Navigation"));
+
+
+ QBoxLayout *vbox = new QVBoxLayout(mouse, KDialog::marginHint(),
+ KDialog::spacingHint());
+
+ QVBoxLayout *vvbox = new QVBoxLayout(mouse->layout(), KDialog::spacingHint());
+
+ mouseKeys = new QCheckBox(i18n("&Move pointer with keyboard (using the num pad)"), mouse);
+ vvbox->addWidget(mouseKeys);
+
+ QBoxLayout *hbox = new QHBoxLayout(vvbox, KDialog::spacingHint());
+ hbox->addSpacing(24);
+ mk_delay = new KIntNumInput(mouse);
+ mk_delay->setLabel(i18n("&Acceleration delay:"), AlignVCenter);
+ mk_delay->setSuffix(i18n(" msec"));
+ mk_delay->setRange(1, 1000, 50);
+ hbox->addWidget(mk_delay);
+
+ hbox = new QHBoxLayout(vvbox, KDialog::spacingHint());
+ hbox->addSpacing(24);
+ mk_interval = new KIntNumInput(mk_delay, 0, mouse);
+ mk_interval->setLabel(i18n("R&epeat interval:"), AlignVCenter);
+ mk_interval->setSuffix(i18n(" msec"));
+ mk_interval->setRange(1, 1000, 10);
+ hbox->addWidget(mk_interval);
+
+ hbox = new QHBoxLayout(vvbox, KDialog::spacingHint());
+ hbox->addSpacing(24);
+ mk_time_to_max = new KIntNumInput(mk_interval, 0, mouse);
+ mk_time_to_max->setLabel(i18n("Acceleration &time:"), AlignVCenter);
+ mk_time_to_max->setRange(100, 10000, 200);
+ mk_time_to_max->setSuffix(i18n(" msec"));
+ hbox->addWidget(mk_time_to_max);
+
+ hbox = new QHBoxLayout(vvbox, KDialog::spacingHint());
+ hbox->addSpacing(24);
+ mk_max_speed = new KIntNumInput(mk_time_to_max, 0, mouse);
+ mk_max_speed->setLabel(i18n("Ma&ximum speed:"), AlignVCenter);
+ mk_max_speed->setRange(1, 2000, 20);
+ mk_max_speed->setSuffix(i18n(" pixel/sec"));
+ hbox->addWidget(mk_max_speed);
+
+ hbox = new QHBoxLayout(vvbox, KDialog::spacingHint());
+ hbox->addSpacing(24);
+ mk_curve = new KIntNumInput(mk_max_speed, 0, mouse);
+ mk_curve->setLabel(i18n("Acceleration &profile:"), AlignVCenter);
+ mk_curve->setRange(-1000, 1000, 100);
+ hbox->addWidget(mk_curve);
+
+ connect(mouseKeys, SIGNAL(clicked()), this, SLOT(checkAccess()));
+ connect(mouseKeys, SIGNAL(clicked()), this, SLOT(changed()));
+ connect(mk_delay, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(mk_interval, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(mk_time_to_max, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(mk_max_speed, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(mk_curve, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+
+ vbox->addStretch();
+}
+
+ settings = new MouseSettings;
+
+ // This part is for handling features on Logitech USB mice.
+ // It only works if libusb is available.
+#ifdef HAVE_LIBUSB
+
+ struct device_table {
+ int idVendor;
+ int idProduct;
+ QString Model;
+ QString Name;
+ int flags;
+ } device_table[] = {
+ { VENDOR_LOGITECH, 0xC00E, "M-BJ58", "Wheel Mouse Optical", HAS_RES },
+ { VENDOR_LOGITECH, 0xC00F, "M-BJ79", "MouseMan Traveler", HAS_RES },
+ { VENDOR_LOGITECH, 0xC012, "M-BL63B", "MouseMan Dual Optical", HAS_RES },
+ { VENDOR_LOGITECH, 0xC01B, "M-BP86", "MX310 Optical Mouse", HAS_RES },
+ { VENDOR_LOGITECH, 0xC01D, "M-BS81A", "MX510 Optical Mouse", HAS_RES | HAS_SS | HAS_SSR },
+ { VENDOR_LOGITECH, 0xC024, "M-BP82", "MX300 Optical Mouse", HAS_RES },
+ { VENDOR_LOGITECH, 0xC025, "M-BP81A", "MX500 Optical Mouse", HAS_RES | HAS_SS | HAS_SSR },
+ { VENDOR_LOGITECH, 0xC031, "M-UT58A", "iFeel Mouse (silver)", HAS_RES },
+ { VENDOR_LOGITECH, 0xC501, "C-BA4-MSE", "Mouse Receiver", HAS_CSR },
+ { VENDOR_LOGITECH, 0xC502, "C-UA3-DUAL", "Dual Receiver", HAS_CSR | USE_CH2},
+ { VENDOR_LOGITECH, 0xC504, "C-BD9-DUAL", "Cordless Freedom Optical", HAS_CSR | USE_CH2 },
+ { VENDOR_LOGITECH, 0xC505, "C-BG17-DUAL", "Cordless Elite Duo", HAS_SS | HAS_SSR | HAS_CSR | USE_CH2},
+ { VENDOR_LOGITECH, 0xC506, "C-BF16-MSE", "MX700 Optical Mouse", HAS_SS | HAS_CSR },
+ { VENDOR_LOGITECH, 0xC508, "C-BA4-MSE", "Cordless Optical TrackMan", HAS_SS | HAS_CSR },
+ { VENDOR_LOGITECH, 0xC50B, "967300-0403", "Cordless MX Duo Receiver", HAS_SS|HAS_CSR },
+ { VENDOR_LOGITECH, 0xC50E, "M-RAG97", "MX1000 Laser Mouse", HAS_SS | HAS_CSR },
+ { VENDOR_LOGITECH, 0xC512, "M-RAK89B", "Cordless Desktop Pro LX700", HAS_CSR | USE_CH2 },
+ { VENDOR_LOGITECH, 0xC702, "C-UF15", "Receiver for Cordless Presenter", HAS_CSR },
+ { 0, 0, QString(), QString(), 0 }
+ };
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ struct usb_bus *bus;
+ struct usb_device *dev;
+
+ for (bus = usb_busses; bus; bus = bus->next) {
+ for (dev = bus->devices; dev; dev = dev->next) {
+ for (int n = 0; device_table[n].idVendor; n++)
+ if ( (device_table[n].idVendor == dev->descriptor.idVendor) &&
+ (device_table[n].idProduct == dev->descriptor.idProduct) ) {
+ // OK, we have a device that appears to be one of the ones we support
+ LogitechMouse *mouse = new LogitechMouse( dev, device_table[n].flags, this, device_table[n].Name.latin1() );
+ settings->logitechMouseList.append(mouse);
+ tabwidget->addTab( (QWidget*)mouse, device_table[n].Name );
+ }
+ }
+ }
+
+#endif
+
+ load();
+
+ KAboutData* about = new KAboutData("kcmmouse", I18N_NOOP("Mouse"), 0, 0,
+ KAboutData::License_GPL, I18N_NOOP("(c) 1997 - 2005 Mouse developers"));
+ about->addAuthor("Patrick Dowler", 0, 0);
+ about->addAuthor("Dirk A. Mueller", 0, 0);
+ about->addAuthor("David Faure", 0, 0);
+ about->addAuthor("Bernd Gehrmann", 0, 0);
+ about->addAuthor("Rik Hemsley", 0, 0);
+ about->addAuthor("Brad Hughes", 0, 0);
+ about->addAuthor("Ralf Nolden", 0, 0);
+ about->addAuthor("Brad Hards", 0, 0);
+ setAboutData( about );
+}
+
+void MouseConfig::checkAccess()
+{
+ mk_delay->setEnabled(mouseKeys->isChecked());
+ mk_interval->setEnabled(mouseKeys->isChecked());
+ mk_time_to_max->setEnabled(mouseKeys->isChecked());
+ mk_max_speed->setEnabled(mouseKeys->isChecked());
+ mk_curve->setEnabled(mouseKeys->isChecked());
+}
+
+
+MouseConfig::~MouseConfig()
+{
+ delete settings;
+}
+
+double MouseConfig::getAccel()
+{
+ return accel->value();
+}
+
+void MouseConfig::setAccel(double val)
+{
+ accel->setValue(val);
+}
+
+int MouseConfig::getThreshold()
+{
+ return thresh->value();
+}
+
+void MouseConfig::setThreshold(int val)
+{
+ thresh->setValue(val);
+}
+
+
+int MouseConfig::getHandedness()
+{
+ if (tab1->rightHanded->isChecked())
+ return RIGHT_HANDED;
+ else
+ return LEFT_HANDED;
+}
+
+void MouseConfig::setHandedness(int val)
+{
+ tab1->rightHanded->setChecked(false);
+ tab1->leftHanded->setChecked(false);
+ if (val == RIGHT_HANDED){
+ tab1->rightHanded->setChecked(true);
+ tab1->mousePix->setPixmap(locate("data", "kcminput/pics/mouse_rh.png"));
+ }
+ else{
+ tab1->leftHanded->setChecked(true);
+ tab1->mousePix->setPixmap(locate("data", "kcminput/pics/mouse_lh.png"));
+ }
+}
+
+void MouseConfig::load()
+{
+ load( false );
+}
+
+void MouseConfig::load( bool useDefaults )
+{
+
+ KConfig config( "kcminputrc", true );
+
+ config.setReadDefaults( useDefaults );
+
+ settings->load(&config);
+
+ tab1->rightHanded->setEnabled(settings->handedEnabled);
+ tab1->leftHanded->setEnabled(settings->handedEnabled);
+ if ( tab1->cbScrollPolarity->isEnabled() )
+ tab1->cbScrollPolarity->setEnabled(settings->handedEnabled);
+ tab1->cbScrollPolarity->setChecked( settings->reverseScrollPolarity );
+
+ setAccel(settings->accelRate);
+ setThreshold(settings->thresholdMove);
+ setHandedness(settings->handed);
+
+ doubleClickInterval->setValue(settings->doubleClickInterval);
+ dragStartTime->setValue(settings->dragStartTime);
+ dragStartDist->setValue(settings->dragStartDist);
+ wheelScrollLines->setValue(settings->wheelScrollLines);
+
+ tab1->singleClick->setChecked( settings->singleClick );
+ tab1->doubleClick->setChecked(!settings->singleClick);
+ tab1->cb_pointershape->setChecked(settings->changeCursor);
+ tab1->cbAutoSelect->setChecked( settings->autoSelectDelay >= 0 );
+ if ( settings->autoSelectDelay < 0 )
+ tab1->slAutoSelect->setValue( 0 );
+ else
+ tab1->slAutoSelect->setValue( settings->autoSelectDelay );
+ tab1->cbVisualActivate->setChecked( settings->visualActivate );
+ slotClick();
+
+
+ KConfig ac("kaccessrc", true);
+
+ ac.setGroup("Mouse");
+ mouseKeys->setChecked(ac.readBoolEntry("MouseKeys", false));
+ mk_delay->setValue(ac.readNumEntry("MKDelay", 160));
+
+ int interval = ac.readNumEntry("MKInterval", 5);
+ mk_interval->setValue(interval);
+
+ // Default time to reach maximum speed: 5000 msec
+ int time_to_max = ac.readNumEntry("MKTimeToMax",
+ (5000+interval/2)/interval);
+ time_to_max = ac.readNumEntry("MK-TimeToMax",
+ time_to_max*interval);
+ mk_time_to_max->setValue(time_to_max);
+
+ // Default maximum speed: 1000 pixels/sec
+ // (The old default maximum speed from KDE <= 3.4
+ // (100000 pixels/sec) was way too fast)
+ long max_speed = ac.readNumEntry("MKMaxSpeed", interval);
+ max_speed = max_speed * 1000 / interval;
+ if (max_speed > 2000)
+ max_speed = 2000;
+ max_speed = ac.readNumEntry("MK-MaxSpeed", max_speed);
+ mk_max_speed->setValue(max_speed);
+
+ mk_curve->setValue(ac.readNumEntry("MKCurve", 0));
+
+ themetab->load();
+
+ checkAccess();
+ changed( useDefaults );
+}
+
+void MouseConfig::save()
+{
+ settings->accelRate = getAccel();
+ settings->thresholdMove = getThreshold();
+ settings->handed = getHandedness();
+
+ settings->doubleClickInterval = doubleClickInterval->value();
+ settings->dragStartTime = dragStartTime->value();
+ settings->dragStartDist = dragStartDist->value();
+ settings->wheelScrollLines = wheelScrollLines->value();
+ settings->singleClick = !tab1->doubleClick->isChecked();
+ settings->autoSelectDelay = tab1->cbAutoSelect->isChecked()? tab1->slAutoSelect->value():-1;
+ settings->visualActivate = tab1->cbVisualActivate->isChecked();
+// settings->changeCursor = tab1->singleClick->isChecked();
+ settings->changeCursor = tab1->cb_pointershape->isChecked();
+ settings->reverseScrollPolarity = tab1->cbScrollPolarity->isChecked();
+
+ settings->apply();
+ KConfig config( "kcminputrc" );
+ settings->save(&config);
+
+ KConfig ac("kaccessrc", false);
+
+ ac.setGroup("Mouse");
+
+ int interval = mk_interval->value();
+ ac.writeEntry("MouseKeys", mouseKeys->isChecked());
+ ac.writeEntry("MKDelay", mk_delay->value());
+ ac.writeEntry("MKInterval", interval);
+ ac.writeEntry("MK-TimeToMax", mk_time_to_max->value());
+ ac.writeEntry("MKTimeToMax",
+ (mk_time_to_max->value() + interval/2)/interval);
+ ac.writeEntry("MK-MaxSpeed", mk_max_speed->value());
+ ac.writeEntry("MKMaxSpeed",
+ (mk_max_speed->value()*interval + 500)/1000);
+ ac.writeEntry("MKCurve", mk_curve->value());
+ ac.sync();
+
+ themetab->save();
+
+ // restart kaccess
+ kapp->startServiceByDesktopName("kaccess");
+
+ KCModule::changed(false);
+
+}
+
+void MouseConfig::defaults()
+{
+ load( true );
+}
+
+void MouseConfig::slotClick()
+{
+ // Autoselect has a meaning only in single-click mode
+ tab1->cbAutoSelect->setEnabled(!tab1->doubleClick->isChecked() || tab1->singleClick->isChecked());
+ // Delay has a meaning only for autoselect
+ bool bDelay = tab1->cbAutoSelect->isChecked() && ! tab1->doubleClick->isChecked();
+ tab1->slAutoSelect->setEnabled( bDelay );
+ tab1->lDelay->setEnabled( bDelay );
+ tab1->lb_short->setEnabled( bDelay );
+ tab1->lb_long->setEnabled( bDelay );
+
+}
+
+/** No descriptions */
+void MouseConfig::slotHandedChanged(int val){
+ if(val==RIGHT_HANDED)
+ tab1->mousePix->setPixmap(locate("data", "kcminput/pics/mouse_rh.png"));
+ else
+ tab1->mousePix->setPixmap(locate("data", "kcminput/pics/mouse_lh.png"));
+ settings->m_handedNeedsApply = true;
+}
+
+void MouseSettings::load(KConfig *config)
+{
+ int accel_num, accel_den, threshold;
+ double accel;
+ XGetPointerControl( kapp->getDisplay(),
+ &accel_num, &accel_den, &threshold );
+ accel = float(accel_num) / float(accel_den);
+
+ // get settings from X server
+ int h = RIGHT_HANDED;
+ unsigned char map[20];
+ num_buttons = XGetPointerMapping(kapp->getDisplay(), map, 20);
+
+ handedEnabled = true;
+
+ // ## keep this in sync with KGlobalSettings::mouseSettings
+ if( num_buttons == 1 )
+ {
+ /* disable button remapping */
+ handedEnabled = false;
+ }
+ else if( num_buttons == 2 )
+ {
+ if ( (int)map[0] == 1 && (int)map[1] == 2 )
+ h = RIGHT_HANDED;
+ else if ( (int)map[0] == 2 && (int)map[1] == 1 )
+ h = LEFT_HANDED;
+ else
+ /* custom button setup: disable button remapping */
+ handedEnabled = false;
+ }
+ else
+ {
+ middle_button = (int)map[1];
+ if ( (int)map[0] == 1 && (int)map[2] == 3 )
+ h = RIGHT_HANDED;
+ else if ( (int)map[0] == 3 && (int)map[2] == 1 )
+ h = LEFT_HANDED;
+ else
+ {
+ /* custom button setup: disable button remapping */
+ handedEnabled = false;
+ }
+ }
+
+ config->setGroup("Mouse");
+ double a = config->readDoubleNumEntry("Acceleration",-1);
+ if (a == -1)
+ accelRate = accel;
+ else
+ accelRate = a;
+
+ int t = config->readNumEntry("Threshold",-1);
+ if (t == -1)
+ thresholdMove = threshold;
+ else
+ thresholdMove = t;
+
+ QString key = config->readEntry("MouseButtonMapping");
+ if (key == "RightHanded")
+ handed = RIGHT_HANDED;
+ else if (key == "LeftHanded")
+ handed = LEFT_HANDED;
+ else if (key == NULL)
+ handed = h;
+ reverseScrollPolarity = config->readBoolEntry( "ReverseScrollPolarity", false );
+ m_handedNeedsApply = false;
+
+ // SC/DC/AutoSelect/ChangeCursor
+ config->setGroup("KDE");
+ doubleClickInterval = config->readNumEntry("DoubleClickInterval", 400);
+ dragStartTime = config->readNumEntry("StartDragTime", 500);
+ dragStartDist = config->readNumEntry("StartDragDist", 4);
+ wheelScrollLines = config->readNumEntry("WheelScrollLines", 3);
+
+ singleClick = config->readBoolEntry("SingleClick", KDE_DEFAULT_SINGLECLICK);
+ autoSelectDelay = config->readNumEntry("AutoSelectDelay", KDE_DEFAULT_AUTOSELECTDELAY);
+ visualActivate = config->readBoolEntry("VisualActivate", KDE_DEFAULT_VISUAL_ACTIVATE);
+ changeCursor = config->readBoolEntry("ChangeCursor", KDE_DEFAULT_CHANGECURSOR);
+}
+
+void MouseConfig::slotThreshChanged(int value)
+{
+ thresh->setSuffix(i18n(" pixel", " pixels", value));
+}
+
+void MouseConfig::slotDragStartDistChanged(int value)
+{
+ dragStartDist->setSuffix(i18n(" pixel", " pixels", value));
+}
+
+void MouseConfig::slotWheelScrollLinesChanged(int value)
+{
+ wheelScrollLines->setSuffix(i18n(" line", " lines", value));
+}
+
+void MouseSettings::apply(bool force)
+{
+ XChangePointerControl( kapp->getDisplay(),
+ true, true, int(qRound(accelRate*10)), 10, thresholdMove);
+
+ // 256 might seems extreme, but X has already been known to return 32,
+ // and we don't want to truncate things. Xlib limits the table to 256 bytes,
+ // so it's a good uper bound..
+ unsigned char map[256];
+ num_buttons = XGetPointerMapping(kapp->getDisplay(), map, 256);
+
+ int remap=(num_buttons>=1);
+ if (handedEnabled && (m_handedNeedsApply || force)) {
+ if( num_buttons == 1 )
+ {
+ map[0] = (unsigned char) 1;
+ }
+ else if( num_buttons == 2 )
+ {
+ if (handed == RIGHT_HANDED)
+ {
+ map[0] = (unsigned char) 1;
+ map[1] = (unsigned char) 3;
+ }
+ else
+ {
+ map[0] = (unsigned char) 3;
+ map[1] = (unsigned char) 1;
+ }
+ }
+ else // 3 buttons and more
+ {
+ if (handed == RIGHT_HANDED)
+ {
+ map[0] = (unsigned char) 1;
+ map[1] = (unsigned char) middle_button;
+ map[2] = (unsigned char) 3;
+ }
+ else
+ {
+ map[0] = (unsigned char) 3;
+ map[1] = (unsigned char) middle_button;
+ map[2] = (unsigned char) 1;
+ }
+ if( num_buttons >= 5 )
+ {
+ // Apps seem to expect logical buttons 4,5 are the vertical wheel.
+ // With mice with more than 3 buttons (not including wheel) the physical
+ // buttons mapped to logical 4,5 may not be physical 4,5 , so keep
+ // this mapping, only possibly reversing them.
+ int pos;
+ for( pos = 0; pos < num_buttons; ++pos )
+ if( map[pos] == 4 || map[pos] == 5 )
+ break;
+ if( pos < num_buttons - 1 )
+ {
+ map[pos] = reverseScrollPolarity ? (unsigned char) 5 : (unsigned char) 4;
+ map[pos+1] = reverseScrollPolarity ? (unsigned char) 4 : (unsigned char) 5;
+ }
+ }
+ }
+ int retval;
+ if (remap)
+ while ((retval=XSetPointerMapping(kapp->getDisplay(), map,
+ num_buttons)) == MappingBusy)
+ /* keep trying until the pointer is free */
+ { };
+ m_handedNeedsApply = false;
+ }
+
+ // This iterates through the various Logitech mice, if we have support.
+ #ifdef HAVE_LIBUSB
+ LogitechMouse *logitechMouse;
+ for (logitechMouse = logitechMouseList.first(); logitechMouse; logitechMouse = logitechMouseList.next() ) {
+ logitechMouse->applyChanges();
+ }
+ #endif
+}
+
+void MouseSettings::save(KConfig *config)
+{
+ config->setGroup("Mouse");
+ config->writeEntry("Acceleration",accelRate);
+ config->writeEntry("Threshold",thresholdMove);
+ if (handed == RIGHT_HANDED)
+ config->writeEntry("MouseButtonMapping",QString("RightHanded"));
+ else
+ config->writeEntry("MouseButtonMapping",QString("LeftHanded"));
+ config->writeEntry( "ReverseScrollPolarity", reverseScrollPolarity );
+
+ config->setGroup("KDE");
+ config->writeEntry("DoubleClickInterval", doubleClickInterval, true, true);
+ config->writeEntry("StartDragTime", dragStartTime, true, true);
+ config->writeEntry("StartDragDist", dragStartDist, true, true);
+ config->writeEntry("WheelScrollLines", wheelScrollLines, true, true);
+ config->writeEntry("SingleClick", singleClick, true, true);
+ config->writeEntry("AutoSelectDelay", autoSelectDelay, true, true );
+ config->writeEntry("VisualActivate", visualActivate, true, true);
+ config->writeEntry("ChangeCursor", changeCursor, true, true);
+ // This iterates through the various Logitech mice, if we have support.
+#ifdef HAVE_LIBUSB
+ LogitechMouse *logitechMouse;
+ for (logitechMouse = logitechMouseList.first(); logitechMouse; logitechMouse = logitechMouseList.next() ) {
+ logitechMouse->save(config);
+ }
+#endif
+ config->sync();
+ KIPC::sendMessageAll(KIPC::SettingsChanged, KApplication::SETTINGS_MOUSE);
+}
+
+void MouseConfig::slotScrollPolarityChanged()
+{
+ settings->m_handedNeedsApply = true;
+}
+
+#include "mouse.moc"
diff --git a/kcontrol/input/mouse.desktop b/kcontrol/input/mouse.desktop
new file mode 100644
index 000000000..fe0f30281
--- /dev/null
+++ b/kcontrol/input/mouse.desktop
@@ -0,0 +1,242 @@
+[Desktop Entry]
+Exec=kcmshell mouse
+Icon=mouse
+Type=Application
+DocPath=kcontrol/mouse/index.html
+
+
+X-KDE-Library=input
+X-KDE-FactoryName=mouse
+X-KDE-Init=mouse
+X-KDE-ParentApp=kcontrol
+
+Name=Mouse
+Name[af]=Muis
+Name[ar]=الÙأرة
+Name[az]=Siçan
+Name[be]=Мыш
+Name[bg]=Мишка
+Name[bn]=মাউস
+Name[br]=Logodenn
+Name[bs]=Miš
+Name[ca]=Ratolí
+Name[cs]=Myš
+Name[csb]=Mësz
+Name[cy]=Llygoden
+Name[da]=Mus
+Name[de]=Maus
+Name[el]=Ποντίκι
+Name[eo]=Muso
+Name[es]=Ratón
+Name[et]=Hiir
+Name[eu]=Sagua
+Name[fa]=موشی
+Name[fi]=Hiiri
+Name[fr]=Souris
+Name[fy]=Mûs
+Name[ga]=Luch
+Name[gl]=Rato
+Name[he]=עכבר
+Name[hi]=माउस
+Name[hr]=Miš
+Name[hu]=Egér
+Name[is]=Mús
+Name[ja]=マウス
+Name[ka]=თáƒáƒ’ვი
+Name[kk]=Тышқан
+Name[km]=កណ្ដុរ
+Name[ko]=마우스
+Name[lo]=ເມົາສ໌
+Name[lt]=PelÄ—
+Name[lv]=Pele
+Name[mk]=Глушец
+Name[mn]=Хулгана
+Name[ms]=Tetikus
+Name[mt]=Maws
+Name[nb]=Mus
+Name[nds]=Muus
+Name[ne]=माउस
+Name[nl]=Muis
+Name[nn]=Mus
+Name[nso]=Legotlo
+Name[oc]=Ratolí
+Name[pa]=ਮਾਊਸ
+Name[pl]=Mysz
+Name[pt]=Rato
+Name[ru]=Мышь
+Name[rw]=Imbeba
+Name[se]=Sáhpán
+Name[sk]=Myš
+Name[sl]=Miška
+Name[sr]=Миш
+Name[sr@Latn]=Miš
+Name[ss]=Ligundvwane
+Name[sv]=Mus
+Name[ta]=சà¯à®Ÿà¯à®Ÿà®¿
+Name[te]=మౌసà±
+Name[tg]=Муш
+Name[th]=เม้าส์
+Name[tr]=Fare
+Name[tt]=Küse
+Name[uk]=Мишка
+Name[uz]=Sichqoncha
+Name[uz@cyrillic]=Сичқонча
+Name[ven]=Mausu
+Name[vi]=Chuá»™t
+Name[wa]=Sori
+Name[zh_CN]=é¼ æ ‡
+Name[zh_TW]=滑鼠
+Name[zu]=i-Mouse
+
+Comment=Mouse settings
+Comment[af]=Muis instellings
+Comment[ar]=اعدادات الÙأرة
+Comment[az]=Siçan qurğuları
+Comment[be]=ÐаÑтаўленні мышы
+Comment[bg]=ÐаÑтройване на мишката
+Comment[bn]=মাউস সেটিংস
+Comment[br]=Kefluniañ al logodenn
+Comment[bs]=Podešavanje miša
+Comment[ca]=Arranjament del ratolí
+Comment[cs]=Nastavení myši
+Comment[csb]=Nastôw mëszë
+Comment[cy]=Gosodiadau Llygoden
+Comment[da]=Opsætning af mus
+Comment[de]=Einstellung der Maus
+Comment[el]=Ρυθμίσεις ΠοντικιοÏ
+Comment[eo]=Agordo de la muso
+Comment[es]=Preferencias sobre el ratón
+Comment[et]=Hiire seadistused
+Comment[eu]=Saguaren konfigurazioa
+Comment[fa]=تنظیمات موشی
+Comment[fi]=Hiiriasetukset
+Comment[fr]=Configuration de la souris
+Comment[fy]=Mûsynstellings
+Comment[ga]=Socruithe luiche
+Comment[gl]=Configuración do rato
+Comment[he]=שינוי הגדרות העכבר
+Comment[hi]=माउस विनà¥à¤¯à¤¾à¤¸
+Comment[hr]=Postavke miša
+Comment[hu]=Az egér beállításai
+Comment[id]=Seting Mouse
+Comment[is]=Stillingar músar
+Comment[it]=Impostazione del mouse
+Comment[ja]=マウスã®è¨­å®š
+Comment[ka]=თáƒáƒ’ვის კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ
+Comment[kk]=Тышқан баптаулары
+Comment[km]=ការ​កំណážáŸ‹â€‹áž€ážŽáŸ’ដុរ
+Comment[ko]=마우스 설정
+Comment[lo]=ຂà»à»‰àº¡àº¹àº™àº„ວາມສະà»àº”ງຕົວເຄື່ອງມືຂອງຜູ້ໃຊ້
+Comment[lt]=PelÄ—s parametrai
+Comment[lv]=Peles parametri
+Comment[mk]=ПоÑтавувања на глушецот
+Comment[mn]=Хулгана тохируулга
+Comment[ms]=Seting tetikus
+Comment[mt]=Konfigurazzjoni tal-Maws
+Comment[nb]=Musinnstillinger
+Comment[nds]=Muus instellen
+Comment[ne]=माउस सेटिङ
+Comment[nl]=Muisinstellingen
+Comment[nn]=Musinnstillingar
+Comment[nso]=Dipeakanyo tsa Legotlo
+Comment[oc]=Arranjament dèu ratolí
+Comment[pa]=ਮਾਊਸ ਸੈਟਿੰਗ
+Comment[pl]=Ustawienia myszy
+Comment[pt]=Configuração do rato
+Comment[pt_BR]=Configurações do mouse
+Comment[ro]=Configurează mouse-ul
+Comment[ru]=ÐаÑтройка мыши
+Comment[rw]=Amagenamiterere y'Imbeba
+Comment[se]=Sáhpánheivehusat
+Comment[sk]=Nastavenie myši
+Comment[sl]=Nastavitve miške
+Comment[sr]=ПоÑтавке миша
+Comment[sr@Latn]=Postavke miša
+Comment[ss]=Kuhlelwka kweligundvwane
+Comment[sv]=Anpassa mus
+Comment[ta]=சà¯à®Ÿà¯à®Ÿà®¿ அமைபà¯à®ªà¯à®•à®³à¯
+Comment[te]=మౌసౠఅమరికలà±
+Comment[tg]=Танзимоти муш
+Comment[th]=ตั้งค่าเม้าส์
+Comment[tr]=Fare ayarları
+Comment[tt]=Küse Caylaw
+Comment[uk]=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¸ÑˆÑ–
+Comment[uz]=Sichqonchaning moslamalari
+Comment[uz@cyrillic]=Сичқончанинг моÑламалари
+Comment[ven]=Mavhekanyele a Mausu
+Comment[vi]=Thiết lập chuột
+Comment[wa]=Apontiaedjes del sori
+Comment[xh]=Izicwangciso ze mouse
+Comment[zh_CN]=鼠标设置
+Comment[zh_TW]=滑鼠設定
+Comment[zu]=Izilungiselelo ze-Mouse
+
+Keywords=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed
+Keywords[af]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handig,left handig
+Keywords[ar]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed,الÙأرة,تسارع الÙأرة,الحد الأقضى للÙأرة,Ùأرة,.أزرار الÙأرة, اختيار,مؤشر,الاختيار,المؤشر,أجهزة الادخال,.خريطة الأزرار,نقر,أبقونات,ارجاع,مؤشرات,سحب, نقر مزدوج,خريطة,أيمن,أعسر
+Keywords[az]=siçan,Siçan Sür'ətləndirmə,Siçan sərhədi,Siçan Düymələri,Seçim,ox şəkli,giriş avadanlıqları,Düymə Xəritəsi,Tıqlama,timsallar,əks təs'ir,İşarətçilər,Daşı,Cüt Tıqla,xəritələmə,sağ əlli,sol əlli
+Keywords[be]=Мыш,ПаÑкарÑнне мышы,Кнопкі мышы,ВылучÑнне,Форма курÑора,Прылады ўводу,ПрызначÑнне кнопак,ДзеÑнне кнопак,ÐаціÑк,значкі,Указальнік,КурÑор,ПерацÑгваць,Двайны націÑк,Ð´Ð»Ñ Ð»ÐµÐ²Ð°Ð¹ рукі,Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð°Ð¹ рукі,Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed
+Keywords[bg]=наÑтройки, мишка, поÑочващо, уÑтройÑтво, Mouse, Mouse acceleration, Mouse threshold, Mouse buttons, Selection, Cursor Shape, Input Devices, Button Mapping, Click, icons, feedback, Pointers, Drag, DoubleClick, mapping, right handed, left handed
+Keywords[ca]=Ratolí,acceleració del ratolí,llindar del ratolí,botons del ratolí,selecció,forma del cursor,dispositius d'entrada,mapejat de botons,clic,icones,realimentació,apuntadors,arrossegar,clic doble,mapejat,dretà,esquerrà
+Keywords[cs]=MyÅ¡,Akcelerace myÅ¡i,Práh myÅ¡i,TlaÄítka myÅ¡i,VýbÄ›r,Tvar kurzoru,Vstupní zařízení,Mapování tlaÄítek,Kurzor,Kliknutí,Odezva,Dvojité kliknutí,Pravák,Levák
+Keywords[csb]=Mësz,przërëchlënié mëszë,Próg mëszë,Knąpë mëszë,Zaznaczenié,Sztôłt kùrsora,Ùrządzenia wéńdzeniô,mapòwanié knąpów,klëkniãce,ikònë,widzałé efektë,wskôzywôczë,przecyganié,podwójné klëkniãce,mapòwanié,prawòrãczny,lewòrãczny
+Keywords[cy]=Llygoden,Cyflymu Llygoden,Trothwy Llygoden,Botymau Llygoden,Dewis,Si?p Cyrchydd,Dyfeisiau Mewnbwn,Mapio Botymau, Clic,eiconau,adborth,Pwyntyddion,Llusgo,Clic Dwbl,mapio,llaw dde,llaw chwith
+Keywords[da]=Mus,Museacceleration,Musegrænse,Museknapper,Markering,Markørform,Inddataenheder,Knap-mapping,Klik,ikoner,feedback,Pegere, Træk,Dobbeltklik,mapping,højrehåndet,venstrehåndet
+Keywords[de]=Maus,Mausbeschleunigung,Mausschwellenwert,Maustasten,Auswahl,Cursor,Cursorform,Eingabegeräte,Knöpfe,Buttons,Zuordnungen,Klicks,Zeigegeräte,Doppelklick,Rechtshänder,Linkshänder
+Keywords[el]=Ποντίκι,Επιτάχυνση δÏομέα,Κατώφλι ποντικιοÏ,ΠλήκτÏα ποντικιοÏ,Επιλογή,Σχήμα ΔÏομέα,Συσκευές Εισόδου,ΧαÏτογÏάφηση πλήκτÏων,Κλικ,εικονίδια,ανάδÏαση,Δείκτες,ΣÏÏσιμο,Διπλό κλικ,αντιστοίχηση,δεξιόχειÏας,αÏιστεÏόχειÏας
+Keywords[eo]=muso,akcelado,butonoj,elekto,montrilo,kursoro,enigo,aparatoj,butonsignifo,klako,piktogramoj,reago,montriloj,Åovado,trenado,duklako,dekstrmanulo,maldekstramanulo
+Keywords[es]=Ratón,Aceleración del ratón,Umbral del ratón,Botones del ratón,Selección,Forma del cursor,Dispositivos de entrada,Asignaciones de botones,Pulsación,iconos,notificación,Punteros,Arrastrar,Doble pulsación,asignaciones,diestro,zurdo
+Keywords[et]=hiir,hiire kiirendus,hiire lävi,hiire nupud,valimine,kursori kuju,sisendseadmed,nuppude asetus,klikk,klõps,ikoonid,tagasiside,kursorid,lohistamine,topeltklikk,topeltklõps,asetus,paremakäeline,vasakukäeline
+Keywords[eu]=Sagua,Saguaren azelerazioa,Saguaren atalasea,Saguarenbotoiak,Hautespena,Kurtsorearen itxura,Sarrera dispositiboak,Botoien esleipena,Klika,ikonoak,atzeraelikadura,Geziak,Arrastatu,Klik bikoitza,esleipenak, eskuinak,ezkertiak
+Keywords[fa]=موشی، شتاب‌دهی موشی، آستانۀ موشی، دکمه‌های موشی، گزینش، Ø´Ú©Ù„ مکان‌نما، دستگاههای ورودی، نگاشت دکمه، Ùشار دادن، شمایلها، بازخورد، اشاره‌گرها، کشیدن، دو بار Ùشار دادن، نگاشت، راست‌دست، چپ‌دست
+Keywords[fi]=Hiiri,Hiiren kiihdytys,Hiiren raja-arvo,Hiiren painikkeet,Valinta,Osoittimen muoto,Syöttölaitteet,Painikkeiden järjestys,Napsautus,kuvakkeet,palaute,Osoittimet,Vedä,Tuplanapsautus,järjestys,oikeakätinen,vasenkätinen
+Keywords[fr]=souris,accélération de la souris,seuil de la souris,boutons de la souris,sélection,forme du curseur,périphériques d'entrée,curseur,clic,icônes,gaucher,droitier,double clic,simple clic,clic gauche,clic droit
+Keywords[fy]=Mûs,Mûs fluggens,Mûsknoppen,seleksje,rinnerke-úterlik,ynfier devices,ynfierapparaten,knopyndieling,klikken,Ikoanen,icons,Oanwizers,pointers,drag,slepe,dûbelklikken,loftshandich,rjochtshandich.râneapparaten
+Keywords[gl]=Rato,Aceleración do rato,Umbral do rato,botóns do rato,Selección,Forma do Cursores,Dispositivos de Entrada,Mapa do botón,Clic,iconas,indicador,Ponteiros,Arrastar,DobreClic,mapear,dereiteiro,esquerdeiro
+Keywords[he]=עכבר,ת×וצת עכבר,סף עכבר,לחצני עכבר,בחירה,צורת מצביע,התקני קלט,לחיצה,סמלי×,תגובה,מצביעי×,גרירה,לחיצה כפולה,תצורה,ימני,שמ×לי,תצורת לחצני×, Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed
+Keywords[hi]=माउस,माउस तà¥à¤µà¤°à¤£,माउस दहलीज,माउस बटन,चयन,संकेतक आकार,इनपà¥à¤Ÿ औज़ार,बटन मैपिंग,कà¥à¤²à¤¿à¤•,पà¥à¤°à¤¤à¥€à¤•,फ़ीडबैक,पà¥à¤µà¤¾à¤‡à¤‚टरà¥à¤¸,खींचें,डबल-कà¥à¤²à¤¿à¤•,मैपिंग,दाहिने हाथ वाला, खबà¥à¤¬à¥‚(बाà¤à¤ हाथ वाला)
+Keywords[hr]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed,MiÅ¡,Ubrzavanje miÅ¡a,Prag miÅ¡a,Tipke miÅ¡a,Odabir,Oblik pokazivaÄa,Ulazni ureÄ‘aji,Mapiranje tipki,Klikanje,ikone,povratni podaci,PokazivaÄi,PrevlaÄenje,Dvostruki klik,mapiranje,desnoruk,ljevoruk
+Keywords[hu]=egér,egérgyorsítás,egérérzékenység,egérgombok,kiválasztás,kurzoralak,beviteli eszközök,gombhozzárendelés,kattintás,ikonok,visszajelzés,mutatók,húzás,dupla kattintás,hozzárendelés,jobbkezes,balkezes
+Keywords[id]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input DevicesButton Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed
+Keywords[is]=Næmni músar,bendill,inntakstæki,hröðun,örvhentur,rétthentur,smella,tákn,bendill,tvísmella
+Keywords[it]=mouse,accelerazione del mouse,soglia del mouse,tasti del mouse,selezione,forma del cursore,dispositivi di input,mappatura dei tasti,clic,icone,puntatori,trascinamento,doppio clic,mouse per mancini,mancini
+Keywords[ja]=マウス,マウスã®åŠ é€Ÿ,マウスã®ã—ãã„,マウスボタン,é¸æŠž,カーソルã®å½¢,入力デãƒã‚¤ã‚¹,入力デãƒã‚¤ã‚¹,ボタンã®å‰²ã‚Šå½“ã¦,クリック,アイコン,フィードãƒãƒƒã‚¯,ãƒã‚¤ãƒ³ã‚¿,ドラッグ,ダブルクリック,割り当ã¦,å³åˆ©ã,左利ã
+Keywords[km]=កណ្ដុរ,ការ​បង្កើន​ល្បឿង​កណ្ដុរ,កម្រិážâ€‹áž–ន្លឺ​កណ្ដុរ,ប៊ូážáž»áž„​កណ្ដុរ,ការ​ជ្រើស,រាង​ទស្សនáŸâ€‹áž‘្រនិច,ឧបករណáŸâ€‹áž”ញ្ចូល,ប្លង់​ប៊ូážáž»áž„,ចុច,រូបážáŸ†ážŽáž¶áž„,មážáž·â€‹ážšáž·áŸ‡áž‚ន់,ទ្រនិច,អូស,ចុច​ទ្វáŸážŠáž„,ធ្វើ​ប្លង់,ដៃ​ស្ដាំ,ដៃ​ឆ្វáŸáž„
+Keywords[lo]=ເມົາສ໌,àºàº²àº™à»€àºžàºµà»‰àº¡àº„ວາມໄວຂອງເມົາສ໌,ໄລàºàº°àº•àº»àº§àºŠàºµà»‰àº‚ອງເມົາສ໌, ປຸ່ມເມົາສ໌,àºàº²àº™à»€àº¥àº·àº­àº,ຮູບຮ່າງເຄີເຊີ,ອຸປະàºàº­àº™àº™àº³à»€àº‚ົ້າ,àºàº²àº™àºˆàº±àºšàº„ູ່ປຸ່ມ,ຄລິàº,ໄອຄອນ,ຕົວຊີ້,ລາàº,ດັບເບີ້ນຄລິàº,àºàº²àº™à»àº¡àºšàº›à»ˆàº¸àº¡,ໃຊ້ມືຊ້າàº, ໃຊ້ມືຂວາ
+Keywords[lt]=Mouse,pelė,Mouse acceleration,pelės pagreitinimas,Mouse threshold,Mouse buttons,pelės mygtukai,Selection,pažymėjimas,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,right handed,left handed,kairiarankė
+Keywords[lv]=Pele,Peles paÄtrinÄjums,Peles slieksnis,Peles taustiņi,IzvÄ“le,Kursora Forma,Ievades IekÄrtas,Pogu Sasaiste,KlikÅ¡Ä·is,ikonas,atpakaļsaite,RÄdÄ«tÄji,Vilkt,DubultklikÅ¡Ä·is,sasaiste,labÄs rokas,kreisÄs rokas
+Keywords[mk]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed,Глушец,Забрзување на глушец,Граница на глушец,Копчиња на глушец,Селекција,Избор,Форма на курÑор,Влезни уреди,Мапирање на копче,Клик,икони,Покажувачи,Влечи,Двоен клик,мапирање,деÑнорак,леворак
+Keywords[mn]=Хулгана,Хулгана-хурдаÑгуур, Хулгана-Ñ…Ñзгаар,Хулгана товшуур,Сонголт, ТүүчÑÑ,ТүүчÑÑний Ñ…ÑлбÑÑ€,Оролтын төхөөрөмж,Товч,Товшилуур,ХолбооÑ,Товшилт, Зурах төхөөрөмж,Давхар товшилт,Баруун гарын, Зүүн гарын
+Keywords[mt]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed,Maws,lemini,xellugi
+Keywords[nb]=Mus,musehastighet,museknapper,valg,merking,kursoregenskaper,pekeregenskaper,innenheter,inn-enheter,knappetilordning,trykk,klikk,pekere,dra,dobbeltklikk, høyrehendt,venstrehendt
+Keywords[nds]=Muus,Muus-Gauheit,Muus-Grenzweert,Muusknööp,Utwahl,Knooptoornen, Wieserform,Ingaavreedschappen,Klicken,Lüttbiller,Torüchmellen,Wieser,Dregen,Dubbelklick,Toornen,Rechtpoot,Linkpoot
+Keywords[ne]=माउस, माउस गतिवरà¥à¤§à¤¨, माउस थà¥à¤°à¥‡à¤¸à¤¹à¥‹à¤²à¥à¤¡, माउस बटनहरू, चयन, करà¥à¤¸à¤° आकार, आगत यनà¥à¤¤à¥à¤°à¤¹à¤°à¥‚, बटन मिलाउने, कà¥à¤²à¤¿à¤•, पà¥à¤°à¤¤à¤¿à¤®à¤¾, पृषà¥à¤ à¤ªà¥‹à¤·à¤£, सूचक, तानà¥à¤¨à¥à¤¹à¥‹à¤¸à¥, डबल कà¥à¤²à¤¿à¤• गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥, मिलाउनà¥à¤¹à¥‹à¤¸à¥, दायाà¤, बायाà¤
+Keywords[nl]=muis,muissnelheid,muisknoppen,selectie,cursor-uiterlijk,input devices,invoerapparaten,knopindeling,klikken,iconen,pictogrammen,icons,aanwijzers,pointers,drag,verslepen,dubbelklikken,linkshandig,rechtshandig.randapparaten
+Keywords[nn]=mus,musakselerasjon,musterskel,musknappar,val,peikar,peikarform,inneiningar,knappar,klikk,ikon,tilbakemelding,dra,dobbeltklikk,høgrehendt,venstrehendt
+Keywords[nso]=Legotlo,Koketso ya legotlo,Threshold ya legotlo,Ditobetswa tsa legotlo, Kgetho,Sebopego sa Cursor,Maano a Tsenyo,Mapping Setobetswa,Tobetsa, diemedi,phetolo,Disupi,Topa,Tobetsopedi,mapping,swerwe ka lagoja,swerwe ka lanngele
+Keywords[pa]=ਮਾਊਸ,ਮਾਊਸ ਪà©à¨°à¨µà©‡à¨¶,ਮਾਊਸ threshold,ਮਾਊਸ buttons,Selection,CursorShape,Input ਜੰਤਰ,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,righthanded,left handed,ਕਲਿੱਕ,ਆਈਕਾਨ
+Keywords[pl]=Mysz,Akceleracja myszy,Próg myszy,Przyciski myszy,Zaznaczenie,Kształt kursora,Urządzenia wejściowe,mapowanie przycisków,kliknięcie,ikony,widoczne efekty,wskaźniki,przeciąganie,podwójne kliknięcie,mapowanie,praworęczny,leworęczny
+Keywords[pt]=rato,aceleração do rato,limite do rato,botões do rato,selecção,forma do cursor,dispositivos de entrada,atribuição de botões,click,ícones,feedback,cursores,arrastar,duplo 'click',atribuição,destro,esquerdino
+Keywords[pt_BR]=Mouse,aceleração do mouse,limiar do mouse, botões do mouse,Seleção,Formato do Cursor,Dispositivos de entrada,mapeamento de botões,clique,ícones,retorno,ponteiros,arrastar,clique duplo,mapeamento,destro,canhoto
+Keywords[ro]=mouse,accelerație mouse,prag mouse,butoane mouse,selecție,formă cursor,dispozitive de intrare,mapare butoane,clicuri,iconițe,răspuns,pointeri,indicatori,tragere,dublu clic,dreptaci,stîngaci,drag-and-drop
+Keywords[rw]=Imbeba,Ukwihutisha imbeba,Intambwe y'imbeba,Buto z'imbeba, Ihitamo,Imisusire y'inyoborayandika,Apareye z'Icyinjira,Guhuza buto,Gukanda,udushushondanga,inkurikizi,Mweretsi,Gukurura,GukandaKabiri,guhuza,kiganza iburyo, kiganza ibumoso.
+Keywords[se]=sáhpán,sáhpánaksellerašuvdna,sáhpánšielbma,sáhpánboalut, merken, njoallahápmi,sisaovttadagat,boalut,coahkkalit,govažat,feedback,geassit, duppalcoahkkaleapmi,olgešgiehtat,gurutgiehtat
+Keywords[sk]=MyÅ¡,rýchlosÅ¥ myÅ¡i,tlaÄidlá myÅ¡i,OznaÄenie,kurzor,Vstupné zariadenia,výber,tvar kurzoru,mapovanie tlaÄidiel,klik,kliknutie,ikony,Å¥ahanie,dvojité kliknutie,dvojklik,mapovanie,praváci,ľaváci
+Keywords[sl]=miÅ¡ka,pospeÅ¡itev miÅ¡ke,gumbi miÅ¡ke,izbira,oblika kazalca,vhodne enote,preslikava gumbov,klik,ikone,povratna informacija,kazalci,potegni,dvojni klik,preslikava,leviÄarji,desniÄarji
+Keywords[sr]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed,миш,убрзавање миша,означавање,избор,облик показивача,показивач,мапирање дугмади,клик,иконе,показивачи,превуци,двоклик,мапирање,леворуки,деÑноруки
+Keywords[sr@Latn]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed,miÅ¡,ubrzavanje miÅ¡a,oznaÄavanje,izbor,oblik pokazivaÄa,pokazivaÄ,mapiranje dugmadi,klik,ikone,pokazivaÄi,prevuci,dvoklik,mapiranje,levoruki,desnoruki
+Keywords[sv]=Mus,Musacceleration,Muströskel,Musknappar,Val,Markörutseende,Inmatningsenheter,Knapptolkning,klickning,ikoner,respons,Pekare,Drag,Dubbelklick,Tolkning,högerhänt,vänsterhänt
+Keywords[ta]=சà¯à®Ÿà¯à®Ÿà®¿, à®®à¯à®Ÿà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ சà¯à®Ÿà¯à®Ÿà®¿ , சà¯à®Ÿà¯à®Ÿà®¿ படà¯à®Ÿà®©à¯, தேரà¯à®µà¯à®•à®³à¯, காடà¯à®Ÿà®¿à®¯à®¿à®©à¯ வடிவமà¯, உளà¯à®³à®¿à®Ÿà¯à®®à¯ சாதனமà¯, படà¯à®Ÿà®©à¯ பொரà¯à®¤à¯à®¤à®²à¯, கà¯à®³à®¿à®•à¯, சினà¯à®©à®®à¯, கரà¯à®¤à¯à®¤à¯ , காடà¯à®Ÿà®¿à®•à®³à¯, இழà¯, இரணà¯à®Ÿà¯à®®à¯à®±à¯ˆ கà¯à®³à®¿à®•à¯, பொரà¯à®¤à¯à®¤à¯,வலதà¯à®•à¯ˆ பழகà¯à®•à®®à¯, இடத௠கை பழகà¯à®•à®®à¯.
+Keywords[th]=เม้าส์,à¸à¸²à¸£à¹€à¸£à¹ˆà¸‡à¸„วามเร็วของเม้าส์,ระยะตัวชี้ของเม้าส์,ปุ่มเม้าส์,à¸à¸²à¸£à¹€à¸¥à¸·à¸­à¸,รูปร่างเคอร์เซอร์,อุปà¸à¸£à¸“์นำเข้า,à¸à¸²à¸£à¸ˆà¸±à¸šà¸„ู่ปุ่ม,คลิ้à¸,ไอคอน,ตัวชี้,ลาà¸,ดับเบิลคลิ้à¸,à¸à¸²à¸£à¹à¸¡à¸žà¸›à¸¸à¹ˆà¸¡,ใช้มือซ้าย,ใช้มือขวา
+Keywords[tr]=fare,Fare Hızlandırma,Fare eşiği,Fare Tuşları,Seçim,imleç şekli,girdi aygıtları,Tuş Haritası,Tıklama,simgeler,geri besleme,İşaretçiler,Taşı,Çift Tıkla,haritalama,sağ elli,sol elli
+Keywords[uk]=Миша,Mouse,приÑÐºÐ¾Ñ€ÐµÐ½Ð½Ñ Ð¼Ð¸ÑˆÑ–,поріг миші,кнопки миші,вибір,форма курÑора,вхідні приÑтрої,відповідніÑÑ‚ÑŒ клавіш,клацаннÑ,піктограми,зворотній зв'Ñзок,вказівники,перетÑгнути,подвійне клацаннÑ,відображеннÑ,лівша,правша
+Keywords[uz]=Sichqoncha,Sichqonchani tezlashtirish,Mouse threshold,Sichqonchaning tugmalari,Tanlash,Kursorning shakillari,Kiritish uskunasi,Tugmani aniqlash,Bosish,nishonchalar,feedback,Koʻrsatgichlar,Drag,Ikki marta bosish,mapping,chap qoʻl,oʻng qoʻl
+Keywords[uz@cyrillic]=Сичқонча,Сичқончани тезлаштириш,Mouse threshold,Сичқончанинг тугмалари,Танлаш,КурÑорнинг шакиллари,Киритиш уÑкунаÑи,Тугмани аниқлаш,БоÑиш,нишончалар,feedback,КўрÑатгичлар,Drag,Икки марта боÑиш,mapping,чап қўл,ўнг қўл
+Keywords[ven]=Mausu,U gonyisa mausu,mausu,bathene ya mausu,nanga,tshivhumbeo tsha Cursor,maano a InputSedzulusa bathene,u putedza,aikhonoPhindulo,vhasumbedzi,kokodza,uputedza luvhili,utalulusa,tshaula,tshamonde
+Keywords[vi]=Chuá»™t,Gia tốc chuá»™t,Giá»›i hạn chuá»™t,Nút chuá»™t,Chá»n,Kiểu dáng Con trá»,Thiết bị Nhập,Ãnh xạ Nút,Nhấn,biểu tượng,phản hồi,Con trá»,Kéo,Nhấn đúp,ánh xạ,thuận tay phải,thuận tay trái
+Keywords[wa]=Sori,botons del sori,foime del fletche,éndjins d' intrêye,clitche,clitchî,imådjetes,ritour,pondjeu,bodjî,dobe clitchî,dobe clitche,hintche mwin,gôchî,droetî
+Keywords[xh]=Mouse,Unyuso lwesantya seMouse,Ungeno lwe Mouse,Amaqhosha eMouse,Ukhetho,Ukumila kwesalathisi,Amacebo egalelo,Ukucetywa kwamaqhosha,Nqakraza,ii-icon, isiphumo,Izalathi,Tsala,Nqakraza kabini,iyaceba,isandla sokunene,isandla sasekhohlo
+Keywords[zh_CN]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed,é¼ æ ‡,鼠标加速,鼠标加速阈值,鼠标按钮,选择,光标形状,输入设备,按钮映射,å•å‡»,图标,å馈,拖放,åŒå‡»,映射,å³æ‰‹ä¹ æƒ¯,左手习惯
+Keywords[zh_TW]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed,滑鼠,滑鼠游標加速,滑鼠游標加速間è·,滑鼠按鈕,é¸æ“‡,指標外觀,輸入設備,按éµå°æ‡‰,單擊,圖示,å饋,指標,拖放,雙擊,映射,ç¿’æ…£å³æ‰‹,習慣左手
+Keywords[zu]=i-Mouse,Ukugijimisa kwe-Mouse,i-Mouse threshold, Izinkinobho ze-Mouse,Ukhetho,Isimo senkomba,Amthuluzi Omphumela wangaphakathi,Ukuqondanisa Izinkinobho,Cofa,Izimpawu zezithombe, umphumela obuyayo,Izinkomba zendawo yokubhala,Hudula,Cofa-kabili, ukuqondanisa,okwesanadla sangakwesokudla,okwesandla sangakwesokunxele
+Categories=Qt;KDE;X-KDE-settings-hardware;
diff --git a/kcontrol/input/mouse.h b/kcontrol/input/mouse.h
new file mode 100644
index 000000000..005c7a2fc
--- /dev/null
+++ b/kcontrol/input/mouse.h
@@ -0,0 +1,156 @@
+/*
+ * mouse.h
+ *
+ * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca
+ *
+ * Layout management, enhancements:
+ * Copyright (c) 1999 Dirk A. Mueller <dmuell@gmx.net>
+ *
+ * SC/DC/AutoSelect/ChangeCursor:
+ * Copyright (c) 2000 David Faure <faure@kde.org>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef __MOUSECONFIG_H__
+#define __MOUSECONFIG_H__
+
+#include <qbuttongroup.h>
+#include <qdialog.h>
+#include <qlabel.h>
+#include <qlcdnumber.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+
+#include <kapplication.h>
+
+#include <kglobalsettings.h>
+#include <knuminput.h>
+
+#include <config.h>
+#ifdef HAVE_LIBUSB
+#include "logitechmouse.h"
+#endif
+
+#include <kcmodule.h>
+#include "kmousedlg.h"
+#include "themepage.h"
+
+#define RIGHT_HANDED 0
+#define LEFT_HANDED 1
+
+class QCheckBox;
+class QSlider;
+class QTabWidget;
+
+class MouseSettings
+{
+public:
+ void save(KConfig *);
+ void load(KConfig *);
+ void apply(bool force=false);
+public:
+ int num_buttons;
+ int middle_button;
+ bool handedEnabled;
+ bool m_handedNeedsApply;
+ int handed;
+ double accelRate;
+ int thresholdMove;
+ int doubleClickInterval;
+ int dragStartTime;
+ int dragStartDist;
+ bool singleClick;
+ int autoSelectDelay;
+ int visualActivate;
+ bool changeCursor;
+ int wheelScrollLines;
+ bool reverseScrollPolarity;
+
+ #ifdef HAVE_LIBUSB
+ // TODO: In Qt4, replace with a better container.
+ QPtrList <LogitechMouse> logitechMouseList;
+ #endif
+};
+
+class MouseConfig : public KCModule
+{
+ Q_OBJECT
+public:
+ MouseConfig(QWidget *parent=0, const char* name=0);
+ ~MouseConfig();
+
+ void save();
+ void load();
+ void load( bool useDefaults );
+ void defaults();
+
+private slots:
+
+ void slotClick();
+ /** No descriptions */
+ void slotHandedChanged(int val);
+ void slotScrollPolarityChanged();
+ void checkAccess();
+ void slotThreshChanged(int value);
+ void slotDragStartDistChanged(int value);
+ void slotWheelScrollLinesChanged(int value);
+
+private:
+
+ double getAccel();
+ int getThreshold();
+ int getHandedness();
+
+ void setAccel(double);
+ void setThreshold(int);
+ void setHandedness(int);
+
+ KDoubleNumInput *accel;
+ KIntNumInput *thresh;
+ KIntNumInput *doubleClickInterval;
+ KIntNumInput *dragStartTime;
+ KIntNumInput *dragStartDist;
+ KIntNumInput *wheelScrollLines;
+
+ QButtonGroup *handedBox;
+// QRadioButton *leftHanded, *rightHanded;
+// QCheckBox *doubleClick;
+// QCheckBox *cbAutoSelect;
+ QLabel *lDelay;
+// QSlider *slAutoSelect;
+// QCheckBox *cbVisualActivate;
+// QCheckBox *cbCursor;
+// QCheckBox *cbLargeCursor;
+
+ QTabWidget *tabwidget;
+ QWidget *tab2;
+ KMouseDlg* tab1;
+ ThemePage* themetab;
+ MouseSettings *settings;
+
+ QCheckBox *mouseKeys;
+ KIntNumInput *mk_delay, *mk_interval, *mk_time_to_max, *mk_max_speed,
+ *mk_curve;
+
+
+};
+
+#endif
+
diff --git a/kcontrol/input/mouse_cursor_theme.upd b/kcontrol/input/mouse_cursor_theme.upd
new file mode 100644
index 000000000..da71abb19
--- /dev/null
+++ b/kcontrol/input/mouse_cursor_theme.upd
@@ -0,0 +1,5 @@
+Id=kde3.4.99
+File=kdeglobals,kcminputrc
+Group=KDE,Mouse
+Options=overwrite
+Key=cursorTheme
diff --git a/kcontrol/input/pics/Makefile.am b/kcontrol/input/pics/Makefile.am
new file mode 100644
index 000000000..fa9cd0d71
--- /dev/null
+++ b/kcontrol/input/pics/Makefile.am
@@ -0,0 +1,3 @@
+kcminput_pics_data_DATA = mouse_rh.png mouse_lh.png
+kcminput_pics_datadir = $(kde_datadir)/kcminput/pics
+
diff --git a/kcontrol/input/pics/mouse_lh.png b/kcontrol/input/pics/mouse_lh.png
new file mode 100644
index 000000000..acec7fe85
--- /dev/null
+++ b/kcontrol/input/pics/mouse_lh.png
Binary files differ
diff --git a/kcontrol/input/pics/mouse_lh.svgz b/kcontrol/input/pics/mouse_lh.svgz
new file mode 100644
index 000000000..9bf18f4f9
--- /dev/null
+++ b/kcontrol/input/pics/mouse_lh.svgz
Binary files differ
diff --git a/kcontrol/input/pics/mouse_rh.png b/kcontrol/input/pics/mouse_rh.png
new file mode 100644
index 000000000..de5cd8a86
--- /dev/null
+++ b/kcontrol/input/pics/mouse_rh.png
Binary files differ
diff --git a/kcontrol/input/pics/mouse_rh.svgz b/kcontrol/input/pics/mouse_rh.svgz
new file mode 100644
index 000000000..5597f588f
--- /dev/null
+++ b/kcontrol/input/pics/mouse_rh.svgz
Binary files differ
diff --git a/kcontrol/input/xcursor/Makefile.am b/kcontrol/input/xcursor/Makefile.am
new file mode 100644
index 000000000..9ef9c9bbf
--- /dev/null
+++ b/kcontrol/input/xcursor/Makefile.am
@@ -0,0 +1,7 @@
+AM_CPPFLAGS = $(all_includes)
+
+noinst_LTLIBRARIES = libthemepage.la
+libthemepage_la_SOURCES = themepage.cpp previewwidget.cpp
+METASOURCES = AUTO
+noinst_HEADERS = themepage.h previewwidget.h
+
diff --git a/kcontrol/input/xcursor/previewwidget.cpp b/kcontrol/input/xcursor/previewwidget.cpp
new file mode 100644
index 000000000..36108ef36
--- /dev/null
+++ b/kcontrol/input/xcursor/previewwidget.cpp
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2003 Fredrik Höglund <fredrik@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <kglobal.h>
+
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qstring.h>
+#include <qcursor.h>
+
+#include <kglobal.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/Xcursor/Xcursor.h>
+
+#include "previewwidget.h"
+
+
+extern bool qt_has_xft;
+extern bool qt_use_xrender;
+
+
+namespace {
+
+ // Preview cursors
+ const char *cursor_names[] =
+ {
+ "left_ptr",
+ "left_ptr_watch",
+ "watch",
+ "hand2",
+ "question_arrow",
+ "sb_h_double_arrow",
+ "sb_v_double_arrow",
+ "bottom_left_corner",
+ "bottom_right_corner",
+ "fleur",
+ "pirate",
+ "cross",
+ "X_cursor",
+ "right_ptr",
+ "right_side",
+ "right_tee",
+ "sb_right_arrow",
+ "sb_right_tee",
+ "base_arrow_down",
+ "base_arrow_up",
+ "bottom_side",
+ "bottom_tee",
+ "center_ptr",
+ "circle",
+ "dot",
+ "dot_box_mask",
+ "dot_box_mask",
+ "double_arrow",
+ "draped_box",
+ "left_side",
+ "left_tee",
+ "ll_angle",
+ "top_side",
+ "top_tee",
+ };
+
+ const int numCursors = 6; // The number of cursors in the above list to be previewed
+ const int previewSize = 24; // The cursor size to be used in the preview widget
+ const int cursorSpacing = 20;
+}
+
+
+class PreviewCursor
+{
+ public:
+ PreviewCursor();
+ ~PreviewCursor();
+
+ void load( const QString &, const QString & );
+ const Picture picture() const { return m_pict; }
+ const Cursor handle() const { return m_handle; }
+ const int width() const { return m_width; }
+ const int height() const { return m_height; }
+
+ private:
+ Picture createPicture( const XcursorImage* ) const;
+ void cropCursorImage( XcursorImage*& ) const;
+ Picture m_pict;
+ Cursor m_handle;
+ int m_width;
+ int m_height;
+}; // class PreviewCursor
+
+
+PreviewCursor::PreviewCursor() :
+ m_pict( 0 ), m_handle( 0 ), m_width( 0 ), m_height( 0 )
+{
+}
+
+
+void PreviewCursor::load( const QString &name, const QString &theme )
+{
+ Display *dpy = QPaintDevice::x11AppDisplay();
+
+ if ( m_pict ) XRenderFreePicture( dpy, m_pict );
+ if ( m_handle ) XFreeCursor( dpy, m_handle );
+ m_pict = 0;
+ m_handle = 0;
+ m_width = m_height = 0;
+
+ // Load the preview cursor image
+ XcursorImage *image =
+ XcursorLibraryLoadImage( name.latin1(), theme.latin1(), previewSize );
+
+ // If the theme doesn't have this cursor, load the default cursor for now
+ if ( !image )
+ image = XcursorLibraryLoadImage( "left_ptr", theme.latin1(), previewSize );
+
+ // TODO The old classic X cursors
+ if ( !image )
+ return;
+
+ // Auto-crop the image (some cursor themes use a fixed image size
+ // for all cursors, and doing this results in correctly centered images)
+ cropCursorImage( image );
+
+ m_pict = createPicture( image );
+ m_width = image->width;
+ m_height = image->height;
+
+ // Scale the image if its height is greater than 2x the requested size
+ if ( m_height > previewSize * 2.0 ) {
+ double factor = double( previewSize * 2.0 / m_height );
+ XTransform xform = {
+ {{ XDoubleToFixed(1.0), XDoubleToFixed(0), XDoubleToFixed(0) },
+ { XDoubleToFixed(0), XDoubleToFixed(1.0), XDoubleToFixed(0) },
+ { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(factor) }}
+ };
+ XRenderSetPictureTransform( dpy, m_pict, &xform );
+ m_width = int( m_width * factor );
+ m_height = int( m_height * factor );
+ }
+
+ // We don't need this image anymore
+ XcursorImageDestroy( image );
+
+ // Load the actual cursor we will use
+ int size = XcursorGetDefaultSize( dpy );
+ XcursorImages *images = XcursorLibraryLoadImages( name.latin1(), theme.latin1(), size );
+
+ if ( images ) {
+ m_handle = XcursorImagesLoadCursor( dpy, images );
+ XcursorImagesDestroy( images );
+ } else {
+ images = XcursorLibraryLoadImages( "left_ptr", theme.latin1(), size );
+ m_handle = XcursorImagesLoadCursor( dpy, images );
+ XcursorImagesDestroy( images );
+ }
+}
+
+
+PreviewCursor::~PreviewCursor()
+{
+ if ( m_handle ) XFreeCursor( QPaintDevice::x11AppDisplay(), m_handle );
+ if ( m_pict ) XRenderFreePicture( QPaintDevice::x11AppDisplay(), m_pict );
+}
+
+
+Picture PreviewCursor::createPicture( const XcursorImage* image ) const
+{
+ Display *dpy = QPaintDevice::x11AppDisplay();
+
+ XImage ximage;
+ ximage.width = image->width;
+ ximage.height = image->height;
+ ximage.xoffset = 0;
+ ximage.format = ZPixmap;
+ ximage.data = reinterpret_cast<char*>( image->pixels );
+ ximage.byte_order = ImageByteOrder( dpy );
+ ximage.bitmap_unit = 32;
+ ximage.bitmap_bit_order = ximage.byte_order;
+ ximage.bitmap_pad = 32;
+ ximage.depth = 32;
+ ximage.bits_per_pixel = 32;
+ ximage.bytes_per_line = image->width * 4;
+ ximage.red_mask = 0x00ff0000;
+ ximage.green_mask = 0x0000ff00;
+ ximage.blue_mask = 0x000000ff;
+ ximage.obdata = 0;
+
+ XInitImage( &ximage );
+
+ Pixmap pix = XCreatePixmap( dpy, DefaultRootWindow(dpy), ximage.width, ximage.height, 32 );
+ GC gc = XCreateGC( dpy, pix, 0, NULL );
+ XPutImage( dpy, pix, gc, &ximage, 0, 0, 0, 0, ximage.width, ximage.height );
+ XFreeGC( dpy, gc );
+
+ XRenderPictFormat *fmt = XRenderFindStandardFormat( dpy, PictStandardARGB32 );
+ Picture pict = XRenderCreatePicture( dpy, pix, fmt, 0, NULL );
+ XFreePixmap( dpy, pix );
+
+ return pict;
+}
+
+
+void PreviewCursor::cropCursorImage( XcursorImage *&image ) const
+{
+ // Calculate the auto-crop rectangle
+ QRect r( QPoint( image->width, image->height ), QPoint() );
+ XcursorPixel *pixels = image->pixels;
+ for ( int y = 0; y < int(image->height); y++ ) {
+ for ( int x = 0; x < int(image->width); x++ ) {
+ if ( *(pixels++) >> 24 ) {
+ if ( x < r.left() ) r.setLeft( x );
+ if ( x > r.right() ) r.setRight( x );
+ if ( y < r.top() ) r.setTop( y );
+ if ( y > r.bottom() ) r.setBottom( y );
+ }
+ }
+ }
+
+ // Normalize the rectangle
+ r = r.normalize();
+
+ // Don't crop the image if the size isn't going to change
+ if ( r.width() == int( image->width ) && r.height() == int( image->height ) )
+ return;
+
+ // Create the new image
+ XcursorImage *cropped = XcursorImageCreate( r.width(), r.height() );
+ XcursorPixel *src = image->pixels + r.top() * image->width + r.left();
+ XcursorPixel *dst = cropped->pixels;
+ for ( int y = 0; y < r.height(); y++, src += (image->width - r.width()) ) {
+ for ( int x = 0; x < r.width(); x++ ) {
+ *(dst++) = *(src++);
+ }
+ }
+
+ // Destroy the original
+ XcursorImageDestroy( image );
+ image = cropped;
+}
+
+
+
+// ------------------------------------------------------------------------------------------------
+
+
+
+PreviewWidget::PreviewWidget( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ cursors = new PreviewCursor* [ numCursors ];
+ for ( int i = 0; i < numCursors; i++ )
+ cursors[i] = new PreviewCursor;
+
+ current = -1;
+ setMouseTracking( true );
+ setFixedHeight( previewSize + 20 );
+}
+
+
+PreviewWidget::~PreviewWidget()
+{
+ for ( int i = 0; i < numCursors; i++ )
+ delete cursors[i];
+
+ delete [] cursors;
+}
+
+
+void PreviewWidget::setTheme( const QString &theme )
+{
+ setUpdatesEnabled( false );
+
+ int minHeight = previewSize + 20; // Minimum height of the preview widget
+ int maxHeight = height(); // Tallest cursor height
+ int maxWidth = previewSize; // Widest cursor width
+
+ for ( int i = 0; i < numCursors; i++ ) {
+ cursors[i]->load( cursor_names[i], theme.latin1() );
+ if ( cursors[i]->width() > maxWidth )
+ maxWidth = cursors[i]->width();
+ if ( cursors[i]->height() > maxHeight )
+ maxHeight = cursors[i]->height();
+ }
+
+ current = -1;
+ setFixedSize( ( maxWidth + cursorSpacing ) * numCursors, kMax( maxHeight, minHeight ) );
+ setUpdatesEnabled( true );
+ repaint( false );
+}
+
+
+void PreviewWidget::paintEvent( QPaintEvent * )
+{
+ QPixmap buffer( size() );
+ QPainter p( &buffer );
+ p.fillRect( rect(), colorGroup().brush( QColorGroup::Background ) );
+ Picture dest;
+
+ if ( !qt_has_xft || !qt_use_xrender ) {
+ XRenderPictFormat *fmt = XRenderFindVisualFormat( x11Display(), (Visual*)buffer.x11Visual() );
+ dest = XRenderCreatePicture( x11Display(), buffer.handle(), fmt, 0, NULL );
+ } else
+ dest = buffer.x11RenderHandle();
+
+ int rwidth = width() / numCursors;
+
+ for ( int i = 0; i < numCursors; i++ ) {
+ if ( cursors[i]->picture() ) {
+ XRenderComposite( x11Display(), PictOpOver,
+ cursors[i]->picture(), 0, dest, 0, 0, 0, 0,
+ rwidth * i + (rwidth - cursors[i]->width()) / 2,
+ (height() - cursors[i]->height()) / 2,
+ cursors[i]->width(), cursors[i]->height() );
+ }
+ }
+
+ bitBlt( this, 0, 0, &buffer );
+
+ if ( !qt_has_xft || !qt_use_xrender )
+ XRenderFreePicture( x11Display(), dest );
+}
+
+
+void PreviewWidget::mouseMoveEvent( QMouseEvent *e )
+{
+ int pos = e->x() / ( width() / numCursors );
+
+ if ( pos != current && pos < numCursors ) {
+ XDefineCursor( x11Display(), winId(), cursors[pos]->handle() );
+ current = pos;
+ }
+}
+
+
+// vim: set noet ts=4 sw=4:
diff --git a/kcontrol/input/xcursor/previewwidget.h b/kcontrol/input/xcursor/previewwidget.h
new file mode 100644
index 000000000..1c1d12c0f
--- /dev/null
+++ b/kcontrol/input/xcursor/previewwidget.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2003 Fredrik Höglund <fredrik@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef __CURSORPREVIEW_H
+#define __CURSORPREVIEW_H
+
+
+class PreviewCursor;
+
+
+class PreviewWidget : public QWidget
+{
+ public:
+ PreviewWidget( QWidget *parent = NULL, const char *name = NULL );
+ ~PreviewWidget();
+
+ void setTheme( const QString & );
+
+ void paintEvent( QPaintEvent * );
+ void mouseMoveEvent( QMouseEvent * );
+
+ private:
+ PreviewCursor **cursors;
+ int current;
+}; // class CursorPreview
+
+
+
+#endif
+
+// vim: set noet ts=4 sw=4:
diff --git a/kcontrol/input/xcursor/themepage.cpp b/kcontrol/input/xcursor/themepage.cpp
new file mode 100644
index 000000000..96e3e6871
--- /dev/null
+++ b/kcontrol/input/xcursor/themepage.cpp
@@ -0,0 +1,637 @@
+/*
+ * Copyright (C) 2003 Fredrik H�lund <fredrik@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <klocale.h>
+#include <kaboutdata.h>
+#include <kstandarddirs.h>
+#include <klistview.h>
+#include <ksimpleconfig.h>
+#include <kglobalsettings.h>
+#include <kdialog.h>
+#include <kmessagebox.h>
+#include <kurlrequesterdlg.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <ktar.h>
+
+#include <qlayout.h>
+#include <qdir.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qlabel.h>
+#include <qhbox.h>
+#include <qpainter.h>
+#include <qfileinfo.h>
+#include <qpushbutton.h>
+
+#include <cstdlib> // for getenv()
+
+#include "themepage.h"
+#include "themepage.moc"
+
+#include "previewwidget.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xcursor/Xcursor.h>
+
+// Check for older version
+#if !defined(XCURSOR_LIB_MAJOR) && defined(XCURSOR_MAJOR)
+# define XCURSOR_LIB_MAJOR XCURSOR_MAJOR
+# define XCURSOR_LIB_MINOR XCURSOR_MINOR
+#endif
+
+namespace {
+ // Listview icon size
+ const int iconSize = 24;
+
+ // Listview columns
+ enum Columns { NameColumn = 0, DescColumn, /* hidden */ DirColumn };
+}
+
+struct ThemeInfo {
+ QString path; // Path to the cursor theme
+ bool writable; // Theme directory is writable
+};
+
+
+ThemePage::ThemePage( QWidget* parent, const char* name )
+ : QWidget( parent, name ), selectedTheme( NULL ), currentTheme( NULL )
+{
+ QBoxLayout *layout = new QVBoxLayout( this );
+ layout->setAutoAdd( true );
+ layout->setMargin( KDialog::marginHint() );
+ layout->setSpacing( KDialog::spacingHint() );
+
+ new QLabel( i18n("Select the cursor theme you want to use (hover preview to test cursor):"), this );
+
+ // Create the preview widget
+ preview = new PreviewWidget( new QHBox( this ) );
+
+ // Create the theme list view
+ listview = new KListView( this );
+ listview->setFullWidth( true );
+ listview->setAllColumnsShowFocus( true );
+ listview->addColumn( i18n("Name") );
+ listview->addColumn( i18n("Description") );
+
+ connect( listview, SIGNAL(selectionChanged(QListViewItem*)),
+ SLOT(selectionChanged(QListViewItem*)) );
+
+ themeDirs = getThemeBaseDirs();
+ insertThemes();
+
+ QHBox *hbox = new QHBox( this );
+ hbox->setSpacing( KDialog::spacingHint() );
+ installButton = new QPushButton( i18n("Install New Theme..."), hbox );
+ removeButton = new QPushButton( i18n("Remove Theme"), hbox );
+
+ connect( installButton, SIGNAL( clicked() ), SLOT( installClicked() ) );
+ connect( removeButton, SIGNAL( clicked() ), SLOT( removeClicked() ) );
+
+ // Disable the install button if ~/.icons isn't writable
+ QString path = QDir::homeDirPath() + "/.icons";
+ QFileInfo icons = QFileInfo( path );
+
+ if ( ( icons.exists() && !icons.isWritable() ) ||
+ ( !icons.exists() && !QFileInfo( QDir::homeDirPath() ).isWritable() ) )
+ installButton->setEnabled( false );
+
+ if ( !themeDirs.contains( path ) )
+ installButton->setEnabled( false );
+
+ selectionChanged( listview->currentItem() );
+}
+
+
+ThemePage::~ThemePage()
+{
+}
+
+
+void ThemePage::save()
+{
+ if ( currentTheme == selectedTheme )
+ return;
+
+ KConfig c( "kcminputrc" );
+ c.setGroup( "Mouse" );
+ c.writeEntry( "cursorTheme", selectedTheme != "system" ? selectedTheme : QString::null );
+
+ KMessageBox::information( this, i18n("You have to restart KDE for these "
+ "changes to take effect."), i18n("Cursor Settings Changed"),
+ "CursorSettingsChanged" );
+
+ currentTheme = selectedTheme;
+}
+
+void ThemePage::load()
+{
+ load( false );
+}
+
+void ThemePage::load( bool useDefaults )
+{
+ // Get the name of the theme libXcursor currently uses
+ const char *theme = XcursorGetTheme( x11Display() );
+ currentTheme = theme;
+
+ // Get the name of the theme KDE is configured to use
+ KConfig c( "kcminputrc" );
+ c.setReadDefaults( useDefaults );
+ c.setGroup( "Mouse" );
+ currentTheme = c.readEntry( "cursorTheme", currentTheme );
+ if( currentTheme.isEmpty())
+ currentTheme = "system";
+
+ // Find the theme in the listview and select it
+ QListViewItem *item = listview->findItem( currentTheme, DirColumn );
+ if( !item )
+ item = listview->findItem( "system", DirColumn );
+ selectedTheme = item->text( DirColumn );
+ listview->setSelected( item, true );
+ listview->ensureItemVisible( item );
+
+ // Update the preview widget as well
+ if ( preview )
+ preview->setTheme( selectedTheme );
+
+ // Disable the listview if we're in kiosk mode
+ if ( c.entryIsImmutable( "cursorTheme" ) )
+ listview->setEnabled( false );
+}
+
+
+void ThemePage::defaults()
+{
+ load( true );
+}
+
+
+void ThemePage::selectionChanged( QListViewItem *item )
+{
+ if ( !item )
+ {
+ removeButton->setEnabled( false );
+ return;
+ }
+
+ selectedTheme = item->text( DirColumn );
+
+ // Update the preview widget
+ if ( preview )
+ preview->setTheme( selectedTheme );
+
+ removeButton->setEnabled( themeInfo[ selectedTheme ] && themeInfo[ selectedTheme ]->writable );
+
+ emit changed( currentTheme != selectedTheme );
+}
+
+
+void ThemePage::installClicked()
+{
+ // Get the URL for the theme we're going to install
+ KURL url = KURLRequesterDlg::getURL( QString::null, this, i18n( "Drag or Type Theme URL" ) );
+ if ( url.isEmpty() )
+ return;
+
+ QString tmpFile;
+ if ( !KIO::NetAccess::download( url, tmpFile, this ) ) {
+ QString text;
+
+ if ( url.isLocalFile() )
+ text = i18n( "Unable to find the cursor theme archive %1." );
+ else
+ text = i18n( "Unable to download the cursor theme archive; "
+ "please check that the address %1 is correct." );
+
+ KMessageBox::sorry( this, text.arg( url.prettyURL() ) );
+ return;
+ }
+
+ if ( !installThemes( tmpFile ) )
+ KMessageBox::error( this, i18n( "The file %1 does not appear to be a valid "
+ "cursor theme archive.").arg( url.fileName() ) );
+
+ KIO::NetAccess::removeTempFile( tmpFile );
+}
+
+
+void ThemePage::removeClicked()
+{
+ QString question = i18n( "<qt>Are you sure you want to remove the "
+ "<strong>%1</strong> cursor theme?<br>"
+ "This will delete all the files installed by this theme.</qt>")
+ .arg( listview->currentItem()->text( NameColumn ) );
+
+ // Get confirmation from the user
+ int answer = KMessageBox::warningContinueCancel( this, question, i18n( "Confirmation" ), KStdGuiItem::del() );
+ if ( answer != KMessageBox::Continue )
+ return;
+
+ // Delete the theme from the harddrive
+ KURL u;
+ u.setPath( themeInfo[ selectedTheme ]->path );
+ KIO::del( u );
+
+ // Remove the theme from the listview and from the themeinfo dict
+ delete listview->findItem( selectedTheme, DirColumn );
+ themeInfo.remove( selectedTheme );
+ listview->setSelected( listview->currentItem(), true );
+
+ // TODO:
+ // Since it's possible to substitute cursors in a system theme by adding a local
+ // theme with the same name, we shouldn't remove the theme from the list if it's
+ // still available elsewhere. This could be solved by calling insertThemes() here,
+ // but since KIO::del() is an asynchronos operation, the theme we're deleting will
+ // be readded to the list again before KIO has removed it.
+}
+
+
+bool ThemePage::installThemes( const QString &file )
+{
+ KTar archive( file );
+
+ if ( !archive.open( IO_ReadOnly ) )
+ return false;
+
+ const KArchiveDirectory *archiveDir = archive.directory();
+ QStringList themeDirs;
+
+ const QStringList entries = archiveDir->entries();
+ for ( QStringList::ConstIterator it = entries.begin(); it != entries.end(); ++it )
+ {
+ const KArchiveEntry *entry = archiveDir->entry( *it );
+ if ( entry->isDirectory() && entry->name().lower() != "default" ) {
+ const KArchiveDirectory *dir = static_cast< const KArchiveDirectory* >( entry );
+ if ( dir->entry( "index.theme" ) && dir->entry( "cursors" ) )
+ themeDirs << dir->name();
+ }
+ }
+
+ if ( themeDirs.count() < 1 )
+ return false;
+
+ const QString destDir = QDir::homeDirPath() + "/.icons/";
+ KStandardDirs::makeDir( destDir ); // Make sure the directory exists
+
+ for ( QStringList::ConstIterator it = themeDirs.begin(); it != themeDirs.end(); ++it )
+ {
+ // Check if a theme with that name already exists
+ if ( QDir( destDir ).exists( *it ) ) {
+ const QString question = i18n( "A theme named %1 already exists in your icon "
+ "theme folder. Do you want replace it with this one?" ).arg( *it );
+ int answer = KMessageBox::warningContinueCancel( this, question, i18n( "Overwrite Theme?"), i18n("Replace") );
+ if ( answer != KMessageBox::Continue )
+ continue;
+
+ // ### If the theme that's being replaced is the current theme, it
+ // will cause cursor inconsistencies in newly started apps.
+ }
+
+ // ### Should we check if a theme with the same name exists in a global theme dir?
+ // If that's the case it will effectively replace it, even though the global theme
+ // won't be deleted. Checking for this situation is easy, since the global theme
+ // will be in the listview. Maybe this should never be allowed since it might
+ // result in strange side effects (from the average users point of view). OTOH
+ // a user might want to do this 'upgrade' a global theme.
+
+ const QString dest = destDir + *it;
+ const KArchiveDirectory *dir = static_cast< const KArchiveDirectory* >( archiveDir->entry( *it ) );
+ dir->copyTo( dest );
+ insertTheme( dest );
+ }
+
+ listview->sort();
+
+ archive.close();
+ return true;
+}
+
+
+void ThemePage::insertTheme( const QString &path )
+{
+ QString dirName = QDir( path ).dirName();
+
+ // Defaults in case there's no name or comment field.
+ QString name = dirName;
+ QString desc = i18n( "No description available" );
+ QString sample = "left_ptr";
+
+ KSimpleConfig c( path + "/index.theme", true ); // Open read-only
+ c.setGroup( "Icon Theme" );
+
+ // Don't insert the theme if it's hidden.
+ if ( c.readBoolEntry( "Hidden", false ) )
+ return;
+
+ // ### If the theme is hidden, the user will probably find it strange that it
+ // doesn't appear in the list view. There also won't be a way for the user
+ // to delete the theme using the KCM. Perhaps a warning about this should
+ // be issued, and the user given a chance to undo the installation.
+
+ // Read the name, description and sample cursor
+ name = c.readEntry( "Name", name );
+ desc = c.readEntry( "Comment", desc );
+ sample = c.readEntry( "Example", sample );
+
+ // Create a ThemeInfo object if one doesn't already exist, and fill in the members
+ ThemeInfo *info = themeInfo[ dirName ];
+ if ( !info ) {
+ info = new ThemeInfo;
+ themeInfo.insert( dirName, info );
+ }
+
+ info->path = path;
+ info->writable = true;
+
+ // If an item with the same name already exists, remove it
+ delete listview->findItem( dirName, DirColumn );
+
+ // Create the listview item and insert it into the list.
+ KListViewItem *item = new KListViewItem( listview, name, desc, /*hidden*/ dirName );
+ item->setPixmap( NameColumn, createIcon( dirName, sample ) );
+ listview->insertItem( item );
+}
+
+
+const QStringList ThemePage::getThemeBaseDirs() const
+{
+#if XCURSOR_LIB_MAJOR == 1 && XCURSOR_LIB_MINOR < 1
+ // These are the default paths Xcursor will scan for cursor themes
+ QString path( "~/.icons:/usr/share/icons:/usr/share/pixmaps:/usr/X11R6/lib/X11/icons" );
+
+ // If XCURSOR_PATH is set, use that instead of the default path
+ char *xcursorPath = std::getenv( "XCURSOR_PATH" );
+ if ( xcursorPath )
+ path = xcursorPath;
+#else
+ // Get the search patch from Xcursor
+ QString path = XcursorLibraryPath();
+#endif
+ // Expand all occurences of ~ to the home dir
+ path.replace( "~/", QDir::homeDirPath() + '/' );
+ return QStringList::split( ':', path );
+}
+
+
+bool ThemePage::isCursorTheme( const QString &theme, const int depth ) const
+{
+ // Prevent infinate recursion
+ if ( depth > 10 )
+ return false;
+
+ // Search each icon theme directory for 'theme'
+ for ( QStringList::ConstIterator it = themeDirs.begin(); it != themeDirs.end(); ++it )
+ {
+ QDir dir( *it );
+ if ( !dir.exists() )
+ continue;
+
+ const QStringList subdirs( dir.entryList( QDir::Dirs ) );
+ if ( subdirs.contains( theme ) )
+ {
+ const QString path = *it + '/' + theme;
+ const QString indexfile = path + "/index.theme";
+ const bool haveIndexFile = dir.exists( indexfile );
+ const bool haveCursors = dir.exists( path + "/cursors" );
+ QStringList inherit;
+
+ // Return true if we have a cursors subdirectory
+ if ( haveCursors )
+ return true;
+
+ // Parse the index.theme file if one exists
+ if ( haveIndexFile )
+ {
+ KSimpleConfig c( indexfile, true ); // Open read-only
+ c.setGroup( "Icon Theme" );
+ inherit = c.readListEntry( "Inherits" );
+ }
+
+ // Recurse through the list of inherited themes
+ for ( QStringList::ConstIterator it2 = inherit.begin(); it2 != inherit.end(); ++it2 )
+ {
+ if ( *it2 == theme ) // Avoid possible DoS
+ continue;
+
+ if ( isCursorTheme( *it2, depth + 1 ) )
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+void ThemePage::insertThemes()
+{
+ // Scan each base dir for cursor themes and add them to the listview.
+ // An icon theme is considered to be a cursor theme if it contains
+ // a cursors subdirectory or if it inherits a cursor theme.
+ for ( QStringList::ConstIterator it = themeDirs.begin(); it != themeDirs.end(); ++it )
+ {
+ QDir dir( *it );
+ if ( !dir.exists() )
+ continue;
+
+ QStringList subdirs( dir.entryList( QDir::Dirs ) );
+ subdirs.remove( "." );
+ subdirs.remove( ".." );
+
+ for ( QStringList::ConstIterator it = subdirs.begin(); it != subdirs.end(); ++it )
+ {
+ // Only add the theme if we don't already have a theme with that name
+ // in the list. Xcursor will use the first theme it finds in that
+ // case, and since we use the same search order that should also be
+ // the theme we end up adding to the list.
+ if ( listview->findItem( *it, DirColumn ) )
+ continue;
+
+ const QString path = dir.path() + '/' + *it;
+ const QString indexfile = path + "/index.theme";
+ const bool haveIndexFile = dir.exists( *it + "/index.theme" );
+ const bool haveCursors = dir.exists( *it + "/cursors" );
+
+ // If the directory doesn't have a cursors subdir and lack an
+ // index.theme file it's definately not a cursor theme
+ if ( !haveIndexFile && !haveCursors )
+ continue;
+
+ // Defaults in case there's no index.theme file or it lacks
+ // a name and a comment field.
+ QString name = *it;
+ QString desc = i18n( "No description available" );
+ QString sample = "left_ptr";
+
+ // Parse the index.theme file if the theme has one.
+ if ( haveIndexFile )
+ {
+ KSimpleConfig c( indexfile, true );
+ c.setGroup( "Icon Theme" );
+
+ // Skip this theme if it's hidden.
+ if ( c.readBoolEntry( "Hidden", false ) )
+ continue;
+
+ // If there's no cursors subdirectory we'll do a recursive scan
+ // to check if the theme inherits a theme with one.
+ if ( !haveCursors )
+ {
+ bool result = false;
+ QStringList inherit = c.readListEntry( "Inherits" );
+ for ( QStringList::ConstIterator it2 = inherit.begin(); it2 != inherit.end(); ++it2 )
+ if ( result = isCursorTheme( *it2 ) )
+ break;
+
+ // If this theme doesn't inherit a cursor theme, proceed
+ // to the next theme in the list.
+ if ( !result )
+ continue;
+ }
+
+ // Read the name, description and sample cursor
+ name = c.readEntry( "Name", name );
+ desc = c.readEntry( "Comment", desc );
+ sample = c.readEntry( "Example", sample );
+ }
+
+ // Create a ThemeInfo object, and fill in the members
+ ThemeInfo *info = new ThemeInfo;
+ info->path = path;
+ info->writable = QFileInfo( path ).isWritable();
+ themeInfo.insert( *it, info );
+
+ // Create the listview item and insert it into the list.
+ KListViewItem *item = new KListViewItem( listview, name, desc, /*hidden*/ *it );
+ item->setPixmap( NameColumn, createIcon( *it, sample ) );
+ listview->insertItem( item );
+ }
+ }
+
+ // Note: If a default theme dir wasn't found in the above search, Xcursor will
+ // default to using the cursor font.
+
+ // Sort the theme list
+ listview->sort();
+
+ KListViewItem *item = new KListViewItem( listview, ' ' + i18n( "No theme" ), i18n( "The old classic X cursors") , /*hidden*/ "none" );
+ listview->insertItem( item );
+ item = new KListViewItem( listview, ' ' + i18n( "System theme" ), i18n( "Do not change cursor theme") , /*hidden*/ "system" );
+ listview->insertItem( item );
+ // no ThemeInfo object for this one
+}
+
+
+QPixmap ThemePage::createIcon( const QString &theme, const QString &sample ) const
+{
+ XcursorImage *xcur;
+ QPixmap pix;
+
+ xcur = XcursorLibraryLoadImage( sample.latin1(), theme.latin1(), iconSize );
+ if ( !xcur ) xcur = XcursorLibraryLoadImage( "left_ptr", theme.latin1(), iconSize );
+
+ if ( xcur ) {
+ // Calculate an auto-crop rectangle for the cursor image
+ // (helps with cursors converted from windows .cur or .ani files)
+ QRect r( QPoint( xcur->width, xcur->height ), QPoint() );
+ XcursorPixel *src = xcur->pixels;
+
+ for ( int y = 0; y < int( xcur->height ); y++ ) {
+ for ( int x = 0; x < int( xcur->width ); x++ ) {
+ if ( *(src++) >> 24 ) {
+ if ( x < r.left() ) r.setLeft( x );
+ if ( x > r.right() ) r.setRight( x );
+ if ( y < r.top() ) r.setTop( y );
+ if ( y > r.bottom() ) r.setBottom( y );
+ }
+ }
+ }
+
+ // Normalize the rectangle
+ r = r.normalize();
+
+ // Calculate the image size
+ int size = kMax( iconSize, kMax( r.width(), r.height() ) );
+
+ // Create the intermediate QImage
+ QImage image( size, size, 32 );
+ image.setAlphaBuffer( true );
+
+ // Clear the image
+ Q_UINT32 *dst = reinterpret_cast<Q_UINT32*>( image.bits() );
+ for ( int i = 0; i < image.width() * image.height(); i++ )
+ dst[i] = 0;
+
+ // Compute the source and destination offsets
+ QPoint dstOffset( (image.width() - r.width()) / 2, (image.height() - r.height()) / 2 );
+ QPoint srcOffset( r.topLeft() );
+
+ dst = reinterpret_cast<Q_UINT32*>( image.scanLine(dstOffset.y()) ) + dstOffset.x();
+ src = reinterpret_cast<Q_UINT32*>( xcur->pixels ) + srcOffset.y() * xcur->width + srcOffset.x();
+
+ // Copy the XcursorImage into the QImage, converting it from premultiplied
+ // to non-premultiplied alpha and cropping it if needed.
+ for ( int y = 0; y < r.height(); y++ )
+ {
+ for ( int x = 0; x < r.width(); x++, dst++, src++ ) {
+ const Q_UINT32 pixel = *src;
+
+ const Q_UINT8 a = qAlpha( pixel );
+ const Q_UINT8 r = qRed( pixel );
+ const Q_UINT8 g = qGreen( pixel );
+ const Q_UINT8 b = qBlue( pixel );
+
+ if ( !a || a == 255 ) {
+ *dst = pixel;
+ } else {
+ float alpha = a / 255.0;
+ *dst = qRgba( int(r / alpha), int(g / alpha), int(b / alpha), a );
+ }
+ }
+ dst += ( image.width() - r.width() );
+ src += ( xcur->width - r.width() );
+ }
+
+ // Scale down the image if we need to
+ if ( image.width() > iconSize || image.height() > iconSize )
+ image = image.smoothScale( iconSize, iconSize, QImage::ScaleMin );
+
+ pix.convertFromImage( image );
+ XcursorImageDestroy( xcur );
+ } else {
+
+ QImage image( iconSize, iconSize, 32 );
+ image.setAlphaBuffer( true );
+
+ Q_UINT32 *data = reinterpret_cast< Q_UINT32* >( image.bits() );
+ for ( int i = 0; i < image.width() * image.height(); i++ )
+ data[ i ] = 0;
+
+ pix.convertFromImage( image );
+ }
+
+ return pix;
+}
+
+
+// vim: set noet ts=4 sw=4:
diff --git a/kcontrol/input/xcursor/themepage.h b/kcontrol/input/xcursor/themepage.h
new file mode 100644
index 000000000..7d4dec675
--- /dev/null
+++ b/kcontrol/input/xcursor/themepage.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2003 Fredrik Höglund <fredrik@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __THEMEPAGE_H
+#define __THEMEPAGE_H
+
+#include <qdict.h>
+
+
+class KListView;
+class QString;
+class PreviewWidget;
+class QStringList;
+class QListViewItem;
+class QPushButton;
+
+struct ThemeInfo;
+
+
+class ThemePage : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ ThemePage( QWidget* parent = 0, const char* name = 0 );
+ ~ThemePage();
+
+ // Called by the KCM
+ void save();
+ void load();
+ void load( bool useDefaults );
+ void defaults();
+
+ signals:
+ void changed( bool );
+
+ private slots:
+ void selectionChanged( QListViewItem * );
+ void installClicked();
+ void removeClicked();
+
+ private:
+ bool installThemes( const QString &file );
+ void insertTheme( const QString & );
+ const QStringList getThemeBaseDirs() const;
+ bool isCursorTheme( const QString &theme, const int depth = 0 ) const;
+ void insertThemes();
+ QPixmap createIcon( const QString &, const QString & ) const;
+
+ KListView *listview;
+ PreviewWidget *preview;
+ QPushButton *installButton, *removeButton;
+ QString selectedTheme;
+ QString currentTheme;
+ QStringList themeDirs;
+ QDict<ThemeInfo> themeInfo;
+};
+
+#endif // __THEMEPAGE_H
+
+// vim: set noet ts=4 sw=4: