kdecore Library API Documentation

kglobalaccel_win.cpp

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., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, 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 KGlobalAccelPrivate::KGlobalAccelPrivate() 00041 : KAccelBase( KAccelBase::NATIVE_KEYS ) 00042 { 00043 m_sConfigGroup = "Global Shortcuts"; 00044 // kapp->installX11EventFilter( this ); 00045 } 00046 00047 KGlobalAccelPrivate::~KGlobalAccelPrivate() 00048 { 00049 // TODO: Need to release all grabbed keys if the main window is not shutting down. 00050 //for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) { 00051 // const CodeMod& codemod = it.key(); 00052 //} 00053 } 00054 00055 void KGlobalAccelPrivate::setEnabled( bool bEnable ) 00056 { 00057 m_bEnabled = bEnable; 00058 //updateConnections(); 00059 } 00060 00061 bool KGlobalAccelPrivate::emitSignal( Signal ) 00062 { 00063 return false; 00064 } 00065 00066 bool KGlobalAccelPrivate::connectKey( KAccelAction& action, const KKeyServer::Key& key ) 00067 { return grabKey( key, true, &action ); } 00068 bool KGlobalAccelPrivate::connectKey( const KKeyServer::Key& key ) 00069 { return grabKey( key, true, 0 ); } 00070 bool KGlobalAccelPrivate::disconnectKey( KAccelAction& action, const KKeyServer::Key& key ) 00071 { return grabKey( key, false, &action ); } 00072 bool KGlobalAccelPrivate::disconnectKey( const KKeyServer::Key& key ) 00073 { return grabKey( key, false, 0 ); } 00074 00075 bool KGlobalAccelPrivate::grabKey( const KKeyServer::Key& key, bool bGrab, KAccelAction* pAction ) 00076 { 00077 /* 00078 if( !key.code() ) { 00079 kdWarning(125) << "KGlobalAccelPrivate::grabKey( " << key.key().toStringInternal() << ", " << bGrab << ", \"" << (pAction ? pAction->name().latin1() : "(null)") << "\" ): Tried to grab key with null code." << endl; 00080 return false; 00081 } 00082 00083 // Make sure that grab masks have been initialized. 00084 if( g_keyModMaskXOnOrOff == 0 ) 00085 calculateGrabMasks(); 00086 00087 uchar keyCodeX = key.code(); 00088 uint keyModX = key.mod() & g_keyModMaskXAccel; // Get rid of any non-relevant bits in mod 00089 // HACK: make Alt+Print work 00090 if( key.sym() == XK_Sys_Req ) { 00091 keyModX |= KKeyServer::modXAlt(); 00092 keyCodeX = 111; 00093 } 00094 00095 kdDebug(125) << QString( "grabKey( key: '%1', bGrab: %2 ): keyCodeX: %3 keyModX: %4\n" ) 00096 .arg( key.key().toStringInternal() ).arg( bGrab ) 00097 .arg( keyCodeX, 0, 16 ).arg( keyModX, 0, 16 ); 00098 if( !keyCodeX ) 00099 return false; 00100 00101 // We'll have to grab 8 key modifier combinations in order to cover all 00102 // combinations of CapsLock, NumLock, ScrollLock. 00103 // Does anyone with more X-savvy know how to set a mask on qt_xrootwin so that 00104 // the irrelevant bits are always ignored and we can just make one XGrabKey 00105 // call per accelerator? -- ellis 00106 #ifndef NDEBUG 00107 QString sDebug = QString("\tcode: 0x%1 state: 0x%2 | ").arg(keyCodeX,0,16).arg(keyModX,0,16); 00108 #endif 00109 uint keyModMaskX = ~g_keyModMaskXOnOrOff; 00110 for( uint irrelevantBitsMask = 0; irrelevantBitsMask <= 0xff; irrelevantBitsMask++ ) { 00111 if( (irrelevantBitsMask & keyModMaskX) == 0 ) { 00112 #ifndef NDEBUG 00113 sDebug += QString("0x%3, ").arg(irrelevantBitsMask, 0, 16); 00114 #endif 00115 if( bGrab ) 00116 XGrabKey( qt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask, 00117 qt_xrootwin(), True, GrabModeAsync, GrabModeSync ); 00118 else 00119 XUngrabKey( qt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask, qt_xrootwin() ); 00120 } 00121 } 00122 #ifndef NDEBUG 00123 kdDebug(125) << sDebug << endl; 00124 #endif 00125 00126 bool failed = false; 00127 if( bGrab ) { 00128 #ifdef Q_WS_X11 00129 failed = handler.error( true ); // sync now 00130 #endif 00131 // If grab failed, then ungrab any grabs that could possibly succeed 00132 if( failed ) { 00133 kdDebug(125) << "grab failed!\n"; 00134 for( uint m = 0; m <= 0xff; m++ ) { 00135 if( m & keyModMaskX == 0 ) 00136 XUngrabKey( qt_xdisplay(), keyCodeX, keyModX | m, qt_xrootwin() ); 00137 } 00138 } 00139 } 00140 if( !failed ) 00141 { 00142 CodeMod codemod; 00143 codemod.code = keyCodeX; 00144 codemod.mod = keyModX; 00145 if( key.mod() & KKeyServer::MODE_SWITCH ) 00146 codemod.mod |= KKeyServer::MODE_SWITCH; 00147 00148 if( bGrab ) 00149 m_rgCodeModToAction.insert( codemod, pAction ); 00150 else 00151 m_rgCodeModToAction.remove( codemod ); 00152 } 00153 return !failed;*/ 00154 return false; 00155 } 00156 00157 /*bool KGlobalAccelPrivate::x11Event( XEvent* pEvent ) 00158 { 00159 //kdDebug(125) << "x11EventFilter( type = " << pEvent->type << " )" << endl; 00160 switch( pEvent->type ) { 00161 case MappingNotify: 00162 XRefreshKeyboardMapping( &pEvent->xmapping ); 00163 x11MappingNotify(); 00164 return false; 00165 case XKeyPress: 00166 if( x11KeyPress( pEvent ) ) 00167 return true; 00168 default: 00169 return QWidget::x11Event( pEvent ); 00170 } 00171 } 00172 00173 void KGlobalAccelPrivate::x11MappingNotify() 00174 { 00175 kdDebug(125) << "KGlobalAccelPrivate::x11MappingNotify()" << endl; 00176 if( m_bEnabled ) { 00177 // Maybe the X modifier map has been changed. 00178 KKeyServer::initializeMods(); 00179 calculateGrabMasks(); 00180 // Do new XGrabKey()s. 00181 updateConnections(); 00182 } 00183 } 00184 00185 bool KGlobalAccelPrivate::x11KeyPress( const XEvent *pEvent ) 00186 { 00187 // do not change this line unless you really really know what you are doing (Matthias) 00188 if ( !QWidget::keyboardGrabber() && !QApplication::activePopupWidget() ) { 00189 XUngrabKeyboard( qt_xdisplay(), pEvent->xkey.time ); 00190 XFlush( qt_xdisplay()); // avoid X(?) bug 00191 } 00192 00193 if( !m_bEnabled ) 00194 return false; 00195 00196 CodeMod codemod; 00197 codemod.code = pEvent->xkey.keycode; 00198 codemod.mod = pEvent->xkey.state & (g_keyModMaskXAccel | KKeyServer::MODE_SWITCH); 00199 00200 // If numlock is active and a keypad key is pressed, XOR the SHIFT state. 00201 // e.g., KP_4 => Shift+KP_Left, and Shift+KP_4 => KP_Left. 00202 if( pEvent->xkey.state & KKeyServer::modXNumLock() ) { 00203 // TODO: what's the xor operator in c++? 00204 uint sym = XKeycodeToKeysym( qt_xdisplay(), codemod.code, 0 ); 00205 // If this is a keypad key, 00206 if( sym >= XK_KP_Space && sym <= XK_KP_9 ) { 00207 switch( sym ) { 00208 // Leave the following keys unaltered 00209 // FIXME: The proper solution is to see which keysyms don't change when shifted. 00210 case XK_KP_Multiply: 00211 case XK_KP_Add: 00212 case XK_KP_Subtract: 00213 case XK_KP_Divide: 00214 break; 00215 default: 00216 if( codemod.mod & KKeyServer::modXShift() ) 00217 codemod.mod &= ~KKeyServer::modXShift(); 00218 else 00219 codemod.mod |= KKeyServer::modXShift(); 00220 } 00221 } 00222 } 00223 00224 KKeyNative keyNative( pEvent ); 00225 KKey key = keyNative; 00226 00227 kdDebug(125) << "x11KeyPress: seek " << key.toStringInternal() 00228 << QString( " keyCodeX: %1 state: %2 keyModX: %3" ) 00229 .arg( codemod.code, 0, 16 ).arg( pEvent->xkey.state, 0, 16 ).arg( codemod.mod, 0, 16 ) << endl; 00230 00231 // Search for which accelerator activated this event: 00232 if( !m_rgCodeModToAction.contains( codemod ) ) { 00233 #ifndef NDEBUG 00234 for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) { 00235 KAccelAction* pAction = *it; 00236 kdDebug(125) << "\tcode: " << QString::number(it.key().code, 16) << " mod: " << QString::number(it.key().mod, 16) 00237 << (pAction ? QString(" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : QString::null) 00238 << endl; 00239 } 00240 #endif 00241 return false; 00242 } 00243 KAccelAction* pAction = m_rgCodeModToAction[codemod]; 00244 00245 if( !pAction ) { 00246 static bool recursion_block = false; 00247 if( !recursion_block ) { 00248 recursion_block = true; 00249 QPopupMenu* pMenu = createPopupMenu( 0, KKeySequence(key) ); 00250 connect( pMenu, SIGNAL(activated(int)), this, SLOT(slotActivated(int)) ); 00251 pMenu->exec( QPoint( 0, 0 ) ); 00252 disconnect( pMenu, SIGNAL(activated(int)), this, SLOT(slotActivated(int))); 00253 delete pMenu; 00254 recursion_block = false; 00255 } 00256 } else if( !pAction->objSlotPtr() || !pAction->isEnabled() ) 00257 return false; 00258 else 00259 activate( pAction, KKeySequence(key) ); 00260 00261 return true; 00262 }*/ 00263 00264 void KGlobalAccelPrivate::activate( KAccelAction* pAction, const KKeySequence& seq ) 00265 { 00266 kdDebug(125) << "KGlobalAccelPrivate::activate( \"" << pAction->name() << "\" ) " << endl; 00267 00268 QRegExp rexPassIndex( "([ ]*int[ ]*)" ); 00269 QRegExp rexPassInfo( " QString" ); 00270 QRegExp rexIndex( " ([0-9]+)$" ); 00271 00272 // If the slot to be called accepts an integer index 00273 // and an index is present at the end of the action's name, 00274 // then send the slot the given index #. 00275 if( rexPassIndex.search( pAction->methodSlotPtr() ) >= 0 && rexIndex.search( pAction->name() ) >= 0 ) { 00276 int n = rexIndex.cap(1).toInt(); 00277 kdDebug(125) << "Calling " << pAction->methodSlotPtr() << " int = " << n << endl; 00278 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true ); 00279 if( slot_id >= 0 ) { 00280 QUObject o[2]; 00281 static_QUType_int.set(o+1,n); 00282 const_cast< QObject* >( pAction->objSlotPtr())->qt_invoke( slot_id, o ); 00283 } 00284 } else if( rexPassInfo.search( pAction->methodSlotPtr() ) ) { 00285 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true ); 00286 if( slot_id >= 0 ) { 00287 QUObject o[4]; 00288 static_QUType_QString.set(o+1,pAction->name()); 00289 static_QUType_QString.set(o+2,pAction->label()); 00290 static_QUType_ptr.set(o+3,&seq); 00291 const_cast< QObject* >( pAction->objSlotPtr())->qt_invoke( slot_id, o ); 00292 } 00293 } else { 00294 int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true ); 00295 if( slot_id >= 0 ) 00296 const_cast< QObject* >( pAction->objSlotPtr())->qt_invoke( slot_id, 0 ); 00297 } 00298 } 00299 00300 void KGlobalAccelPrivate::slotActivated( int iAction ) 00301 { 00302 KAccelAction* pAction = actions().actionPtr( iAction ); 00303 if( pAction ) 00304 activate( pAction, KKeySequence() ); 00305 } 00306 00307 #include "kglobalaccel_win.moc" 00308 00309 #endif // !Q_WS_WIN
KDE Logo
This file is part of the documentation for kdecore Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 22:47:34 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003