////////////////////////////////////////////////////////////////////////////// // oxygen.cpp // ------------------- // // Copyright (c) 2009 Hugo Pereira Da Costa // Copyright (c) 2006, 2007 Riccardo Iaconelli // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////// #include "oxygenfactory.h" #include "oxygenfactory.moc" #include "oxygenclient.h" #include #include #include #include #include #include extern "C" { KDE_EXPORT KDecorationFactory* create_factory() { return new Oxygen::Factory(); } } namespace Oxygen { //___________________________________________________ Factory::Factory(): initialized_( false ), helper_( "oxygenDeco" ), shadowCache_( helper_ ) { readConfig(); setInitialized( true ); } //___________________________________________________ Factory::~Factory() { setInitialized( false ); } //___________________________________________________ KDecoration* Factory::createDecoration(KDecorationBridge* bridge ) { return (new Client( bridge, this ))->decoration(); } //___________________________________________________ bool Factory::reset(unsigned long changed) { if( changed & SettingColors ) { shadowCache().invalidateCaches(); } // read in the configuration setInitialized( false ); bool configuration_changed = readConfig(); setInitialized( true ); if( configuration_changed || (changed & (SettingDecoration | SettingButtons | SettingBorder)) ) { // returning true triggers all decorations to be re-created return true; } else { // no need to re-create the decorations // trigger repaint only resetDecorations(changed); return false; } } //___________________________________________________ bool Factory::readConfig() { bool changed( false ); /* always reload helper this is needed to properly handle color contrast settings changed */ helper().invalidateCaches(); helper().reloadConfig(); // create a config object KConfig config("oxygenrc"); KConfigGroup group( config.group("Windeco") ); Configuration configuration( group ); if( !( configuration == defaultConfiguration() ) ) { setDefaultConfiguration( configuration ); changed = true; } // initialize shadow cache switch( defaultConfiguration().shadowCacheMode() ) { case Configuration::CacheDisabled: { shadowCache_.setEnabled( false ); break; } default: case Configuration::CacheVariable: { shadowCache_.setEnabled( true ); shadowCache_.setMaxIndex( qMin( 256, int( 120*defaultConfiguration().animationsDuration()/1000 ) ) ); break; } case Configuration::CacheMaximum: { shadowCache_.setEnabled( true ); shadowCache_.setMaxIndex( 256 ); break; } } // read exceptionsreadConfig ExceptionList exceptions( config ); if( !( exceptions == exceptions_ ) ) { exceptions_ = exceptions; changed = true; } // shadow mode if( configuration.shadowMode() != Configuration::OxygenShadows ) { defaultConfiguration().setUseOxygenShadows( false ); defaultConfiguration().setUseDropShadows( false ); } // read shadow configurations ShadowConfiguration activeShadowConfiguration( QPalette::Active, config.group( "ActiveShadow" ) ); activeShadowConfiguration.setEnabled( defaultConfiguration().useOxygenShadows() ); if( shadowCache().shadowConfigurationChanged( activeShadowConfiguration ) ) { shadowCache().setShadowConfiguration( activeShadowConfiguration ); shadowCache().invalidateCaches(); changed = true; } // read shadow configurations ShadowConfiguration inactiveShadowConfiguration( QPalette::Inactive, config.group( "InactiveShadow" ) ); inactiveShadowConfiguration.setEnabled( defaultConfiguration().useDropShadows() ); if( shadowCache().shadowConfigurationChanged( inactiveShadowConfiguration ) ) { shadowCache().setShadowConfiguration( inactiveShadowConfiguration ); shadowCache().invalidateCaches(); changed = true; } return changed; } //_________________________________________________________________ bool Factory::supports( Ability ability ) const { switch( ability ) { // announce case AbilityAnnounceButtons: case AbilityAnnounceColors: // buttons case AbilityButtonMenu: case AbilityButtonHelp: case AbilityButtonMinimize: case AbilityButtonMaximize: case AbilityButtonClose: case AbilityButtonOnAllDesktops: case AbilityButtonAboveOthers: case AbilityButtonBelowOthers: case AbilityButtonSpacer: case AbilityButtonShade: // // colors // case AbilityColorTitleBack: // case AbilityColorTitleFore: // case AbilityColorFrame: // compositing case AbilityProvidesShadow: // TODO: UI option to use default shadows instead return defaultConfiguration().shadowMode() != Configuration::KWinShadows; case AbilityUsesAlphaChannel: return true; // tabs case AbilityClientGrouping: return defaultConfiguration().tabsEnabled(); // no colors supported at this time default: return false; }; } //____________________________________________________________________ Configuration Factory::configuration( const Client& client ) { QString window_title; QString class_name; for( ExceptionList::const_iterator iter = exceptions_.constBegin(); iter != exceptions_.constEnd(); ++iter ) { // discard disabled exceptions if( !iter->enabled() ) continue; /* decide which value is to be compared to the regular expression, based on exception type */ QString value; switch( iter->type() ) { case Exception::WindowTitle: { value = window_title.isEmpty() ? (window_title = client.caption()):window_title; break; } case Exception::WindowClassName: { if( class_name.isEmpty() ) { // retrieve class name KWindowInfo info( client.windowId(), 0, NET::WM2WindowClass ); QString window_class_name( info.windowClassName() ); QString window_class( info.windowClassClass() ); class_name = window_class_name + ' ' + window_class; } value = class_name; break; } default: assert( false ); } if( iter->regExp().indexIn( value ) < 0 ) continue; Configuration configuration( defaultConfiguration() ); configuration.readException( *iter ); return configuration; } return defaultConfiguration(); } } //namespace Oxygen