Source Code (Use browser search to find items of interest.)

Class Index

kdesktop'KBackgroundManager (./kdebase/kdesktop/bgmanager.h:96)

class KBackgroundManager
    : public QObject,
      virtual public KBackgroundIface
{
    Q_OBJECT

public:
    KBackgroundManager(QWidget *desktop, KWinModule* kwinModule);
    ~KBackgroundManager();

    void configure();
    void changeDesktop(int desk);
    void setCommon(int);
    void setExport(int);
    void setDocking(int);

private slots:
    void slotImageDone(int desk);
    void slotWallpaperDropped(QString wallpaper, int mode);
    void slotUnDocked();
    void slotCommon(bool);
    void slotExport(bool);
    void slotTimeout();
    void slotChangeWallpaper();
    void slotChangeDesktop(int);
    void slotDesktopNumberChanged(int);

private:
    void applyCommon(bool common);
    void applyDocking(bool dock);
    void applyExport(bool _export);
    void applyCache(bool limit, int size);

    int realDesktop();
    int effectiveDesktop();

    void renderBackground(int desk);
    void exportBackground(int pixmap, int desk);
    int pixmapSize(QPixmap *pm);
    int cacheSize();
    void removeCache(int desk);
    bool freeCache(int size);
    void addCache(KPixmap *pm, int hash, int desk);
    void setPixmap(KPixmap *pm, int hash, int desk);

    bool m_bExport, m_bCommon, m_bDock;
    bool m_bLimitCache, m_bInit;

    int m_CacheLimit, m_X, m_Y;
    int m_Serial, m_Hash, m_Current;

    KConfig *m_pConfig;
    QWidget *m_pDesktop;
    KBackgroundDockWidget *m_pDockWidget;
    QTimer *m_pTimer;

    QVector<KBackgroundRenderer> m_Renderer;
    QVector<KBackgroundCacheEntry> m_Cache;
    
    KWinModule *m_pKwinmodule;
    KPixmapServer *m_pPixmapServer;
};


kdesktop'KBackgroundManager::KBackgroundManager() (./kdebase/kdesktop/bgmanager.cc:199)

KBackgroundManager::KBackgroundManager(QWidget *desktop, KWinModule* kwinModule)
    : DCOPObject("KBackgroundIface")
{
    if (desktop == 0L)
        m_pDesktop = QApplication::desktop();
    else
        m_pDesktop = desktop;

    m_X = m_pDesktop->width();
    m_Y = m_pDesktop->height();

    // We need kwin for this, but startkde starts kwin after us
    int nod = KWin::numberOfDesktops();
    m_Renderer.resize(nod ? nod : 1);
    m_Cache.resize(m_Renderer.size());

    m_Serial = 0; m_Hash = 0;
    m_pConfig = KGlobal::config();
    m_bDock = m_bExport = m_bCommon = m_bInit = false;
    m_pKwinmodule = kwinModule;
    m_pPixmapServer = new KPixmapServer();

    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 KBackgroundRenderer(i));
        connect(m_Renderer[i], SIGNAL(imageDone(int)), SLOT(slotImageDone(int)));
    }

    m_pDockWidget = new KBackgroundDockWidget();
    connect(m_pDockWidget, SIGNAL(wallpaperDropped(QString,int)),
	    SLOT(slotWallpaperDropped(QString,int)));
    connect(m_pDockWidget, SIGNAL(changeWallpaper()), SLOT(slotChangeWallpaper()));
    connect(m_pDockWidget, SIGNAL(unDocked()), SLOT(slotUnDocked()));
    connect(m_pDockWidget, SIGNAL(exportChanged(bool)), SLOT(slotExport(bool)));
    connect(m_pDockWidget, SIGNAL(commonChanged(bool)), SLOT(slotCommon(bool)));

    configure();

    m_pTimer = new QTimer(this);
    connect(m_pTimer, SIGNAL(timeout()), SLOT(slotTimeout()));
    m_pTimer->start(5000, true); // Init after 5 secs

    connect(m_pKwinmodule, SIGNAL(desktopChange(int)), SLOT(slotChangeDesktop(int)));
    connect(m_pKwinmodule, SIGNAL(desktopNumberChange(int)), SLOT(slotDesktopNumberChanged(int)));
}



kdesktop'KBackgroundManager::~KBackgroundManager() (./kdebase/kdesktop/bgmanager.cc:249)

KBackgroundManager::~KBackgroundManager()
{
    for (unsigned i=0; i<m_Renderer.size(); i++)
        delete m_Renderer[i];
    
    delete m_pConfig;
    delete m_pPixmapServer;
    delete m_pDockWidget;
    delete m_pTimer;

    if (m_bExport)
	return;

    for (unsigned i=0; i<m_Cache.size(); i++)
	if (m_Cache[i]->pixmap) delete m_Cache[i]->pixmap;
}



kdesktop'KBackgroundManager::applyDocking() (./kdebase/kdesktop/bgmanager.cc:267)

void KBackgroundManager::applyDocking(bool dock)
{
    if (dock == m_bDock)
	return;
    m_bDock = dock;

    if (m_bDock && m_bInit)
	m_pDockWidget->show();
    else
	m_pDockWidget->hide();
}



kdesktop'KBackgroundManager::applyExport() (./kdebase/kdesktop/bgmanager.cc:280)

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;
    m_pDockWidget->setExport(m_bExport);
}



kdesktop'KBackgroundManager::applyCommon() (./kdebase/kdesktop/bgmanager.cc:299)

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);
    }

    m_pDockWidget->setCommon(m_bCommon);
}



kdesktop'KBackgroundManager::applyCache() (./kdebase/kdesktop/bgmanager.cc:318)

void KBackgroundManager::applyCache(bool limit, int size)
{
    m_bLimitCache = limit;
    m_CacheLimit = size;
    freeCache(0);
}


/*
 * Call this when the configuration has changed.
 */

kdesktop'KBackgroundManager::configure() (./kdebase/kdesktop/bgmanager.cc:329)

void KBackgroundManager::configure()
{    
    // Read individual settings
    KBackgroundRenderer *r;
    for (unsigned i=0; i<m_Renderer.size(); i++) {
        r = m_Renderer[i];
        int ohash = r->hash();
        r->load(i);
        if ((r->hash() != ohash))
            removeCache(i);
    }

    // Global settings
    m_pConfig->reparseConfiguration();
    m_pConfig->setGroup("Background Common");

    applyDocking(m_pConfig->readBoolEntry("Dock", _defDock));
    applyExport(m_pConfig->readBoolEntry("Export", _defExport));
    applyCommon(m_pConfig->readBoolEntry("CommonDesktop", _defCommon));

    bool limit = m_pConfig->readBoolEntry("LimitCache", _defLimitCache);
    int size = m_pConfig->readNumEntry("CacheSize", _defCacheSize) * 1024;
    applyCache(limit, size);

    // Repaint desktop
    changeDesktop(0);
}



kdesktop'KBackgroundManager::realDesktop() (./kdebase/kdesktop/bgmanager.cc:358)

int KBackgroundManager::realDesktop()
{
    int desk = m_pKwinmodule->currentDesktop();
    if (desk) desk--;
    return desk;
}



kdesktop'KBackgroundManager::effectiveDesktop() (./kdebase/kdesktop/bgmanager.cc:366)

int KBackgroundManager::effectiveDesktop()
{
    return m_bCommon ? 0 : realDesktop();
}


/*
 * Auxiliary slot because dcop functions cannot be slots currently (unfortunately).
 */

kdesktop'KBackgroundManager::slotChangeDesktop() (./kdebase/kdesktop/bgmanager.cc:375)

void KBackgroundManager::slotChangeDesktop(int desk)
{
    changeDesktop(desk);
}

/*
 * Number of desktops changed
 */

kdesktop'KBackgroundManager::slotDesktopNumberChanged() (./kdebase/kdesktop/bgmanager.cc:383)

void KBackgroundManager::slotDesktopNumberChanged(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 KBackgroundRenderer(i));
	    connect(m_Renderer[i], SIGNAL(imageDone(int)), SLOT(slotImageDone(int)));
	}
    }
}

/*
 * Call this when the desktop has been changed.
 * Desk is in KWM convention: [1..desks], instead of [0..desks-1].
 * 0 repaints the current desktop.
 * This method is DCOP exported.
 */

kdesktop'KBackgroundManager::changeDesktop() (./kdebase/kdesktop/bgmanager.cc:420)

void KBackgroundManager::changeDesktop(int desk)
{
    if (desk == 0)
	desk = realDesktop();
    else
	desk--;

    // Lazy initialisation of # of desktops
    if ((unsigned) desk >= m_Renderer.size())
	slotDesktopNumberChanged(KWin::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;
    }

    // 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;
        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 indentical 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.
 */

kdesktop'KBackgroundManager::exportBackground() (./kdebase/kdesktop/bgmanager.cc:466)

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(QString("DESKTOP%1").arg(desk+1), 
	    m_Cache[pixmap]->pixmap);
    KIPC::sendMessageAll(KIPC::BackgroundChanged);
}


/*
 * Paint the pixmap to the root window.
 */

kdesktop'KBackgroundManager::setPixmap() (./kdebase/kdesktop/bgmanager.cc:481)

void KBackgroundManager::setPixmap(KPixmap *pm, int hash, int desk)
{
    m_pDesktop->setBackgroundPixmap(*pm);
    m_Hash = hash;
    m_Current = desk;
}


/*
 * Start the render of a desktop background.
 */

kdesktop'KBackgroundManager::renderBackground() (./kdebase/kdesktop/bgmanager.cc:492)

void KBackgroundManager::renderBackground(int desk)
{
    KBackgroundRenderer *r = m_Renderer[desk];
    if (r->isActive()) {
        qDebug("renderer %d already active", desk);
        return;
    }

    // Allow tiles!
    r->setTile(true);
    r->start();
}


/*
 * This slot is called when a renderer is done.
 */

kdesktop'KBackgroundManager::slotImageDone() (./kdebase/kdesktop/bgmanager.cc:509)

void KBackgroundManager::slotImageDone(int desk)
{
    KPixmap *pm = new KPixmap();
    KBackgroundRenderer *r = m_Renderer[desk];

    // Convert with correct color conversion
    if (QPixmap::defaultDepth() < 15)
        pm->convertFromImage(*r->image(), KPixmap::LowColor);
    else
        pm->convertFromImage(*r->image());
    r->cleanup();

    // If current: paint it
    bool current = (r->hash() == m_Renderer[effectiveDesktop()]->hash());
    if (current)
        setPixmap(pm, r->hash(), desk);
    if (m_bExport || !m_bCommon)
	addCache(pm, r->hash(), desk);
    if (current)
        exportBackground(desk, realDesktop());
}


/*
 * Size in bytes of a QPixmap. For use in the pixmap cache.
 */

kdesktop'KBackgroundManager::pixmapSize() (./kdebase/kdesktop/bgmanager.cc:535)

int KBackgroundManager::pixmapSize(QPixmap *pm)
{
    return (pm->width() * pm->height()) * ((pm->depth() + 7) / 8);
}


/*
 * Total size of the pixmap cache.
 */

kdesktop'KBackgroundManager::cacheSize() (./kdebase/kdesktop/bgmanager.cc:544)

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.
 */

kdesktop'KBackgroundManager::removeCache() (./kdebase/kdesktop/bgmanager.cc:557)

void KBackgroundManager::removeCache(int desk)
{
    if (m_bExport)
	m_pPixmapServer->remove(QString("DESKTOP%1").arg(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(QString("DESKTOP%1").arg(i+1));
	}
}


/*
 * Try to free up to size bytes from the cache.
 */

kdesktop'KBackgroundManager::freeCache() (./kdebase/kdesktop/bgmanager.cc:581)

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.
 */

kdesktop'KBackgroundManager::addCache() (./kdebase/kdesktop/bgmanager.cc:609)

void KBackgroundManager::addCache(KPixmap *pm, int hash, int desk)
{
    if (m_Cache[desk]->pixmap)
	removeCache(desk);

    if (m_bLimitCache && !m_bExport)
	if (!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);
}



kdesktop'KBackgroundManager::slotChangeWallpaper() (./kdebase/kdesktop/bgmanager.cc:628)

void KBackgroundManager::slotChangeWallpaper()
{
    KBackgroundRenderer *r = m_Renderer[effectiveDesktop()];
    if (r->multiWallpaperMode() == KBackgroundSettings::NoMulti)
	return;

    r->changeWallpaper();
    changeDesktop(0);
}



kdesktop'KBackgroundManager::slotWallpaperDropped() (./kdebase/kdesktop/bgmanager.cc:639)

void KBackgroundManager::slotWallpaperDropped(QString wallpaper, int mode)
{
    KBackgroundRenderer *r = m_Renderer[effectiveDesktop()];
    r->stop();
    r->setWallpaperMode(mode);
    r->setWallpaper(wallpaper);
    r->writeSettings();

    changeDesktop(0);
}



kdesktop'KBackgroundManager::slotUnDocked() (./kdebase/kdesktop/bgmanager.cc:651)

void KBackgroundManager::slotUnDocked()
{
    setDocking(false);
}



kdesktop'KBackgroundManager::slotExport() (./kdebase/kdesktop/bgmanager.cc:657)

void KBackgroundManager::slotExport(bool _export)
{
    setExport(_export);
}



kdesktop'KBackgroundManager::slotCommon() (./kdebase/kdesktop/bgmanager.cc:663)

void KBackgroundManager::slotCommon(bool common)
{
    setCommon(common);
}


// DCOP exported

kdesktop'KBackgroundManager::setDocking() (./kdebase/kdesktop/bgmanager.cc:670)

void KBackgroundManager::setDocking(int dock)
{
    applyDocking(dock);
    m_pConfig->setGroup("Background Common");
    m_pConfig->writeEntry("Dock", m_bDock);
    m_pConfig->sync();
}


// DCOP exported

kdesktop'KBackgroundManager::setExport() (./kdebase/kdesktop/bgmanager.cc:680)

void KBackgroundManager::setExport(int _export)
{
    applyExport(_export);
    m_pConfig->setGroup("Background Common");
    m_pConfig->writeEntry("Export", m_bExport);
    m_pConfig->sync();
    changeDesktop(0);
}


// DCOP exported

kdesktop'KBackgroundManager::setCommon() (./kdebase/kdesktop/bgmanager.cc:691)

void KBackgroundManager::setCommon(int common)
{
    applyCommon(common);
    m_pConfig->setGroup("Background Common");
    m_pConfig->writeEntry("CommonDesktop", m_bCommon);
    m_pConfig->sync();
    changeDesktop(0);
}


/*
 * Called every minute to check if we need to rerun a background program.
 * or change a wallpaper.
 */

kdesktop'KBackgroundManager::slotTimeout() (./kdebase/kdesktop/bgmanager.cc:705)

void KBackgroundManager::slotTimeout()
{
    // First time init. It's done this way because kdesktop starts before
    // kicker and it needs the latter for docking. Hacky indeed....

    if (!m_bInit) {
	m_bInit = true;
	if (m_bDock)
	    m_pDockWidget->show();
	m_pTimer->start(60000);
	return;
    }

    for (unsigned i=0; i<m_Renderer.size(); i++) {
        KBackgroundRenderer *r = m_Renderer[i];
        bool change = false;

        if ((r->backgroundMode() == KBackgroundSettings::Program) &&
            (m_Cache[i]->hash != 0) &&
	    (r->KBackgroundProgram::needUpdate())
	   ) {
	    r->KBackgroundProgram::update();
            change = true;
        }

        if (r->needWallpaperChange()) {
            r->changeWallpaper();
            change = true;
        }

        if (change)
            r->start();
    }
}