You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/khotkeys/shared/triggers.cpp

436 lines
13 KiB

/****************************************************************************
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 )
{
TQString 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 )
: TQPtrList< Trigger >()
{
setAutoDelete( true );
_comment = cfg_P.readEntry( "Comment" );
TQString 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 + TQString::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());
TQString save_cfg_group = cfg_P.group();
int i = 0;
for( Iterator it( *this );
it;
++it, ++i )
{
cfg_P.setGroup( save_cfg_group + TQString::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 TQString 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;
TQString 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, TQT_SIGNAL( window_added( WId )), this, TQT_SLOT( window_added( WId )));
connect( windows_handler, TQT_SIGNAL( window_removed( WId )), this, TQT_SLOT( window_removed( WId )));
if( window_actions & ( WINDOW_ACTIVATES | WINDOW_DEACTIVATES /*| WINDOW_DISAPPEARS*/ ))
connect( windows_handler, TQT_SIGNAL( active_window_changed( WId )),
this, TQT_SLOT( active_window_changed( WId )));
connect( windows_handler, TQT_SIGNAL( window_changed( WId, unsigned int )),
this, TQT_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 );
TQString 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 TQString Window_trigger::description() const
{
return i18n( "Window trigger: " ) + windows()->comment();
}
// Gesture_trigger
Gesture_trigger::Gesture_trigger( Action_data* data_P, const TQString &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, TQT_SLOT( handle_gesture( const TQString&, 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 TQString Gesture_trigger::description() const
{
return i18n( "Gesture trigger: " ) + gesturecode();
}
void Gesture_trigger::handle_gesture( const TQString &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, TQT_SLOT( handle_gesture( const TQString&, WId )));
else
gesture_handler->unregister_handler( this, TQT_SLOT( handle_gesture( const TQString&, WId )));
}
// Voice_trigger
Voice_trigger::Voice_trigger( Action_data* data_P, const TQString &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 TQString 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"