summaryrefslogtreecommitdiffstats
path: root/superkaramba/src/taskmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'superkaramba/src/taskmanager.cpp')
-rw-r--r--superkaramba/src/taskmanager.cpp829
1 files changed, 829 insertions, 0 deletions
diff --git a/superkaramba/src/taskmanager.cpp b/superkaramba/src/taskmanager.cpp
new file mode 100644
index 0000000..c1f2568
--- /dev/null
+++ b/superkaramba/src/taskmanager.cpp
@@ -0,0 +1,829 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <elter@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <kwinmodule.h>
+#include <netwm.h>
+#include <qtimer.h>
+#include <qimage.h>
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "taskmanager.h"
+#include "taskmanager.moc"
+
+template class QPtrList<Task>;
+
+// Hack: create a global KWinModule without a parent. We
+// can't make it a child of TaskManager because more than one
+// TaskManager might be created. We can't make it a class
+// variable without changing Task, which also uses it.
+// So, we'll leak a little memory, but it's better than crashing.
+// The real problem is that KWinModule should be a singleton.
+KWinModule* kwin_module = 0;
+
+TaskManager::TaskManager(QObject *parent, const char *name)
+ : QObject(parent, name), _active(0), _startup_info( NULL )
+{
+
+ kwin_module = new KWinModule();
+
+// KGlobal::locale()->insertCatalogue("libtaskmanager");
+ connect(kwin_module, SIGNAL(windowAdded(WId)), SLOT(windowAdded(WId)));
+ connect(kwin_module, SIGNAL(windowRemoved(WId)), SLOT(windowRemoved(WId)));
+ connect(kwin_module, SIGNAL(activeWindowChanged(WId)), SLOT(activeWindowChanged(WId)));
+ connect(kwin_module, SIGNAL(currentDesktopChanged(int)), SLOT(currentDesktopChanged(int)));
+ connect(kwin_module, SIGNAL(windowChanged(WId,unsigned int)), SLOT(windowChanged(WId,unsigned int)));
+
+ // register existing windows
+ const QValueList<WId> windows = kwin_module->windows();
+ QValueList<WId>::ConstIterator end( windows.end() );
+ for (QValueList<WId>::ConstIterator it = windows.begin(); it != end; ++it )
+ windowAdded(*it);
+
+ // set active window
+ WId win = kwin_module->activeWindow();
+ activeWindowChanged(win);
+
+ configure_startup();
+}
+
+TaskManager::~TaskManager()
+{
+}
+
+void TaskManager::configure_startup()
+{
+ KConfig c("klaunchrc", true);
+ c.setGroup("FeedbackStyle");
+ if (!c.readBoolEntry("TaskbarButton", true))
+ return;
+ _startup_info = new KStartupInfo( true, this );
+ connect( _startup_info,
+ SIGNAL( gotNewStartup( const KStartupInfoId&, const KStartupInfoData& )),
+ SLOT( gotNewStartup( const KStartupInfoId&, const KStartupInfoData& )));
+ connect( _startup_info,
+ SIGNAL( gotStartupChange( const KStartupInfoId&, const KStartupInfoData& )),
+ SLOT( gotStartupChange( const KStartupInfoId&, const KStartupInfoData& )));
+ connect( _startup_info,
+ SIGNAL( gotRemoveStartup( const KStartupInfoId&, const KStartupInfoData& )),
+ SLOT( gotRemoveStartup( const KStartupInfoId& )));
+ c.setGroup( "TaskbarButtonSettings" );
+ _startup_info->setTimeout( c.readUnsignedNumEntry( "Timeout", 30 ));
+}
+
+Task* TaskManager::findTask(WId w)
+{
+ for (Task* t = _tasks.first(); t != 0; t = _tasks.next())
+ if (t->window() == w || t->hasTransient(w))
+ return t;
+ return 0;
+}
+
+#ifdef KDE_3_3
+#define NET_ALL_TYPES_MASK (NET::AllTypesMask)
+#else
+#define NET_ALL_TYPES_MASK (-1LU)
+#endif
+
+void TaskManager::windowAdded(WId w )
+{
+ NETWinInfo info(qt_xdisplay(), w, qt_xrootwin(),
+ NET::WMWindowType | NET::WMPid | NET::WMState );
+ #ifdef KDE_3_2
+ NET::WindowType windowType = info.windowType(NET_ALL_TYPES_MASK);
+ #else
+ NET::WindowType windowType = info.windowType();
+ #endif
+ // ignore NET::Tool and other special window types
+ if (windowType != NET::Normal && windowType != NET::Override
+ && windowType != NET::Unknown && windowType != NET::Dialog)
+ return;
+ // ignore windows that want to be ignored by the taskbar
+ if ((info.state() & NET::SkipTaskbar) != 0)
+ {
+ _skiptaskbar_windows.push_front( w ); // remember them though
+ return;
+ }
+
+ Window transient_for_tmp;
+ if (XGetTransientForHint(qt_xdisplay(), (Window) w, &transient_for_tmp))
+ {
+ WId transient_for = (WId) transient_for_tmp;
+
+ // check if it's transient for a skiptaskbar window
+ if (_skiptaskbar_windows.contains(transient_for))
+ return;
+
+ // lets see if this is a transient for an existing task
+ if (transient_for != qt_xrootwin() && transient_for != 0 )
+ {
+ Task* t = findTask(transient_for);
+ if (t)
+ {
+ if (t->window() != w)
+ {
+ t->addTransient(w);
+ // kdDebug() << "TM: Transient " << w << " added for Task: " << t->window() << endl;
+ }
+ return;
+ }
+ }
+ }
+ Task* t = new Task(w, this);
+ _tasks.append(t);
+
+ // kdDebug() << "TM: Task added for WId: " << w << endl;
+ emit taskAdded(t);
+}
+
+void TaskManager::windowRemoved(WId w )
+{
+ _skiptaskbar_windows.remove( w );
+ // find task
+ Task* t = findTask(w);
+ if (!t) return;
+
+ if (t->window() == w) {
+ _tasks.removeRef(t);
+
+ emit taskRemoved(t);
+
+ if(t == _active) _active = 0;
+ delete t;
+ //kdDebug() << "TM: Task for WId " << w << " removed." << endl;
+ }
+ else {
+ t->removeTransient( w );
+ //kdDebug() << "TM: Transient " << w << " for Task " << t->window() << " removed." << endl;
+ }
+}
+
+void TaskManager::windowChanged(WId w, unsigned int dirty)
+{
+ if( dirty & NET::WMState ) {
+ NETWinInfo info ( qt_xdisplay(), w, qt_xrootwin(), NET::WMState );
+ if ( (info.state() & NET::SkipTaskbar) != 0 ) {
+ windowRemoved( w );
+ _skiptaskbar_windows.push_front( w );
+ return;
+ }
+ else {
+ _skiptaskbar_windows.remove( w );
+ if( !findTask( w ))
+ windowAdded( w ); // skipTaskBar state was removed, so add this window
+ }
+ }
+
+ // check if any state we are interested in is marked dirty
+ if(!(dirty & (NET::WMVisibleName|NET::WMName|NET::WMState|NET::WMIcon|NET::XAWMState|NET::WMDesktop)) )
+ return;
+
+ // find task
+ Task* t = findTask( w );
+ if (!t) return;
+
+ //kdDebug() << "TaskManager::windowChanged " << w << " " << dirty << endl;
+
+
+ // refresh icon pixmap if necessary
+ if (dirty & NET::WMIcon)
+ t->refresh(true);
+ else
+ t->refresh();
+
+ if(dirty & (NET::WMDesktop|NET::WMState|NET::XAWMState))
+ emit windowChanged(w); // moved to different desktop or is on all or change in iconification/withdrawnnes
+}
+
+void TaskManager::activeWindowChanged(WId w )
+{
+ //kdDebug() << "TaskManager::activeWindowChanged" << endl;
+
+ Task* t = findTask( w );
+ if (!t) {
+ if (_active) {
+ _active->setActive(false);
+ _active = 0;
+
+ // there is no active window at the moment
+ emit activeTaskChanged(0);
+ }
+ }
+ else {
+ if (_active)
+ _active->setActive(false);
+
+ _active = t;
+ _active->setActive(true);
+
+ emit activeTaskChanged(_active);
+ }
+}
+
+void TaskManager::currentDesktopChanged(int desktop)
+{
+ emit desktopChanged(desktop);
+}
+
+void TaskManager::gotNewStartup( const KStartupInfoId& id, const KStartupInfoData& data )
+{
+ Startup* s = new Startup( id, data, this );
+ _startups.append(s);
+
+ emit startupAdded(s);
+}
+
+void TaskManager::gotStartupChange( const KStartupInfoId& id, const KStartupInfoData& data )
+{
+ for( Startup* s = _startups.first(); s != 0; s = _startups.next()) {
+ if ( s->id() == id ) {
+ s->update( data );
+ return;
+ }
+ }
+}
+
+void TaskManager::gotRemoveStartup( const KStartupInfoId& id )
+{
+ killStartup( id );
+}
+
+void TaskManager::killStartup( const KStartupInfoId& id )
+{
+ Startup* s = 0;
+ for(s = _startups.first(); s != 0; s = _startups.next()) {
+ if (s->id() == id)
+ break;
+ }
+ if (s == 0) return;
+
+ _startups.removeRef(s);
+ emit startupRemoved(s);
+ delete s;
+}
+
+void TaskManager::killStartup(Startup* s)
+{
+ if (s == 0) return;
+
+ _startups.removeRef(s);
+ emit startupRemoved(s);
+ delete s;
+}
+
+QString TaskManager::desktopName(int desk) const
+{
+ return kwin_module->desktopName(desk);
+}
+
+int TaskManager::numberOfDesktops() const
+{
+ return kwin_module->numberOfDesktops();
+}
+
+bool TaskManager::isOnTop(const Task* task)
+{
+ if(!task) return false;
+
+ for (QValueList<WId>::ConstIterator it = kwin_module->stackingOrder().fromLast();
+ it != kwin_module->stackingOrder().end(); --it ) {
+ for (Task* t = _tasks.first(); t != 0; t = _tasks.next() ) {
+ if ( (*it) == t->window() ) {
+ if ( t == task )
+ return true;
+ if ( !t->isIconified() && (t->isAlwaysOnTop() == task->isAlwaysOnTop()) )
+ return false;
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+
+Task::Task(WId win, TaskManager * parent, const char *name) :
+ QObject(parent, name),
+ _active(false), _win(win),
+ _lastWidth(0), _lastHeight(0), _lastResize(false), _lastIcon(),
+ _thumbSize(0.2), _thumb(), _grab()
+{
+#ifdef KDE_3_2
+ _info = KWin::windowInfo(_win, 0, 0);
+#else
+ _info = KWin::info(_win);
+#endif
+ // try to load icon via net_wm
+ _pixmap = KWin::icon(_win, 16, 16, true);
+
+ // try to guess the icon from the classhint
+ if(_pixmap.isNull())
+ KGlobal::instance()->iconLoader()->loadIcon(className().lower(),
+ KIcon::Small,KIcon::Small,
+ KIcon::DefaultState, 0, true);
+
+ // load xapp icon
+ if (_pixmap.isNull())
+ _pixmap = SmallIcon("kcmx");
+}
+
+Task::~Task()
+{
+}
+
+void Task::refresh(bool icon)
+{
+#ifdef KDE_3_2
+ _info = KWin::windowInfo(_win, 0, 0);
+#else
+ _info = KWin::info(_win);
+#endif
+ if (icon)
+ {
+ // try to load icon via net_wm
+ _pixmap = KWin::icon(_win, 16, 16, true);
+
+ // try to guess the icon from the classhint
+ if(_pixmap.isNull())
+ {
+ KGlobal::instance()->iconLoader()->loadIcon(className().lower(),
+ KIcon::Small, KIcon::Small, KIcon::DefaultState, 0, true);
+ }
+
+ // load xapp icon
+ if (_pixmap.isNull())
+ _pixmap = SmallIcon("kcmx");
+
+ _lastIcon.resize(0,0);
+ emit iconChanged();
+ }
+ emit changed();
+}
+
+void Task::setActive(bool a)
+{
+ _active = a;
+ emit changed();
+ if ( a )
+ emit activated();
+ else
+ emit deactivated();
+}
+
+bool Task::isMaximized() const
+{
+#ifdef KDE_3_2
+ return(_info.state() & NET::Max);
+#else
+ return(_info.state & NET::Max);
+#endif
+}
+
+bool Task::isIconified() const
+{
+#ifdef KDE_3_2
+ return (_info.mappingState() == NET::Iconic);
+#else
+ return (_info.mappingState == NET::Iconic);
+#endif
+}
+
+bool Task::isAlwaysOnTop() const
+{
+#ifdef KDE_3_2
+ return (_info.state() & NET::StaysOnTop);
+#else
+ return (_info.state & NET::StaysOnTop);
+#endif
+}
+
+bool Task::isShaded() const
+{
+#ifdef KDE_3_2
+ return (_info.state() & NET::Shaded);
+#else
+ return (_info.state & NET::Shaded);
+#endif
+}
+
+bool Task::isOnCurrentDesktop() const
+{
+#ifdef KDE_3_2
+ return (_info.onAllDesktops() || _info.desktop() == kwin_module->currentDesktop());
+#else
+ return (_info.onAllDesktops || _info.desktop == kwin_module->currentDesktop());
+#endif
+}
+
+bool Task::isOnAllDesktops() const
+{
+#ifdef KDE_3_2
+ return _info.onAllDesktops();
+#else
+ return _info.onAllDesktops;
+#endif
+}
+
+bool Task::isActive() const
+{
+ return _active;
+}
+
+bool Task::isOnTop() const
+{
+ return taskManager()->isOnTop( this );
+}
+
+bool Task::isModified() const
+{
+ static QString modStr = QString::fromUtf8("[") + i18n("modified") + QString::fromUtf8("]");
+#ifdef KDE_3_2
+ int modStrPos = _info.visibleName().find(modStr);
+#else
+ int modStrPos = _info.visibleName.find(modStr);
+#endif
+
+ return ( modStrPos != -1 );
+}
+
+QString Task::iconName() const
+{
+ NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMIconName);
+ return QString::fromUtf8(ni.iconName());
+}
+QString Task::visibleIconName() const
+{
+ NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMVisibleIconName);
+ return QString::fromUtf8(ni.visibleIconName());
+}
+
+QString Task::className()
+{
+ XClassHint hint;
+ if(XGetClassHint(qt_xdisplay(), _win, &hint)) {
+ QString nh( hint.res_name );
+ XFree( hint.res_name );
+ XFree( hint.res_class );
+ return nh;
+ }
+ return QString::null;
+}
+
+QString Task::classClass()
+{
+ XClassHint hint;
+ if(XGetClassHint(qt_xdisplay(), _win, &hint)) {
+ QString ch( hint.res_class );
+ XFree( hint.res_name );
+ XFree( hint.res_class );
+ return ch;
+ }
+ return QString::null;
+}
+
+QPixmap Task::icon( int width, int height, bool allowResize )
+{
+ if ( (width == _lastWidth)
+ && (height == _lastHeight)
+ && (allowResize == _lastResize )
+ && (!_lastIcon.isNull()) )
+ return _lastIcon;
+
+ QPixmap newIcon = KWin::icon( _win, width, height, allowResize );
+ if ( !newIcon.isNull() ) {
+ _lastIcon = newIcon;
+ _lastWidth = width;
+ _lastHeight = height;
+ _lastResize = allowResize;
+ }
+
+ return newIcon;
+}
+
+QPixmap Task::bestIcon( int size, bool &isStaticIcon )
+{
+ QPixmap pixmap;
+ isStaticIcon = false;
+
+ switch( size ) {
+ case KIcon::SizeSmall:
+ {
+ pixmap = icon( 16, 16, true );
+
+ // Icon of last resort
+ if( pixmap.isNull() ) {
+ pixmap = KGlobal::iconLoader()->loadIcon( "go",
+ KIcon::NoGroup,
+ KIcon::SizeSmall );
+ isStaticIcon = true;
+ }
+ }
+ break;
+ case KIcon::SizeMedium:
+ {
+ //
+ // Try 34x34 first for KDE 2.1 icons with shadows, if we don't
+ // get one then try 32x32.
+ //
+ pixmap = icon( 34, 34, false );
+
+ if ( ( pixmap.width() != 34 ) || ( pixmap.height() != 34 ) ) {
+ if ( ( pixmap.width() != 32 ) || ( pixmap.height() != 32 ) ) {
+ pixmap = icon( 32, 32, true );
+ }
+ }
+
+ // Icon of last resort
+ if( pixmap.isNull() ) {
+ pixmap = KGlobal::iconLoader()->loadIcon( "go",
+ KIcon::NoGroup,
+ KIcon::SizeMedium );
+ isStaticIcon = true;
+ }
+ }
+ break;
+ case KIcon::SizeLarge:
+ {
+ // If there's a 48x48 icon in the hints then use it
+ pixmap = icon( size, size, false );
+
+ // If not, try to get one from the classname
+ if ( pixmap.isNull() || pixmap.width() != size || pixmap.height() != size ) {
+ pixmap = KGlobal::iconLoader()->loadIcon( className(),
+ KIcon::NoGroup,
+ size,
+ KIcon::DefaultState,
+ 0L,
+ true );
+ isStaticIcon = true;
+ }
+
+ // If we still don't have an icon then scale the one in the hints
+ if ( pixmap.isNull() || ( pixmap.width() != size ) || ( pixmap.height() != size ) ) {
+ pixmap = icon( size, size, true );
+ isStaticIcon = false;
+ }
+
+ // Icon of last resort
+ if( pixmap.isNull() ) {
+ pixmap = KGlobal::iconLoader()->loadIcon( "go",
+ KIcon::NoGroup,
+ size );
+ isStaticIcon = true;
+ }
+ }
+ }
+
+ return pixmap;
+}
+
+bool Task::idMatch( const QString& id1, const QString& id2 )
+{
+ if ( id1.isEmpty() || id2.isEmpty() )
+ return false;
+
+ if ( id1.contains( id2 ) > 0 )
+ return true;
+
+ if ( id2.contains( id1 ) > 0 )
+ return true;
+
+ return false;
+}
+
+
+void Task::maximize()
+{
+ NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMState);
+ ni.setState( NET::Max, NET::Max );
+
+#ifdef KDE_3_2
+ if (_info.mappingState() == NET::Iconic)
+#else
+ if (_info.mappingState == NET::Iconic)
+#endif
+ activate();
+}
+
+void Task::restore()
+{
+ NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMState);
+ ni.setState( 0, NET::Max );
+#ifdef KDE_3_2
+ if (_info.mappingState() == NET::Iconic)
+#else
+ if (_info.mappingState == NET::Iconic)
+#endif
+ activate();
+}
+
+void Task::iconify()
+{
+ XIconifyWindow( qt_xdisplay(), _win, qt_xscreen() );
+}
+
+void Task::close()
+{
+ NETRootInfo ri( qt_xdisplay(), NET::CloseWindow );
+ ri.closeWindowRequest( _win );
+}
+
+void Task::raise()
+{
+// kdDebug(1210) << "Task::raise(): " << name() << endl;
+ XRaiseWindow( qt_xdisplay(), _win );
+}
+
+void Task::lower()
+{
+// kdDebug(1210) << "Task::lower(): " << name() << endl;
+ XLowerWindow( qt_xdisplay(), _win );
+}
+
+void Task::activate()
+{
+// kdDebug(1210) << "Task::activate():" << name() << endl;
+ NETRootInfo ri( qt_xdisplay(), 0 );
+ ri.setActiveWindow( _win );
+}
+
+void Task::activateRaiseOrIconify()
+{
+ if ( !isActive() || isIconified() ) {
+ activate();
+ } else if ( !isOnTop() ) {
+ raise();
+ } else {
+ iconify();
+ }
+}
+
+void Task::toDesktop(int desk)
+{
+ NETWinInfo ni(qt_xdisplay(), _win, qt_xrootwin(), NET::WMDesktop);
+ if (desk == 0)
+ {
+#ifdef KDE_3_2
+ if (_info.onAllDesktops())
+ {
+ ni.setDesktop(kwin_module->currentDesktop());
+ KWin::forceActiveWindow(_win);
+ }
+#else
+ if (_info.onAllDesktops)
+ {
+ ni.setDesktop(kwin_module->currentDesktop());
+ KWin::setActiveWindow(_win);
+ }
+#endif
+ else
+ ni.setDesktop(NETWinInfo::OnAllDesktops);
+ return;
+ }
+ ni.setDesktop(desk);
+ if (desk == kwin_module->currentDesktop())
+#ifdef KDE_3_2
+ KWin::forceActiveWindow(_win);
+#else
+ KWin::setActiveWindow(_win);
+#endif
+}
+
+void Task::toCurrentDesktop()
+{
+ toDesktop(kwin_module->currentDesktop());
+}
+
+void Task::setAlwaysOnTop(bool stay)
+{
+ NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMState);
+ if(stay)
+ ni.setState( NET::StaysOnTop, NET::StaysOnTop );
+ else
+ ni.setState( 0, NET::StaysOnTop );
+}
+
+void Task::toggleAlwaysOnTop()
+{
+ setAlwaysOnTop( !isAlwaysOnTop() );
+}
+
+void Task::setShaded(bool shade)
+{
+ NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMState);
+ if(shade)
+ ni.setState( NET::Shaded, NET::Shaded );
+ else
+ ni.setState( 0, NET::Shaded );
+}
+
+void Task::toggleShaded()
+{
+ setShaded( !isShaded() );
+}
+
+void Task::publishIconGeometry(QRect rect)
+{
+ NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMIconGeometry);
+ NETRect r;
+ r.pos.x = rect.x();
+ r.pos.y = rect.y();
+ r.size.width = rect.width();
+ r.size.height = rect.height();
+ ni.setIconGeometry(r);
+}
+
+void Task::updateThumbnail()
+{
+ if ( !isOnCurrentDesktop() )
+ return;
+ if ( !isActive() )
+ return;
+ if ( !_grab.isNull() ) // We're already processing one...
+ return;
+
+ //
+ // We do this as a two stage process to remove the delay caused
+ // by the thumbnail generation. This makes things much smoother
+ // on slower machines.
+ //
+ QWidget *rootWin = qApp->desktop();
+#ifdef KDE_3_2
+ QRect geom = _info.geometry();
+#else
+ QRect geom = _info.geometry;
+#endif
+ _grab = QPixmap::grabWindow( rootWin->winId(),
+ geom.x(), geom.y(),
+ geom.width(), geom.height() );
+
+ if ( !_grab.isNull() )
+ QTimer::singleShot( 200, this, SLOT( generateThumbnail() ) );
+}
+
+void Task::generateThumbnail()
+{
+ if ( _grab.isNull() )
+ return;
+
+ QImage img = _grab.convertToImage();
+
+ double width = img.width();
+ double height = img.height();
+ width = width * _thumbSize;
+ height = height * _thumbSize;
+
+ img = img.smoothScale( (int) width, (int) height );
+ _thumb = img;
+ _grab.resize( 0, 0 ); // Makes grab a null image.
+
+ emit thumbnailChanged();
+}
+
+Startup::Startup( const KStartupInfoId& id, const KStartupInfoData& data,
+ QObject * parent, const char *name)
+ : QObject(parent, name), _id( id ), _data( data )
+{
+}
+
+Startup::~Startup()
+{
+
+}
+
+void Startup::update( const KStartupInfoData& data )
+{
+ _data.update( data );
+ emit changed();
+}
+
+int TaskManager::currentDesktop() const
+{
+ return kwin_module->currentDesktop();
+}