kwin Library API Documentation

kcmkwin/kwinrules/main.cpp

00001 /*
00002  * Copyright (c) 2004 Lubos Lunak <l.lunak@kde.org>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 #include <kcmdlineargs.h>
00020 #include <kapplication.h>
00021 #include <dcopclient.h>
00022 #include <kconfig.h>
00023 #include <klocale.h>
00024 #include <kwin.h>
00025 
00026 #include <X11/Xlib.h>
00027 #include <fixx11h.h>
00028 
00029 #include "ruleswidget.h"
00030 #include "../../rules.h"
00031 
00032 namespace KWinInternal
00033 {
00034 
00035 static void loadRules( QValueList< Rules* >& rules )
00036     {
00037     KConfig cfg( "kwinrulesrc", true );
00038     cfg.setGroup( "General" );
00039     int count = cfg.readNumEntry( "count" );
00040     for( int i = 1;
00041          i <= count;
00042          ++i )
00043         {
00044         cfg.setGroup( QString::number( i ));
00045         Rules* rule = new Rules( cfg );
00046         rules.append( rule );
00047         }
00048     }
00049 
00050 static void saveRules( const QValueList< Rules* >& rules )
00051     {
00052     KConfig cfg( "kwinrulesrc" );
00053     cfg.setGroup( "General" );
00054     cfg.writeEntry( "count", rules.count());
00055     int i = 1;
00056     for( QValueList< Rules* >::ConstIterator it = rules.begin();
00057          it != rules.end();
00058          ++it )
00059         {
00060         cfg.setGroup( QString::number( i ));
00061         (*it)->write( cfg );
00062         ++i;
00063         }
00064     }
00065 
00066 static Rules* findRule( const QValueList< Rules* >& rules, Window wid )
00067     {
00068     KWin::WindowInfo info = KWin::windowInfo( wid,
00069         NET::WMName | NET::WMWindowType,
00070         NET::WM2WindowClass | NET::WM2WindowRole | NET::WM2ClientMachine );
00071     if( !info.valid()) // shouldn't really happen
00072         return NULL;
00073     QCString wmclass_class = info.windowClassClass().lower();
00074     QCString wmclass_name = info.windowClassName().lower();
00075     QCString role = info.windowRole().lower();
00076     NET::WindowType type = info.windowType( NET::NormalMask | NET::DesktopMask | NET::DockMask
00077         | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask
00078         | NET::UtilityMask | NET::SplashMask );
00079     QString title = info.name();
00080 //    QCString extrarole = ""; // TODO
00081     QCString machine = info.clientMachine().lower();
00082     Rules* best_match = NULL;
00083     int match_quality = 0; // 0 - no, 1 - generic windowrole or title, 2 - exact match
00084     for( QValueList< Rules* >::ConstIterator it = rules.begin();
00085          it != rules.end();
00086          ++it )
00087         {
00088         // try to find an exact match, i.e. not a generic rule
00089         Rules* rule = *it;
00090         int quality = 0;
00091         bool generic = true;
00092         if( rule->wmclassmatch != Rules::ExactMatch )
00093             continue; // too generic
00094         if( !rule->matchWMClass( wmclass_class, wmclass_name ))
00095             continue;
00096         // from now on, it matches the app - now try to match for a specific window
00097         if( rule->wmclasscomplete )
00098             {
00099             quality += 1;
00100             generic = false;  // this can be considered specific enough (old X apps)
00101             }
00102         if( rule->windowrolematch != Rules::UnimportantMatch )
00103             {
00104             quality += rule->windowrolematch == Rules::ExactMatch ? 5 : 1;
00105             generic = false;
00106             }
00107         if( rule->titlematch != Rules::UnimportantMatch )
00108             {
00109             quality += rule->titlematch == Rules::ExactMatch ? 3 : 1;
00110             generic = false;
00111             }
00112         if( rule->types != NET::AllTypesMask )
00113             {
00114             int bits = 0;
00115             for( int bit = 1;
00116                  bit < 1 << 31;
00117                  bit <<= 1 )
00118                 if( rule->types & bit )
00119                     ++bits;
00120             if( bits == 1 )
00121                 quality += 2;
00122             }
00123         if( generic )
00124             continue;
00125         if( !rule->matchType( type )
00126             || !rule->matchRole( role )
00127             || !rule->matchTitle( title )
00128             || !rule->matchClientMachine( machine ))
00129             continue;
00130         if( quality > match_quality )
00131             {
00132             best_match = rule;
00133             match_quality = quality;
00134             }
00135         }
00136     return best_match;
00137     }
00138 
00139 static int edit( Window wid )
00140     {
00141     QValueList< Rules* > rules;
00142     loadRules( rules );
00143     Rules* orig_rule = findRule( rules, wid );
00144     RulesDialog dlg;
00145     // dlg.edit() creates new Rules instance if edited
00146     Rules* edited_rule = dlg.edit( orig_rule, wid );
00147     if( edited_rule == NULL ) // cancelled
00148         return 0;
00149     if( edited_rule->isEmpty())
00150         {
00151         if( orig_rule == NULL )
00152             { // new, without any settings
00153             delete edited_rule;
00154             return 0;
00155             }
00156         else
00157             { // removed all settings from already existing
00158             rules.remove( orig_rule );
00159             delete orig_rule;
00160             delete edited_rule;
00161             }
00162         }
00163     else if( edited_rule != orig_rule )
00164         {
00165         QValueList< Rules* >::Iterator pos = rules.find( orig_rule );
00166         if( pos != rules.end())
00167             *pos = edited_rule;
00168         else
00169             rules.prepend( edited_rule );
00170         delete orig_rule;
00171         }
00172     saveRules( rules );
00173     if( !kapp->dcopClient()->isAttached())
00174         kapp->dcopClient()->attach();
00175     kapp->dcopClient()->send("kwin*", "", "reconfigure()", "");
00176     return 0;
00177     }
00178     
00179 } // namespace
00180 
00181 static const KCmdLineOptions options[] =
00182     {
00183     // no need for I18N_NOOP(), this is not supposed to be used directly
00184         { "wid <wid>", "WId of the window for special window settings.", 0 },
00185         KCmdLineLastOption
00186     };
00187 
00188 extern "C"
00189 int kdemain( int argc, char* argv[] )
00190     {
00191     KLocale::setMainCatalogue( "kcmkwinrules" );
00192     KCmdLineArgs::init( argc, argv, "kwin_rules_dialog", I18N_NOOP( "KWin" ),
00193     I18N_NOOP( "KWin helper utility" ), "1.0" );
00194     KCmdLineArgs::addCmdLineOptions( options );
00195     KApplication app;
00196     KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
00197     bool id_ok = false;
00198     Window id = args->getOption( "wid" ).toULong( &id_ok );
00199     args->clear();
00200     if( !id_ok || id == None )
00201         {
00202     KCmdLineArgs::usage( i18n( "This helper utility is not supposed to be called directly." ));
00203     return 1;
00204         }
00205     return KWinInternal::edit( id );
00206     }
KDE Logo
This file is part of the documentation for kwin Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Sep 25 20:35:06 2004 by doxygen 1.3.8-20040913 written by Dimitri van Heesch, © 1997-2003