summaryrefslogtreecommitdiffstats
path: root/kcontrol/keys/modifiers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/keys/modifiers.cpp')
-rw-r--r--kcontrol/keys/modifiers.cpp354
1 files changed, 354 insertions, 0 deletions
diff --git a/kcontrol/keys/modifiers.cpp b/kcontrol/keys/modifiers.cpp
new file mode 100644
index 000000000..8391c7938
--- /dev/null
+++ b/kcontrol/keys/modifiers.cpp
@@ -0,0 +1,354 @@
+#include "modifiers.h"
+
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <kkeynative.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#define XK_MISCELLANY
+#define XK_XKB_KEYS
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysymdef.h>
+#include <ctype.h>
+#undef NONE
+
+/*Modifier Scheme
+ PC: Shift/Ctrl/Alt/Win
+ Mac: Shift/Command/Apple/Alt
+ Custom
+
+X11
+Modifier XMod Label
+Shift Shift [Shift]
+Ctrl Control [Ctrl] Ctrl|Apple
+Alt [Mod1] [Alt] Alt|Command
+Win [Mod4] [Win] Win|Alt|Meta|Super|Hyper
+Extra1 [] [] User definable
+
+ Shift
+ Lock Caps_Lock
+ Control Control_L, Control_R
+ Mod1 Alt_L, Alt_R
+ Mod2 Num_Lock
+ Mod3 Mode_switch
+ Mod4 Super_L, Super_R
+ Mod5 Scroll_Lock
+*/
+
+//For Mac keyboards:
+//1) labels: Shift | Ctrl | Option | Command
+//2) swap Ctrl & Command
+
+ModifiersModule::ModifiersModule( QWidget *parent, const char *name )
+: QWidget( parent, name )
+{
+ initGUI();
+ load( false );
+}
+
+void ModifiersModule::load( bool useDefaults )
+{
+ KConfig *c = KGlobal::config();
+
+ c->setReadDefaults( useDefaults );
+
+ c->setGroup( "Keyboard" );
+
+ m_sLabelCtrlOrig = c->readEntry( "Label Ctrl", "Ctrl" );
+ m_sLabelAltOrig = c->readEntry( "Label Alt", "Alt" );
+ m_sLabelWinOrig = c->readEntry( "Label Win", "Win" );
+
+ m_bMacKeyboardOrig = c->readBoolEntry( "Mac Keyboard", false );
+ m_bMacSwapOrig = m_bMacKeyboardOrig && c->readBoolEntry( "Mac Modifier Swap", false );
+
+ updateWidgetData();
+}
+
+// When [Apply] or [OK] are clicked.
+void ModifiersModule::save()
+{
+ kdDebug(125) << "ModifiersModule::save()" << endl;
+
+ KConfigGroupSaver cgs( KGlobal::config(), "Keyboard" );
+
+ if( m_plblCtrl->text() != "Ctrl" )
+ KGlobal::config()->writeEntry( "Label Ctrl", m_plblCtrl->text(), true, true );
+ else
+ KGlobal::config()->deleteEntry( "Label Ctrl", false, true );
+
+ if( m_plblAlt->text() != "Alt" )
+ KGlobal::config()->writeEntry( "Label Alt", m_plblAlt->text(), true, true );
+ else
+ KGlobal::config()->deleteEntry( "Label Alt", false, true );
+
+ if( m_plblWin->text() != "Win" )
+ KGlobal::config()->writeEntry( "Label Win", m_plblWin->text(), true, true );
+ else
+ KGlobal::config()->deleteEntry( "Label Win", false, true );
+
+ if( m_pchkMacKeyboard->isChecked() )
+ KGlobal::config()->writeEntry( "Mac Keyboard", true, true, true );
+ else
+ KGlobal::config()->deleteEntry( "Mac Keyboard", false, true );
+
+ bool bMacSwap = m_pchkMacKeyboard->isChecked() && m_pchkMacSwap->isChecked();
+ if( bMacSwap )
+ KGlobal::config()->writeEntry( "Mac Modifier Swap", true, true, true );
+ else
+ KGlobal::config()->deleteEntry( "Mac Modifier Swap", false, true );
+
+ KGlobal::config()->sync();
+
+ if( m_bMacSwapOrig != bMacSwap ) {
+ if( bMacSwap )
+ setupMacModifierKeys();
+ else
+ kapp->kdeinitExec("kxkb");
+ m_bMacSwapOrig = bMacSwap;
+ updateWidgets();
+ }
+}
+
+void ModifiersModule::defaults()
+{
+ load( true );
+}
+
+#define SET_CODE_SYM( iCode, sym ) \
+ if( iCode >= keyCodeMin && iCode <= keyCodeMax ) \
+ rgKeySyms[(iCode-keyCodeMin) * nSymsPerCode] = sym;
+#define SET_MOD_CODE( iMod, code1, code2 ) \
+ xmk->modifiermap[iMod * xmk->max_keypermod + 0] = code1; \
+ xmk->modifiermap[iMod * xmk->max_keypermod + 1] = code2;
+void ModifiersModule::setupMacModifierKeys()
+{
+ const int CODE_Ctrl_L = 0x25, CODE_Ctrl_R = 0x6d;
+ const int CODE_Win_L = 0x73, CODE_Win_R = 0x74;
+ //const int CODE_Alt_L = 0x40, CODE_Alt_R = 0x71;
+ int keyCodeMin, keyCodeMax, nKeyCodes, nSymsPerCode;
+
+ XDisplayKeycodes( qt_xdisplay(), &keyCodeMin, &keyCodeMax );
+ nKeyCodes = keyCodeMax - keyCodeMin + 1;
+ KeySym* rgKeySyms = XGetKeyboardMapping( qt_xdisplay(), keyCodeMin, nKeyCodes, &nSymsPerCode );
+ XModifierKeymap* xmk = XGetModifierMapping( qt_xdisplay() );
+
+ SET_CODE_SYM( CODE_Ctrl_L, XK_Super_L )
+ SET_CODE_SYM( CODE_Ctrl_R, XK_Super_R )
+ SET_CODE_SYM( CODE_Win_L, XK_Control_L )
+ SET_CODE_SYM( CODE_Win_R, XK_Control_R )
+ //SET_CODE_SYM( CODE_Win_L, XK_Alt_L )
+ //SET_CODE_SYM( CODE_Win_R, XK_Alt_R )
+ //SET_CODE_SYM( CODE_Alt_L, XK_Control_L )
+ //SET_CODE_SYM( CODE_Alt_R, XK_Control_R )
+
+ SET_MOD_CODE( ControlMapIndex, CODE_Win_L, CODE_Win_R );
+ SET_MOD_CODE( Mod4MapIndex, CODE_Ctrl_L, CODE_Ctrl_R );
+ //SET_MOD_CODE( ControlMapIndex, CODE_Alt_L, CODE_Alt_R );
+ //SET_MOD_CODE( Mod1MapIndex, CODE_Win_L, CODE_Win_R );
+ //SET_MOD_CODE( Mod4MapIndex, CODE_Ctrl_L, CODE_Ctrl_R );
+
+ XSetModifierMapping( qt_xdisplay(), xmk );
+ XChangeKeyboardMapping( qt_xdisplay(), keyCodeMin, nSymsPerCode, rgKeySyms, nKeyCodes );
+ XFree( rgKeySyms );
+ XFreeModifiermap( xmk );
+}
+#undef SET_CODE_SYM
+
+void ModifiersModule::initGUI()
+{
+ QGridLayout* pLayoutTop = new QGridLayout( this, 6, 2, KDialog::marginHint() );
+ pLayoutTop->setColStretch( 1, 1 );
+
+ QGroupBox* pGroup = new QGroupBox( 2, Qt::Horizontal, i18n("KDE Modifiers"), this );
+ pLayoutTop->addWidget( pGroup, 0, 0 );
+
+ QLabel* plbl = new QLabel( i18n("Modifier"), pGroup );
+ QFont font = plbl->font();
+ font.setUnderline( true );
+ font.setWeight( QFont::Bold );
+ plbl->setFont( font );
+ plbl = new QLabel( i18n("X11-Mod"), pGroup );
+ plbl->setFont( font );
+
+ new QLabel( i18n("QAccel", "Shift"), pGroup );
+ new QLabel( "shift", pGroup );
+
+ m_plblCtrl = new QLabel( i18n("QAccel", "Ctrl"), pGroup );
+ new QLabel( "control", pGroup );
+
+ m_plblAlt = new QLabel( i18n("QAccel", "Alt"), pGroup );
+ new QLabel( "mod1", pGroup );
+
+ m_plblWin = new QLabel( i18n("Win"), pGroup );
+ m_plblWinModX = new QLabel( "", pGroup );
+ /*m_pcbWinX = newModXComboBox( pGroup );
+ int i;
+ switch( KKeyNative::modX(KKey::WIN) ) {
+ case Mod2Mask: i = 1; break;
+ case Mod3Mask: i = 2; break;
+ case Mod4Mask: i = 3; break;
+ case Mod5Mask: i = 5; break;
+ default: i = 0;
+ }
+ m_pcbWinX->setCurrentItem( i );*/
+
+ m_pchkMacKeyboard = new QCheckBox( i18n("Macintosh keyboard"), this );
+ m_pchkMacKeyboard->setChecked( m_bMacKeyboardOrig );
+ connect( m_pchkMacKeyboard, SIGNAL(clicked()), SLOT(slotMacKeyboardClicked()) );
+ pLayoutTop->addWidget( m_pchkMacKeyboard, 1, 0 );
+
+ m_pchkMacSwap = new QCheckBox( i18n("MacOS-style modifier usage"), this );
+ m_pchkMacSwap->setChecked( m_bMacSwapOrig );
+ QWhatsThis::add( m_pchkMacSwap,
+ i18n("Checking this box will change your X Modifier Mapping to "
+ "better reflect the standard MacOS modifier key usage. "
+ "It allows you to use <i>Command+C</i> for <i>Copy</i>, for instance, "
+ "instead of the PC standard of <i>Ctrl+C</I>. "
+ "<b>Command</b> will be used for application and console commands, "
+ "<b>Option</b> as a command modifier and for navigating menus and dialogs, "
+ "and <b>Control</b> for window manager commands.") );
+ connect( m_pchkMacSwap, SIGNAL(clicked()), SLOT(slotMacSwapClicked()) );
+ pLayoutTop->addWidget( m_pchkMacSwap, 2, 0 );
+
+ //------------------
+ pLayoutTop->addRowSpacing( 3, KDialog::spacingHint() * 3 );
+
+ pGroup = new QGroupBox( 1, Qt::Horizontal, i18n("X Modifier Mapping"), this );
+ pLayoutTop->addWidget( pGroup, 4, 0 );
+
+ m_plstXMods = new KListView( pGroup );
+ m_plstXMods->setSorting( -1 );
+ m_plstXMods->setSelectionMode( QListView::NoSelection );
+ m_plstXMods->setAllColumnsShowFocus( true );
+ m_plstXMods->addColumn( i18n("X11-Mod") );
+
+ new KListViewItem( m_plstXMods, "mod5" );
+ new KListViewItem( m_plstXMods, "mod4" );
+ new KListViewItem( m_plstXMods, "mod3" );
+ new KListViewItem( m_plstXMods, "mod2" );
+ new KListViewItem( m_plstXMods, "mod1" );
+ new KListViewItem( m_plstXMods, "control" );
+ new KListViewItem( m_plstXMods, "lock" );
+ new KListViewItem( m_plstXMods, "shift" );
+
+ //------------------
+ pLayoutTop->setRowStretch( 5, 1 );
+
+ updateWidgets();
+}
+
+/*KComboBox* ModifiersModule::newModXComboBox( QWidget* parent )
+{
+ KComboBox* pcb = new KComboBox( parent );
+ pcb->insertItem( "" );
+ pcb->insertItem( "mod2" );
+ pcb->insertItem( "mod3" );
+ pcb->insertItem( "mod4" );
+ pcb->insertItem( "mod5" );
+ return pcb;
+}*/
+
+void ModifiersModule::updateWidgetData()
+{
+ m_plblCtrl->setText( m_sLabelCtrlOrig );
+ m_plblAlt->setText( m_sLabelAltOrig );
+ m_plblWin->setText( m_sLabelWinOrig );
+ m_pchkMacKeyboard->setChecked( m_bMacKeyboardOrig );
+ m_pchkMacSwap->setChecked( m_bMacSwapOrig );
+ m_pchkMacSwap->setEnabled( m_bMacKeyboardOrig );
+}
+
+void ModifiersModule::updateWidgets()
+{
+ if( m_pchkMacKeyboard->isChecked() ) {
+ // If keys are swapped around to reflect MacOS norms:
+ if( m_pchkMacSwap->isChecked() ) {
+ m_plblCtrl->setText( i18n("Command") ); // Ctrl in Alt's place
+ m_plblAlt->setText( i18n("Option") ); // Alt in Win's place
+ m_plblWin->setText( i18n("Control") ); // Win in Ctrl's place
+ } else {
+ m_plblCtrl->setText( i18n("Control") ); // Ctrl labeled Control
+ m_plblAlt->setText( i18n("Option") ); // Alt labeled Command
+ m_plblWin->setText( i18n("Command") ); // Win labeled Option
+ }
+ m_pchkMacSwap->setEnabled( true );
+ } else {
+ m_plblCtrl->setText( i18n("QAccel", "Ctrl") );
+ m_plblAlt->setText( i18n("QAccel", "Alt") );
+ m_plblWin->setText( i18n("Win") );
+ m_pchkMacSwap->setEnabled( false );
+ }
+
+ XModifierKeymap* xmk = XGetModifierMapping( qt_xdisplay() );
+
+ for( int iKey = m_plstXMods->columns()-1; iKey < xmk->max_keypermod; iKey++ )
+ m_plstXMods->addColumn( i18n("Key %1").arg(iKey+1) );
+
+ //int iModWinDef = -1;
+ for( int iMod = 0; iMod < 8; iMod++ ) {
+ // Find the default modifier index for the Win key.
+ /*if( iMod > Mod2Index ) {
+ uint symX = XKeycodeToKeysym( qt_xdisplay(), xmk->modifiermap[xmk->max_keypermod * iMod], 0 );
+ if( symX == XK_Super_L || symX == XK_Super_R )
+ iModWinDef = iMod;
+ else if( iModWinDef == -1 && (symX == XK_Meta_L || symX == XK_Meta_R) )
+ iModWinDef = iMod;
+ }*/
+
+ // Insert items into X modifier map list
+ for( int iKey = 0; iKey < xmk->max_keypermod; iKey++ ) {
+ uint symX = XKeycodeToKeysym( qt_xdisplay(), xmk->modifiermap[xmk->max_keypermod * iMod + iKey], 0 );
+ m_plstXMods->itemAtIndex( iMod )->setText( 1 + iKey, XKeysymToString( symX ) );
+ }
+ }
+
+ XFreeModifiermap( xmk );
+
+ int i;
+ switch( KKeyNative::modX(KKey::WIN) ) {
+ case Mod2Mask: i = 2; break;
+ case Mod3Mask: i = 3; break;
+ case Mod4Mask: i = 4; break;
+ case Mod5Mask: i = 5; break;
+ default: i = 0;
+ }
+ if( i != 0 )
+ m_plblWinModX->setText( "mod" + QString::number(i) );
+ else
+ m_plblWinModX->setText( "<" + i18n("None") + ">" );
+}
+
+void ModifiersModule::slotMacKeyboardClicked()
+{
+ updateWidgets();
+ emit changed( true );
+}
+
+void ModifiersModule::slotMacSwapClicked()
+{
+ if( m_pchkMacKeyboard->isChecked() && !KKeyNative::keyboardHasWinKey() ) {
+ KMessageBox::sorry( this,
+ i18n("You can only activate this option if your "
+ "X keyboard layout has the 'Super' or 'Meta' keys "
+ "properly configured as modifier keys."),
+ "Incompatibility" );
+ m_pchkMacSwap->setChecked( false );
+ } else {
+ updateWidgets();
+ emit changed( true );
+ }
+}
+
+#include "modifiers.moc"