a33f4313ab
clients by adding an unnecessary 'enable-bidi' checkbox which was never agreed upon on the kwin mailing list. The use of --reverse is sufficient without needing this checkbox. Please discuss largish patches like these first, especially during a feature freeze! (Everyone also seems to forget the kwin-styles in kdeartwork) - Make clients look the same with --reverse instead of the broken state they were in previously. If the button ordering is not to your liking in reverse mode, just change the button positions. (Or send patches for those clients that have not got these features yet). - Clean up popupMenu handling somewhat. - Remove a global static object in keramik. svn path=/trunk/kdebase/kwin/; revision=174079
485 lines
15 KiB
C++
485 lines
15 KiB
C++
/*
|
|
$Id$
|
|
|
|
This is the new kwindecoration kcontrol module
|
|
|
|
Copyright (c) 2001
|
|
Karol Szwed <gallium@kde.org>
|
|
http://gallium.n3.net/
|
|
|
|
Supports new kwin configuration plugins, and titlebar button position
|
|
modification via dnd interface.
|
|
|
|
Based on original "kwintheme" (Window Borders)
|
|
Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
|
|
*/
|
|
|
|
#include <qdir.h>
|
|
#include <qfileinfo.h>
|
|
#include <qlayout.h>
|
|
#include <qwhatsthis.h>
|
|
#include <qlistbox.h>
|
|
#include <qgroupbox.h>
|
|
#include <qcheckbox.h>
|
|
#include <qtabwidget.h>
|
|
#include <qvbox.h>
|
|
#include <qlabel.h>
|
|
#include <qfile.h>
|
|
|
|
#include <kapplication.h>
|
|
#include <kdebug.h>
|
|
#include <kdesktopfile.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kglobal.h>
|
|
#include <klocale.h>
|
|
#include <kdialog.h>
|
|
#include <kgenericfactory.h>
|
|
#include <kaboutdata.h>
|
|
#include <dcopclient.h>
|
|
|
|
#include "kwindecoration.h"
|
|
|
|
|
|
// KCModule plugin interface
|
|
// =========================
|
|
typedef KGenericFactory<KWinDecorationModule, QWidget> KWinDecoFactory;
|
|
K_EXPORT_COMPONENT_FACTORY( kcm_kwindecoration, KWinDecoFactory("kcmkwindecoration") );
|
|
|
|
KWinDecorationModule::KWinDecorationModule(QWidget* parent, const char* name, const QStringList &)
|
|
: KCModule(KWinDecoFactory::instance(), parent, name), DCOPObject("KWinClientDecoration")
|
|
{
|
|
KConfig kwinConfig("kwinrc");
|
|
kwinConfig.setGroup("Style");
|
|
|
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
|
tabWidget = new QTabWidget( this );
|
|
layout->addWidget( tabWidget );
|
|
|
|
// Page 1 (General Options)
|
|
QVBox* page1 = new QVBox( tabWidget );
|
|
page1->setSpacing( KDialog::spacingHint() );
|
|
page1->setMargin( KDialog::marginHint() );
|
|
|
|
QGroupBox* btnGroup = new QGroupBox( 1, Qt::Horizontal, i18n("Window Decoration"), page1 );
|
|
QWhatsThis::add( btnGroup,
|
|
i18n("Select the window decoration. This is the look and feel of both "
|
|
"the window borders and the window handle.") );
|
|
decorationListBox = new QListBox( btnGroup );
|
|
|
|
QGroupBox* checkGroup = new QGroupBox( 1, Qt::Horizontal,
|
|
i18n("General Options (if available)"), page1 );
|
|
|
|
|
|
cbUseCustomButtonPositions = new QCheckBox(
|
|
i18n("Use custom titlebar button &positions"), checkGroup );
|
|
QWhatsThis::add( cbUseCustomButtonPositions,
|
|
i18n( "The appropriate settings can be found in the \"Buttons\" Tab. "
|
|
"Please note that this option is not available on all styles yet!" ) );
|
|
|
|
cbShowToolTips = new QCheckBox(
|
|
i18n("&Show window button tooltips"), checkGroup );
|
|
QWhatsThis::add( cbShowToolTips,
|
|
i18n( "Enabling this checkbox will show window button tooltips. "
|
|
"If this checkbox is off, no window button tooltips will be shown."));
|
|
|
|
// Save this for later...
|
|
// cbUseMiniWindows = new QCheckBox( i18n( "Render mini &titlebars for all windows"), checkGroup );
|
|
// QWhatsThis::add( cbUseMiniWindows, i18n( "Note that this option is not available on all styles yet!" ) );
|
|
|
|
// Page 2 (Button Selector)
|
|
buttonPage = new QVBox( tabWidget );
|
|
buttonPage->setSpacing( KDialog::spacingHint() );
|
|
buttonPage->setMargin( KDialog::marginHint() );
|
|
|
|
QGroupBox* buttonBox = new QGroupBox( 1, Qt::Horizontal,
|
|
i18n("Titlebar Button Position"), buttonPage );
|
|
|
|
// Add nifty dnd button modification widgets
|
|
QLabel* label = new QLabel( buttonBox );
|
|
dropSite = new ButtonDropSite( buttonBox );
|
|
label->setText( i18n( "To add or remove titlebar buttons, simply <i>drag</i> items "
|
|
"between the available item list and the titlebar preview. Similarly, "
|
|
"drag items within the titlebar preview to re-position them.") );
|
|
buttonSource = new ButtonSource( buttonBox );
|
|
|
|
// Page 3 (Configure decoration via client plugin page)
|
|
pluginPage = new QVBox( tabWidget );
|
|
pluginPage->setSpacing( KDialog::spacingHint() );
|
|
pluginPage->setMargin( KDialog::marginHint() );
|
|
pluginObject = NULL;
|
|
|
|
// Load all installed decorations into memory
|
|
// Set up the decoration lists and other UI settings
|
|
findDecorations();
|
|
createDecorationList();
|
|
readConfig( &kwinConfig );
|
|
resetPlugin( &kwinConfig );
|
|
|
|
tabWidget->insertTab( page1, i18n("&General") );
|
|
tabWidget->insertTab( buttonPage, i18n("&Buttons") );
|
|
tabWidget->insertTab( pluginPage, i18n("&Configure [") +
|
|
decorationListBox->currentText() + i18n("]") );
|
|
|
|
tabWidget->setTabEnabled( buttonPage, cbUseCustomButtonPositions->isChecked() );
|
|
tabWidget->setTabEnabled( pluginPage, pluginObject ? true : false );
|
|
|
|
connect( dropSite, SIGNAL(buttonAdded(char)), buttonSource, SLOT(hideButton(char)) );
|
|
connect( dropSite, SIGNAL(buttonRemoved(char)), buttonSource, SLOT(showButton(char)) );
|
|
connect( buttonSource, SIGNAL(buttonDropped()), dropSite, SLOT(removeClickedButton()) );
|
|
connect( dropSite, SIGNAL(changed()), this, SLOT(slotSelectionChanged()) );
|
|
connect( buttonSource, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()) );
|
|
connect( decorationListBox, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged()) );
|
|
connect( decorationListBox, SIGNAL(highlighted(const QString&)),
|
|
SLOT(slotDecorationHighlighted(const QString&)) );
|
|
connect( cbUseCustomButtonPositions, SIGNAL(clicked()), SLOT(slotSelectionChanged()) );
|
|
connect( cbUseCustomButtonPositions, SIGNAL(toggled(bool)), SLOT(slotEnableButtonTab(bool)) );
|
|
connect( cbShowToolTips, SIGNAL(clicked()), SLOT(slotSelectionChanged()) );
|
|
// connect( cbUseMiniWindows, SIGNAL(clicked()), SLOT(slotSelectionChanged()) );
|
|
|
|
// Allow kwin dcop signal to update our selection list
|
|
connectDCOPSignal("kwin", 0, "dcopResetAllClients()", "dcopUpdateClientList()", false);
|
|
}
|
|
|
|
|
|
KWinDecorationModule::~KWinDecorationModule()
|
|
{
|
|
}
|
|
|
|
|
|
// Find all theme desktop files in all 'data' dirs owned by kwin.
|
|
// And insert these into a DecorationInfo structure
|
|
void KWinDecorationModule::findDecorations()
|
|
{
|
|
QStringList dirList = KGlobal::dirs()->findDirs("data", "kwin");
|
|
QStringList::ConstIterator it;
|
|
|
|
for (it = dirList.begin(); it != dirList.end(); it++)
|
|
{
|
|
QDir d(*it);
|
|
if (d.exists())
|
|
for (QFileInfoListIterator it(*d.entryInfoList()); it.current(); ++it)
|
|
{
|
|
QString filename(it.current()->absFilePath());
|
|
if (KDesktopFile::isDesktopFile(filename))
|
|
{
|
|
KDesktopFile desktopFile(filename);
|
|
QString libName = desktopFile.readEntry("X-KDE-Library");
|
|
|
|
if (!libName.isEmpty())
|
|
{
|
|
DecorationInfo di;
|
|
di.name = desktopFile.readName();
|
|
di.libraryName = libName;
|
|
decorations.append( di );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Fills the decorationListBox with a list of available kwin decorations
|
|
void KWinDecorationModule::createDecorationList()
|
|
{
|
|
QValueList<DecorationInfo>::ConstIterator it;
|
|
|
|
// Sync with kwin hardcoded KDE2 style which has no desktop item
|
|
decorationListBox->insertItem( i18n("KDE Default") );
|
|
|
|
for (it = decorations.begin(); it != decorations.end(); ++it)
|
|
{
|
|
DecorationInfo info = *it;
|
|
decorationListBox->insertItem( info.name );
|
|
}
|
|
decorationListBox->sort();
|
|
}
|
|
|
|
|
|
// Reset the decoration plugin to what the user just selected
|
|
void KWinDecorationModule::slotDecorationHighlighted( const QString& s )
|
|
{
|
|
KConfig kwinConfig("kwinrc");
|
|
kwinConfig.setGroup("Style");
|
|
|
|
// Let the user see config options for the currently selected decoration
|
|
resetPlugin( &kwinConfig, &s );
|
|
|
|
tabWidget->setTabEnabled( pluginPage, pluginObject ? true : false );
|
|
tabWidget->changeTab( pluginPage, i18n("&Configure [%1]").arg( decorationListBox->currentText() ) );
|
|
}
|
|
|
|
|
|
// This is the selection handler setting
|
|
void KWinDecorationModule::slotSelectionChanged()
|
|
{
|
|
emit changed(true);
|
|
}
|
|
|
|
|
|
void KWinDecorationModule::slotEnableButtonTab(bool on)
|
|
{
|
|
tabWidget->setTabEnabled( buttonPage, on );
|
|
}
|
|
|
|
|
|
QString KWinDecorationModule::decorationName( QString& libName )
|
|
{
|
|
QString decoName;
|
|
|
|
QValueList<DecorationInfo>::Iterator it;
|
|
for( it = decorations.begin(); it != decorations.end(); ++it )
|
|
if ( (*it).libraryName == libName )
|
|
{
|
|
decoName = (*it).name;
|
|
break;
|
|
}
|
|
|
|
return decoName;
|
|
}
|
|
|
|
|
|
QString KWinDecorationModule::decorationLibName( const QString& name )
|
|
{
|
|
QString libName;
|
|
|
|
// Find the corresponding library name to that of
|
|
// the current plugin name
|
|
QValueList<DecorationInfo>::Iterator it;
|
|
for( it = decorations.begin(); it != decorations.end(); ++it )
|
|
if ( (*it).name == name )
|
|
{
|
|
libName = (*it).libraryName;
|
|
break;
|
|
}
|
|
|
|
if (libName.isEmpty())
|
|
libName = "kwin_default";
|
|
|
|
return libName;
|
|
}
|
|
|
|
|
|
// Loads/unloads and inserts the decoration config plugin into the
|
|
// pluginPage, allowing for dynamic configuration of decorations
|
|
void KWinDecorationModule::resetPlugin( KConfig* conf, const QString* currentDecoName )
|
|
{
|
|
// Config names are "kwin_icewm_config"
|
|
// for "kwin_icewm" kwin client
|
|
|
|
QString oldName = oldLibraryName;
|
|
oldName += "_config";
|
|
|
|
QString currentName;
|
|
if (currentDecoName)
|
|
currentName = decorationLibName( *currentDecoName ); // Use what the user selected
|
|
else
|
|
currentName = currentLibraryName; // Use what was read from readConfig()
|
|
|
|
currentName += "_config";
|
|
|
|
// Delete old plugin widget if it exists
|
|
if (pluginObject)
|
|
delete pluginObject;
|
|
|
|
// Use klibloader for library manipulation
|
|
KLibLoader* loader = KLibLoader::self();
|
|
|
|
// Free the old library if possible
|
|
if (!oldLibraryName.isNull())
|
|
loader->unloadLibrary( QFile::encodeName(oldName) );
|
|
|
|
KLibrary* library = loader->library( QFile::encodeName(currentName) );
|
|
if (library != NULL)
|
|
{
|
|
void* alloc_ptr = library->symbol("allocate_config");
|
|
|
|
if (alloc_ptr != NULL)
|
|
{
|
|
allocatePlugin = (QObject* (*)(KConfig* conf, QWidget* parent))alloc_ptr;
|
|
pluginObject = allocatePlugin( conf, pluginPage );
|
|
|
|
// connect required signals and slots together...
|
|
connect( pluginObject, SIGNAL(changed()), this, SLOT(slotSelectionChanged()) );
|
|
connect( this, SIGNAL(pluginLoad(KConfig*)), pluginObject, SLOT(load(KConfig*)) );
|
|
connect( this, SIGNAL(pluginSave(KConfig*)), pluginObject, SLOT(save(KConfig*)) );
|
|
connect( this, SIGNAL(pluginDefaults()), pluginObject, SLOT(defaults()) );
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
pluginObject = NULL;
|
|
}
|
|
|
|
|
|
|
|
// Reads the kwin config settings, and sets all UI controls to those settings
|
|
// Updating the config plugin if required
|
|
void KWinDecorationModule::readConfig( KConfig* conf )
|
|
{
|
|
// General tab
|
|
// ============
|
|
cbUseCustomButtonPositions->setChecked( conf->readBoolEntry("CustomButtonPositions", false));
|
|
tabWidget->setTabEnabled( buttonPage, cbUseCustomButtonPositions->isChecked() );
|
|
cbShowToolTips->setChecked( conf->readBoolEntry("ShowToolTips", true ));
|
|
// cbUseMiniWindows->setChecked( conf->readBoolEntry("MiniWindowBorders", false));
|
|
|
|
// Find the corresponding decoration name to that of
|
|
// the current plugin library name
|
|
|
|
oldLibraryName = currentLibraryName;
|
|
currentLibraryName = conf->readEntry("PluginLib", "kwin_default");
|
|
QString decoName = decorationName( currentLibraryName );
|
|
|
|
// If we are using the "default" kde client, use the "default" entry.
|
|
if (decoName.isEmpty())
|
|
decorationListBox->setSelected( decorationListBox->findItem( i18n("KDE Default") ), true );
|
|
else
|
|
// Update the decoration listbox
|
|
decorationListBox->setSelected( decorationListBox->findItem( decoName ), true);
|
|
|
|
// Buttons tab
|
|
// ============
|
|
// Menu and sticky buttons are default on LHS
|
|
dropSite->buttonsLeft = conf->readEntry("ButtonsOnLeft", "MS");
|
|
// Help, Minimize, Maximize and Close are default on RHS
|
|
dropSite->buttonsRight = conf->readEntry("ButtonsOnRight", "HIAX");
|
|
dropSite->repaint(false);
|
|
|
|
buttonSource->showAllButtons();
|
|
|
|
// Step through the button lists, and hide the dnd button source items
|
|
unsigned int i;
|
|
for(i = 0; i < dropSite->buttonsLeft.length(); i++)
|
|
buttonSource->hideButton( dropSite->buttonsLeft[i].latin1() );
|
|
for(i = 0; i < dropSite->buttonsRight.length(); i++)
|
|
buttonSource->hideButton( dropSite->buttonsRight[i].latin1() );
|
|
|
|
emit changed(false);
|
|
}
|
|
|
|
|
|
// Writes the selected user configuration to the kwin config file
|
|
void KWinDecorationModule::writeConfig( KConfig* conf )
|
|
{
|
|
QString name = decorationListBox->currentText();
|
|
QString libName = decorationLibName( name );
|
|
|
|
KConfig kwinConfig("kwinrc");
|
|
kwinConfig.setGroup("Style");
|
|
|
|
// General settings
|
|
conf->writeEntry("PluginLib", libName);
|
|
conf->writeEntry("CustomButtonPositions", cbUseCustomButtonPositions->isChecked());
|
|
conf->writeEntry("ShowToolTips", cbShowToolTips->isChecked());
|
|
// conf->writeEntry("MiniWindowBorders", cbUseMiniWindows->isChecked());
|
|
|
|
// Button settings
|
|
conf->writeEntry("ButtonsOnLeft", dropSite->buttonsLeft );
|
|
conf->writeEntry("ButtonsOnRight", dropSite->buttonsRight );
|
|
|
|
oldLibraryName = currentLibraryName;
|
|
currentLibraryName = libName;
|
|
|
|
// We saved, so tell kcmodule that there have been no new user changes made.
|
|
emit changed(false);
|
|
}
|
|
|
|
|
|
void KWinDecorationModule::dcopUpdateClientList()
|
|
{
|
|
// Changes the current active ListBox item, and
|
|
// Loads a new plugin configuration tab if required.
|
|
KConfig kwinConfig("kwinrc");
|
|
kwinConfig.setGroup("Style");
|
|
|
|
readConfig( &kwinConfig );
|
|
resetPlugin( &kwinConfig );
|
|
}
|
|
|
|
|
|
// Virutal functions required by KCModule
|
|
void KWinDecorationModule::load()
|
|
{
|
|
KConfig kwinConfig("kwinrc");
|
|
kwinConfig.setGroup("Style");
|
|
|
|
// Reset by re-reading the config
|
|
// The plugin doesn't need changing, as we have not saved
|
|
readConfig( &kwinConfig );
|
|
emit pluginLoad( &kwinConfig );
|
|
}
|
|
|
|
|
|
void KWinDecorationModule::save()
|
|
{
|
|
KConfig kwinConfig("kwinrc");
|
|
kwinConfig.setGroup("Style");
|
|
|
|
writeConfig( &kwinConfig );
|
|
emit pluginSave( &kwinConfig );
|
|
|
|
kwinConfig.sync();
|
|
resetKWin();
|
|
// resetPlugin() will get called via the above DCOP function
|
|
}
|
|
|
|
|
|
void KWinDecorationModule::defaults()
|
|
{
|
|
// Set the KDE defaults
|
|
cbUseCustomButtonPositions->setChecked( false );
|
|
cbShowToolTips->setChecked( true );
|
|
// cbUseMiniWindows->setChecked( false);
|
|
// Don't set default for now
|
|
// decorationListBox->setSelected(
|
|
// decorationListBox->findItem( i18n("KDE Default") ), true ); // KDE default client
|
|
|
|
dropSite->buttonsLeft = "MS";
|
|
dropSite->buttonsRight= "HIAX";
|
|
dropSite->repaint(false);
|
|
|
|
buttonSource->showAllButtons();
|
|
buttonSource->hideButton('M');
|
|
buttonSource->hideButton('S');
|
|
buttonSource->hideButton('H');
|
|
buttonSource->hideButton('I');
|
|
buttonSource->hideButton('A');
|
|
buttonSource->hideButton('X');
|
|
|
|
// Set plugin defaults
|
|
emit pluginDefaults();
|
|
}
|
|
|
|
|
|
QString KWinDecorationModule::quickHelp() const
|
|
{
|
|
return i18n( "<h1>Window Manager Decoration</h1>"
|
|
"This module allows you to choose the window border decorations, "
|
|
"as well as titlebar button positions and custom decoration options.");
|
|
}
|
|
|
|
|
|
const KAboutData* KWinDecorationModule::aboutData() const
|
|
{
|
|
KAboutData* about =
|
|
new KAboutData(I18N_NOOP("kcmkwindecoration"),
|
|
I18N_NOOP("Window Decoration Control Module"),
|
|
0, 0, KAboutData::License_GPL,
|
|
I18N_NOOP("(c) 2001 Karol Szwed"));
|
|
about->addAuthor("Karol Szwed", 0, "gallium@kde.org");
|
|
return about;
|
|
}
|
|
|
|
|
|
void KWinDecorationModule::resetKWin()
|
|
{
|
|
bool ok = kapp->dcopClient()->send("kwin", "KWinInterface",
|
|
"reconfigure()", QByteArray());
|
|
if (!ok)
|
|
kdDebug() << "kcmkwindecoration: Could not reconfigure kwin" << endl;
|
|
}
|
|
|
|
#include "kwindecoration.moc"
|
|
// vim: ts=4
|
|
|