• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
kglobalaccel_win.cpp
1 /* This file is part of the KDE libraries
2  Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include "config.h"
21 
22 #include <tqwindowdefs.h>
23 #ifdef Q_WS_WIN
24 
25 #include "kglobalaccel_win.h"
26 #include "kglobalaccel.h"
27 #include "kkeyserver_x11.h"
28 
29 #include <tqpopupmenu.h>
30 #include <tqregexp.h>
31 #include <tqwidget.h>
32 #include <tqmetaobject.h>
33 #include <private/qucomextra_p.h>
34 #include <tdeapplication.h>
35 #include <kdebug.h>
36 #include <kkeynative.h>
37 
38 //----------------------------------------------------
39 
40 static TQValueList< TDEGlobalAccelPrivate* >* all_accels = 0;
41 
42 TDEGlobalAccelPrivate::TDEGlobalAccelPrivate()
43 : TDEAccelBase( TDEAccelBase::NATIVE_KEYS )
44 , m_blocked( false )
45 , m_blockingDisabled( false )
46 {
47  if( all_accels == NULL )
48  all_accels = new TQValueList< TDEGlobalAccelPrivate* >;
49  all_accels->append( this );
50  m_sConfigGroup = "Global Shortcuts";
51 // kapp->installX11EventFilter( this );
52 }
53 
54 TDEGlobalAccelPrivate::~TDEGlobalAccelPrivate()
55 {
56  // TODO: Need to release all grabbed keys if the main window is not shutting down.
57  //for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
58  // const CodeMod& codemod = it.key();
59  //}
60  all_accels->remove( this );
61  if( all_accels->count() == 0 ) {
62  delete all_accels;
63  all_accels = NULL;
64  }
65 }
66 
67 void TDEGlobalAccelPrivate::setEnabled( bool bEnable )
68 {
69  m_bEnabled = bEnable;
70  //updateConnections();
71 }
72 
73 void TDEGlobalAccelPrivate::blockShortcuts( bool block )
74 {
75  if( all_accels == NULL )
76  return;
77  for( TQValueList< TDEGlobalAccelPrivate* >::ConstIterator it = all_accels->begin();
78  it != all_accels->end();
79  ++it ) {
80  if( (*it)->m_blockingDisabled )
81  continue;
82  (*it)->m_blocked = block;
83  (*it)->updateConnections();
84  }
85 }
86 
87 void TDEGlobalAccelPrivate::disableBlocking( bool block )
88 {
89  m_blockingDisabled = block;
90 }
91 
92 bool TDEGlobalAccelPrivate::isEnabledInternal() const
93 {
94  return TDEAccelBase::isEnabled() && !m_blocked;
95 }
96 
97 bool TDEGlobalAccelPrivate::emitSignal( Signal )
98 {
99  return false;
100 }
101 
102 bool TDEGlobalAccelPrivate::connectKey( TDEAccelAction& action, const KKeyServer::Key& key )
103  { return grabKey( key, true, &action ); }
104 bool TDEGlobalAccelPrivate::connectKey( const KKeyServer::Key& key )
105  { return grabKey( key, true, 0 ); }
106 bool TDEGlobalAccelPrivate::disconnectKey( TDEAccelAction& action, const KKeyServer::Key& key )
107  { return grabKey( key, false, &action ); }
108 bool TDEGlobalAccelPrivate::disconnectKey( const KKeyServer::Key& key )
109  { return grabKey( key, false, 0 ); }
110 
111 bool TDEGlobalAccelPrivate::grabKey( const KKeyServer::Key& key, bool bGrab, TDEAccelAction* pAction )
112 {
113  /*
114  if( !key.code() ) {
115  kdWarning(125) << "TDEGlobalAccelPrivate::grabKey( " << key.key().toStringInternal() << ", " << bGrab << ", \"" << (pAction ? pAction->name().latin1() : "(null)") << "\" ): Tried to grab key with null code." << endl;
116  return false;
117  }
118 
119  // Make sure that grab masks have been initialized.
120  if( g_keyModMaskXOnOrOff == 0 )
121  calculateGrabMasks();
122 
123  uchar keyCodeX = key.code();
124  uint keyModX = key.mod() & g_keyModMaskXAccel; // Get rid of any non-relevant bits in mod
125  // HACK: make Alt+Print work
126  if( key.sym() == XK_Sys_Req ) {
127  keyModX |= KKeyServer::modXAlt();
128  keyCodeX = 111;
129  }
130 
131  kdDebug(125) << TQString( "grabKey( key: '%1', bGrab: %2 ): keyCodeX: %3 keyModX: %4\n" )
132  .arg( key.key().toStringInternal() ).arg( bGrab )
133  .arg( keyCodeX, 0, 16 ).arg( keyModX, 0, 16 );
134  if( !keyCodeX )
135  return false;
136 
137  // We'll have to grab 8 key modifier combinations in order to cover all
138  // combinations of CapsLock, NumLock, ScrollLock.
139  // Does anyone with more X-savvy know how to set a mask on tqt_xrootwin so that
140  // the irrelevant bits are always ignored and we can just make one XGrabKey
141  // call per accelerator? -- ellis
142 #ifndef NDEBUG
143  TQString sDebug = TQString("\tcode: 0x%1 state: 0x%2 | ").arg(keyCodeX,0,16).arg(keyModX,0,16);
144 #endif
145  uint keyModMaskX = ~g_keyModMaskXOnOrOff;
146  for( uint irrelevantBitsMask = 0; irrelevantBitsMask <= 0xff; irrelevantBitsMask++ ) {
147  if( (irrelevantBitsMask & keyModMaskX) == 0 ) {
148 #ifndef NDEBUG
149  sDebug += TQString("0x%3, ").arg(irrelevantBitsMask, 0, 16);
150 #endif
151  if( bGrab )
152  XGrabKey( tqt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask,
153  tqt_xrootwin(), True, GrabModeAsync, GrabModeSync );
154  else
155  XUngrabKey( tqt_xdisplay(), keyCodeX, keyModX | irrelevantBitsMask, tqt_xrootwin() );
156  }
157  }
158 #ifndef NDEBUG
159  kdDebug(125) << sDebug << endl;
160 #endif
161 
162  bool failed = false;
163  if( bGrab ) {
164 #ifdef Q_WS_X11
165  failed = handler.error( true ); // sync now
166 #endif
167  // If grab failed, then ungrab any grabs that could possibly succeed
168  if( failed ) {
169  kdDebug(125) << "grab failed!\n";
170  for( uint m = 0; m <= 0xff; m++ ) {
171  if( m & keyModMaskX == 0 )
172  XUngrabKey( tqt_xdisplay(), keyCodeX, keyModX | m, tqt_xrootwin() );
173  }
174  }
175  }
176  if( !failed )
177  {
178  CodeMod codemod;
179  codemod.code = keyCodeX;
180  codemod.mod = keyModX;
181  if( key.mod() & KKeyServer::MODE_SWITCH )
182  codemod.mod |= KKeyServer::MODE_SWITCH;
183 
184  if( bGrab )
185  m_rgCodeModToAction.insert( codemod, pAction );
186  else
187  m_rgCodeModToAction.remove( codemod );
188  }
189  return !failed;*/
190  return false;
191 }
192 
193 /*bool TDEGlobalAccelPrivate::x11Event( XEvent* pEvent )
194 {
195  //kdDebug(125) << "x11EventFilter( type = " << pEvent->type << " )" << endl;
196  switch( pEvent->type ) {
197  case MappingNotify:
198  XRefreshKeyboardMapping( &pEvent->xmapping );
199  x11MappingNotify();
200  return false;
201  case XKeyPress:
202  if( x11KeyPress( pEvent ) )
203  return true;
204  default:
205  return TQWidget::x11Event( pEvent );
206  }
207 }
208 
209 void TDEGlobalAccelPrivate::x11MappingNotify()
210 {
211  kdDebug(125) << "TDEGlobalAccelPrivate::x11MappingNotify()" << endl;
212  if( m_bEnabled ) {
213  // Maybe the X modifier map has been changed.
214  KKeyServer::initializeMods();
215  calculateGrabMasks();
216  // Do new XGrabKey()s.
217  updateConnections();
218  }
219 }
220 
221 bool TDEGlobalAccelPrivate::x11KeyPress( const XEvent *pEvent )
222 {
223  // do not change this line unless you really really know what you are doing (Matthias)
224  if ( !TQWidget::keyboardGrabber() && !TQApplication::activePopupWidget() ) {
225  XUngrabKeyboard( tqt_xdisplay(), pEvent->xkey.time );
226  XFlush( tqt_xdisplay()); // avoid X(?) bug
227  }
228 
229  if( !m_bEnabled )
230  return false;
231 
232  CodeMod codemod;
233  codemod.code = pEvent->xkey.keycode;
234  codemod.mod = pEvent->xkey.state & (g_keyModMaskXAccel | KKeyServer::MODE_SWITCH);
235 
236  // If numlock is active and a keypad key is pressed, XOR the SHIFT state.
237  // e.g., KP_4 => Shift+KP_Left, and Shift+KP_4 => KP_Left.
238  if( pEvent->xkey.state & KKeyServer::modXNumLock() ) {
239  // TODO: what's the xor operator in c++?
240  uint sym = XkbKeycodeToKeysym( tqt_xdisplay(), codemod.code, 0, 0 );
241  // If this is a keypad key,
242  if( sym >= XK_KP_Space && sym <= XK_KP_9 ) {
243  switch( sym ) {
244  // Leave the following keys unaltered
245  // FIXME: The proper solution is to see which keysyms don't change when shifted.
246  case XK_KP_Multiply:
247  case XK_KP_Add:
248  case XK_KP_Subtract:
249  case XK_KP_Divide:
250  break;
251  default:
252  if( codemod.mod & KKeyServer::modXShift() )
253  codemod.mod &= ~KKeyServer::modXShift();
254  else
255  codemod.mod |= KKeyServer::modXShift();
256  }
257  }
258  }
259 
260  KKeyNative keyNative( pEvent );
261  KKey key = keyNative;
262 
263  kdDebug(125) << "x11KeyPress: seek " << key.toStringInternal()
264  << TQString( " keyCodeX: %1 state: %2 keyModX: %3" )
265  .arg( codemod.code, 0, 16 ).arg( pEvent->xkey.state, 0, 16 ).arg( codemod.mod, 0, 16 ) << endl;
266 
267  // Search for which accelerator activated this event:
268  if( !m_rgCodeModToAction.contains( codemod ) ) {
269 #ifndef NDEBUG
270  for( CodeModMap::ConstIterator it = m_rgCodeModToAction.begin(); it != m_rgCodeModToAction.end(); ++it ) {
271  TDEAccelAction* pAction = *it;
272  kdDebug(125) << "\tcode: " << TQString::number(it.key().code, 16) << " mod: " << TQString::number(it.key().mod, 16)
273  << (pAction ? TQString(" name: \"%1\" shortcut: %2").arg(pAction->name()).arg(pAction->shortcut().toStringInternal()) : TQString::null)
274  << endl;
275  }
276 #endif
277  return false;
278  }
279  TDEAccelAction* pAction = m_rgCodeModToAction[codemod];
280 
281  if( !pAction ) {
282  static bool recursion_block = false;
283  if( !recursion_block ) {
284  recursion_block = true;
285  TQPopupMenu* pMenu = createPopupMenu( 0, KKeySequence(key) );
286  connect( pMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotActivated(int)) );
287  pMenu->exec( TQPoint( 0, 0 ) );
288  disconnect( pMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotActivated(int)));
289  delete pMenu;
290  recursion_block = false;
291  }
292  } else if( !pAction->objSlotPtr() || !pAction->isEnabled() )
293  return false;
294  else
295  activate( pAction, KKeySequence(key) );
296 
297  return true;
298 }*/
299 
300 void TDEGlobalAccelPrivate::activate( TDEAccelAction* pAction, const KKeySequence& seq )
301 {
302  kdDebug(125) << "TDEGlobalAccelPrivate::activate( \"" << pAction->name() << "\" ) " << endl;
303 
304  TQRegExp rexPassIndex( "([ ]*int[ ]*)" );
305  TQRegExp rexPassInfo( " TQString" );
306  TQRegExp rexIndex( " ([0-9]+)$" );
307 
308  // If the slot to be called accepts an integer index
309  // and an index is present at the end of the action's name,
310  // then send the slot the given index #.
311  if( rexPassIndex.search( pAction->methodSlotPtr() ) >= 0 && rexIndex.search( pAction->name() ) >= 0 ) {
312  int n = rexIndex.cap(1).toInt();
313  kdDebug(125) << "Calling " << pAction->methodSlotPtr() << " int = " << n << endl;
314  int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
315  if( slot_id >= 0 ) {
316  QUObject o[2];
317  static_QUType_int.set(o+1,n);
318  const_cast< TQObject* >( pAction->objSlotPtr())->tqt_invoke( slot_id, o );
319  }
320  } else if( rexPassInfo.search( pAction->methodSlotPtr() ) ) {
321  int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
322  if( slot_id >= 0 ) {
323  QUObject o[4];
324  static_QUType_QString.set(o+1,pAction->name());
325  static_QUType_QString.set(o+2,pAction->label());
326  static_QUType_ptr.set(o+3,&seq);
327  const_cast< TQObject* >( pAction->objSlotPtr())->tqt_invoke( slot_id, o );
328  }
329  } else {
330  int slot_id = pAction->objSlotPtr()->metaObject()->findSlot( normalizeSignalSlot( pAction->methodSlotPtr() ).data() + 1, true );
331  if( slot_id >= 0 )
332  const_cast< TQObject* >( pAction->objSlotPtr())->tqt_invoke( slot_id, 0 );
333  }
334 }
335 
336 void TDEGlobalAccelPrivate::slotActivated( int iAction )
337 {
338  TDEAccelAction* pAction = actions().actionPtr( iAction );
339  if( pAction )
340  activate( pAction, KKeySequence() );
341 }
342 
343 #include "kglobalaccel_win.moc"
344 
345 #endif // !Q_WS_WIN
TDEGlobal::kdDebug
kdbgstream kdDebug(int area=0)
Definition: kdebug.cpp:369
KKeySequence
A KKeySequence object holds a sequence of up to 4 keys.
Definition: tdeshortcut.h:288
KKeyServer::Key
Represents a key press.
Definition: kkeyserver_x11.h:137
TDEGlobal::endl
kdbgstream & endl(kdbgstream &s)
Definition: kdebug.h:430

tdecore

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

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.8.8
This website is maintained by Timothy Pearson.