• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

kglobalaccel_win.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "config.h"
00021 
00022 #include <qwindowdefs.h>
00023 #ifdef Q_WS_WIN
00024 
00025 #include "kglobalaccel_win.h"
00026 #include "kglobalaccel.h"
00027 #include "kkeyserver_x11.h"
00028 
00029 #include <qpopupmenu.h>
00030 #include <qregexp.h>
00031 #include <qwidget.h>
00032 #include <qmetaobject.h>
00033 #include <private/qucomextra_p.h>
00034 #include <kapplication.h>
00035 #include <kdebug.h>
00036 #include <kkeynative.h>
00037 
00038 //----------------------------------------------------
00039 
00040 static QValueList< KGlobalAccelPrivate* >* all_accels = 0;
00041 
00042 KGlobalAccelPrivate::KGlobalAccelPrivate()
00043 : KAccelBase( KAccelBase::NATIVE_KEYS )
00044 , m_blocked( false )
00045 , m_blockingDisabled( false )
00046 {
00047         if( all_accels == NULL )
00048             all_accels = new QValueList< KGlobalAccelPrivate* >;
00049         all_accels->append( this );
00050     m_sConfigGroup = "Global Shortcuts";
00051 //  kapp->installX11EventFilter( this );
00052 }
00053 
00054 KGlobalAccelPrivate::~KGlobalAccelPrivate()
00055 {
00056     // TODO: Need to release all grabbed keys if the main window is not shutting down.
00057     //for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
00058     //  const CodeMod& codemod = it.key();
00059     //}
00060         all_accels->remove( this );
00061         if( all_accels->count() == 0 ) {
00062             delete all_accels;
00063             all_accels = NULL;
00064         }
00065 }
00066 
00067 void KGlobalAccelPrivate::setEnabled( bool bEnable )
00068 {
00069     m_bEnabled = bEnable;
00070     //updateConnections();
00071 }
00072 
00073 void KGlobalAccelPrivate::blockShortcuts( bool block )
00074 {
00075         if( all_accels == NULL )
00076             return;
00077         for( QValueList< KGlobalAccelPrivate* >::ConstIterator it = all_accels->begin();
00078              it != all_accels->end();
00079              ++it ) {
00080             if( (*it)->m_blockingDisabled )
00081                 continue;
00082             (*it)->m_blocked = block;
00083             (*it)->updateConnections();
00084         }
00085 }
00086 
00087 void KGlobalAccelPrivate::disableBlocking( bool block )
00088 {
00089         m_blockingDisabled = block;
00090 }
00091 
00092 bool KGlobalAccelPrivate::isEnabledInternal() const
00093 {
00094         return KAccelBase::isEnabled() && !m_blocked;
00095 }
00096 
00097 bool KGlobalAccelPrivate::emitSignal( Signal )
00098 {
00099     return false;
00100 }
00101 
00102 bool KGlobalAccelPrivate::connectKey( KAccelAction& action, const KKeyServer::Key& key )
00103     { return grabKey( key, true, &action ); }
00104 bool KGlobalAccelPrivate::connectKey( const KKeyServer::Key& key )
00105     { return grabKey( key, true, 0 ); }
00106 bool KGlobalAccelPrivate::disconnectKey( KAccelAction& action, const KKeyServer::Key& key )
00107     { return grabKey( key, false, &action ); }
00108 bool KGlobalAccelPrivate::disconnectKey( const KKeyServer::Key& key )
00109     { return grabKey( key, false, 0 ); }
00110 
00111 bool KGlobalAccelPrivate::grabKey( const KKeyServer::Key& key, bool bGrab, KAccelAction* pAction )
00112 {
00113     /*
00114     if( !key.code() ) {
00115         kdWarning(125) << "KGlobalAccelPrivate::grabKey( " << key.key().toStringInternal() << ", " << bGrab << ", \"" << (pAction ? pAction->name().latin1() : "(null)") << "\" ): Tried to grab key with null code." << endl;
00116         return false;
00117     }
00118 
00119     // Make sure that grab masks have been initialized.
00120     if( g_keyModMaskXOnOrOff == 0 )
00121         calculateGrabMasks();
00122 
00123     uchar keyCodeX = key.code();
00124     uint keyModX = key.mod() & g_keyModMaskXAccel; // Get rid of any non-relevant bits in mod
00125     // HACK: make Alt+Print work
00126     if( key.sym() == XK_Sys_Req ) {
00127         keyModX |= KKeyServer::modXAlt();
00128         keyCodeX = 111;
00129     }
00130 
00131     kdDebug(125) << QString( "grabKey( key: '%1', bGrab: %2 ): keyCodeX: %3 keyModX: %4\n" )
00132         .arg( key.key().toStringInternal() ).arg( bGrab )
00133         .arg( keyCodeX, 0, 16 ).arg( keyModX, 0, 16 );
00134     if( !keyCodeX )
00135         return false;
00136 
00137     // We'll have to grab 8 key modifier combinations in order to cover all
00138     //  combinations of CapsLock, NumLock, ScrollLock.
00139     // Does anyone with more X-savvy know how to set a mask on qt_xrootwin so that
00140     //  the irrelevant bits are always ignored and we can just make one XGrabKey
00141     //  call per accelerator? -- ellis
00142 #ifndef NDEBUG
00143     QString sDebug = QString("\tcode: 0x%1 state: 0x%2 | ").arg(keyCodeX,0,16).arg(keyModX,0,16);
00144 #endif
00145     uint keyModMaskX = ~g_keyModMaskXOnOrOff;
00146     for( uint irrelevantBitsMask = 0; irrelevantBitsMask <= 0xff; irrelevantBitsMask++ ) {
00147         if( (irrelevantBitsMask & keyModMaskX) == 0 ) {
00148 #ifndef NDEBUG
00149             sDebug += QString("0x%3, ").arg(irrelevantBitsMask, 0, 16);
00150 #endif
00151             if( bGrab )
00152                 XGrabKey( qt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask,
00153                     qt_xrootwin(), True, GrabModeAsync, GrabModeSync );
00154             else
00155                 XUngrabKey( qt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask, qt_xrootwin() );
00156         }
00157     }
00158 #ifndef NDEBUG
00159     kdDebug(125) << sDebug << endl;
00160 #endif
00161 
00162         bool failed = false;
00163         if( bGrab ) {
00164 #ifdef Q_WS_X11
00165             failed = handler.error( true ); // sync now
00166 #endif
00167             // If grab failed, then ungrab any grabs that could possibly succeed
00168         if( failed ) {
00169             kdDebug(125) << "grab failed!\n";
00170             for( uint m = 0; m <= 0xff; m++ ) {
00171                 if( m & keyModMaskX == 0 )
00172                     XUngrabKey( qt_xdisplay(), keyCodeX, keyModX | m, qt_xrootwin() );
00173                 }
00174                 }
00175     }
00176         if( !failed )
00177         {
00178         CodeMod codemod;
00179         codemod.code = keyCodeX;
00180         codemod.mod = keyModX;
00181         if( key.mod() & KKeyServer::MODE_SWITCH )
00182             codemod.mod |= KKeyServer::MODE_SWITCH;
00183 
00184         if( bGrab )
00185             m_rgCodeModToAction.insert( codemod, pAction );
00186         else
00187             m_rgCodeModToAction.remove( codemod );
00188     }
00189     return !failed;*/
00190     return false;
00191 }
00192 
00193 /*bool KGlobalAccelPrivate::x11Event( XEvent* pEvent )
00194 {
00195     //kdDebug(125) << "x11EventFilter( type = " << pEvent->type << " )" << endl;
00196     switch( pEvent->type ) {
00197      case MappingNotify:
00198             XRefreshKeyboardMapping( &pEvent->xmapping );
00199         x11MappingNotify();
00200         return false;
00201      case XKeyPress:
00202         if( x11KeyPress( pEvent ) )
00203             return true;
00204      default:
00205         return QWidget::x11Event( pEvent );
00206     }
00207 }
00208 
00209 void KGlobalAccelPrivate::x11MappingNotify()
00210 {
00211     kdDebug(125) << "KGlobalAccelPrivate::x11MappingNotify()" << endl;
00212     if( m_bEnabled ) {
00213         // Maybe the X modifier map has been changed.
00214         KKeyServer::initializeMods();
00215         calculateGrabMasks();
00216         // Do new XGrabKey()s.
00217         updateConnections();
00218     }
00219 }
00220 
00221 bool KGlobalAccelPrivate::x11KeyPress( const XEvent *pEvent )
00222 {
00223     // do not change this line unless you really really know what you are doing (Matthias)
00224     if ( !QWidget::keyboardGrabber() && !QApplication::activePopupWidget() ) {
00225         XUngrabKeyboard( qt_xdisplay(), pEvent->xkey.time );
00226                 XFlush( qt_xdisplay()); // avoid X(?) bug
00227         }
00228 
00229     if( !m_bEnabled )
00230         return false;
00231 
00232     CodeMod codemod;
00233     codemod.code = pEvent->xkey.keycode;
00234     codemod.mod = pEvent->xkey.state & (g_keyModMaskXAccel | KKeyServer::MODE_SWITCH);
00235 
00236     // If numlock is active and a keypad key is pressed, XOR the SHIFT state.
00237     //  e.g., KP_4 => Shift+KP_Left, and Shift+KP_4 => KP_Left.
00238     if( pEvent->xkey.state & KKeyServer::modXNumLock() ) {
00239         // TODO: what's the xor operator in c++?
00240         uint sym = XKeycodeToKeysym( qt_xdisplay(), codemod.code, 0 );
00241         // If this is a keypad key,
00242         if( sym >= XK_KP_Space && sym <= XK_KP_9 ) {
00243             switch( sym ) {
00244                 // Leave the following keys unaltered
00245                 // FIXME: The proper solution is to see which keysyms don't change when shifted.
00246                 case XK_KP_Multiply:
00247                 case XK_KP_Add:
00248                 case XK_KP_Subtract:
00249                 case XK_KP_Divide:
00250                     break;
00251                 default:
00252                     if( codemod.mod & KKeyServer::modXShift() )
00253                         codemod.mod &= ~KKeyServer::modXShift();
00254                     else
00255                         codemod.mod |= KKeyServer::modXShift();
00256             }
00257         }
00258     }
00259 
00260     KKeyNative keyNative( pEvent );
00261     KKey key = keyNative;
00262 
00263     kdDebug(125) << "x11KeyPress: seek " << key.toStringInternal()
00264         << QString( " keyCodeX: %1 state: %2 keyModX: %3" )
00265             .arg( codemod.code, 0, 16 ).arg( pEvent->xkey.state, 0, 16 ).arg( codemod.mod, 0, 16 ) << endl;
00266 
00267     // Search for which accelerator activated this event:
00268     if( !m_rgCodeModToAction.contains( codemod ) ) {
00269 #ifndef NDEBUG
00270         for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
00271             KAccelAction* pAction = *it;
00272             kdDebug(125) << "\tcode: " << QString::number(it.key().code, 16) << " mod: " << QString::number(it.key().mod, 16)
00273                 << (pAction ? QString(" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : QString::null)
00274                 << endl;
00275         }
00276 #endif
00277         return false;
00278     }
00279     KAccelAction* pAction = m_rgCodeModToAction[codemod];
00280 
00281     if( !pAction ) {
00282                 static bool recursion_block = false;
00283                 if( !recursion_block ) {
00284                         recursion_block = true;
00285                 QPopupMenu* pMenu = createPopupMenu( 0, KKeySequence(key) );
00286                 connect( pMenu, SIGNAL(activated(int)), this, SLOT(slotActivated(int)) );
00287                 pMenu->exec( QPoint( 0, 0 ) );
00288                 disconnect( pMenu, SIGNAL(activated(int)), this, SLOT(slotActivated(int)));
00289                 delete pMenu;
00290                         recursion_block = false;
00291                 }
00292     } else if( !pAction->objSlotPtr() || !pAction->isEnabled() )
00293         return false;
00294     else
00295         activate( pAction, KKeySequence(key) );
00296 
00297     return true;
00298 }*/
00299 
00300 void KGlobalAccelPrivate::activate( KAccelAction* pAction, const KKeySequence& seq )
00301 {
00302     kdDebug(125) << "KGlobalAccelPrivate::activate( \"" << pAction->name() << "\" ) " << endl;
00303 
00304     QRegExp rexPassIndex( "([ ]*int[ ]*)" );
00305     QRegExp rexPassInfo( " QString" );
00306     QRegExp rexIndex( " ([0-9]+)$" );
00307 
00308     // If the slot to be called accepts an integer index
00309     //  and an index is present at the end of the action's name,
00310     //  then send the slot the given index #.
00311     if( rexPassIndex.search( pAction->methodSlotPtr() ) >= 0 && rexIndex.search( pAction->name() ) >= 0 ) {
00312         int n = rexIndex.cap(1).toInt();
00313         kdDebug(125) << "Calling " << pAction->methodSlotPtr() << " int = " << n << endl;
00314                 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
00315                 if( slot_id >= 0 ) {
00316                     QUObject o[2];
00317                     static_QUType_int.set(o+1,n);
00318                     const_cast< QObject* >( pAction->objSlotPtr())->qt_invoke( slot_id, o );
00319                 }
00320     } else if( rexPassInfo.search( pAction->methodSlotPtr() ) ) {
00321                 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
00322                 if( slot_id >= 0 ) {
00323                     QUObject o[4];
00324                     static_QUType_QString.set(o+1,pAction->name());
00325                     static_QUType_QString.set(o+2,pAction->label());
00326                     static_QUType_ptr.set(o+3,&seq);
00327                     const_cast< QObject* >( pAction->objSlotPtr())->qt_invoke( slot_id, o );
00328                 }
00329     } else {
00330                 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
00331                 if( slot_id >= 0 )
00332                     const_cast< QObject* >( pAction->objSlotPtr())->qt_invoke( slot_id, 0 );
00333     }
00334 }
00335 
00336 void KGlobalAccelPrivate::slotActivated( int iAction )
00337 {
00338     KAccelAction* pAction = actions().actionPtr( iAction );
00339     if( pAction )
00340         activate( pAction, KKeySequence() );
00341 }
00342 
00343 #include "kglobalaccel_win.moc"
00344 
00345 #endif // !Q_WS_WIN

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal