/**************************************************************************** KHotKeys Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org> Distributed under the terms of the GNU General Public License version 2. ****************************************************************************/ #define _TRIGGERS_CPP_ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include "triggers.h" #include <kglobalaccel.h> #include <kconfig.h> #include <kdebug.h> #include <kwinmodule.h> #include <klocale.h> #include <netwm_def.h> #include <kaccel.h> #include <X11/Xlib.h> #include <X11/keysym.h> #include "actions.h" #include "action_data.h" #include "input.h" #include "gestures.h" #include "windows.h" #include "voices.h" namespace KHotKeys { // Trigger void Trigger::cfg_write( KConfig& cfg_P ) const { cfg_P.writeEntry( "Type", "ERROR" ); } Trigger* Trigger::create_cfg_read( KConfig& cfg_P, Action_data* data_P ) { QString type = cfg_P.readEntry( "Type" ); if( type == "SHORTCUT" || type == "SINGLE_SHORTCUT" ) return new Shortcut_trigger( cfg_P, data_P ); if( type == "WINDOW" ) return new Window_trigger( cfg_P, data_P ); if( type == "GESTURE" ) return new Gesture_trigger(cfg_P, data_P ); if( type == "VOICE" ) return new Voice_trigger (cfg_P, data_P ); kdWarning( 1217 ) << "Unknown Trigger type read from cfg file\n"; return NULL; } // Trigger_list Trigger_list::Trigger_list( KConfig& cfg_P, Action_data* data_P ) : QPtrList< Trigger >() { setAutoDelete( true ); _comment = cfg_P.readEntry( "Comment" ); QString save_cfg_group = cfg_P.group(); int cnt = cfg_P.readNumEntry( "TriggersCount", 0 ); for( int i = 0; i < cnt; ++i ) { cfg_P.setGroup( save_cfg_group + QString::number( i )); Trigger* trigger = Trigger::create_cfg_read( cfg_P, data_P ); if( trigger ) append( trigger ); } cfg_P.setGroup( save_cfg_group ); } void Trigger_list::cfg_write( KConfig& cfg_P ) const { cfg_P.writeEntry( "Comment", comment()); QString save_cfg_group = cfg_P.group(); int i = 0; for( Iterator it( *this ); it; ++it, ++i ) { cfg_P.setGroup( save_cfg_group + QString::number( i )); it.current()->cfg_write( cfg_P ); } cfg_P.setGroup( save_cfg_group ); cfg_P.writeEntry( "TriggersCount", i ); } Trigger_list* Trigger_list::copy( Action_data* data_P ) const { Trigger_list* ret = new Trigger_list( comment()); for( Iterator it( *this ); it; ++it ) ret->append( it.current()->copy( data_P )); return ret; } void Trigger_list::activate( bool activate_P ) { for( Iterator it( *this ); it; ++it ) ( *it )->activate( activate_P ); } // Shortcut_trigger Shortcut_trigger::Shortcut_trigger( Action_data* data_P, const KShortcut& shortcut_P ) : Trigger( data_P ), _shortcut( shortcut_P ) { keyboard_handler->insert_item( shortcut(), this ); } Shortcut_trigger::Shortcut_trigger( KConfig& cfg_P, Action_data* data_P ) : Trigger( cfg_P, data_P ), _shortcut( cfg_P.readEntry( "Key", 0 )) { keyboard_handler->insert_item( shortcut(), this ); } Shortcut_trigger::~Shortcut_trigger() { keyboard_handler->remove_item( shortcut(), this ); } void Shortcut_trigger::cfg_write( KConfig& cfg_P ) const { base::cfg_write( cfg_P ); cfg_P.writeEntry( "Key", _shortcut.toStringInternal()); cfg_P.writeEntry( "Type", "SHORTCUT" ); // overwrites value set in base::cfg_write() } Shortcut_trigger* Shortcut_trigger::copy( Action_data* data_P ) const { kdDebug( 1217 ) << "Shortcut_trigger::copy()" << endl; return new Shortcut_trigger( data_P ? data_P : data, shortcut()); } const QString Shortcut_trigger::description() const { // CHECKME vice mods return i18n( "Shortcut trigger: " ) + _shortcut.toString(); // CHECKME i18n pro toString() ? } bool Shortcut_trigger::handle_key( const KShortcut& shortcut_P ) { if( shortcut() == shortcut_P ) { windows_handler->set_action_window( 0 ); // use active window data->execute(); return true; } return false; } void Shortcut_trigger::activate( bool activate_P ) { if( activate_P && khotkeys_active()) keyboard_handler->activate_receiver( this ); else keyboard_handler->deactivate_receiver( this ); } // Window_trigger Window_trigger::Window_trigger( KConfig& cfg_P, Action_data* data_P ) : Trigger( cfg_P, data_P ), active( false ) { // kdDebug( 1217 ) << "Window_trigger" << endl; QString save_cfg_group = cfg_P.group(); cfg_P.setGroup( save_cfg_group + "Windows" ); _windows = new Windowdef_list( cfg_P ); cfg_P.setGroup( save_cfg_group ); window_actions = cfg_P.readNumEntry( "WindowActions" ); init(); } Window_trigger::~Window_trigger() { // kdDebug( 1217 ) << "~Window_trigger :" << this << endl; disconnect( windows_handler, NULL, this, NULL ); delete _windows; } void Window_trigger::init() { kdDebug( 1217 ) << "Window_trigger::init()" << endl; connect( windows_handler, SIGNAL( window_added( WId )), this, SLOT( window_added( WId ))); connect( windows_handler, SIGNAL( window_removed( WId )), this, SLOT( window_removed( WId ))); if( window_actions & ( WINDOW_ACTIVATES | WINDOW_DEACTIVATES /*| WINDOW_DISAPPEARS*/ )) connect( windows_handler, SIGNAL( active_window_changed( WId )), this, SLOT( active_window_changed( WId ))); connect( windows_handler, SIGNAL( window_changed( WId, unsigned int )), this, SLOT( window_changed( WId, unsigned int ))); } void Window_trigger::activate( bool activate_P ) { active = activate_P && khotkeys_active(); } void Window_trigger::window_added( WId window_P ) { bool matches = windows()->match( Window_data( window_P )); existing_windows[ window_P ] = matches; kdDebug( 1217 ) << "Window_trigger::w_added() : " << matches << endl; if( active && matches && ( window_actions & WINDOW_APPEARS )) { windows_handler->set_action_window( window_P ); data->execute(); } } void Window_trigger::window_removed( WId window_P ) { if( existing_windows.contains( window_P )) { bool matches = existing_windows[ window_P ]; kdDebug( 1217 ) << "Window_trigger::w_removed() : " << matches << endl; if( active && matches && ( window_actions & WINDOW_DISAPPEARS )) { windows_handler->set_action_window( window_P ); data->execute(); } existing_windows.remove( window_P ); // CHECKME jenze co kdyz se window_removed zavola pred active_window_changed ? } else kdDebug( 1217 ) << "Window_trigger::w_removed()" << endl; } void Window_trigger::active_window_changed( WId window_P ) { bool was_match = false; if( existing_windows.contains( last_active_window )) was_match = existing_windows[ last_active_window ]; if( active && was_match && ( window_actions & WINDOW_DEACTIVATES )) { windows_handler->set_action_window( window_P ); data->execute(); } /* bool matches = windows()->match( Window_data( window_P )); existing_windows[ window_P ] = matches;*/ bool matches = existing_windows.contains( window_P ) ? existing_windows[ window_P ] : false; if( active && matches && ( window_actions & WINDOW_ACTIVATES )) { windows_handler->set_action_window( window_P ); data->execute(); } kdDebug( 1217 ) << "Window_trigger::a_w_changed() : " << was_match << "|" << matches << endl; last_active_window = window_P; } void Window_trigger::window_changed( WId window_P, unsigned int dirty_P ) { // CHECKME snad nebude mit vliv, kdyz budu kaslat na properties_P a zkratka // kontrolovat kazdou zmenu // CHECKME kdyz se zmeni okno z match na non-match, asi to nebrat jako DISAPPEAR if( ! ( dirty_P & ( NET::WMName | NET::WMWindowType ))) return; kdDebug( 1217 ) << "Window_trigger::w_changed()" << endl; bool was_match = false; if( existing_windows.contains( window_P )) was_match = existing_windows[ window_P ]; bool matches = windows()->match( Window_data( window_P )); existing_windows[ window_P ] = matches; if( active && matches && !was_match ) if( window_actions & WINDOW_APPEARS ) { windows_handler->set_action_window( window_P ); data->execute(); } else if( window_actions & WINDOW_ACTIVATES && window_P == windows_handler->active_window()) { windows_handler->set_action_window( window_P ); data->execute(); } kdDebug( 1217 ) << "Window_trigger::w_changed() : " << was_match << "|" << matches << endl; } void Window_trigger::cfg_write( KConfig& cfg_P ) const { base::cfg_write( cfg_P ); QString save_cfg_group = cfg_P.group(); cfg_P.setGroup( save_cfg_group + "Windows" ); windows()->cfg_write( cfg_P ); cfg_P.setGroup( save_cfg_group ); cfg_P.writeEntry( "WindowActions", window_actions ); cfg_P.writeEntry( "Type", "WINDOW" ); // overwrites value set in base::cfg_write() } #ifndef COVARIANT_RETURN_BROKEN // stupid gcc, it doesn't even warn it can't do this Window_trigger* Window_trigger::copy( Action_data* data_P ) const #else Trigger* Window_trigger::copy( Action_data* data_P ) const #endif { Window_trigger* ret = new Window_trigger( data_P ? data_P : data, windows()->copy(), window_actions ); ret->existing_windows = existing_windows; // CHECKME je tohle vazne treba ? return ret; } const QString Window_trigger::description() const { return i18n( "Window trigger: " ) + windows()->comment(); } // Gesture_trigger Gesture_trigger::Gesture_trigger( Action_data* data_P, const QString &gesturecode_P ) : Trigger( data_P ), _gesturecode( gesturecode_P ) { } Gesture_trigger::Gesture_trigger( KConfig& cfg_P, Action_data* data_P ) : Trigger( cfg_P, data_P ) { _gesturecode = cfg_P.readEntry( "Gesture" ); } Gesture_trigger::~Gesture_trigger() { gesture_handler->unregister_handler( this, SLOT( handle_gesture( const QString&, WId ))); } void Gesture_trigger::cfg_write( KConfig& cfg_P ) const { base::cfg_write( cfg_P ); cfg_P.writeEntry( "Gesture", gesturecode()); cfg_P.writeEntry( "Type", "GESTURE" ); // overwrites value set in base::cfg_write() } Trigger* Gesture_trigger::copy( Action_data* data_P ) const { kdDebug( 1217 ) << "Gesture_trigger::copy()" << endl; return new Gesture_trigger( data_P ? data_P : data, gesturecode()); } const QString Gesture_trigger::description() const { return i18n( "Gesture trigger: " ) + gesturecode(); } void Gesture_trigger::handle_gesture( const QString &gesture_P, WId window_P ) { if( gesturecode() == gesture_P ) { windows_handler->set_action_window( window_P ); data->execute(); } } void Gesture_trigger::activate( bool activate_P ) { if( activate_P ) gesture_handler->register_handler( this, SLOT( handle_gesture( const QString&, WId ))); else gesture_handler->unregister_handler( this, SLOT( handle_gesture( const QString&, WId ))); } // Voice_trigger Voice_trigger::Voice_trigger( Action_data* data_P, const QString &Voicecode_P, const VoiceSignature& signature1_P, const VoiceSignature& signature2_P ) : Trigger( data_P ), _voicecode( Voicecode_P ) { _voicesignature[0]=signature1_P; _voicesignature[1]=signature2_P; } Voice_trigger::Voice_trigger( KConfig& cfg_P, Action_data* data_P ) : Trigger( cfg_P, data_P ) { _voicecode = cfg_P.readEntry( "Name" ); _voicesignature[0].read( &cfg_P , "Signature1" ); _voicesignature[1].read( &cfg_P , "Signature2" ); } Voice_trigger::~Voice_trigger() { voice_handler->unregister_handler( this ); } void Voice_trigger::cfg_write( KConfig& cfg_P ) const { base::cfg_write( cfg_P ); cfg_P.writeEntry( "Name", voicecode()); cfg_P.writeEntry( "Type", "VOICE" ); // overwrites value set in base::cfg_write() _voicesignature[0].write( &cfg_P , "Signature1" ); _voicesignature[1].write( &cfg_P , "Signature2" ); } Trigger* Voice_trigger::copy( Action_data* data_P ) const { kdDebug( 1217 ) << "Voice_trigger::copy()" << endl; return new Voice_trigger( data_P ? data_P : data, voicecode(), voicesignature(1) , voicesignature(2) ); } const QString Voice_trigger::description() const { return i18n( "Voice trigger: " ) + voicecode(); } void Voice_trigger::handle_Voice( ) { windows_handler->set_action_window( 0 ); // use active window data->execute(); } void Voice_trigger::activate( bool activate_P ) { if( activate_P && khotkeys_active()) voice_handler->register_handler( this ); else voice_handler->unregister_handler( this ); } } // namespace KHotKeys #include "triggers.moc"