You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/kdesktop/bgmanager.cc

1109 lines
30 KiB

/* 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 "kdesktopapp.h"
#include "KCrossBGRender.h"
#include "crossfade.h"
#include <assert.h>
#include <tqtimer.h>
#include <tqscrollview.h>
#include <tqpainter.h>
#include <tqdesktopwidget.h>
#include <kiconloader.h>
#include <tdeconfig.h>
#include <twin.h>
#include <tdeapplication.h>
#include <kdebug.h>
#include <kipc.h>
#include <tdepopupmenu.h>
#include <twinmodule.h>
#include <krootpixmap.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <unistd.h>
#ifndef None
#define None 0L
#endif
#ifdef COMPOSITE
# include <X11/Xlib.h>
# include <X11/extensions/Xrender.h>
# include <fixx11h.h>
#endif
#include "pixmapserver.h"
template class TQPtrVector<KCrossBGRender>;
template class TQPtrVector<KBackgroundCacheEntry>;
template class TQMemArray<int>;
static Atom prop_root;
static bool properties_inited = false;
extern bool argb_visual;
extern KDesktopApp *myApp;
/**** KBackgroundManager ****/
KBackgroundManager::KBackgroundManager(TQWidget *desktop, KWinModule* twinModule)
: KBackgroundIface()
{
if( !properties_inited )
{
prop_root = XInternAtom(tqt_xdisplay(), "_XROOTPMAP_ID", False);
properties_inited = true;
}
m_bBgInitDone = false;
m_bEnabled = true;
m_pDesktop = desktop;
if (desktop == 0L)
desktop = TQT_TQWIDGET(TDEApplication::desktop()->screen());
m_Renderer.resize( 1 );
m_Cache.resize( 1 );
m_Serial = 0; m_Hash = 0;
m_pConfig = TDEGlobal::config();
m_bExport = m_bCommon = m_bInit = false;
m_pKwinmodule = twinModule;
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], TQT_SIGNAL(imageDone(int)), TQT_SLOT(slotImageDone(int)));
m_Renderer[i]->enableTiling( true ); // optimize
}
#ifdef COMPOSITE
m_tPixmap = new KPixmap(kapp->desktop()->size());
m_tPixmap->fill(TQColor(0, 0x0));
connect(myApp, TQT_SIGNAL(cmBackgroundChanged( bool )),
TQT_SLOT(slotCmBackgroundChanged( bool )));
#endif
configure();
m_pTimer = new TQTimer(this);
connect(m_pTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimeout()));
m_pTimer->start( 60000 );
/*CrossFade's config*/
m_crossTimer = new TQTimer(this);
connect(m_crossTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotCrossFadeTimeout()));
resizingDesktop = true;
/*Ends here*/
connect(m_pKwinmodule, TQT_SIGNAL(currentDesktopChanged(int)),
TQT_SLOT(slotChangeDesktop(int)));
connect(m_pKwinmodule, TQT_SIGNAL(numberOfDesktopsChanged(int)),
TQT_SLOT(slotChangeNumberOfDesktops(int)));
connect(m_pKwinmodule, TQT_SIGNAL(currentDesktopViewportChanged(int, const TQPoint&)),
TQT_SLOT(slotChangeViewport(int, const TQPoint&)));
#if (TQT_VERSION-0 >= 0x030200)
connect( kapp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( desktopResized())); // RANDR support
#endif
TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
m_numberOfViewports = s.width() * s.height();
if (m_numberOfViewports < 1) {
m_numberOfViewports = 1;
}
for (signed j=0;j<(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);j++) {
renderBackground(j);
}
}
KBackgroundManager::~KBackgroundManager()
{
for (unsigned i=0; i<m_Renderer.size(); i++)
delete m_Renderer[i];
//delete m_pConfig; Very bad idea, this is TDEGlobal::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( tqt_xdisplay(), tqt_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(tqt_xdisplay(), tqt_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);
// Redraw all desktops so that applications relying on exported data, e.g. kpager, continue to work properly
TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
m_numberOfViewports = s.width() * s.height();
if (m_numberOfViewports < 1) {
m_numberOfViewports = 1;
}
for (signed j=0;j<(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);j++) {
renderBackground(j);
}
}
int KBackgroundManager::realDesktop()
{
int desk = m_pKwinmodule->currentDesktop();
if (desk) desk--;
return desk;
}
int KBackgroundManager::effectiveDesktop()
{
TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
m_numberOfViewports = s.width() * s.height();
if (m_numberOfViewports > 1) {
if (m_bCommon) {
return 0;
}
else {
TQPoint vx(m_pKwinmodule->currentViewport(m_pKwinmodule->currentDesktop()));
return (realDesktop() * m_numberOfViewports) + ((vx.x() * vx.y()) - 1);
}
}
else {
return m_bCommon ? 0 : realDesktop();
}
}
/*
* Number of desktops changed
*/
void KBackgroundManager::slotChangeNumberOfDesktops(int num)
{
TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
m_numberOfViewports = s.width() * s.height();
if (m_numberOfViewports < 1) {
m_numberOfViewports = 1;
}
num = (num * m_numberOfViewports);
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], TQT_SIGNAL(imageDone(int)), TQT_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)
{
resizingDesktop = true;
TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
m_numberOfViewports = s.width() * s.height();
if (m_numberOfViewports < 1) {
m_numberOfViewports = 1;
}
if (desk == 0)
desk = realDesktop();
else
desk--;
// Lazy initialisation of # of desktops
if ((unsigned)(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports) >= m_Renderer.size())
slotChangeNumberOfDesktops( m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);
int edesk = effectiveDesktop();
m_Serial++;
// If the background is the same: do nothing
if ((m_Hash == m_Renderer[edesk]->hash()) && (desk != 0))
{
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;
if (desk == 0)
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())) && (desk != 0))
return;
}
renderBackground(edesk);
}
/*
* Call this when the viewport has been changed.
* Desk is in KWin convention: [1..desks], instead of [0..desks-1].
* 0 repaints the current viewport.
*/
void KBackgroundManager::slotChangeViewport(int desk, const TQPoint& viewport)
{
TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
m_numberOfViewports = s.width() * s.height();
if (m_numberOfViewports < 1) {
m_numberOfViewports = 1;
}
if (desk == 0)
desk = realDesktop();
else
desk--;
// Lazy initialisation of # of desktops
if ((unsigned)(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports) >= m_Renderer.size())
slotChangeNumberOfDesktops( m_pKwinmodule->numberOfDesktops() * m_numberOfViewports );
int edesk = effectiveDesktop();
m_Serial++;
// If the background is the same: do nothing
if ((m_Hash == m_Renderer[edesk]->hash()) && (desk != 0))
{
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;
if (desk == 0)
continue;
// kdDebug() << "slotChangeDesktop i=" << i << endl;
//KPixmap * viewport_background = new KPixmap(TQPixmap(m_Cache[i]->pixmap->width()*s.width(), m_Cache[i]->pixmap->height()*s.height()));
//setPixmap(viewport_background, m_Cache[i]->hash, i);
//delete viewport_background;
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())) && (desk != 0))
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)
{
KPixmap *ep = pm;
#ifdef COMPOSITE
if (argb_visual && (KDesktopSettings::backgroundOpacity() < 100
|| myApp->cmBackground()))
{
ep = m_tPixmap;
if (KDesktopSettings::backgroundOpacity() > 0 && pm
&& !myApp->cmBackground())
{
XRenderPictFormat *format;
format = XRenderFindStandardFormat (tqt_xdisplay(), PictStandardARGB32);
XRenderColor fillColor;
int color = KDesktopSettings::backgroundOpacity() * 0xffff / 100;
fillColor.red = color;
fillColor.green = color;
fillColor.blue = color;
fillColor.alpha = color;
Picture fill = XRenderCreateSolidFill (tqt_xdisplay(), &fillColor);
Picture src = XRenderCreatePicture(tqt_xdisplay(), pm->handle(),
format, 0, NULL);
Picture dst = XRenderCreatePicture(tqt_xdisplay(), ep->handle(),
format, 0, NULL);
XRenderComposite (tqt_xdisplay(), PictOpSrc, src, fill, dst, 0, 0, 0,
0, 0, 0, pm->width(), pm->height());
XRenderFreePicture (tqt_xdisplay(), fill);
XRenderFreePicture (tqt_xdisplay(), src);
XRenderFreePicture (tqt_xdisplay(), dst);
}
}
#endif
if (m_pDesktop)
{
TQScrollView* sv = dynamic_cast<TQScrollView*>( m_pDesktop );
if ( sv ) {
// Qt eats repaint events in this case :-((
sv->viewport()->update();
}
m_pDesktop->setErasePixmap(*ep);
m_pDesktop->repaint();
static bool root_cleared = false;
if( !root_cleared )
{ // clear the root window pixmap set by tdm
root_cleared = true;
TQTimer::singleShot( 0, this, TQT_SLOT( clearRoot()));
// but make the pixmap visible until m_pDesktop is visible
TQT_TQWIDGET(TDEApplication::desktop()->screen())->setErasePixmap(*ep);
TQT_TQWIDGET(TDEApplication::desktop()->screen())->erase();
}
}
else
{
TQT_TQWIDGET(TDEApplication::desktop()->screen())->setErasePixmap(*ep);
TQT_TQWIDGET(TDEApplication::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(tqt_xdisplay(), tqt_xrootwin(), prop_root, XA_PIXMAP, 32, PropModeReplace,
(unsigned char *) &bgPm, 1);
m_xrootpmap = bgPm;
m_Hash = hash;
m_Current = desk;
}
void KBackgroundManager::clearRoot()
{
TQT_TQWIDGET(TDEApplication::desktop()->screen())->setErasePixmap( TQPixmap());
TQT_TQWIDGET(TDEApplication::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 the Timeout is executed
*/
void KBackgroundManager::slotCrossFadeTimeout()
{
KVirtualBGRenderer *r = m_Renderer[fadeDesk];
if (crossInit) {
mBenchmark.start();
}
if (mAlpha <= 0.0 || mBenchmark.elapsed() > 300 ) {
bool do_cleanup = true;
mAlpha = 1;
m_crossTimer->stop();
KPixmap pixm(mNextScreen);
setPixmap(&pixm, r->hash(), fadeDesk);
return;
}
// Reset Timer
mBenchmark.start();
TQPixmap dst = crossFade(*mOldScreen, mNextScreen, mAlpha, crossInit);
KPixmap pixm(dst);
setPixmap(&pixm, r->hash(), fadeDesk);
mAlpha -=0.03;
crossInit = false;
}
/*
* This slot is called when a renderer is done.
*/
void KBackgroundManager::slotImageDone(int desk)
{
bool t_useViewports = 1;
TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
m_numberOfViewports = s.width() * s.height();
if (m_numberOfViewports < 1) {
m_numberOfViewports = 1;
t_useViewports = 0;
}
KPixmap *pm = new KPixmap();
KVirtualBGRenderer *r = m_Renderer[desk];
bool do_cleanup = true;
fadeDesk = desk;
mAlpha = 1.0;
int width,height;
*pm = r->pixmap();
// If current: paint it
bool current = (r->hash() == m_Renderer[effectiveDesktop()]->hash());
if (current)
{
//START
if (m_Renderer[effectiveDesktop()]->renderer(0)->crossFadeBg() && !m_Renderer[effectiveDesktop()]->renderer(0)->usingCrossXml() && !resizingDesktop) {
int mode = m_Renderer[effectiveDesktop()]->renderer(0)->wallpaperMode();
width = TQApplication::desktop()->screenGeometry().width();
height = TQApplication::desktop()->screenGeometry().height();
if (mode == KBackgroundSettings::NoWallpaper || mode == KBackgroundSettings::Tiled || mode == KBackgroundSettings::CenterTiled ){
mNextScreen = TQPixmap(width,height);
TQPainter p (&mNextScreen);
p.drawTiledPixmap(0,0,width,height,*pm);
} else {
mNextScreen = TQPixmap(*pm);
}
if (m_pDesktop){
mOldScreen = const_cast<TQPixmap *>( m_pDesktop->backgroundPixmap() );
}else{
mOldScreen = const_cast<TQPixmap *>(
TQApplication::desktop()->screen()->backgroundPixmap() );
}
//TODO Find a way to discover if CrossFade effect needs to run
if (mOldScreen){
crossInit = true;
m_crossTimer->start(70);
} else{
setPixmap(pm, r->hash(), desk);
}
}else{
setPixmap(pm, r->hash(), desk);
}
//ENDS HERE */
if (!m_bBgInitDone)
{
m_bBgInitDone = true;
emit initDone();
TQTimer::singleShot( 30000, this, TQT_SLOT( saveImages()));
do_cleanup = false;
}
}
if (m_bExport || !m_bCommon)
addCache(pm, r->hash(), desk);
else
delete pm;
if (current)
//exportBackground(desk, realDesktop());
exportBackground(desk, desk);
if( do_cleanup )
{
r->saveCacheFile();
r->cleanup();
}
resizingDesktop = false;
}
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 TQPixmap. For use in the pixmap cache.
*/
int KBackgroundManager::pixmapSize(TQPixmap *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 TQPixmapCache 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()
{
TQMemArray<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.
TQString KBackgroundManager::currentWallpaper(int desk)
{
//TODO Is the behaviour of this function appropriate for multiple screens?
KCrossBGRender *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(TQString 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)
{
KCrossBGRender *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(TQString wallpaper)
{
//TODO Is the behaviour of this function appropriate for multiple screens?
KCrossBGRender *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.
TQStringList KBackgroundManager::wallpaperFiles(int desk)
{
//TODO Is the behaviour of this function appropriate for multiple screens?
KCrossBGRender *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.
TQStringList KBackgroundManager::wallpaperList(int desk)
{
//TODO Is the behaviour of this function appropriate for multiple screens?
KCrossBGRender *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, TQString 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)
{
KCrossBGRender *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
TQT_TQWIDGET(TDEApplication::desktop()->screen())->erase();
}
void KBackgroundManager::desktopResized()
{
resizingDesktop = true;
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();
for (unsigned j=0; j<(r->numRenderers()); ++j) {
r->renderer(j)->desktopResized();
}
}
#ifdef COMPOSITE
if (m_tPixmap)
delete m_tPixmap;
m_tPixmap = new KPixmap(kapp->desktop()->size());
m_tPixmap->fill(TQColor(0, 0x0));
#endif
m_Hash = 0;
if( m_pDesktop ) {
m_pDesktop->resize( kapp->desktop()->geometry().size());
if (m_Renderer[effectiveDesktop()]->renderer(0)->usingCrossXml()){
m_Renderer[effectiveDesktop()]->renderer(0)->changeWallpaper();
}
}
// Repaint desktop
slotChangeDesktop(0);
repaintBackground();
// Redraw all desktops so that applications relying on exported data, e.g. kpager, continue to work properly
TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
m_numberOfViewports = s.width() * s.height();
if (m_numberOfViewports < 1) {
m_numberOfViewports = 1;
}
for (signed j=0;j<(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);j++) {
renderBackground(j);
}
}
// DCOP exported
void KBackgroundManager::setColor(const TQColor & c, bool isColorA)
{
//TODO Is the behaviour of this function appropriate for multiple screens?
for (unsigned i=0; i < m_Renderer[effectiveDesktop()]->numRenderers(); ++i)
{
KCrossBGRender *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);
}
#ifdef COMPOSITE
void KBackgroundManager::slotCmBackgroundChanged( bool )
{
m_tPixmap->fill(TQColor(0, 0x0));
m_Hash = 0;
slotChangeDesktop(0);
}
#endif
#include "bgmanager.moc"