1
/****************************************************************************
4
** KRDB - puts current KDE color scheme into preprocessor statements
5
** cats specially written application default files and uses xrdb -merge to
6
** write to RESOURCE_MANAGER. Thus it gives a simple way to make non-KDE
7
** applications fit in with the desktop
9
** Copyright (C) 1998 by Mark Donohoe
10
** Copyright (C) 1999 by Dirk A. Mueller (reworked for KDE 2.0)
11
** Copyright (C) 2001 by Matthias Ettrich (add support for GTK applications )
12
** Copyright (C) 2001 by Waldo Bastian <bastian@kde.org>
13
** Copyright (C) 2002 by Karol Szwed <gallium@kde.org>
14
** This application is freely distributable under the GNU Public License.
16
*****************************************************************************/
18
#include <config-workspace.h>
27
#include <QtCore/QSettings>
28
#include <QtCore/QTextCodec>
33
#include <QTextStream>
35
#include <QtDBus/QtDBus>
36
#include <ktoolinvocation.h>
37
#include <klauncher_iface.h>
39
#include <kapplication.h>
41
#include <kconfiggroup.h>
43
#include <kglobalsettings.h>
44
#include <kstandarddirs.h>
46
#include <ksavefile.h>
47
#include <ktemporaryfile.h>
56
inline const char * gtkEnvVar(int version)
58
return 2==version ? "GTK2_RC_FILES" : "GTK_RC_FILES";
61
inline const char * sysGtkrc(int version)
65
if(access("/etc/opt/gnome/gtk-2.0", F_OK) == 0)
66
return "/etc/opt/gnome/gtk-2.0/gtkrc";
68
return "/etc/gtk-2.0/gtkrc";
72
if(access("/etc/opt/gnome/gtk", F_OK) == 0)
73
return "/etc/opt/gnome/gtk/gtkrc";
75
return "/etc/gtk/gtkrc";
79
inline const char * userGtkrc(int version)
81
return 2==version ? "/.gtkrc-2.0" : "/.gtkrc";
84
// -----------------------------------------------------------------------------
85
static void applyGtkStyles(bool active, int version)
87
QString gtkkde = KStandardDirs::locateLocal("config", 2==version?"gtkrc-2.0":"gtkrc");
88
QByteArray gtkrc = getenv(gtkEnvVar(version));
89
QStringList list = QFile::decodeName(gtkrc).split( ':');
90
QString userHomeGtkrc = QDir::homePath()+userGtkrc(version);
91
if (!list.contains(userHomeGtkrc))
92
list.prepend(userHomeGtkrc);
93
QLatin1String systemGtkrc = QLatin1String(sysGtkrc(version));
94
if (!list.contains(systemGtkrc))
95
list.prepend(systemGtkrc);
97
list.removeAll(gtkkde);
100
// Pass env. var to kdeinit.
101
QString name = gtkEnvVar(version);
102
QString value = QFile::encodeName(list.join(":"));
103
KToolInvocation::klauncher()->setLaunchEnv(name, value);
106
// -----------------------------------------------------------------------------
108
static void applyQtColors( KSharedConfigPtr kglobalcfg, QSettings& settings, QPalette& newPal )
110
QStringList actcg, inactcg, discg;
111
/* export kde color settings */
113
for (i = 0; i < QPalette::NColorRoles; i++)
114
actcg << newPal.color(QPalette::Active,
115
(QPalette::ColorRole) i).name();
116
for (i = 0; i < QPalette::NColorRoles; i++)
117
inactcg << newPal.color(QPalette::Inactive,
118
(QPalette::ColorRole) i).name();
119
for (i = 0; i < QPalette::NColorRoles; i++)
120
discg << newPal.color(QPalette::Disabled,
121
(QPalette::ColorRole) i).name();
123
settings.setValue("/qt/Palette/active", actcg);
124
settings.setValue("/qt/Palette/inactive", inactcg);
125
settings.setValue("/qt/Palette/disabled", discg);
127
// export kwin's colors to qtrc for kstyle to use
128
KConfigGroup wmCfgGroup(kglobalcfg, "WM");
131
QColor clr = newPal.color( QPalette::Active, QPalette::Background );
132
clr = wmCfgGroup.readEntry("activeBackground", clr);
133
settings.setValue("/qt/KWinPalette/activeBackground", clr.name());
134
if (QPixmap::defaultDepth() > 8)
136
clr = wmCfgGroup.readEntry("activeBlend", clr);
137
settings.setValue("/qt/KWinPalette/activeBlend", clr.name());
138
clr = newPal.color( QPalette::Active, QPalette::HighlightedText );
139
clr = wmCfgGroup.readEntry("activeForeground", clr);
140
settings.setValue("/qt/KWinPalette/activeForeground", clr.name());
141
clr = newPal.color( QPalette::Active,QPalette::Background );
142
clr = wmCfgGroup.readEntry("frame", clr);
143
settings.setValue("/qt/KWinPalette/frame", clr.name());
144
clr = wmCfgGroup.readEntry("activeTitleBtnBg", clr);
145
settings.setValue("/qt/KWinPalette/activeTitleBtnBg", clr.name());
148
clr = newPal.color(QPalette::Inactive, QPalette::Background);
149
clr = wmCfgGroup.readEntry("inactiveBackground", clr);
150
settings.setValue("/qt/KWinPalette/inactiveBackground", clr.name());
151
if (QPixmap::defaultDepth() > 8)
153
clr = wmCfgGroup.readEntry("inactiveBlend", clr);
154
settings.setValue("/qt/KWinPalette/inactiveBlend", clr.name());
155
clr = newPal.color(QPalette::Inactive, QPalette::Background).dark();
156
clr = wmCfgGroup.readEntry("inactiveForeground", clr);
157
settings.setValue("/qt/KWinPalette/inactiveForeground", clr.name());
158
clr = newPal.color(QPalette::Inactive, QPalette::Background);
159
clr = wmCfgGroup.readEntry("inactiveFrame", clr);
160
settings.setValue("/qt/KWinPalette/inactiveFrame", clr.name());
161
clr = wmCfgGroup.readEntry("inactiveTitleBtnBg", clr);
162
settings.setValue("/qt/KWinPalette/inactiveTitleBtnBg", clr.name());
164
KConfigGroup kdeCfgGroup(kglobalcfg, "KDE");
165
settings.setValue("/qt/KDE/contrast", kdeCfgGroup.readEntry("contrast", 7));
168
// -----------------------------------------------------------------------------
170
static void applyQtSettings( KSharedConfigPtr kglobalcfg, QSettings& settings )
172
/* export font settings */
173
settings.setValue("/qt/font", KGlobalSettings::generalFont().toString());
175
/* export effects settings */
176
KConfigGroup kdeCfgGroup(kglobalcfg, "General");
177
bool effectsEnabled = kdeCfgGroup.readEntry("EffectsEnabled", false);
178
bool fadeMenus = kdeCfgGroup.readEntry("EffectFadeMenu", false);
179
bool fadeTooltips = kdeCfgGroup.readEntry("EffectFadeTooltip", false);
180
bool animateCombobox = kdeCfgGroup.readEntry("EffectAnimateCombo", false);
182
QStringList guieffects;
183
if (effectsEnabled) {
184
guieffects << QString("general");
186
guieffects << QString("fademenu");
188
guieffects << QString("animatecombo");
190
guieffects << QString("fadetooltip");
193
guieffects << QString("none");
195
settings.setValue("/qt/GUIEffects", guieffects);
198
// -----------------------------------------------------------------------------
200
static void addColorDef(QString& s, const char* n, const QColor& col)
204
tmp.sprintf("#define %s #%02x%02x%02x\n",
205
n, col.red(), col.green(), col.blue());
211
// -----------------------------------------------------------------------------
213
static void copyFile(QFile& tmp, QString const& filename, bool )
216
if ( f.open(QIODevice::ReadOnly) ) {
217
QByteArray buf( 8192, ' ' );
218
while ( !f.atEnd() ) {
219
int read = f.read( buf.data(), buf.size() );
221
tmp.write( buf.data(), read );
227
// -----------------------------------------------------------------------------
229
static QString item( int i ) {
230
return QString::number( i / 255.0, 'f', 3 );
233
static QString color( const QColor& col )
235
return QString( "{ %1, %2, %3 }" ).arg( item( col.red() ) ).arg( item( col.green() ) ).arg( item( col.blue() ) );
238
static void createGtkrc( bool exportColors, const QPalette& cg, bool exportGtkTheme, const QString& gtkTheme, int version )
240
// lukas: why does it create in ~/.kde/share/config ???
241
// pfeiffer: so that we don't overwrite the user's gtkrc.
242
// it is found via the GTK_RC_FILES environment variable.
243
KSaveFile saveFile( KStandardDirs::locateLocal( "config", 2==version?"gtkrc-2.0":"gtkrc" ) );
244
if ( !saveFile.open() )
247
QTextStream t ( &saveFile );
248
t.setCodec( QTextCodec::codecForLocale () );
251
"# created by KDE, %1\n"
253
"# If you do not want KDE to override your GTK settings, select\n"
254
"# Appearance -> Colors in the System Settings and disable the checkbox\n"
255
"# \"Apply colors to non-KDE4 applications\"\n"
257
"#\n", QDateTime::currentDateTime().toString());
259
if ( 2==version ) { // we should maybe check for MacOS settings here
261
t << "gtk-alternative-button-order = 1" << endl;
268
if (gtkTheme.toLower() == "oxygen")
269
gtkStyle = QString("oxygen-gtk");
273
bool exist_gtkrc = false;
274
QByteArray gtkrc = getenv(gtkEnvVar(version));
275
QStringList listGtkrc = QFile::decodeName(gtkrc).split(":");
276
if (listGtkrc.contains(saveFile.fileName()))
277
listGtkrc.removeAll(saveFile.fileName());
278
listGtkrc.append(QDir::homePath() + userGtkrc(version));
279
listGtkrc.append(QDir::homePath() + "/.gtkrc-2.0-kde");
280
listGtkrc.append(QDir::homePath() + "/.gtkrc-2.0-kde4");
281
listGtkrc.removeAll("");
282
listGtkrc.removeDuplicates();
283
for (int i = 0; i < listGtkrc.size(); ++i)
285
if ((exist_gtkrc = QFile::exists(listGtkrc.at(i))))
291
QString gtk2ThemeFilename;
292
gtk2ThemeFilename = QString("%1/.themes/%2/gtk-2.0/gtkrc").arg(QDir::homePath()).arg(gtkStyle);
293
if (!QFile::exists(gtk2ThemeFilename)) {
294
QStringList gtk2ThemePath;
295
gtk2ThemeFilename.clear();
296
QByteArray xdgDataDirs = getenv("XDG_DATA_DIRS");
297
gtk2ThemePath.append(QDir::homePath() + "/.local");
298
gtk2ThemePath.append(QFile::decodeName(xdgDataDirs).split(":"));
299
gtk2ThemePath.removeDuplicates();
300
for (int i = 0; i < gtk2ThemePath.size(); ++i)
302
gtk2ThemeFilename = QString("%1/themes/%2/gtk-2.0/gtkrc").arg(gtk2ThemePath.at(i)).arg(gtkStyle);
303
if (QFile::exists(gtk2ThemeFilename))
306
gtk2ThemeFilename.clear();
310
if (!gtk2ThemeFilename.isEmpty())
312
t << "include \"" << gtk2ThemeFilename << "\"" << endl;
314
t << "gtk-theme-name=\"" << gtkStyle << "\"" << endl;
316
if (gtkStyle == "oxygen-gtk")
317
exportColors = false;
325
t << "style \"default\"" << endl;
327
t << " bg[NORMAL] = " << color( cg.color( QPalette::Active, QPalette::Background ) ) << endl;
328
t << " bg[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl;
329
t << " bg[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Background ) ) << endl;
330
t << " bg[ACTIVE] = " << color( cg.color( QPalette::Active, QPalette::Mid ) ) << endl;
331
t << " bg[PRELIGHT] = " << color( cg.color( QPalette::Active, QPalette::Background ) ) << endl;
333
t << " base[NORMAL] = " << color( cg.color( QPalette::Active, QPalette::Base ) ) << endl;
334
t << " base[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl;
335
t << " base[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Background ) ) << endl;
336
t << " base[ACTIVE] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl;
337
t << " base[PRELIGHT] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl;
339
t << " text[NORMAL] = " << color( cg.color(QPalette::Active, QPalette::Text) ) << endl;
340
t << " text[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl;
341
t << " text[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Mid ) ) << endl;
342
t << " text[ACTIVE] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl;
343
t << " text[PRELIGHT] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl;
345
t << " fg[NORMAL] = " << color ( cg.color( QPalette::Active, QPalette::Foreground ) ) << endl;
346
t << " fg[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl;
347
t << " fg[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Mid ) ) << endl;
348
t << " fg[ACTIVE] = " << color( cg.color( QPalette::Active, QPalette::Foreground ) ) << endl;
349
t << " fg[PRELIGHT] = " << color( cg.color( QPalette::Active, QPalette::Foreground ) ) << endl;
352
t << "class \"*\" style \"default\"" << endl;
355
// tooltips don't have the standard background color
356
t << "style \"ToolTip\"" << endl;
358
QPalette group = QToolTip::palette();
359
t << " bg[NORMAL] = " << color( group.color( QPalette::Active, QPalette::Background ) ) << endl;
360
t << " base[NORMAL] = " << color( group.color( QPalette::Active, QPalette::Base ) ) << endl;
361
t << " text[NORMAL] = " << color( group.color( QPalette::Active, QPalette::Text ) ) << endl;
362
t << " fg[NORMAL] = " << color( group.color( QPalette::Active, QPalette::Foreground ) ) << endl;
365
t << "widget \"gtk-tooltip\" style \"ToolTip\"" << endl;
366
t << "widget \"gtk-tooltips\" style \"ToolTip\"" << endl;
370
// highlight the current (mouse-hovered) menu-item
371
// not every button, checkbox, etc.
372
t << "style \"MenuItem\"" << endl;
374
t << " bg[PRELIGHT] = " << color( cg.color(QPalette::Highlight) ) << endl;
377
t << "class \"*MenuItem\" style \"MenuItem\"" << endl;
383
// -----------------------------------------------------------------------------
385
void runRdb( uint flags )
387
// Obtain the application palette that is about to be set.
388
bool exportColors = flags & KRdbExportColors;
389
bool exportQtColors = flags & KRdbExportQtColors;
390
bool exportQtSettings = flags & KRdbExportQtSettings;
391
bool exportXftSettings = flags & KRdbExportXftSettings;
392
bool exportGtkTheme = flags & KRdbExportGtkTheme;
394
KSharedConfigPtr kglobalcfg = KSharedConfig::openConfig( "kdeglobals" );
395
KConfigGroup kglobals(kglobalcfg, "KDE");
396
QPalette newPal = KGlobalSettings::createApplicationPalette(kglobalcfg);
398
KTemporaryFile tmpFile;
401
kDebug() << "Couldn't open temp file";
406
KConfigGroup generalCfgGroup(kglobalcfg, "General");
409
if (generalCfgGroup.hasKey("widgetStyle"))
410
gtkTheme = generalCfgGroup.readEntry("widgetStyle");
414
createGtkrc( exportColors, newPal, exportGtkTheme, gtkTheme, 1 );
415
createGtkrc( exportColors, newPal, exportGtkTheme, gtkTheme, 2 );
417
// Export colors to non-(KDE/Qt) apps (e.g. Motif, GTK+ apps)
420
KGlobal::dirs()->addResourceType("appdefaults", "data", "kdisplay/app-defaults/");
421
KGlobal::locale()->insertCatalog("krdb");
424
QColor backCol = newPal.color( QPalette::Active, QPalette::Background );
425
addColorDef(preproc, "FOREGROUND" , newPal.color( QPalette::Active, QPalette::Foreground ) );
426
addColorDef(preproc, "BACKGROUND" , backCol);
427
addColorDef(preproc, "HIGHLIGHT" , backCol.light(100+(2*KGlobalSettings::contrast()+4)*16/1));
428
addColorDef(preproc, "LOWLIGHT" , backCol.dark(100+(2*KGlobalSettings::contrast()+4)*10));
429
addColorDef(preproc, "SELECT_BACKGROUND" , newPal.color( QPalette::Active, QPalette::Highlight));
430
addColorDef(preproc, "SELECT_FOREGROUND" , newPal.color( QPalette::Active, QPalette::HighlightedText));
431
addColorDef(preproc, "WINDOW_BACKGROUND" , newPal.color( QPalette::Active, QPalette::Base ) );
432
addColorDef(preproc, "WINDOW_FOREGROUND" , newPal.color( QPalette::Active, QPalette::Foreground ) );
433
addColorDef(preproc, "INACTIVE_BACKGROUND", KGlobalSettings::inactiveTitleColor());
434
addColorDef(preproc, "INACTIVE_FOREGROUND", KGlobalSettings::inactiveTitleColor());
435
addColorDef(preproc, "ACTIVE_BACKGROUND" , KGlobalSettings::activeTitleColor());
436
addColorDef(preproc, "ACTIVE_FOREGROUND" , KGlobalSettings::activeTitleColor());
437
//---------------------------------------------------------------
439
tmpFile.write( preproc.toLatin1(), preproc.length() );
443
const QStringList adPaths = KGlobal::dirs()->findDirs("appdefaults", "");
444
for (QStringList::ConstIterator it = adPaths.constBegin(); it != adPaths.constEnd(); ++it) {
447
if ( dSys.exists() ) {
448
dSys.setFilter( QDir::Files );
449
dSys.setSorting( QDir::Name );
450
dSys.setNameFilters(QStringList("*.ad"));
451
list += dSys.entryList();
455
for (QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it)
456
copyFile(tmpFile, KStandardDirs::locate("appdefaults", *it ), true);
459
// Merge ~/.Xresources or fallback to ~/.Xdefaults
460
QString homeDir = QDir::homePath();
461
QString xResources = homeDir + "/.Xresources";
463
// very primitive support for ~/.Xresources by appending it
464
if ( QFile::exists( xResources ) )
465
copyFile(tmpFile, xResources, true);
467
copyFile(tmpFile, homeDir + "/.Xdefaults", true);
469
// Export the Xcursor theme & size settings
470
KConfigGroup mousecfg(KSharedConfig::openConfig( "kcminputrc" ), "Mouse" );
471
QString theme = mousecfg.readEntry("cursorTheme", QString());
472
QString size = mousecfg.readEntry("cursorSize", QString());
476
contents = "Xcursor.theme: " + theme + '\n';
479
contents += "Xcursor.size: " + size + '\n';
481
if (exportXftSettings)
483
if (generalCfgGroup.hasKey("XftAntialias"))
485
contents += "Xft.antialias: ";
486
if(generalCfgGroup.readEntry("XftAntialias", true))
492
if (generalCfgGroup.hasKey("XftHintStyle"))
494
QString hintStyle = generalCfgGroup.readEntry("XftHintStyle", "hintmedium");
495
contents += "Xft.hinting: ";
496
if(hintStyle.isEmpty())
500
if(hintStyle!="hintnone")
504
contents += "Xft.hintstyle: " + hintStyle + '\n';
508
if (generalCfgGroup.hasKey("XftSubPixel"))
510
QString subPixel = generalCfgGroup.readEntry("XftSubPixel");
511
if(!subPixel.isEmpty())
512
contents += "Xft.rgba: " + subPixel + '\n';
515
KConfig _cfgfonts( "kcmfonts" );
516
KConfigGroup cfgfonts(&_cfgfonts, "General");
518
if( cfgfonts.readEntry( "forceFontDPI", 0 ) != 0 )
519
contents += "Xft.dpi: " + cfgfonts.readEntry( "forceFontDPI" ) + '\n';
523
proc << "xrdb" << "-quiet" << "-remove" << "-nocpp";
525
if (proc.waitForStarted())
527
proc.write( QByteArray( "Xft.dpi\n" ) );
528
proc.closeWriteChannel();
529
proc.waitForFinished();
534
if (contents.length() > 0)
535
tmpFile.write( contents.toLatin1(), contents.length() );
541
proc << "xrdb" << "-merge" << tmpFile.fileName();
543
proc << "xrdb" << "-quiet" << "-merge" << tmpFile.fileName();
547
applyGtkStyles(exportColors, 1);
548
applyGtkStyles(exportColors, 2);
551
if ( exportQtColors || exportQtSettings )
553
QSettings* settings = new QSettings(QLatin1String("Trolltech"));
555
if ( exportQtColors )
556
applyQtColors( kglobalcfg, *settings, newPal ); // For kcmcolors
558
if ( exportQtSettings )
559
applyQtSettings( kglobalcfg, *settings ); // For kcmstyle
562
QApplication::flush();
564
// We let KIPC take care of ourselves, as we are in a KDE app with
565
// QApp::setDesktopSettingsAware(false);
566
// Instead of calling QApp::x11_apply_settings() directly, we instead
567
// modify the timestamp which propagates the settings changes onto
568
// Qt-only apps without adversely affecting ourselves.
570
// Cheat and use the current timestamp, since we just saved to qtrc.
571
QDateTime settingsstamp = QDateTime::currentDateTime();
573
static Atom qt_settings_timestamp = 0;
574
if (!qt_settings_timestamp) {
575
QString atomname("_QT_SETTINGS_TIMESTAMP_");
576
atomname += XDisplayName( 0 ); // Use the $DISPLAY envvar.
577
qt_settings_timestamp = XInternAtom( QX11Info::display(), atomname.toLatin1(), False);
581
QDataStream s(&stamp.buffer(), QIODevice::WriteOnly);
583
XChangeProperty( QX11Info::display(), QX11Info::appRootWindow(), qt_settings_timestamp,
584
qt_settings_timestamp, 8, PropModeReplace,
585
(unsigned char*) stamp.buffer().data(),
586
stamp.buffer().size() );
587
QApplication::flush();