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/windows.cpp

377 lines
10 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 _WINDOWS_CPP_
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "windows.h"
#include <assert.h>
#include <tqregexp.h>
#include <kconfig.h>
#include <kdebug.h>
#include <twinmodule.h>
#include <twin.h>
#include <klocale.h>
#include "khotkeysglobal.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
extern Atom qt_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, qt_window_role );
}
TQString Windows::get_window_class( WId id_P )
{
XClassHint hints_ret;
if( XGetClassHint( qt_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 = qt_xrootwin();
Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False );
for( int i = 0;
i < 10;
++i )
{
int destx, desty;
// find child at that position
if( !XTranslateCoordinates( qt_xdisplay(), parent, parent, x, y, &destx, &desty, &child )
|| child == None )
return 0;
// and now transform coordinates to the child
if( !XTranslateCoordinates( qt_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( qt_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( KConfig& cfg_P ) const
{
cfg_P.writeEntry( "Type", "ERROR" );
cfg_P.writeEntry( "Comment", comment());
}
Windowdef::Windowdef( KConfig& cfg_P )
{
_comment = cfg_P.readEntry( "Comment" );
}
Windowdef* Windowdef::create_cfg_read( KConfig& 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( KConfig& 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( KConfig& 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( KConfig& 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( KConfig& 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"