summaryrefslogtreecommitdiffstats
path: root/kdesktop/bgmanager.cc
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit4aed2c8219774f5d797760606b8489a92ddc5163 (patch)
tree3f8c130f7d269626bf6a9447407ef6c35954426a /kdesktop/bgmanager.cc
downloadtdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz
tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kdesktop/bgmanager.cc')
-rw-r--r--kdesktop/bgmanager.cc811
1 files changed, 811 insertions, 0 deletions
diff --git a/kdesktop/bgmanager.cc b/kdesktop/bgmanager.cc
new file mode 100644
index 000000000..62f97cecc
--- /dev/null
+++ b/kdesktop/bgmanager.cc
@@ -0,0 +1,811 @@
+/* vi: ts=8 sts=4 sw=4
+ * kate: space-indent on; tab-width 8; indent-width 4; indent-mode cstyle;
+ *
+ * This file is part of the KDE project, module kdesktop.
+ * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
+ *
+ * You can Freely distribute this program under the GNU General Public
+ * License. See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+#include "bgrender.h"
+#include "bgmanager.h"
+#include "bgdefaults.h"
+#include "kdesktopsettings.h"
+#include "bgsettings.h"
+
+#include <assert.h>
+
+#include <qtimer.h>
+#include <qscrollview.h>
+
+#include <kiconloader.h>
+#include <kconfig.h>
+#include <kwin.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kipc.h>
+#include <kpopupmenu.h>
+#include <kwinmodule.h>
+#include <krootpixmap.h>
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#ifndef None
+#define None 0L
+#endif
+
+#include "pixmapserver.h"
+
+template class QPtrVector<KBackgroundRenderer>;
+template class QPtrVector<KBackgroundCacheEntry>;
+template class QMemArray<int>;
+
+static Atom prop_root;
+static bool properties_inited = false;
+
+/**** KBackgroundManager ****/
+
+KBackgroundManager::KBackgroundManager(QWidget *desktop, KWinModule* kwinModule)
+ : DCOPObject("KBackgroundIface")
+{
+ if( !properties_inited )
+ {
+ prop_root = XInternAtom(qt_xdisplay(), "_XROOTPMAP_ID", False);
+ properties_inited = true;
+ }
+ m_bBgInitDone = false;
+ m_bEnabled = true;
+
+ m_pDesktop = desktop;
+ if (desktop == 0L)
+ desktop = QApplication::desktop()->screen();
+
+ m_Renderer.resize( 1 );
+ m_Cache.resize( 1 );
+
+ m_Serial = 0; m_Hash = 0;
+ m_pConfig = KGlobal::config();
+ m_bExport = m_bCommon = m_bInit = false;
+ m_pKwinmodule = kwinModule;
+ m_pPixmapServer = new KPixmapServer();
+ m_xrootpmap = None;
+
+ for (unsigned i=0; i<m_Renderer.size(); i++)
+ {
+ m_Cache.insert(i, new KBackgroundCacheEntry);
+ m_Cache[i]->pixmap = 0L;
+ m_Cache[i]->hash = 0;
+ m_Cache[i]->exp_from = -1;
+ m_Renderer.insert (i, new KVirtualBGRenderer(i,m_pConfig));
+ connect(m_Renderer[i], SIGNAL(imageDone(int)), SLOT(slotImageDone(int)));
+ m_Renderer[i]->enableTiling( true ); // optimize
+ }
+
+ configure();
+
+ m_pTimer = new QTimer(this);
+ connect(m_pTimer, SIGNAL(timeout()), SLOT(slotTimeout()));
+ m_pTimer->start( 60000 );
+
+ connect(m_pKwinmodule, SIGNAL(currentDesktopChanged(int)),
+ SLOT(slotChangeDesktop(int)));
+ connect(m_pKwinmodule, SIGNAL(numberOfDesktopsChanged(int)),
+ SLOT(slotChangeNumberOfDesktops(int)));
+
+#if (QT_VERSION-0 >= 0x030200)
+ connect( kapp->desktop(), SIGNAL( resized( int )), SLOT( desktopResized())); // RANDR support
+#endif
+}
+
+
+KBackgroundManager::~KBackgroundManager()
+{
+ for (unsigned i=0; i<m_Renderer.size(); i++)
+ delete m_Renderer[i];
+
+ //delete m_pConfig; Very bad idea, this is KGlobal::config !
+ delete m_pPixmapServer;
+ delete m_pTimer;
+
+ // clear the Esetroot properties, as the pixmaps they refer to are going away...
+ Pixmap pm = None;
+ Atom type;
+ int format;
+ unsigned long length, after;
+ unsigned char* data_root;
+ if( XGetWindowProperty( qt_xdisplay(), qt_xrootwin(), prop_root, 0L, 1L, False, AnyPropertyType,
+ &type, &format, &length, &after, &data_root) == Success && data_root != NULL )
+ {
+ if (type == XA_PIXMAP)
+ pm = *((Pixmap*)data_root);
+ XFree( data_root );
+ }
+ // only if it's our pixmap
+ if( pm == m_xrootpmap )
+ XDeleteProperty(qt_xdisplay(), qt_xrootwin(), prop_root);
+ m_xrootpmap = None;
+
+ if (m_bExport)
+ return;
+
+ for (unsigned i=0; i<m_Cache.size(); i++)
+ {
+ delete m_Cache[i]->pixmap;
+ delete m_Cache[i];
+ }
+}
+
+
+void KBackgroundManager::applyExport(bool exp)
+{
+ if (exp == m_bExport)
+ return;
+
+ // If export mode changed from true -> false, remove all shared pixmaps.
+ // If it changed false -> true force a redraw because the current screen
+ // image might not have an associated pixmap in the cache.
+ if (!exp)
+ {
+ for (unsigned i=0; i<m_Cache.size(); i++)
+ removeCache(i);
+ } else
+ m_Hash = 0;
+
+ m_bExport = exp;
+}
+
+
+void KBackgroundManager::applyCommon(bool common)
+{
+ if (common == m_bCommon)
+ return;
+ m_bCommon = common;
+
+ // If common changed from false -> true, remove all cache entries, except
+ // at index 0 if exports are on.
+ if (m_bCommon)
+ {
+ if (!m_bExport)
+ removeCache(0);
+ for (unsigned i=1; i<m_Cache.size(); i++)
+ removeCache(i);
+ }
+}
+
+
+void KBackgroundManager::applyCache(bool limit, int size)
+{
+ m_bLimitCache = limit;
+ m_CacheLimit = size;
+ freeCache(0);
+}
+
+
+/*
+ * Call this when the configuration has changed.
+ * This method is exported with DCOP.
+ */
+void KBackgroundManager::configure()
+{
+ // Global settings
+ m_pConfig->reparseConfiguration();
+ KDesktopSettings::self()->readConfig();
+
+ // Read individual settings
+ KVirtualBGRenderer *r;
+ for (unsigned i=0; i<m_Renderer.size(); i++)
+ {
+ r = m_Renderer[i];
+ int ohash = r->hash();
+ r->load(i,false);
+ if ((r->hash() != ohash))
+ removeCache(i);
+ }
+
+ applyCommon(KDesktopSettings::commonDesktop());
+
+ bool limit = KDesktopSettings::limitCache();
+ int size = KDesktopSettings::cacheSize() * 1024;
+ applyCache(limit, size);
+
+ // Repaint desktop
+ slotChangeDesktop(0);
+}
+
+
+int KBackgroundManager::realDesktop()
+{
+ int desk = m_pKwinmodule->currentDesktop();
+ if (desk) desk--;
+ return desk;
+}
+
+
+int KBackgroundManager::effectiveDesktop()
+{
+ return m_bCommon ? 0 : realDesktop();
+}
+
+
+/*
+ * Number of desktops changed
+ */
+void KBackgroundManager::slotChangeNumberOfDesktops(int num)
+{
+ if (m_Renderer.size() == (unsigned) num)
+ return;
+
+ if (m_Renderer.size() > (unsigned) num)
+ {
+ for (unsigned i=num; i<m_Renderer.size(); i++)
+ {
+ if (m_Renderer[i]->isActive())
+ m_Renderer[i]->stop();
+ delete m_Renderer[i];
+ removeCache(i);
+ }
+ for (unsigned i=num; i<m_Renderer.size(); i++)
+ delete m_Cache[i];
+ m_Renderer.resize(num);
+ m_Cache.resize(num);
+ } else
+ {
+ // allocate new renderers and caches
+ int oldsz = m_Renderer.size();
+ m_Renderer.resize(num);
+ m_Cache.resize(num);
+ for (int i=oldsz; i<num; i++)
+ {
+ m_Cache.insert(i, new KBackgroundCacheEntry);
+ m_Cache[i]->pixmap = 0L;
+ m_Cache[i]->hash = 0;
+ m_Cache[i]->exp_from = -1;
+ m_Renderer.insert(i, new KVirtualBGRenderer(i,m_pConfig));
+ connect(m_Renderer[i], SIGNAL(imageDone(int)), SLOT(slotImageDone(int)));
+ m_Renderer[i]->enableTiling( true ); // optimize
+ }
+ }
+}
+
+/*
+ * Call this when the desktop has been changed.
+ * Desk is in KWin convention: [1..desks], instead of [0..desks-1].
+ * 0 repaints the current desktop.
+ */
+void KBackgroundManager::slotChangeDesktop(int desk)
+{
+ if (desk == 0)
+ desk = realDesktop();
+ else
+ desk--;
+
+ // Lazy initialisation of # of desktops
+ if ((unsigned) desk >= m_Renderer.size())
+ slotChangeNumberOfDesktops( m_pKwinmodule->numberOfDesktops() );
+
+ int edesk = effectiveDesktop();
+ m_Serial++;
+
+ // If the background is the same: do nothing
+ if (m_Hash == m_Renderer[edesk]->hash())
+ {
+ exportBackground(m_Current, desk);
+ return;
+ }
+ m_Renderer[edesk]->stop();
+ m_Renderer[edesk]->cleanup();
+
+ // If we have the background already rendered: set it
+ for (unsigned i=0; i<m_Cache.size(); i++)
+ {
+ if (!m_Cache[i]->pixmap)
+ continue;
+ if (m_Cache[i]->hash != m_Renderer[edesk]->hash())
+ continue;
+// kdDebug() << "slotChangeDesktop i=" << i << endl;
+ setPixmap(m_Cache[i]->pixmap, m_Cache[i]->hash, i);
+ m_Cache[i]->atime = m_Serial;
+ exportBackground(i, desk);
+ return;
+ }
+
+ // Do we have this or an identical config already running?
+ for (unsigned i=0; i<m_Renderer.size(); i++)
+ {
+ if ((m_Renderer[i]->hash() == m_Renderer[edesk]->hash()) &&
+ (m_Renderer[i]->isActive()))
+ return;
+ }
+
+ renderBackground(edesk);
+}
+
+
+/*
+ * Share a desktop pixmap.
+ */
+void KBackgroundManager::exportBackground(int pixmap, int desk)
+{
+ if (!m_bExport || (m_Cache[desk]->exp_from == pixmap))
+ return;
+
+ m_Cache[desk]->exp_from = pixmap;
+ m_pPixmapServer->add(KRootPixmap::pixmapName(desk+1),
+ m_Cache[pixmap]->pixmap);
+ KIPC::sendMessageAll(KIPC::BackgroundChanged, desk+1);
+}
+
+
+/*
+ * Paint the pixmap to the root window.
+ */
+void KBackgroundManager::setPixmap(KPixmap *pm, int hash, int desk)
+{
+ if (m_pDesktop)
+ {
+ QScrollView* sv = dynamic_cast<QScrollView*>( m_pDesktop );
+ if ( sv ) {
+ // Qt eats repaint events in this case :-((
+ sv->viewport()->update();
+ }
+ m_pDesktop->setErasePixmap(*pm);
+ m_pDesktop->repaint();
+ static bool root_cleared = false;
+ if( !root_cleared )
+ { // clear the root window pixmap set by kdm
+ root_cleared = true;
+ QTimer::singleShot( 0, this, SLOT( clearRoot()));
+ // but make the pixmap visible until m_pDesktop is visible
+ QApplication::desktop()->screen()->setErasePixmap(*pm);
+ QApplication::desktop()->screen()->erase();
+ }
+ }
+ else
+ {
+ QApplication::desktop()->screen()->setErasePixmap(*pm);
+ QApplication::desktop()->screen()->erase();
+ }
+
+ // and export it via Esetroot-style for gnome/GTK apps to share in the pretties
+ Pixmap bgPm = pm->handle(); // fetch the actual X handle to it
+ //kdDebug() << "Esetroot compat: setting pixmap to " << bgPm << endl;
+
+ // don't set the ESETROOT_PMAP_ID property - that would result in possible XKillClient()
+ // done on kdesktop
+
+ XChangeProperty(qt_xdisplay(), qt_xrootwin(), prop_root, XA_PIXMAP, 32, PropModeReplace,
+ (unsigned char *) &bgPm, 1);
+ m_xrootpmap = bgPm;
+
+ m_Hash = hash;
+ m_Current = desk;
+}
+
+void KBackgroundManager::clearRoot()
+{
+ QApplication::desktop()->screen()->setErasePixmap( QPixmap());
+ QApplication::desktop()->screen()->erase();
+}
+
+/*
+ * Start the render of a desktop background.
+ */
+void KBackgroundManager::renderBackground(int desk)
+{
+ KVirtualBGRenderer *r = m_Renderer[desk];
+ if (r->isActive())
+ {
+ kdDebug() << "renderer " << desk << " already active" << endl;
+ return;
+ }
+
+ r->start();
+}
+
+
+/*
+ * This slot is called when a renderer is done.
+ */
+void KBackgroundManager::slotImageDone(int desk)
+{
+ KPixmap *pm = new KPixmap();
+ KVirtualBGRenderer *r = m_Renderer[desk];
+ bool do_cleanup = true;
+
+ *pm = r->pixmap();
+ // If current: paint it
+ bool current = (r->hash() == m_Renderer[effectiveDesktop()]->hash());
+ if (current)
+ {
+ setPixmap(pm, r->hash(), desk);
+ if (!m_bBgInitDone)
+ {
+ m_bBgInitDone = true;
+ emit initDone();
+ QTimer::singleShot( 30000, this, SLOT( saveImages()));
+ do_cleanup = false;
+ }
+ }
+ if (m_bExport || !m_bCommon)
+ addCache(pm, r->hash(), desk);
+ else
+ delete pm;
+
+ if (current)
+ exportBackground(desk, realDesktop());
+
+ if( do_cleanup )
+ {
+ r->saveCacheFile();
+ r->cleanup();
+ }
+}
+
+
+void KBackgroundManager::saveImages()
+{
+ for (unsigned i=0; i<m_Renderer.size(); i++)
+ {
+ m_Renderer[i]->saveCacheFile();
+ m_Renderer[i]->cleanup();
+ }
+}
+
+/*
+ * Size in bytes of a QPixmap. For use in the pixmap cache.
+ */
+int KBackgroundManager::pixmapSize(QPixmap *pm)
+{
+ return (pm->width() * pm->height()) * ((pm->depth() + 7) / 8);
+}
+
+
+/*
+ * Total size of the pixmap cache.
+ */
+int KBackgroundManager::cacheSize()
+{
+ int total = 0;
+ for (unsigned i=0; i<m_Cache.size(); i++)
+ {
+ if (m_Cache[i]->pixmap)
+ total += pixmapSize(m_Cache[i]->pixmap);
+ }
+ return total;
+}
+
+
+/*
+ * Remove an entry from the pixmap cache.
+ */
+void KBackgroundManager::removeCache(int desk)
+{
+ if (m_bExport)
+ m_pPixmapServer->remove(KRootPixmap::pixmapName(desk+1));
+ else
+ delete m_Cache[desk]->pixmap;
+ m_Cache[desk]->pixmap = 0L;
+ m_Cache[desk]->hash = 0;
+ m_Cache[desk]->exp_from = -1;
+ m_Cache[desk]->atime = 0;
+
+ // Remove cache entries pointing to the removed entry
+ for (unsigned i=0; i<m_Cache.size(); i++)
+ {
+ if (m_Cache[i]->exp_from == desk)
+ {
+ assert(m_bExport);
+ m_Cache[i]->exp_from = -1;
+ m_pPixmapServer->remove(KRootPixmap::pixmapName(i+1));
+ }
+ }
+}
+
+
+/*
+ * Try to free up to size bytes from the cache.
+ */
+bool KBackgroundManager::freeCache(int size)
+{
+ if (m_bExport || !m_bLimitCache)
+ return true;
+
+ // If it doesn't fit at all, return now.
+ if (size > m_CacheLimit)
+ return false;
+
+ // If cache is too full, purge it (LRU)
+ while (size+cacheSize() > m_CacheLimit)
+ {
+ int j, min;
+ min = m_Serial+1; j = 0;
+ for (unsigned i=0; i<m_Cache.size(); i++)
+ {
+ if (m_Cache[i]->pixmap && (m_Cache[i]->atime < min))
+ {
+ min = m_Cache[i]->atime;
+ j = i;
+ }
+ }
+ removeCache(j);
+ }
+ return true;
+}
+
+
+/*
+ * Try to add a pixmap to the pixmap cache. We don't use QPixmapCache here
+ * because if we're exporting pixmaps, this needs special care.
+ */
+void KBackgroundManager::addCache(KPixmap *pm, int hash, int desk)
+{
+ if (m_Cache[desk]->pixmap)
+ removeCache(desk);
+
+ if (m_bLimitCache && !m_bExport && !freeCache(pixmapSize(pm)))
+ {
+ // pixmap does not fit in cache
+ delete pm;
+ return;
+ }
+
+ m_Cache[desk]->pixmap = pm;
+ m_Cache[desk]->hash = hash;
+ m_Cache[desk]->atime = m_Serial;
+ m_Cache[desk]->exp_from = -1;
+ exportBackground(desk, desk);
+}
+
+/*
+ * Called every minute to check if we need to rerun a background program.
+ * or change a wallpaper.
+ */
+void KBackgroundManager::slotTimeout()
+{
+ QMemArray<int> running(m_Renderer.size());
+ running.fill(0);
+
+ int NumDesks = m_Renderer.size();
+ if (m_bCommon)
+ NumDesks = 1;
+
+ int edesk = effectiveDesktop();
+
+ for (int i=0; i<NumDesks; i++)
+ {
+ KVirtualBGRenderer *r = m_Renderer[i];
+ bool change = false;
+
+ if (r->needProgramUpdate())
+ {
+ r->programUpdate();
+ change = true;
+ }
+
+ if (r->needWallpaperChange())
+ {
+ r->changeWallpaper();
+ change = true;
+ }
+
+ if (change && (i == edesk))
+ {
+ running[i] = r->hash();
+ r->start();
+ }
+ }
+}
+
+// Return a valid desk number.
+int KBackgroundManager::validateDesk(int desk)
+{
+ if (desk > (int)m_Renderer.size())
+ slotChangeNumberOfDesktops( m_pKwinmodule->numberOfDesktops() );
+
+ if ( (desk <= 0) || (desk > (int)m_Renderer.size()) )
+ return realDesktop();
+
+ return desk - 1;
+}
+
+// DCOP exported
+// Return current wallpaper for specified desk.
+// 0 is for the current visible desktop.
+QString KBackgroundManager::currentWallpaper(int desk)
+{
+ //TODO Is the behaviour of this function appropriate for multiple screens?
+ KBackgroundRenderer *r = m_Renderer[validateDesk(desk)]->renderer(0);
+
+ return r->currentWallpaper();
+}
+
+// DCOP exported
+void KBackgroundManager::changeWallpaper()
+{
+ KVirtualBGRenderer *r = m_Renderer[effectiveDesktop()];
+
+ r->changeWallpaper();
+ slotChangeDesktop(0);
+}
+
+// DCOP exported
+void KBackgroundManager::setExport(int _export)
+{
+ kdDebug() << "KBackgroundManager enabling exports.\n";
+ applyExport(_export);
+ slotChangeDesktop(0);
+}
+
+// DCOP exported
+void KBackgroundManager::setCommon(int common)
+{
+ applyCommon(common);
+ KDesktopSettings::setCommonDesktop( m_bCommon );
+ KDesktopSettings::writeConfig();
+ slotChangeDesktop(0);
+}
+
+// DCOP exported
+void KBackgroundManager::setWallpaper(QString wallpaper, int mode)
+{
+ if (mode < 0 || mode >= KBackgroundSettings::lastWallpaperMode) {
+ kdDebug() << "Invalid background mode " << mode << " passed to " << k_funcinfo << "\n";
+ return;
+ }
+
+ //TODO Is the behaviour of this function appropriate for multiple screens?
+ for (unsigned i=0; i < m_Renderer[effectiveDesktop()]->numRenderers(); ++i)
+ {
+ KBackgroundRenderer *r = m_Renderer[effectiveDesktop()]->renderer(i);
+ r->stop();
+ r->setWallpaperMode(mode);
+ r->setMultiWallpaperMode(KBackgroundSettings::NoMulti);
+ r->setWallpaper(wallpaper);
+ r->writeSettings();
+ }
+ slotChangeDesktop(0);
+}
+
+void KBackgroundManager::setWallpaper(QString wallpaper)
+{
+ //TODO Is the behaviour of this function appropriate for multiple screens?
+ KBackgroundRenderer *r = m_Renderer[effectiveDesktop()]->renderer(0);
+ int mode = r->wallpaperMode();
+ if (mode == KBackgroundSettings::NoWallpaper)
+ mode = KBackgroundSettings::Tiled;
+ setWallpaper(wallpaper, mode);
+}
+
+// DCOP exported
+// Returns the filenames of all wallpaper entries for specified desk
+// 0 is for current visible desktop.
+QStringList KBackgroundManager::wallpaperFiles(int desk)
+{
+ //TODO Is the behaviour of this function appropriate for multiple screens?
+ KBackgroundRenderer *r = m_Renderer[validateDesk(desk)]->renderer(0);
+
+ return r->wallpaperFiles();
+}
+
+// DCOP exported
+// Returns the list of wallpaper entries (viewable in background slide
+// show window) for specified desk. 0 is for current visible desktop.
+QStringList KBackgroundManager::wallpaperList(int desk)
+{
+ //TODO Is the behaviour of this function appropriate for multiple screens?
+ KBackgroundRenderer *r = m_Renderer[validateDesk(desk)]->renderer(0);;
+
+ return r->wallpaperList();
+}
+
+// DCOP exported
+void KBackgroundManager::setCache( int bLimit, int size )
+{
+ applyCache( bLimit, size*1024 );
+ KDesktopSettings::setLimitCache( (bool) bLimit );
+ KDesktopSettings::setCacheSize( size );
+ KDesktopSettings::writeConfig();
+}
+
+// DCOP exported
+void KBackgroundManager::setWallpaper(int desk, QString wallpaper, int mode)
+{
+ if (mode < 0 || mode >= KBackgroundSettings::lastWallpaperMode) {
+ kdDebug() << "Invalid background mode " << mode << " passed to " << k_funcinfo << "\n";
+ return;
+ }
+
+ int sdesk = validateDesk(desk);
+
+ //TODO Is the behaviour of this function appropriate for multiple screens?
+ for (unsigned i=0; i < m_Renderer[sdesk]->numRenderers(); ++i)
+ {
+ KBackgroundRenderer *r = m_Renderer[sdesk]->renderer(i);
+
+ setCommon(false); // Force each desktop to have it's own wallpaper
+
+ r->stop();
+ r->setWallpaperMode(mode);
+ r->setMultiWallpaperMode(KBackgroundSettings::NoMulti);
+ r->setWallpaper(wallpaper);
+ r->writeSettings();
+ }
+ slotChangeDesktop(sdesk);
+}
+
+void KBackgroundManager::repaintBackground()
+{
+ if (m_pDesktop)
+ m_pDesktop->repaint();
+ else
+ QApplication::desktop()->screen()->erase();
+}
+
+void KBackgroundManager::desktopResized()
+{
+ for (unsigned i=0; i<m_Renderer.size(); i++)
+ {
+ KVirtualBGRenderer * r = m_Renderer[i];
+ if( r->isActive())
+ r->stop();
+ removeCache(i);
+ // make the renderer update its desktop size
+ r->desktopResized();
+ }
+ m_Hash = 0;
+ if( m_pDesktop )
+ m_pDesktop->resize( kapp->desktop()->size());
+ // Repaint desktop
+ slotChangeDesktop(0);
+}
+
+// DCOP exported
+void KBackgroundManager::setColor(const QColor & c, bool isColorA)
+{
+ //TODO Is the behaviour of this function appropriate for multiple screens?
+ for (unsigned i=0; i < m_Renderer[effectiveDesktop()]->numRenderers(); ++i)
+ {
+ KBackgroundRenderer *r = m_Renderer[effectiveDesktop()]->renderer(i);
+ r->stop();
+
+ if (isColorA)
+ r->setColorA(c);
+ else
+ r->setColorB(c);
+
+ int mode = r->backgroundMode();
+ if (mode == KBackgroundSettings::Program)
+ mode = KBackgroundSettings::Flat;
+
+ if (!isColorA && (mode == KBackgroundSettings::Flat))
+ mode = KBackgroundSettings::VerticalGradient;
+ r->setBackgroundMode(mode);
+
+ r->writeSettings();
+ }
+ slotChangeDesktop(0);
+}
+
+void KBackgroundManager::setBackgroundEnabled( const bool enable )
+{
+ if (m_bEnabled == enable)
+ return;
+
+ m_bEnabled= enable;
+
+ int NumDesks = m_Renderer.size();
+ if (m_bCommon)
+ NumDesks = 1;
+
+ for (int i=0; i<NumDesks; i++)
+ {
+ m_Renderer[i]->setEnabled(enable);
+ }
+ slotChangeDesktop(0);
+}
+
+#include "bgmanager.moc"