summaryrefslogtreecommitdiffstats
path: root/khotkeys/shared/windows.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'khotkeys/shared/windows.cpp')
-rw-r--r--khotkeys/shared/windows.cpp376
1 files changed, 376 insertions, 0 deletions
diff --git a/khotkeys/shared/windows.cpp b/khotkeys/shared/windows.cpp
new file mode 100644
index 000000000..d269ef2fe
--- /dev/null
+++ b/khotkeys/shared/windows.cpp
@@ -0,0 +1,376 @@
+/****************************************************************************
+
+ KHotKeys
+
+ Copyright (C) 1999-2001 Lubos Lunak <[email protected]>
+
+ 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 <qregexp.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kwinmodule.h>
+#include <kwin.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, QObject* parent_P )
+ : QObject( parent_P ), signals_enabled( enable_signal_P ),
+ kwin_module( new KWinModule( this )), _action_window( 0 )
+ {
+ assert( windows_handler == NULL );
+ windows_handler = this;
+ if( signals_enabled )
+ {
+ connect( kwin_module, SIGNAL( windowAdded( WId )), SLOT( window_added_slot( WId )));
+ connect( kwin_module, SIGNAL( windowRemoved( WId )), SLOT( window_removed_slot( WId )));
+ connect( kwin_module, SIGNAL( activeWindowChanged( WId )),
+ 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 );
+ }
+
+QString Windows::get_window_role( WId id_P )
+ {
+ // TODO this is probably just a hack
+ return KWin::readNameProperty( id_P, qt_window_role );
+ }
+
+QString Windows::get_window_class( WId id_P )
+ {
+ XClassHint hints_ret;
+ if( XGetClassHint( qt_xdisplay(), id_P, &hints_ret ) == 0 ) // 0 means error
+ return "";
+ QString 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 kwin_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( QValueList< WId >::ConstIterator it = kwin_module->windows().begin();
+ it != kwin_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 kwin_info = KWin::windowInfo( id_P, NET::WMName | NET::WMWindowType ); // TODO optimize
+ if( kwin_info.valid())
+ {
+ title = kwin_info.name();
+ role = windows_handler->get_window_role( id_P );
+ wclass = windows_handler->get_window_class( id_P );
+ type = kwin_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 )
+ {
+ QString 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 )
+ : QPtrList< Windowdef >()
+ {
+ setAutoDelete( true );
+ QString 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 + QString::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
+ {
+ 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( "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 QString& comment_P, const QString& title_P,
+ substr_type_t title_type_P, const QString& wclass_P, substr_type_t wclass_type_P,
+ const QString& 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 QString& str1_P, const QString& 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 :
+ {
+ QRegExp 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 :
+ {
+ QRegExp 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 QString Windowdef_simple::description() const
+ {
+ return i18n( "Window simple: " ) + comment();
+ }
+
+} // namespace KHotKeys
+
+#include "windows.moc"