/**************************************************************************** KHotKeys Copyright (C) 1999-2001 Lubos Lunak Distributed under the terms of the GNU General Public License version 2. ****************************************************************************/ #define _WINDOWS_CPP_ #ifdef HAVE_CONFIG_H #include #endif #include "windows.h" #include #include #include #include #include #include #include #include "khotkeysglobal.h" #include #include extern Atom tqt_window_role; namespace KHotKeys { // Windows Windows::Windows( bool enable_signal_P, TQObject* parent_P ) : TQObject( parent_P ), signals_enabled( enable_signal_P ), twin_module( new KWinModule( this )), _action_window( 0 ) { assert( windows_handler == NULL ); windows_handler = this; if( signals_enabled ) { connect( twin_module, TQT_SIGNAL( windowAdded( WId )), TQT_SLOT( window_added_slot( WId ))); connect( twin_module, TQT_SIGNAL( windowRemoved( WId )), TQT_SLOT( window_removed_slot( WId ))); connect( twin_module, TQT_SIGNAL( activeWindowChanged( WId )), TQT_SLOT( active_window_changed_slot( WId ))); } } Windows::~Windows() { windows_handler = NULL; } void Windows::window_added_slot( WId window_P ) { if( signals_enabled ) emit window_added( window_P ); // CHECKME tyhle i dalsi by asi mely jit nastavit, jestli aktivuji vsechny, nebo jen jeden // pripojeny slot ( stejne jako u Kdb, kde by to take melo jit nastavit ) } void Windows::window_removed_slot( WId window_P ) { if( signals_enabled ) emit window_removed( window_P ); if( window_P == _action_window ) _action_window = 0; } void Windows::active_window_changed_slot( WId window_P ) { if( signals_enabled ) emit active_window_changed( window_P ); } void Windows::window_changed_slot( WId window_P ) { if( signals_enabled ) emit window_changed( window_P ); } void Windows::window_changed_slot( WId window_P, unsigned int flags_P ) { if( signals_enabled ) emit window_changed( window_P, flags_P ); } TQString Windows::get_window_role( WId id_P ) { // TODO this is probably just a hack return KWin::readNameProperty( id_P, tqt_window_role ); } TQString Windows::get_window_class( WId id_P ) { XClassHint hints_ret; if( XGetClassHint( tqt_xdisplay(), id_P, &hints_ret ) == 0 ) // 0 means error return ""; TQString ret( hints_ret.res_name ); ret += ' '; ret += hints_ret.res_class; XFree( hints_ret.res_name ); XFree( hints_ret.res_class ); return ret; } WId Windows::active_window() { return twin_module->activeWindow(); } WId Windows::action_window() { return _action_window; } void Windows::set_action_window( WId window_P ) { _action_window = window_P; } WId Windows::find_window( const Windowdef_list* window_P ) { for( TQValueList< WId >::ConstIterator it = twin_module->windows().begin(); it != twin_module->windows().end(); ++it ) { Window_data tmp( *it ); if( window_P->match( tmp )) return *it; } return None; } WId Windows::window_at_position( int x, int y ) { Window child, dummy; Window parent = tqt_xrootwin(); Atom wm_state = XInternAtom( tqt_xdisplay(), "WM_STATE", False ); for( int i = 0; i < 10; ++i ) { int destx, desty; // find child at that position if( !XTranslateCoordinates( tqt_xdisplay(), parent, parent, x, y, &destx, &desty, &child ) || child == None ) return 0; // and now transform coordinates to the child if( !XTranslateCoordinates( tqt_xdisplay(), parent, child, x, y, &destx, &desty, &dummy )) return 0; x = destx; y = desty; Atom type; int format; unsigned long nitems, after; unsigned char* prop; if( XGetWindowProperty( tqt_xdisplay(), child, wm_state, 0, 0, False, AnyPropertyType, &type, &format, &nitems, &after, &prop ) == Success ) { if( prop != NULL ) XFree( prop ); if( type != None ) return child; } parent = child; } return 0; } void Windows::activate_window( WId id_P ) { KWin::forceActiveWindow( id_P ); } // Window_data Window_data::Window_data( WId id_P ) : type( NET::Unknown ) { KWin::WindowInfo twin_info = KWin::windowInfo( id_P, NET::WMName | NET::WMWindowType ); // TODO optimize if( twin_info.valid()) { title = twin_info.name(); role = windows_handler->get_window_role( id_P ); wclass = windows_handler->get_window_class( id_P ); type = twin_info.windowType( SUPPORTED_WINDOW_TYPES_MASK ); if( type == NET::Override ) // HACK consider non-NETWM fullscreens to be normal too type = NET::Normal; if( type == NET::Unknown ) type = NET::Normal; } } // Windowdef void Windowdef::cfg_write( TDEConfig& cfg_P ) const { cfg_P.writeEntry( "Type", "ERROR" ); cfg_P.writeEntry( "Comment", comment()); } Windowdef::Windowdef( TDEConfig& cfg_P ) { _comment = cfg_P.readEntry( "Comment" ); } Windowdef* Windowdef::create_cfg_read( TDEConfig& cfg_P ) { TQString type = cfg_P.readEntry( "Type" ); if( type == "SIMPLE" ) return new Windowdef_simple( cfg_P ); kdWarning( 1217 ) << "Unknown Windowdef type read from cfg file\n"; return NULL; } // Windowdef_list Windowdef_list::Windowdef_list( TDEConfig& cfg_P ) : TQPtrList< Windowdef >() { setAutoDelete( true ); TQString save_cfg_group = cfg_P.group(); _comment = cfg_P.readEntry( "Comment" ); int cnt = cfg_P.readNumEntry( "WindowsCount", 0 ); for( int i = 0; i < cnt; ++i ) { cfg_P.setGroup( save_cfg_group + TQString::number( i )); Windowdef* window = Windowdef::create_cfg_read( cfg_P ); if( window ) append( window ); } cfg_P.setGroup( save_cfg_group ); } void Windowdef_list::cfg_write( TDEConfig& cfg_P ) const { 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( "WindowsCount", i ); cfg_P.writeEntry( "Comment", comment()); } Windowdef_list* Windowdef_list::copy() const { Windowdef_list* ret = new Windowdef_list( comment()); for( Iterator it( *this ); it; ++it ) ret->append( it.current()->copy()); return ret; } bool Windowdef_list::match( const Window_data& window_P ) const { if( count() == 0 ) // CHECKME no windows to match => ok return true; for( Iterator it( *this ); it; ++it ) if( it.current()->match( window_P )) return true; return false; } // Windowdef_simple Windowdef_simple::Windowdef_simple( const TQString& comment_P, const TQString& title_P, substr_type_t title_type_P, const TQString& wclass_P, substr_type_t wclass_type_P, const TQString& role_P, substr_type_t role_type_P, int window_types_P ) : Windowdef( comment_P ), _title( title_P ), title_type( title_type_P ), _wclass( wclass_P ), wclass_type( wclass_type_P ), _role( role_P ), role_type( role_type_P ), _window_types( window_types_P ) { } Windowdef_simple::Windowdef_simple( TDEConfig& cfg_P ) : Windowdef( cfg_P ) { _title = cfg_P.readEntry( "Title" ); title_type = static_cast< substr_type_t >( cfg_P.readNumEntry( "TitleType" )); _wclass = cfg_P.readEntry( "Class" ); wclass_type = static_cast< substr_type_t >( cfg_P.readNumEntry( "ClassType" )); _role = cfg_P.readEntry( "Role" ); role_type = static_cast< substr_type_t >( cfg_P.readNumEntry( "RoleType" )); _window_types = cfg_P.readNumEntry( "WindowTypes" ); } void Windowdef_simple::cfg_write( TDEConfig& cfg_P ) const { base::cfg_write( cfg_P ); cfg_P.writeEntry( "Title", title()); cfg_P.writeEntry( "TitleType", title_type ); cfg_P.writeEntry( "Class", wclass()); cfg_P.writeEntry( "ClassType", wclass_type ); cfg_P.writeEntry( "Role", role()); cfg_P.writeEntry( "RoleType", role_type ); cfg_P.writeEntry( "WindowTypes", window_types()); cfg_P.writeEntry( "Type", "SIMPLE" ); // overwrites value set in base::cfg_write() } bool Windowdef_simple::match( const Window_data& window_P ) { if( !type_match( window_P.type )) return false; if( !is_substr_match( window_P.title, title(), title_type )) return false; if( !is_substr_match( window_P.wclass, wclass(), wclass_type )) return false; if( !is_substr_match( window_P.role, role(), role_type )) return false; kdDebug( 1217 ) << "window match:" << window_P.title << ":OK" << endl; return true; } bool Windowdef_simple::is_substr_match( const TQString& str1_P, const TQString& str2_P, substr_type_t type_P ) { switch( type_P ) { case NOT_IMPORTANT : return true; case CONTAINS : return str1_P.contains( str2_P ) > 0; case IS : return str1_P == str2_P; case REGEXP : { TQRegExp rg( str2_P ); return rg.search( str1_P ) >= 0; } case CONTAINS_NOT : return str1_P.contains( str2_P ) == 0; case IS_NOT : return str1_P != str2_P; case REGEXP_NOT : { TQRegExp rg( str2_P ); return rg.search( str1_P ) < 0; } } return false; } Windowdef* Windowdef_simple::copy() const { return new Windowdef_simple( comment(), title(), title_match_type(), wclass(), wclass_match_type(), role(), role_match_type(), window_types()); } const TQString Windowdef_simple::description() const { return i18n( "Window simple: " ) + comment(); } } // namespace KHotKeys #include "windows.moc"