TDE base libraries and programs
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.

bgmanager.cc 27KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  1. /* vi: ts=8 sts=4 sw=4
  2. * kate: space-indent on; tab-width 8; indent-width 4; indent-mode cstyle;
  3. *
  4. * This file is part of the KDE project, module kdesktop.
  5. * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
  6. *
  7. * You can Freely distribute this program under the GNU General Public
  8. * License. See the file "COPYING" for the exact licensing terms.
  9. */
  10. #include <config.h>
  11. #include "bgrender.h"
  12. #include "bgmanager.h"
  13. #include "bgdefaults.h"
  14. #include "kdesktopsettings.h"
  15. #include "bgsettings.h"
  16. #include "kdesktopapp.h"
  17. #include <assert.h>
  18. #include <tqtimer.h>
  19. #include <tqscrollview.h>
  20. #include <kiconloader.h>
  21. #include <tdeconfig.h>
  22. #include <twin.h>
  23. #include <tdeapplication.h>
  24. #include <kdebug.h>
  25. #include <kipc.h>
  26. #include <tdepopupmenu.h>
  27. #include <twinmodule.h>
  28. #include <krootpixmap.h>
  29. #include <X11/X.h>
  30. #include <X11/Xlib.h>
  31. #include <X11/Xatom.h>
  32. #ifndef None
  33. #define None 0L
  34. #endif
  35. #ifdef COMPOSITE
  36. # include <X11/Xlib.h>
  37. # include <X11/extensions/Xrender.h>
  38. # include <fixx11h.h>
  39. #endif
  40. #include "pixmapserver.h"
  41. template class TQPtrVector<KBackgroundRenderer>;
  42. template class TQPtrVector<KBackgroundCacheEntry>;
  43. template class TQMemArray<int>;
  44. static Atom prop_root;
  45. static bool properties_inited = false;
  46. extern bool argb_visual;
  47. extern KDesktopApp *myApp;
  48. /**** KBackgroundManager ****/
  49. KBackgroundManager::KBackgroundManager(TQWidget *desktop, KWinModule* twinModule)
  50. : KBackgroundIface()
  51. {
  52. if( !properties_inited )
  53. {
  54. prop_root = XInternAtom(tqt_xdisplay(), "_XROOTPMAP_ID", False);
  55. properties_inited = true;
  56. }
  57. m_bBgInitDone = false;
  58. m_bEnabled = true;
  59. m_pDesktop = desktop;
  60. if (desktop == 0L)
  61. desktop = TQT_TQWIDGET(TDEApplication::desktop()->screen());
  62. m_Renderer.resize( 1 );
  63. m_Cache.resize( 1 );
  64. m_Serial = 0; m_Hash = 0;
  65. m_pConfig = TDEGlobal::config();
  66. m_bExport = m_bCommon = m_bInit = false;
  67. m_pKwinmodule = twinModule;
  68. m_pPixmapServer = new KPixmapServer();
  69. m_xrootpmap = None;
  70. for (unsigned i=0; i<m_Renderer.size(); i++)
  71. {
  72. m_Cache.insert(i, new KBackgroundCacheEntry);
  73. m_Cache[i]->pixmap = 0L;
  74. m_Cache[i]->hash = 0;
  75. m_Cache[i]->exp_from = -1;
  76. m_Renderer.insert (i, new KVirtualBGRenderer(i,m_pConfig));
  77. connect(m_Renderer[i], TQT_SIGNAL(imageDone(int)), TQT_SLOT(slotImageDone(int)));
  78. m_Renderer[i]->enableTiling( true ); // optimize
  79. }
  80. #ifdef COMPOSITE
  81. m_tPixmap = new KPixmap(kapp->desktop()->size());
  82. m_tPixmap->fill(TQColor(0, 0x0));
  83. connect(myApp, TQT_SIGNAL(cmBackgroundChanged( bool )),
  84. TQT_SLOT(slotCmBackgroundChanged( bool )));
  85. #endif
  86. configure();
  87. m_pTimer = new TQTimer(this);
  88. connect(m_pTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimeout()));
  89. m_pTimer->start( 60000 );
  90. connect(m_pKwinmodule, TQT_SIGNAL(currentDesktopChanged(int)),
  91. TQT_SLOT(slotChangeDesktop(int)));
  92. connect(m_pKwinmodule, TQT_SIGNAL(numberOfDesktopsChanged(int)),
  93. TQT_SLOT(slotChangeNumberOfDesktops(int)));
  94. connect(m_pKwinmodule, TQT_SIGNAL(currentDesktopViewportChanged(int, const TQPoint&)),
  95. TQT_SLOT(slotChangeViewport(int, const TQPoint&)));
  96. #if (TQT_VERSION-0 >= 0x030200)
  97. connect( kapp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( desktopResized())); // RANDR support
  98. #endif
  99. TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
  100. m_numberOfViewports = s.width() * s.height();
  101. if (m_numberOfViewports < 1) {
  102. m_numberOfViewports = 1;
  103. }
  104. for (signed j=0;j<(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);j++) {
  105. renderBackground(j);
  106. }
  107. }
  108. KBackgroundManager::~KBackgroundManager()
  109. {
  110. for (unsigned i=0; i<m_Renderer.size(); i++)
  111. delete m_Renderer[i];
  112. //delete m_pConfig; Very bad idea, this is TDEGlobal::config !
  113. delete m_pPixmapServer;
  114. delete m_pTimer;
  115. // clear the Esetroot properties, as the pixmaps they refer to are going away...
  116. Pixmap pm = None;
  117. Atom type;
  118. int format;
  119. unsigned long length, after;
  120. unsigned char* data_root;
  121. if( XGetWindowProperty( tqt_xdisplay(), tqt_xrootwin(), prop_root, 0L, 1L, False, AnyPropertyType,
  122. &type, &format, &length, &after, &data_root) == Success && data_root != NULL )
  123. {
  124. if (type == XA_PIXMAP)
  125. pm = *((Pixmap*)data_root);
  126. XFree( data_root );
  127. }
  128. // only if it's our pixmap
  129. if( pm == m_xrootpmap )
  130. XDeleteProperty(tqt_xdisplay(), tqt_xrootwin(), prop_root);
  131. m_xrootpmap = None;
  132. if (m_bExport)
  133. return;
  134. for (unsigned i=0; i<m_Cache.size(); i++)
  135. {
  136. delete m_Cache[i]->pixmap;
  137. delete m_Cache[i];
  138. }
  139. }
  140. void KBackgroundManager::applyExport(bool exp)
  141. {
  142. if (exp == m_bExport)
  143. return;
  144. // If export mode changed from true -> false, remove all shared pixmaps.
  145. // If it changed false -> true force a redraw because the current screen
  146. // image might not have an associated pixmap in the cache.
  147. if (!exp)
  148. {
  149. for (unsigned i=0; i<m_Cache.size(); i++)
  150. removeCache(i);
  151. } else
  152. m_Hash = 0;
  153. m_bExport = exp;
  154. }
  155. void KBackgroundManager::applyCommon(bool common)
  156. {
  157. if (common == m_bCommon)
  158. return;
  159. m_bCommon = common;
  160. // If common changed from false -> true, remove all cache entries, except
  161. // at index 0 if exports are on.
  162. if (m_bCommon)
  163. {
  164. if (!m_bExport)
  165. removeCache(0);
  166. for (unsigned i=1; i<m_Cache.size(); i++)
  167. removeCache(i);
  168. }
  169. }
  170. void KBackgroundManager::applyCache(bool limit, int size)
  171. {
  172. m_bLimitCache = limit;
  173. m_CacheLimit = size;
  174. freeCache(0);
  175. }
  176. /*
  177. * Call this when the configuration has changed.
  178. * This method is exported with DCOP.
  179. */
  180. void KBackgroundManager::configure()
  181. {
  182. // Global settings
  183. m_pConfig->reparseConfiguration();
  184. KDesktopSettings::self()->readConfig();
  185. // Read individual settings
  186. KVirtualBGRenderer *r;
  187. for (unsigned i=0; i<m_Renderer.size(); i++)
  188. {
  189. r = m_Renderer[i];
  190. int ohash = r->hash();
  191. r->load(i,false);
  192. if ((r->hash() != ohash))
  193. removeCache(i);
  194. }
  195. applyCommon(KDesktopSettings::commonDesktop());
  196. bool limit = KDesktopSettings::limitCache();
  197. int size = KDesktopSettings::cacheSize() * 1024;
  198. applyCache(limit, size);
  199. // Repaint desktop
  200. slotChangeDesktop(0);
  201. // Redraw all desktops so that applications relying on exported data, e.g. kpager, continue to work properly
  202. TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
  203. m_numberOfViewports = s.width() * s.height();
  204. if (m_numberOfViewports < 1) {
  205. m_numberOfViewports = 1;
  206. }
  207. for (signed j=0;j<(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);j++) {
  208. renderBackground(j);
  209. }
  210. }
  211. int KBackgroundManager::realDesktop()
  212. {
  213. int desk = m_pKwinmodule->currentDesktop();
  214. if (desk) desk--;
  215. return desk;
  216. }
  217. int KBackgroundManager::effectiveDesktop()
  218. {
  219. TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
  220. m_numberOfViewports = s.width() * s.height();
  221. if (m_numberOfViewports > 1) {
  222. if (m_bCommon) {
  223. return 0;
  224. }
  225. else {
  226. TQPoint vx(m_pKwinmodule->currentViewport(m_pKwinmodule->currentDesktop()));
  227. return (realDesktop() * m_numberOfViewports) + ((vx.x() * vx.y()) - 1);
  228. }
  229. }
  230. else {
  231. return m_bCommon ? 0 : realDesktop();
  232. }
  233. }
  234. /*
  235. * Number of desktops changed
  236. */
  237. void KBackgroundManager::slotChangeNumberOfDesktops(int num)
  238. {
  239. TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
  240. m_numberOfViewports = s.width() * s.height();
  241. if (m_numberOfViewports < 1) {
  242. m_numberOfViewports = 1;
  243. }
  244. num = (num * m_numberOfViewports);
  245. if (m_Renderer.size() == (unsigned) num)
  246. return;
  247. if (m_Renderer.size() > (unsigned) num)
  248. {
  249. for (unsigned i=num; i<m_Renderer.size(); i++)
  250. {
  251. if (m_Renderer[i]->isActive())
  252. m_Renderer[i]->stop();
  253. delete m_Renderer[i];
  254. removeCache(i);
  255. }
  256. for (unsigned i=num; i<m_Renderer.size(); i++)
  257. delete m_Cache[i];
  258. m_Renderer.resize(num);
  259. m_Cache.resize(num);
  260. } else
  261. {
  262. // allocate new renderers and caches
  263. int oldsz = m_Renderer.size();
  264. m_Renderer.resize(num);
  265. m_Cache.resize(num);
  266. for (int i=oldsz; i<num; i++)
  267. {
  268. m_Cache.insert(i, new KBackgroundCacheEntry);
  269. m_Cache[i]->pixmap = 0L;
  270. m_Cache[i]->hash = 0;
  271. m_Cache[i]->exp_from = -1;
  272. m_Renderer.insert(i, new KVirtualBGRenderer(i,m_pConfig));
  273. connect(m_Renderer[i], TQT_SIGNAL(imageDone(int)), TQT_SLOT(slotImageDone(int)));
  274. m_Renderer[i]->enableTiling( true ); // optimize
  275. }
  276. }
  277. }
  278. /*
  279. * Call this when the desktop has been changed.
  280. * Desk is in KWin convention: [1..desks], instead of [0..desks-1].
  281. * 0 repaints the current desktop.
  282. */
  283. void KBackgroundManager::slotChangeDesktop(int desk)
  284. {
  285. TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
  286. m_numberOfViewports = s.width() * s.height();
  287. if (m_numberOfViewports < 1) {
  288. m_numberOfViewports = 1;
  289. }
  290. if (desk == 0)
  291. desk = realDesktop();
  292. else
  293. desk--;
  294. // Lazy initialisation of # of desktops
  295. if ((unsigned)(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports) >= m_Renderer.size())
  296. slotChangeNumberOfDesktops( m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);
  297. int edesk = effectiveDesktop();
  298. m_Serial++;
  299. // If the background is the same: do nothing
  300. if ((m_Hash == m_Renderer[edesk]->hash()) && (desk != 0))
  301. {
  302. exportBackground(m_Current, desk);
  303. return;
  304. }
  305. m_Renderer[edesk]->stop();
  306. m_Renderer[edesk]->cleanup();
  307. // If we have the background already rendered: set it
  308. for (unsigned i=0; i<m_Cache.size(); i++)
  309. {
  310. if (!m_Cache[i]->pixmap)
  311. continue;
  312. if (m_Cache[i]->hash != m_Renderer[edesk]->hash())
  313. continue;
  314. if (desk == 0)
  315. continue;
  316. // kdDebug() << "slotChangeDesktop i=" << i << endl;
  317. setPixmap(m_Cache[i]->pixmap, m_Cache[i]->hash, i);
  318. m_Cache[i]->atime = m_Serial;
  319. exportBackground(i, desk);
  320. return;
  321. }
  322. // Do we have this or an identical config already running?
  323. for (unsigned i=0; i<m_Renderer.size(); i++)
  324. {
  325. if (((m_Renderer[i]->hash() == m_Renderer[edesk]->hash()) && (m_Renderer[i]->isActive())) && (desk != 0))
  326. return;
  327. }
  328. renderBackground(edesk);
  329. }
  330. /*
  331. * Call this when the viewport has been changed.
  332. * Desk is in KWin convention: [1..desks], instead of [0..desks-1].
  333. * 0 repaints the current viewport.
  334. */
  335. void KBackgroundManager::slotChangeViewport(int desk, const TQPoint& viewport)
  336. {
  337. TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
  338. m_numberOfViewports = s.width() * s.height();
  339. if (m_numberOfViewports < 1) {
  340. m_numberOfViewports = 1;
  341. }
  342. if (desk == 0)
  343. desk = realDesktop();
  344. else
  345. desk--;
  346. // Lazy initialisation of # of desktops
  347. if ((unsigned)(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports) >= m_Renderer.size())
  348. slotChangeNumberOfDesktops( m_pKwinmodule->numberOfDesktops() * m_numberOfViewports );
  349. int edesk = effectiveDesktop();
  350. m_Serial++;
  351. // If the background is the same: do nothing
  352. if ((m_Hash == m_Renderer[edesk]->hash()) && (desk != 0))
  353. {
  354. exportBackground(m_Current, desk);
  355. return;
  356. }
  357. m_Renderer[edesk]->stop();
  358. m_Renderer[edesk]->cleanup();
  359. // If we have the background already rendered: set it
  360. for (unsigned i=0; i<m_Cache.size(); i++)
  361. {
  362. if (!m_Cache[i]->pixmap)
  363. continue;
  364. if (m_Cache[i]->hash != m_Renderer[edesk]->hash())
  365. continue;
  366. if (desk == 0)
  367. continue;
  368. // kdDebug() << "slotChangeDesktop i=" << i << endl;
  369. //KPixmap * viewport_background = new KPixmap(TQPixmap(m_Cache[i]->pixmap->width()*s.width(), m_Cache[i]->pixmap->height()*s.height()));
  370. //setPixmap(viewport_background, m_Cache[i]->hash, i);
  371. //delete viewport_background;
  372. setPixmap(m_Cache[i]->pixmap, m_Cache[i]->hash, i);
  373. m_Cache[i]->atime = m_Serial;
  374. exportBackground(i, desk);
  375. return;
  376. }
  377. // Do we have this or an identical config already running?
  378. for (unsigned i=0; i<m_Renderer.size(); i++)
  379. {
  380. if (((m_Renderer[i]->hash() == m_Renderer[edesk]->hash()) && (m_Renderer[i]->isActive())) && (desk != 0))
  381. return;
  382. }
  383. renderBackground(edesk);
  384. }
  385. /*
  386. * Share a desktop pixmap.
  387. */
  388. void KBackgroundManager::exportBackground(int pixmap, int desk)
  389. {
  390. if (!m_bExport || (m_Cache[desk]->exp_from == pixmap))
  391. return;
  392. m_Cache[desk]->exp_from = pixmap;
  393. m_pPixmapServer->add(KRootPixmap::pixmapName(desk+1),
  394. m_Cache[pixmap]->pixmap);
  395. KIPC::sendMessageAll(KIPC::BackgroundChanged, desk+1);
  396. }
  397. /*
  398. * Paint the pixmap to the root window.
  399. */
  400. void KBackgroundManager::setPixmap(KPixmap *pm, int hash, int desk)
  401. {
  402. KPixmap *ep = pm;
  403. #ifdef COMPOSITE
  404. if (argb_visual && (KDesktopSettings::backgroundOpacity() < 100
  405. || myApp->cmBackground()))
  406. {
  407. ep = m_tPixmap;
  408. if (KDesktopSettings::backgroundOpacity() > 0 && pm
  409. && !myApp->cmBackground())
  410. {
  411. XRenderPictFormat *format;
  412. format = XRenderFindStandardFormat (tqt_xdisplay(), PictStandardARGB32);
  413. XRenderColor fillColor;
  414. int color = KDesktopSettings::backgroundOpacity() * 0xffff / 100;
  415. fillColor.red = color;
  416. fillColor.green = color;
  417. fillColor.blue = color;
  418. fillColor.alpha = color;
  419. Picture fill = XRenderCreateSolidFill (tqt_xdisplay(), &fillColor);
  420. Picture src = XRenderCreatePicture(tqt_xdisplay(), pm->handle(),
  421. format, 0, NULL);
  422. Picture dst = XRenderCreatePicture(tqt_xdisplay(), ep->handle(),
  423. format, 0, NULL);
  424. XRenderComposite (tqt_xdisplay(), PictOpSrc, src, fill, dst, 0, 0, 0,
  425. 0, 0, 0, pm->width(), pm->height());
  426. XRenderFreePicture (tqt_xdisplay(), fill);
  427. XRenderFreePicture (tqt_xdisplay(), src);
  428. XRenderFreePicture (tqt_xdisplay(), dst);
  429. }
  430. }
  431. #endif
  432. if (m_pDesktop)
  433. {
  434. TQScrollView* sv = dynamic_cast<TQScrollView*>( m_pDesktop );
  435. if ( sv ) {
  436. // Qt eats repaint events in this case :-((
  437. sv->viewport()->update();
  438. }
  439. m_pDesktop->setErasePixmap(*ep);
  440. m_pDesktop->repaint();
  441. static bool root_cleared = false;
  442. if( !root_cleared )
  443. { // clear the root window pixmap set by tdm
  444. root_cleared = true;
  445. TQTimer::singleShot( 0, this, TQT_SLOT( clearRoot()));
  446. // but make the pixmap visible until m_pDesktop is visible
  447. TQT_TQWIDGET(TDEApplication::desktop()->screen())->setErasePixmap(*ep);
  448. TQT_TQWIDGET(TDEApplication::desktop()->screen())->erase();
  449. }
  450. }
  451. else
  452. {
  453. TQT_TQWIDGET(TDEApplication::desktop()->screen())->setErasePixmap(*ep);
  454. TQT_TQWIDGET(TDEApplication::desktop()->screen())->erase();
  455. }
  456. // and export it via Esetroot-style for gnome/GTK apps to share in the pretties
  457. Pixmap bgPm = pm->handle(); // fetch the actual X handle to it
  458. //kdDebug() << "Esetroot compat: setting pixmap to " << bgPm << endl;
  459. // don't set the ESETROOT_PMAP_ID property - that would result in possible XKillClient()
  460. // done on kdesktop
  461. XChangeProperty(tqt_xdisplay(), tqt_xrootwin(), prop_root, XA_PIXMAP, 32, PropModeReplace,
  462. (unsigned char *) &bgPm, 1);
  463. m_xrootpmap = bgPm;
  464. m_Hash = hash;
  465. m_Current = desk;
  466. }
  467. void KBackgroundManager::clearRoot()
  468. {
  469. TQT_TQWIDGET(TDEApplication::desktop()->screen())->setErasePixmap( TQPixmap());
  470. TQT_TQWIDGET(TDEApplication::desktop()->screen())->erase();
  471. }
  472. /*
  473. * Start the render of a desktop background.
  474. */
  475. void KBackgroundManager::renderBackground(int desk)
  476. {
  477. KVirtualBGRenderer *r = m_Renderer[desk];
  478. if (r->isActive())
  479. {
  480. kdDebug() << "renderer " << desk << " already active" << endl;
  481. return;
  482. }
  483. r->start();
  484. }
  485. /*
  486. * This slot is called when a renderer is done.
  487. */
  488. void KBackgroundManager::slotImageDone(int desk)
  489. {
  490. bool t_useViewports = 1;
  491. TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
  492. m_numberOfViewports = s.width() * s.height();
  493. if (m_numberOfViewports < 1) {
  494. m_numberOfViewports = 1;
  495. t_useViewports = 0;
  496. }
  497. KPixmap *pm = new KPixmap();
  498. KVirtualBGRenderer *r = m_Renderer[desk];
  499. bool do_cleanup = true;
  500. *pm = r->pixmap();
  501. // If current: paint it
  502. bool current = (r->hash() == m_Renderer[effectiveDesktop()]->hash());
  503. if (current)
  504. {
  505. //KPixmap * viewport_background = new KPixmap(TQPixmap(pm->width()*s.width(), pm->height()*s.height()));
  506. //printf("slotImageDone(): x: %d y: %d\n", viewport_background->size().width(), viewport_background->size().height());
  507. //setPixmap(viewport_background, r->hash(), desk);
  508. //delete viewport_background;
  509. setPixmap(pm, r->hash(), desk);
  510. if (!m_bBgInitDone)
  511. {
  512. m_bBgInitDone = true;
  513. emit initDone();
  514. TQTimer::singleShot( 30000, this, TQT_SLOT( saveImages()));
  515. do_cleanup = false;
  516. }
  517. }
  518. if (m_bExport || !m_bCommon)
  519. addCache(pm, r->hash(), desk);
  520. else
  521. delete pm;
  522. if (current)
  523. //exportBackground(desk, realDesktop());
  524. exportBackground(desk, desk);
  525. if( do_cleanup )
  526. {
  527. r->saveCacheFile();
  528. r->cleanup();
  529. }
  530. }
  531. void KBackgroundManager::saveImages()
  532. {
  533. for (unsigned i=0; i<m_Renderer.size(); i++)
  534. {
  535. m_Renderer[i]->saveCacheFile();
  536. m_Renderer[i]->cleanup();
  537. }
  538. }
  539. /*
  540. * Size in bytes of a TQPixmap. For use in the pixmap cache.
  541. */
  542. int KBackgroundManager::pixmapSize(TQPixmap *pm)
  543. {
  544. return (pm->width() * pm->height()) * ((pm->depth() + 7) / 8);
  545. }
  546. /*
  547. * Total size of the pixmap cache.
  548. */
  549. int KBackgroundManager::cacheSize()
  550. {
  551. int total = 0;
  552. for (unsigned i=0; i<m_Cache.size(); i++)
  553. {
  554. if (m_Cache[i]->pixmap)
  555. total += pixmapSize(m_Cache[i]->pixmap);
  556. }
  557. return total;
  558. }
  559. /*
  560. * Remove an entry from the pixmap cache.
  561. */
  562. void KBackgroundManager::removeCache(int desk)
  563. {
  564. if (m_bExport)
  565. m_pPixmapServer->remove(KRootPixmap::pixmapName(desk+1));
  566. else
  567. delete m_Cache[desk]->pixmap;
  568. m_Cache[desk]->pixmap = 0L;
  569. m_Cache[desk]->hash = 0;
  570. m_Cache[desk]->exp_from = -1;
  571. m_Cache[desk]->atime = 0;
  572. // Remove cache entries pointing to the removed entry
  573. for (unsigned i=0; i<m_Cache.size(); i++)
  574. {
  575. if (m_Cache[i]->exp_from == desk)
  576. {
  577. assert(m_bExport);
  578. m_Cache[i]->exp_from = -1;
  579. m_pPixmapServer->remove(KRootPixmap::pixmapName(i+1));
  580. }
  581. }
  582. }
  583. /*
  584. * Try to free up to size bytes from the cache.
  585. */
  586. bool KBackgroundManager::freeCache(int size)
  587. {
  588. if (m_bExport || !m_bLimitCache)
  589. return true;
  590. // If it doesn't fit at all, return now.
  591. if (size > m_CacheLimit)
  592. return false;
  593. // If cache is too full, purge it (LRU)
  594. while (size+cacheSize() > m_CacheLimit)
  595. {
  596. int j, min;
  597. min = m_Serial+1; j = 0;
  598. for (unsigned i=0; i<m_Cache.size(); i++)
  599. {
  600. if (m_Cache[i]->pixmap && (m_Cache[i]->atime < min))
  601. {
  602. min = m_Cache[i]->atime;
  603. j = i;
  604. }
  605. }
  606. removeCache(j);
  607. }
  608. return true;
  609. }
  610. /*
  611. * Try to add a pixmap to the pixmap cache. We don't use TQPixmapCache here
  612. * because if we're exporting pixmaps, this needs special care.
  613. */
  614. void KBackgroundManager::addCache(KPixmap *pm, int hash, int desk)
  615. {
  616. if (m_Cache[desk]->pixmap)
  617. removeCache(desk);
  618. if (m_bLimitCache && !m_bExport && !freeCache(pixmapSize(pm)))
  619. {
  620. // pixmap does not fit in cache
  621. delete pm;
  622. return;
  623. }
  624. m_Cache[desk]->pixmap = pm;
  625. m_Cache[desk]->hash = hash;
  626. m_Cache[desk]->atime = m_Serial;
  627. m_Cache[desk]->exp_from = -1;
  628. exportBackground(desk, desk);
  629. }
  630. /*
  631. * Called every minute to check if we need to rerun a background program.
  632. * or change a wallpaper.
  633. */
  634. void KBackgroundManager::slotTimeout()
  635. {
  636. TQMemArray<int> running(m_Renderer.size());
  637. running.fill(0);
  638. int NumDesks = m_Renderer.size();
  639. if (m_bCommon)
  640. NumDesks = 1;
  641. int edesk = effectiveDesktop();
  642. for (int i=0; i<NumDesks; i++)
  643. {
  644. KVirtualBGRenderer *r = m_Renderer[i];
  645. bool change = false;
  646. if (r->needProgramUpdate())
  647. {
  648. r->programUpdate();
  649. change = true;
  650. }
  651. if (r->needWallpaperChange())
  652. {
  653. r->changeWallpaper();
  654. change = true;
  655. }
  656. if (change && (i == edesk))
  657. {
  658. running[i] = r->hash();
  659. r->start();
  660. }
  661. }
  662. }
  663. // Return a valid desk number.
  664. int KBackgroundManager::validateDesk(int desk)
  665. {
  666. if (desk > (int)m_Renderer.size())
  667. slotChangeNumberOfDesktops( m_pKwinmodule->numberOfDesktops() );
  668. if ( (desk <= 0) || (desk > (int)m_Renderer.size()) )
  669. return realDesktop();
  670. return desk - 1;
  671. }
  672. // DCOP exported
  673. // Return current wallpaper for specified desk.
  674. // 0 is for the current visible desktop.
  675. TQString KBackgroundManager::currentWallpaper(int desk)
  676. {
  677. //TODO Is the behaviour of this function appropriate for multiple screens?
  678. KBackgroundRenderer *r = m_Renderer[validateDesk(desk)]->renderer(0);
  679. return r->currentWallpaper();
  680. }
  681. // DCOP exported
  682. void KBackgroundManager::changeWallpaper()
  683. {
  684. KVirtualBGRenderer *r = m_Renderer[effectiveDesktop()];
  685. r->changeWallpaper();
  686. slotChangeDesktop(0);
  687. }
  688. // DCOP exported
  689. void KBackgroundManager::setExport(int _export)
  690. {
  691. kdDebug() << "KBackgroundManager enabling exports.\n";
  692. applyExport(_export);
  693. slotChangeDesktop(0);
  694. }
  695. // DCOP exported
  696. void KBackgroundManager::setCommon(int common)
  697. {
  698. applyCommon(common);
  699. KDesktopSettings::setCommonDesktop( m_bCommon );
  700. KDesktopSettings::writeConfig();
  701. slotChangeDesktop(0);
  702. }
  703. // DCOP exported
  704. void KBackgroundManager::setWallpaper(TQString wallpaper, int mode)
  705. {
  706. if (mode < 0 || mode >= KBackgroundSettings::lastWallpaperMode) {
  707. kdDebug() << "Invalid background mode " << mode << " passed to " << k_funcinfo << "\n";
  708. return;
  709. }
  710. //TODO Is the behaviour of this function appropriate for multiple screens?
  711. for (unsigned i=0; i < m_Renderer[effectiveDesktop()]->numRenderers(); ++i)
  712. {
  713. KBackgroundRenderer *r = m_Renderer[effectiveDesktop()]->renderer(i);
  714. r->stop();
  715. r->setWallpaperMode(mode);
  716. r->setMultiWallpaperMode(KBackgroundSettings::NoMulti);
  717. r->setWallpaper(wallpaper);
  718. r->writeSettings();
  719. }
  720. slotChangeDesktop(0);
  721. }
  722. void KBackgroundManager::setWallpaper(TQString wallpaper)
  723. {
  724. //TODO Is the behaviour of this function appropriate for multiple screens?
  725. KBackgroundRenderer *r = m_Renderer[effectiveDesktop()]->renderer(0);
  726. int mode = r->wallpaperMode();
  727. if (mode == KBackgroundSettings::NoWallpaper)
  728. mode = KBackgroundSettings::Tiled;
  729. setWallpaper(wallpaper, mode);
  730. }
  731. // DCOP exported
  732. // Returns the filenames of all wallpaper entries for specified desk
  733. // 0 is for current visible desktop.
  734. TQStringList KBackgroundManager::wallpaperFiles(int desk)
  735. {
  736. //TODO Is the behaviour of this function appropriate for multiple screens?
  737. KBackgroundRenderer *r = m_Renderer[validateDesk(desk)]->renderer(0);
  738. return r->wallpaperFiles();
  739. }
  740. // DCOP exported
  741. // Returns the list of wallpaper entries (viewable in background slide
  742. // show window) for specified desk. 0 is for current visible desktop.
  743. TQStringList KBackgroundManager::wallpaperList(int desk)
  744. {
  745. //TODO Is the behaviour of this function appropriate for multiple screens?
  746. KBackgroundRenderer *r = m_Renderer[validateDesk(desk)]->renderer(0);;
  747. return r->wallpaperList();
  748. }
  749. // DCOP exported
  750. void KBackgroundManager::setCache( int bLimit, int size )
  751. {
  752. applyCache( bLimit, size*1024 );
  753. KDesktopSettings::setLimitCache( (bool) bLimit );
  754. KDesktopSettings::setCacheSize( size );
  755. KDesktopSettings::writeConfig();
  756. }
  757. // DCOP exported
  758. void KBackgroundManager::setWallpaper(int desk, TQString wallpaper, int mode)
  759. {
  760. if (mode < 0 || mode >= KBackgroundSettings::lastWallpaperMode) {
  761. kdDebug() << "Invalid background mode " << mode << " passed to " << k_funcinfo << "\n";
  762. return;
  763. }
  764. int sdesk = validateDesk(desk);
  765. //TODO Is the behaviour of this function appropriate for multiple screens?
  766. for (unsigned i=0; i < m_Renderer[sdesk]->numRenderers(); ++i)
  767. {
  768. KBackgroundRenderer *r = m_Renderer[sdesk]->renderer(i);
  769. setCommon(false); // Force each desktop to have it's own wallpaper
  770. r->stop();
  771. r->setWallpaperMode(mode);
  772. r->setMultiWallpaperMode(KBackgroundSettings::NoMulti);
  773. r->setWallpaper(wallpaper);
  774. r->writeSettings();
  775. }
  776. slotChangeDesktop(sdesk);
  777. }
  778. void KBackgroundManager::repaintBackground()
  779. {
  780. if (m_pDesktop)
  781. m_pDesktop->repaint();
  782. else
  783. TQT_TQWIDGET(TDEApplication::desktop()->screen())->erase();
  784. }
  785. void KBackgroundManager::desktopResized()
  786. {
  787. for (unsigned i=0; i<m_Renderer.size(); i++)
  788. {
  789. KVirtualBGRenderer * r = m_Renderer[i];
  790. if( r->isActive())
  791. r->stop();
  792. removeCache(i);
  793. // make the renderer update its desktop size
  794. r->desktopResized();
  795. for (unsigned j=0; j<(r->numRenderers()); ++j) {
  796. r->renderer(j)->desktopResized();
  797. }
  798. }
  799. #ifdef COMPOSITE
  800. if (m_tPixmap)
  801. delete m_tPixmap;
  802. m_tPixmap = new KPixmap(kapp->desktop()->size());
  803. m_tPixmap->fill(TQColor(0, 0x0));
  804. #endif
  805. m_Hash = 0;
  806. if( m_pDesktop )
  807. m_pDesktop->resize( kapp->desktop()->geometry().size());
  808. // Repaint desktop
  809. slotChangeDesktop(0);
  810. repaintBackground();
  811. // Redraw all desktops so that applications relying on exported data, e.g. kpager, continue to work properly
  812. TQSize s(m_pKwinmodule->numberOfViewports(m_pKwinmodule->currentDesktop()));
  813. m_numberOfViewports = s.width() * s.height();
  814. if (m_numberOfViewports < 1) {
  815. m_numberOfViewports = 1;
  816. }
  817. for (signed j=0;j<(m_pKwinmodule->numberOfDesktops() * m_numberOfViewports);j++) {
  818. renderBackground(j);
  819. }
  820. }
  821. // DCOP exported
  822. void KBackgroundManager::setColor(const TQColor & c, bool isColorA)
  823. {
  824. //TODO Is the behaviour of this function appropriate for multiple screens?
  825. for (unsigned i=0; i < m_Renderer[effectiveDesktop()]->numRenderers(); ++i)
  826. {
  827. KBackgroundRenderer *r = m_Renderer[effectiveDesktop()]->renderer(i);
  828. r->stop();
  829. if (isColorA)
  830. r->setColorA(c);
  831. else
  832. r->setColorB(c);
  833. int mode = r->backgroundMode();
  834. if (mode == KBackgroundSettings::Program)
  835. mode = KBackgroundSettings::Flat;
  836. if (!isColorA && (mode == KBackgroundSettings::Flat))
  837. mode = KBackgroundSettings::VerticalGradient;
  838. r->setBackgroundMode(mode);
  839. r->writeSettings();
  840. }
  841. slotChangeDesktop(0);
  842. }
  843. void KBackgroundManager::setBackgroundEnabled( const bool enable )
  844. {
  845. if (m_bEnabled == enable)
  846. return;
  847. m_bEnabled= enable;
  848. int NumDesks = m_Renderer.size();
  849. if (m_bCommon)
  850. NumDesks = 1;
  851. for (int i=0; i<NumDesks; i++)
  852. {
  853. m_Renderer[i]->setEnabled(enable);
  854. }
  855. slotChangeDesktop(0);
  856. }
  857. #ifdef COMPOSITE
  858. void KBackgroundManager::slotCmBackgroundChanged( bool )
  859. {
  860. m_tPixmap->fill(TQColor(0, 0x0));
  861. m_Hash = 0;
  862. slotChangeDesktop(0);
  863. }
  864. #endif
  865. #include "bgmanager.moc"