not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / khotkeys / libkhotkeysprivate / windows.cpp
blobb96ceaccff98ef7dd007747e82d3302eabb76f8f
1 /****************************************************************************
3 KHotKeys
5 Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
7 Distributed under the terms of the GNU General Public License version 2.
9 ****************************************************************************/
11 #define _WINDOWS_CPP_
13 #include "windows.h"
15 #include <assert.h>
16 #include <QRegExp>
17 #include <Q3PtrList>
19 #include <kconfig.h>
20 #include <kconfiggroup.h>
21 #include <kdebug.h>
22 #include <kwindowsystem.h>
23 #include <klocale.h>
25 #include "khotkeysglobal.h"
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include <QX11Info>
31 namespace KHotKeys
34 // Windows
36 Windows::Windows( bool enable_signal_P, QObject* parent_P )
37 : QObject( parent_P ), signals_enabled( enable_signal_P ),
38 _action_window( 0 )
40 if( signals_enabled )
42 connect( KWindowSystem::self(), SIGNAL( windowAdded( WId )), SLOT( window_added_slot( WId )));
43 connect( KWindowSystem::self(), SIGNAL( windowRemoved( WId )), SLOT( window_removed_slot( WId )));
44 connect( KWindowSystem::self(), SIGNAL( activeWindowChanged( WId )),
45 SLOT( active_window_changed_slot( WId )));
49 Windows::~Windows()
53 void Windows::window_added_slot( WId window_P )
55 if( signals_enabled )
56 emit window_added( window_P );
57 // CHECKME tyhle i dalsi by asi mely jit nastavit, jestli aktivuji vsechny, nebo jen jeden
58 // pripojeny slot ( stejne jako u Kdb, kde by to take melo jit nastavit )
61 void Windows::window_removed_slot( WId window_P )
63 if( signals_enabled )
64 emit window_removed( window_P );
65 if( window_P == _action_window )
66 _action_window = 0;
69 void Windows::active_window_changed_slot( WId window_P )
71 if( signals_enabled )
72 emit active_window_changed( window_P );
75 void Windows::window_changed_slot( WId window_P )
77 if( signals_enabled )
78 emit window_changed( window_P );
81 void Windows::window_changed_slot( WId window_P, unsigned int flags_P )
83 if( signals_enabled )
84 emit window_changed( window_P, flags_P );
87 QString Windows::get_window_role( WId id_P )
89 // TODO this is probably just a hack
90 return KWindowSystem::windowInfo( id_P, 0, NET::WM2WindowRole ).windowRole();
93 QString Windows::get_window_class( WId id_P )
95 XClassHint hints_ret;
96 if( XGetClassHint( QX11Info::display(), id_P, &hints_ret ) == 0 ) // 0 means error
97 return "";
98 QString ret( hints_ret.res_name );
99 ret += ' ';
100 ret += hints_ret.res_class;
101 XFree( hints_ret.res_name );
102 XFree( hints_ret.res_class );
103 return ret;
106 WId Windows::active_window()
108 return KWindowSystem::activeWindow();
111 WId Windows::action_window()
113 return _action_window;
116 void Windows::set_action_window( WId window_P )
118 _action_window = window_P;
121 WId Windows::find_window( const Windowdef_list* window_P )
123 for( QList< WId >::const_iterator it = KWindowSystem::windows().begin();
124 it != KWindowSystem::windows().end();
125 ++it )
127 Window_data tmp( *it );
128 if( window_P->match( tmp ))
129 return *it;
131 return None;
134 WId Windows::window_at_position( int x, int y )
136 Window child, dummy;
137 Window parent = QX11Info::appRootWindow();
138 Atom wm_state = XInternAtom( QX11Info::display(), "WM_STATE", False );
139 for( int i = 0;
140 i < 10;
141 ++i )
143 int destx, desty;
144 // find child at that position
145 if( !XTranslateCoordinates( QX11Info::display(), parent, parent, x, y, &destx, &desty, &child )
146 || child == None )
147 return 0;
148 // and now transform coordinates to the child
149 if( !XTranslateCoordinates( QX11Info::display(), parent, child, x, y, &destx, &desty, &dummy ))
150 return 0;
151 x = destx;
152 y = desty;
153 Atom type;
154 int format;
155 unsigned long nitems, after;
156 unsigned char* prop;
157 if( XGetWindowProperty( QX11Info::display(), child, wm_state, 0, 0, False, AnyPropertyType,
158 &type, &format, &nitems, &after, &prop ) == Success )
160 if( prop != NULL )
161 XFree( prop );
162 if( type != None )
163 return child;
165 parent = child;
167 return 0;
171 void Windows::activate_window( WId id_P )
173 KWindowSystem::forceActiveWindow( id_P );
176 // Window_data
178 Window_data::Window_data( WId id_P )
179 : type( NET::Unknown )
181 KWindowInfo kwin_info = KWindowSystem::windowInfo( id_P, NET::WMName | NET::WMWindowType ); // TODO optimize
182 if( kwin_info.valid())
184 title = kwin_info.name();
185 role = windows_handler->get_window_role( id_P );
186 wclass = windows_handler->get_window_class( id_P );
187 type = kwin_info.windowType( SUPPORTED_WINDOW_TYPES_MASK );
188 if( type == NET::Override ) // HACK consider non-NETWM fullscreens to be normal too
189 type = NET::Normal;
190 if( type == NET::Unknown )
191 type = NET::Normal;
195 // Windowdef
197 void Windowdef::cfg_write( KConfigGroup& cfg_P ) const
199 cfg_P.writeEntry( "Type", "ERROR" );
200 cfg_P.writeEntry( "Comment", comment());
203 Windowdef::Windowdef( KConfigGroup& cfg_P )
205 _comment = cfg_P.readEntry( "Comment" );
208 Windowdef* Windowdef::create_cfg_read( KConfigGroup& cfg_P )
210 QString type = cfg_P.readEntry( "Type" );
211 if( type == "SIMPLE" )
212 return new Windowdef_simple( cfg_P );
213 kWarning() << "Unknown Windowdef type read from cfg file\n";
214 return NULL;
217 // Windowdef_list
219 Windowdef_list::Windowdef_list( KConfigGroup& cfg_P )
220 : Q3PtrList< Windowdef >()
222 setAutoDelete( true );
223 _comment = cfg_P.readEntry( "Comment" );
224 int cnt = cfg_P.readEntry( "WindowsCount", 0 );
225 for( int i = 0;
226 i < cnt;
227 ++i )
229 KConfigGroup windowGroup( cfg_P.config(), cfg_P.name() + QString::number( i ));
230 Windowdef* window = Windowdef::create_cfg_read( windowGroup );
231 if( window )
232 append( window );
236 void Windowdef_list::cfg_write( KConfigGroup& cfg_P ) const
238 int i = 0;
239 for( Iterator it( *this );
241 ++it, ++i )
243 KConfigGroup itGroup( cfg_P.config(), cfg_P.name() + QString::number( i ) );
244 it.current()->cfg_write( itGroup );
246 cfg_P.writeEntry( "WindowsCount", i );
247 cfg_P.writeEntry( "Comment", comment());
250 Windowdef_list* Windowdef_list::copy() const
252 Windowdef_list* ret = new Windowdef_list( comment());
253 for( Iterator it( *this );
255 ++it )
256 ret->append( it.current()->copy());
257 return ret;
261 bool Windowdef_list::match( const Window_data& window_P ) const
263 if( count() == 0 ) // CHECKME no windows to match => ok
264 return true;
265 for( Iterator it( *this );
267 ++it )
268 if( it.current()->match( window_P ))
269 return true;
270 return false;
273 // Windowdef_simple
275 Windowdef_simple::Windowdef_simple( const QString& comment_P, const QString& title_P,
276 substr_type_t title_type_P, const QString& wclass_P, substr_type_t wclass_type_P,
277 const QString& role_P, substr_type_t role_type_P, int window_types_P )
278 : Windowdef( comment_P ), _title( title_P ), title_type( title_type_P ),
279 _wclass( wclass_P ), wclass_type( wclass_type_P ), _role( role_P ),
280 role_type( role_type_P ), _window_types( window_types_P )
284 Windowdef_simple::Windowdef_simple( KConfigGroup& cfg_P )
285 : Windowdef( cfg_P )
287 _title = cfg_P.readEntry( "Title" );
288 title_type = static_cast< substr_type_t >( cfg_P.readEntry( "TitleType",0 ));
289 _wclass = cfg_P.readEntry( "Class" );
290 wclass_type = static_cast< substr_type_t >( cfg_P.readEntry( "ClassType",0 ));
291 _role = cfg_P.readEntry( "Role" );
292 role_type = static_cast< substr_type_t >( cfg_P.readEntry( "RoleType", 0 ));
293 _window_types = cfg_P.readEntry( "WindowTypes",0 );
296 void Windowdef_simple::cfg_write( KConfigGroup& cfg_P ) const
298 base::cfg_write( cfg_P );
299 cfg_P.writeEntry( "Title", title());
300 cfg_P.writeEntry( "TitleType", int(title_type) );
301 cfg_P.writeEntry( "Class", wclass());
302 cfg_P.writeEntry( "ClassType", int(wclass_type) );
303 cfg_P.writeEntry( "Role", role());
304 cfg_P.writeEntry( "RoleType", int(role_type) );
305 cfg_P.writeEntry( "WindowTypes", window_types());
306 cfg_P.writeEntry( "Type", "SIMPLE" ); // overwrites value set in base::cfg_write()
309 bool Windowdef_simple::match( const Window_data& window_P )
311 if( !type_match( window_P.type ))
312 return false;
313 if( !is_substr_match( window_P.title, title(), title_type ))
314 return false;
315 if( !is_substr_match( window_P.wclass, wclass(), wclass_type ))
316 return false;
317 if( !is_substr_match( window_P.role, role(), role_type ))
318 return false;
319 kDebug() << "window match:" << window_P.title << ":OK";
320 return true;
323 bool Windowdef_simple::is_substr_match( const QString& str1_P, const QString& str2_P,
324 substr_type_t type_P )
326 switch( type_P )
328 case NOT_IMPORTANT :
329 return true;
330 case CONTAINS :
331 return str1_P.contains( str2_P ) > 0;
332 case IS :
333 return str1_P == str2_P;
334 case REGEXP :
336 QRegExp rg( str2_P );
337 return rg.indexIn( str1_P ) >= 0;
339 case CONTAINS_NOT :
340 return str1_P.contains( str2_P ) == 0;
341 case IS_NOT :
342 return str1_P != str2_P;
343 case REGEXP_NOT :
345 QRegExp rg( str2_P );
346 return rg.indexIn( str1_P ) < 0;
349 return false;
352 Windowdef* Windowdef_simple::copy() const
354 return new Windowdef_simple( comment(), title(), title_match_type(), wclass(),
355 wclass_match_type(), role(), role_match_type(), window_types());
358 const QString Windowdef_simple::description() const
360 return i18n( "Window simple: " ) + comment();
363 } // namespace KHotKeys
365 #include "windows.moc"