kcmkwin/kwinrules/main.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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())
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
00081 QCString machine = info.clientMachine().lower();
00082 Rules* best_match = NULL;
00083 int match_quality = 0;
00084 for( QValueList< Rules* >::ConstIterator it = rules.begin();
00085 it != rules.end();
00086 ++it )
00087 {
00088
00089 Rules* rule = *it;
00090 int quality = 0;
00091 bool generic = true;
00092 if( rule->wmclassmatch != Rules::ExactMatch )
00093 continue;
00094 if( !rule->matchWMClass( wmclass_class, wmclass_name ))
00095 continue;
00096
00097 if( rule->wmclasscomplete )
00098 {
00099 quality += 1;
00100 generic = false;
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 if( best_match != NULL )
00137 return best_match;
00138 Rules* ret = new Rules;
00139 ret->description = i18n( "Settings for %1" ).arg( wmclass_class );
00140 if( type == NET::Unknown )
00141 ret->types = NET::NormalMask;
00142 else
00143 ret->types = 1 << type;
00144 ret->title = title;
00145 ret->titlematch = Rules::UnimportantMatch;
00146 ret->clientmachine = machine;
00147 ret->clientmachine = Rules::UnimportantMatch;
00148
00149 ret->extrarolematch = Rules::UnimportantMatch;
00150 if( !role.isEmpty()
00151 && role != "unknown" && role != "unnamed" )
00152 {
00153 ret->windowrole = role;
00154 ret->windowrolematch = Rules::ExactMatch;
00155 if( wmclass_name == wmclass_class )
00156 {
00157 ret->wmclasscomplete = false;
00158 ret->wmclass = wmclass_class;
00159 ret->wmclassmatch = Rules::ExactMatch;
00160 }
00161 else
00162 {
00163
00164 ret->wmclasscomplete = true;
00165 ret->wmclass = wmclass_name + ' ' + wmclass_class;
00166 ret->wmclassmatch = Rules::ExactMatch;
00167 }
00168 }
00169 else
00170 {
00171 if( wmclass_name != wmclass_class )
00172 {
00173 ret->wmclasscomplete = true;
00174 ret->wmclass = wmclass_name + ' ' + wmclass_class;
00175 ret->wmclassmatch = Rules::ExactMatch;
00176 }
00177 else
00178 {
00179
00180
00181
00182
00183
00184
00185
00186 ret->titlematch = Rules::ExactMatch;
00187 ret->wmclasscomplete = false;
00188 ret->wmclass = wmclass_class;
00189 ret->wmclassmatch = Rules::ExactMatch;
00190 }
00191 }
00192 return ret;
00193 }
00194
00195 static int edit( Window wid )
00196 {
00197 QValueList< Rules* > rules;
00198 loadRules( rules );
00199 Rules* orig_rule = findRule( rules, wid );
00200 RulesDialog dlg;
00201
00202 Rules* edited_rule = dlg.edit( orig_rule, wid );
00203 if( edited_rule == NULL || edited_rule->isEmpty())
00204 {
00205 rules.remove( orig_rule );
00206 delete orig_rule;
00207 if( orig_rule != edited_rule )
00208 delete edited_rule;
00209 }
00210 else if( edited_rule != orig_rule )
00211 {
00212 QValueList< Rules* >::Iterator pos = rules.find( orig_rule );
00213 if( pos != rules.end())
00214 *pos = edited_rule;
00215 else
00216 rules.prepend( edited_rule );
00217 delete orig_rule;
00218 }
00219 saveRules( rules );
00220 if( !kapp->dcopClient()->isAttached())
00221 kapp->dcopClient()->attach();
00222 kapp->dcopClient()->send("kwin*", "", "reconfigure()", "");
00223 return 0;
00224 }
00225
00226 }
00227
00228 static const KCmdLineOptions options[] =
00229 {
00230
00231 { "wid <wid>", "WId of the window for special window settings.", 0 },
00232 KCmdLineLastOption
00233 };
00234
00235 extern "C"
00236 KDE_EXPORT int kdemain( int argc, char* argv[] )
00237 {
00238 KLocale::setMainCatalogue( "kcmkwinrules" );
00239 KCmdLineArgs::init( argc, argv, "kwin_rules_dialog", I18N_NOOP( "KWin" ),
00240 I18N_NOOP( "KWin helper utility" ), "1.0" );
00241 KCmdLineArgs::addCmdLineOptions( options );
00242 KApplication app;
00243 KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
00244 bool id_ok = false;
00245 Window id = args->getOption( "wid" ).toULong( &id_ok );
00246 args->clear();
00247 if( !id_ok || id == None )
00248 {
00249 KCmdLineArgs::usage( i18n( "This helper utility is not supposed to be called directly." ));
00250 return 1;
00251 }
00252 return KWinInternal::edit( id );
00253 }
This file is part of the documentation for kwin Library Version 3.3.90.