• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

libtaskmanager

task.cpp

Go to the documentation of this file.
00001 /*****************************************************************
00002 
00003 Copyright (c) 2000-2001 Matthias Elter <elter@kde.org>
00004 Copyright (c) 2001 Richard Moore <rich@kde.org>
00005 
00006 Permission is hereby granted, free of charge, to any person obtaining a copy
00007 of this software and associated documentation files (the "Software"), to deal
00008 in the Software without restriction, including without limitation the rights
00009 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00010 copies of the Software, and to permit persons to whom the Software is
00011 furnished to do so, subject to the following conditions:
00012 
00013 The above copyright notice and this permission notice shall be included in
00014 all copies or substantial portions of the Software.
00015 
00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00019 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00020 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00021 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00022 
00023 ******************************************************************/
00024 
00025 // Own
00026 #include "task.h"
00027 
00028 // Qt
00029 #include <QMimeData>
00030 #include <QTimer>
00031 
00032 // KDE
00033 #include <KDebug>
00034 #include <KIconLoader>
00035 #include <KLocale>
00036 
00037 #include "taskmanager.h"
00038 #include "taskmanager_p.h"
00039 
00040 namespace TaskManager
00041 {
00042 
00043 class Task::Private
00044 {
00045 public:
00046     Private(WId w)
00047      : active(false),
00048        win(w),
00049        frameId(w),
00050        info(KWindowSystem::windowInfo(w,
00051             NET::WMState | NET::XAWMState | NET::WMDesktop |
00052             NET::WMVisibleName | NET::WMGeometry | NET::WMWindowType,
00053             NET::WM2AllowedActions)),
00054        lastWidth(0),
00055        lastHeight(0),
00056        lastResize(false),
00057        lastIcon(),
00058        thumbSize(0.2),
00059        thumb(),
00060        grab()
00061     {
00062     }
00063 
00064     bool active;
00065     WId win;
00066     WId frameId;
00067     QPixmap pixmap;
00068     KWindowInfo info;
00069     WindowList transients;
00070     WindowList transientsDemandingAttention;
00071 
00072     int lastWidth;
00073     int lastHeight;
00074     bool lastResize;
00075     QPixmap lastIcon;
00076 
00077     double thumbSize;
00078     QPixmap thumb;
00079     QPixmap grab;
00080     QRect iconGeometry;
00081 
00082     Pixmap windowPixmap;
00083 };
00084 
00085 Task::Task(WId w, QObject *parent, const char *name)
00086   : QObject(parent),
00087     d(new Private(w))
00088 {
00089     setObjectName( name );
00090 
00091     // try to load icon via net_wm
00092     d->pixmap = KWindowSystem::icon(d->win, 16, 16, true);
00093 
00094     // try to guess the icon from the classhint
00095     if (d->pixmap.isNull())
00096     {
00097         KIconLoader::global()->loadIcon(className().toLower(),
00098                                                     KIconLoader::Small,
00099                                                     KIconLoader::Small,
00100                                                     KIconLoader::DefaultState,
00101                                                     QStringList(), 0, true);
00102     }
00103 
00104     // load the icon for X applications
00105     if (d->pixmap.isNull())
00106     {
00107         d->pixmap = SmallIcon("xorg");
00108     }
00109 
00110 #ifdef THUMBNAILING_POSSIBLE
00111     d->windowPixmap = 0;
00112     findWindowFrameId();
00113 
00114     if (KWindowSystem::compositingActive())
00115     {
00116         updateWindowPixmap();
00117     }
00118 #endif // THUMBNAILING_POSSIBLE
00119 }
00120 
00121 Task::~Task()
00122 {
00123 #ifdef THUMBNAILING_POSSIBLE
00124     //be sure we have something to delete
00125     if (d->windowPixmap && QX11Info::display())
00126     {
00127         XFreePixmap(QX11Info::display(), d->windowPixmap);
00128     }
00129 #endif // THUMBNAILING_POSSIBLE
00130     delete d;
00131 }
00132 
00133 // Task::findWindowFrameId()
00134 // Code was copied from Kompose.
00135 // Copyright (C) 2004 Hans Oischinger
00136 // Permission granted on 2005-04-27.
00137 void Task::findWindowFrameId()
00138 {
00139 #ifdef THUMBNAILING_POSSIBLE
00140     Window targetWin, parent, root;
00141     Window *children;
00142     uint nchildren;
00143 
00144     targetWin = d->win;
00145     for (;;)
00146     {
00147         if (!XQueryTree(QX11Info::display(), targetWin, &root,
00148                         &parent, &children, &nchildren))
00149         {
00150             break;
00151         }
00152 
00153         if (children)
00154         {
00155             XFree(children); // it's a list, that's deallocated!
00156         }
00157 
00158         if (!parent || parent == root)
00159         {
00160             break;
00161         }
00162         else
00163         {
00164             targetWin = parent;
00165         }
00166     }
00167 
00168     d->frameId = targetWin;
00169 #endif // THUMBNAILING_POSSIBLE
00170 }
00171 
00172 void Task::refreshIcon()
00173 {
00174     // try to load icon via net_wm
00175     d->pixmap = KWindowSystem::icon(d->win, 16, 16, true);
00176 
00177     // try to guess the icon from the classhint
00178     if(d->pixmap.isNull())
00179     {
00180         KIconLoader::global()->loadIcon(className().toLower(),
00181                                                     KIconLoader::Small,
00182                                                     KIconLoader::Small,
00183                                                     KIconLoader::DefaultState,
00184                                                     QStringList(), 0, true);
00185     }
00186 
00187     // load the icon for X applications
00188     if (d->pixmap.isNull())
00189     {
00190         d->pixmap = SmallIcon("xorg");
00191     }
00192 
00193     d->lastIcon = QPixmap();
00194     emit iconChanged();
00195 }
00196 
00197 void Task::refresh(unsigned int dirty)
00198 {
00199     QString name = visibleName();
00200     d->info = KWindowSystem::windowInfo(d->win,
00201         NET::WMState | NET::XAWMState | NET::WMDesktop | NET::WMVisibleName | NET::WMGeometry | NET::WMWindowType,
00202         NET::WM2AllowedActions);
00203 
00204     if (dirty != NET::WMName || name != visibleName())
00205     {
00206         emit changed();
00207     }
00208 }
00209 
00210 void Task::setActive(bool a)
00211 {
00212     d->active = a;
00213     emit changed();
00214     if ( a )
00215       emit activated();
00216     else
00217       emit deactivated();
00218 }
00219 
00220 double Task::thumbnailSize() const { return d->thumbSize; }
00221 
00222 
00223 void Task::setThumbnailSize( double size )
00224 {
00225     d->thumbSize = size;
00226 }
00227 
00228 bool Task::hasThumbnail() const
00229 {
00230     return !d->thumb.isNull();
00231 }
00232 
00233 QPixmap Task::thumbnail() const
00234 {
00235     return d->thumb;
00236 }
00237 
00238 bool Task::isMaximized() const
00239 {
00240     return d->info.valid() && (d->info.state() & NET::Max);
00241 }
00242 
00243 bool Task::isMinimized() const
00244 {
00245     return d->info.valid() && d->info.isMinimized();
00246 }
00247 
00248 bool Task::isIconified() const
00249 {
00250     return d->info.valid() && d->info.isMinimized();
00251 }
00252 
00253 bool Task::isAlwaysOnTop() const
00254 {
00255     return d->info.valid() && (d->info.state() & NET::StaysOnTop);
00256 }
00257 
00258 bool Task::isKeptBelowOthers() const
00259 {
00260     return d->info.valid() && (d->info.state() & NET::KeepBelow);
00261 }
00262 
00263 bool Task::isFullScreen() const
00264 {
00265     return d->info.valid() && (d->info.state() & NET::FullScreen);
00266 }
00267 
00268 bool Task::isShaded() const
00269 {
00270     return d->info.valid() && (d->info.state() & NET::Shaded);
00271 }
00272 
00273 bool Task::isOnCurrentDesktop() const
00274 {
00275     return d->info.valid() && d->info.isOnCurrentDesktop();
00276 }
00277 
00278 bool Task::isOnAllDesktops() const
00279 {
00280     return d->info.valid() && d->info.onAllDesktops();
00281 }
00282 
00283 bool Task::isActive() const
00284 {
00285     return d->active;
00286 }
00287 
00288 bool Task::isOnTop() const
00289 {
00290     return TaskManager::self()->isOnTop(this);
00291 }
00292 
00293 bool Task::isModified() const
00294 {
00295   static QString modStr = QString::fromUtf8("[") +
00296                           i18n("modified") +
00297                           QString::fromUtf8("]");
00298   int modStrPos = d->info.visibleName().indexOf(modStr);
00299 
00300   return ( modStrPos != -1 );
00301 }
00302 
00303 int Task::desktop() const
00304 {
00305     return d->info.desktop();
00306 }
00307 
00308 bool Task::demandsAttention() const
00309 {
00310     return (d->info.valid() && (d->info.state() & NET::DemandsAttention)) ||
00311             d->transientsDemandingAttention.count() > 0;
00312 }
00313 
00314 bool Task::isOnScreen( int screen ) const
00315 {
00316     return TaskManager::isOnScreen( screen, d->win );
00317 }
00318 
00319 bool Task::showInTaskbar() const
00320 {
00321     return d->info.state() ^ NET::SkipTaskbar;
00322 }
00323 
00324 bool Task::showInPager() const
00325 {
00326     return d->info.state() ^ NET::SkipPager;
00327 }
00328 
00329 QRect Task::geometry() const
00330 {
00331     return d->info.geometry();
00332 }
00333 
00334 void Task::updateDemandsAttentionState( WId w )
00335 {
00336     if (window() != w)
00337     {
00338         // 'w' is a transient for this task
00339         NETWinInfo i( QX11Info::display(), w, QX11Info::appRootWindow(), NET::WMState );
00340         if(i.state() & NET::DemandsAttention)
00341         {
00342             if (!d->transientsDemandingAttention.contains(w))
00343             {
00344                 d->transientsDemandingAttention.append(w);
00345             }
00346         }
00347         else
00348         {
00349             d->transientsDemandingAttention.removeAll( w );
00350         }
00351     }
00352 }
00353 
00354 void Task::addTransient( WId w, const NETWinInfo& info )
00355 {
00356     d->transients.append(w);
00357     if (info.state() & NET::DemandsAttention)
00358     {
00359         d->transientsDemandingAttention.append(w);
00360         emit changed();
00361     }
00362 }
00363 
00364 void Task::removeTransient(WId w)
00365 {
00366     d->transients.removeAll(w);
00367     d->transientsDemandingAttention.removeAll(w);
00368 }
00369 
00370 bool Task::hasTransient(WId w) const
00371 {
00372     return d->transients.indexOf(w) != -1;
00373 }
00374 
00375 WId Task::window() const
00376 {
00377     return d->win;
00378 }
00379 
00380 KWindowInfo Task::info() const
00381 {
00382     return d->info;
00383 }
00384 
00385 QString Task::visibleName() const
00386 {
00387     return d->info.visibleName();
00388 }
00389 
00390 QString Task::visibleNameWithState() const
00391 {
00392     return d->info.visibleNameWithState();
00393 }
00394 
00395 QString Task::name() const
00396 {
00397     return d->info.name();
00398 }
00399 
00400 QString Task::className()
00401 {
00402     XClassHint hint;
00403     if(XGetClassHint(QX11Info::display(), d->win, &hint)) {
00404         QString nh( hint.res_name );
00405         XFree( hint.res_name );
00406         XFree( hint.res_class );
00407         return nh;
00408     }
00409     return QString();
00410 }
00411 
00412 QString Task::classClass()
00413 {
00414     XClassHint hint;
00415     if(XGetClassHint(QX11Info::display(), d->win, &hint)) {
00416         QString ch( hint.res_class );
00417         XFree( hint.res_name );
00418         XFree( hint.res_class );
00419         return ch;
00420     }
00421     return QString();
00422 }
00423 
00424 QPixmap Task::icon( int width, int height, bool allowResize )
00425 {
00426   if ( (width == d->lastWidth)
00427        && (height == d->lastHeight)
00428        && (allowResize == d->lastResize )
00429        && (!d->lastIcon.isNull()) )
00430     return d->lastIcon;
00431 
00432   QPixmap newIcon = KWindowSystem::icon( d->win, width, height, allowResize );
00433   if ( !newIcon.isNull() ) {
00434     d->lastIcon = newIcon;
00435     d->lastWidth = width;
00436     d->lastHeight = height;
00437     d->lastResize = allowResize;
00438   }
00439 
00440   return newIcon;
00441 }
00442 
00443 WindowList Task::transients() const
00444 {
00445     return d->transients;
00446 }
00447 
00448 QPixmap Task::pixmap() const
00449 {
00450     return d->pixmap;
00451 }
00452 
00453 QPixmap Task::bestIcon( int size, bool &isStaticIcon )
00454 {
00455   QPixmap pixmap;
00456   isStaticIcon = false;
00457 
00458   switch( size ) {
00459   case KIconLoader::SizeSmall:
00460     {
00461       pixmap = icon( 16, 16, true  );
00462 
00463       // Icon of last resort
00464       if( pixmap.isNull() ) {
00465         pixmap = KIconLoader::global()->loadIcon( "xorg",
00466                                                   KIconLoader::NoGroup,
00467                                                   KIconLoader::SizeSmall );
00468         isStaticIcon = true;
00469       }
00470     }
00471     break;
00472   case KIconLoader::SizeMedium:
00473     {
00474       //
00475       // Try 34x34 first for KDE 2.1 icons with shadows, if we don't
00476       // get one then try 32x32.
00477       //
00478       pixmap = icon( 34, 34, false  );
00479 
00480       if ( (( pixmap.width() != 34 ) || ( pixmap.height() != 34 )) &&
00481            (( pixmap.width() != 32 ) || ( pixmap.height() != 32 )) )
00482       {
00483         pixmap = icon( 32, 32, true  );
00484       }
00485 
00486       // Icon of last resort
00487       if( pixmap.isNull() ) {
00488         pixmap = KIconLoader::global()->loadIcon( "xorg",
00489                             KIconLoader::NoGroup,
00490                             KIconLoader::SizeMedium );
00491         isStaticIcon = true;
00492       }
00493     }
00494     break;
00495   case KIconLoader::SizeLarge:
00496     {
00497       // If there's a 48x48 icon in the hints then use it
00498       pixmap = icon( size, size, false  );
00499 
00500       // If not, try to get one from the classname
00501       if ( pixmap.isNull() || pixmap.width() != size || pixmap.height() != size ) {
00502         pixmap = KIconLoader::global()->loadIcon( className(),
00503                             KIconLoader::NoGroup,
00504                             size,
00505                             KIconLoader::DefaultState,
00506                             QStringList(), 0L,
00507                             true );
00508         isStaticIcon = true;
00509       }
00510 
00511       // If we still don't have an icon then scale the one in the hints
00512       if ( pixmap.isNull() || ( pixmap.width() != size ) || ( pixmap.height() != size ) ) {
00513         pixmap = icon( size, size, true  );
00514         isStaticIcon = false;
00515       }
00516 
00517       // Icon of last resort
00518       if( pixmap.isNull() ) {
00519         pixmap = KIconLoader::global()->loadIcon( "xorg",
00520                                                   KIconLoader::NoGroup,
00521                                                   size );
00522         isStaticIcon = true;
00523       }
00524     }
00525   }
00526 
00527   return pixmap;
00528 }
00529 
00530 bool Task::idMatch( const QString& id1, const QString& id2 )
00531 {
00532   if ( id1.isEmpty() || id2.isEmpty() )
00533     return false;
00534 
00535   if ( id1.contains( id2 ) > 0 )
00536     return true;
00537 
00538   if ( id2.contains( id1 ) > 0 )
00539     return true;
00540 
00541   return false;
00542 }
00543 
00544 void Task::move()
00545 {
00546     bool on_current = d->info.isOnCurrentDesktop();
00547 
00548     if (!on_current)
00549     {
00550         KWindowSystem::setCurrentDesktop(d->info.desktop());
00551         KWindowSystem::forceActiveWindow(d->win);
00552     }
00553 
00554     if (d->info.isMinimized())
00555     {
00556         KWindowSystem::unminimizeWindow(d->win);
00557     }
00558 
00559     QRect geom = d->info.geometry();
00560     QCursor::setPos(geom.center());
00561 
00562     NETRootInfo ri(QX11Info::display(), NET::WMMoveResize);
00563     ri.moveResizeRequest(d->win, geom.center().x(),
00564                          geom.center().y(), NET::Move);
00565 }
00566 
00567 void Task::resize()
00568 {
00569     bool on_current = d->info.isOnCurrentDesktop();
00570 
00571     if (!on_current)
00572     {
00573         KWindowSystem::setCurrentDesktop(d->info.desktop());
00574         KWindowSystem::forceActiveWindow(d->win);
00575     }
00576 
00577     if (d->info.isMinimized())
00578     {
00579         KWindowSystem::unminimizeWindow(d->win);
00580     }
00581 
00582     QRect geom = d->info.geometry();
00583     QCursor::setPos(geom.bottomRight());
00584 
00585     NETRootInfo ri(QX11Info::display(), NET::WMMoveResize);
00586     ri.moveResizeRequest(d->win, geom.bottomRight().x(),
00587                          geom.bottomRight().y(), NET::BottomRight);
00588 }
00589 
00590 void Task::setMaximized(bool maximize)
00591 {
00592     KWindowInfo info = KWindowSystem::windowInfo(d->win, NET::WMState | NET::XAWMState | NET::WMDesktop);
00593     bool on_current = info.isOnCurrentDesktop();
00594 
00595     if (!on_current)
00596     {
00597         KWindowSystem::setCurrentDesktop(info.desktop());
00598     }
00599 
00600     if (info.isMinimized())
00601     {
00602         KWindowSystem::unminimizeWindow(d->win);
00603     }
00604 
00605     NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState);
00606 
00607     if (maximize)
00608     {
00609         ni.setState(NET::Max, NET::Max);
00610     }
00611     else
00612     {
00613         ni.setState(0, NET::Max);
00614     }
00615 
00616     if (!on_current)
00617     {
00618         KWindowSystem::forceActiveWindow(d->win);
00619     }
00620 }
00621 
00622 void Task::toggleMaximized()
00623 {
00624     setMaximized(!isMaximized());
00625 }
00626 
00627 void Task::restore()
00628 {
00629     KWindowInfo info = KWindowSystem::windowInfo(d->win, NET::WMState | NET::XAWMState | NET::WMDesktop);
00630     bool on_current = info.isOnCurrentDesktop();
00631 
00632     if (!on_current)
00633     {
00634         KWindowSystem::setCurrentDesktop(info.desktop());
00635     }
00636 
00637     if( info.isMinimized())
00638     {
00639         KWindowSystem::unminimizeWindow(d->win);
00640     }
00641 
00642     NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState);
00643     ni.setState(0, NET::Max);
00644 
00645     if (!on_current)
00646     {
00647         KWindowSystem::forceActiveWindow( d->win );
00648     }
00649 }
00650 
00651 void Task::setIconified(bool iconify)
00652 {
00653     if (iconify)
00654     {
00655         KWindowSystem::minimizeWindow(d->win);
00656     }
00657     else
00658     {
00659         KWindowInfo info = KWindowSystem::windowInfo(d->win, NET::WMState | NET::XAWMState | NET::WMDesktop);
00660         bool on_current = info.isOnCurrentDesktop();
00661 
00662         if (!on_current)
00663         {
00664             KWindowSystem::setCurrentDesktop(info.desktop());
00665         }
00666 
00667         KWindowSystem::unminimizeWindow(d->win);
00668 
00669         if (!on_current)
00670         {
00671             KWindowSystem::forceActiveWindow(d->win);
00672         }
00673     }
00674 }
00675 
00676 void Task::toggleIconified()
00677 {
00678     setIconified(!isIconified());
00679 }
00680 
00681 void Task::close()
00682 {
00683     NETRootInfo ri( QX11Info::display(), NET::CloseWindow );
00684     ri.closeWindowRequest( d->win );
00685 }
00686 
00687 void Task::raise()
00688 {
00689 //    kDebug(1210) << "Task::raise(): " << name();
00690     KWindowSystem::raiseWindow( d->win );
00691 }
00692 
00693 void Task::lower()
00694 {
00695 //    kDebug(1210) << "Task::lower(): " << name();
00696     KWindowSystem::lowerWindow( d->win );
00697 }
00698 
00699 void Task::activate()
00700 {
00701 //    kDebug(1210) << "Task::activate():" << name();
00702     WId w = d->win;
00703     if (d->transientsDemandingAttention.count() > 0)
00704     {
00705         w = d->transientsDemandingAttention.last();
00706     }
00707     KWindowSystem::forceActiveWindow( w );
00708 }
00709 
00710 void Task::activateRaiseOrIconify()
00711 {
00712     if (!isActive() || isIconified())
00713     {
00714         activate();
00715     }
00716     else if (!isOnTop())
00717     {
00718        raise();
00719     }
00720     else
00721     {
00722        setIconified(true);
00723     }
00724 }
00725 
00726 void Task::toDesktop(int desk)
00727 {
00728     NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMDesktop);
00729     if (desk == 0)
00730     {
00731         if (d->info.valid() && d->info.onAllDesktops())
00732         {
00733             ni.setDesktop(KWindowSystem::currentDesktop());
00734             KWindowSystem::forceActiveWindow(d->win);
00735         }
00736         else
00737         {
00738             ni.setDesktop(NETWinInfo::OnAllDesktops);
00739         }
00740 
00741         return;
00742     }
00743     ni.setDesktop(desk);
00744     if(desk == KWindowSystem::currentDesktop())
00745         KWindowSystem::forceActiveWindow(d->win);
00746 }
00747 
00748 void Task::toCurrentDesktop()
00749 {
00750     toDesktop(KWindowSystem::currentDesktop());
00751 }
00752 
00753 void Task::setAlwaysOnTop(bool stay)
00754 {
00755     NETWinInfo ni( QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState);
00756     if(stay)
00757         ni.setState( NET::StaysOnTop, NET::StaysOnTop );
00758     else
00759         ni.setState( 0, NET::StaysOnTop );
00760 }
00761 
00762 void Task::toggleAlwaysOnTop()
00763 {
00764     setAlwaysOnTop( !isAlwaysOnTop() );
00765 }
00766 
00767 void Task::setKeptBelowOthers(bool below)
00768 {
00769     NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState);
00770 
00771     if (below)
00772     {
00773         ni.setState(NET::KeepBelow, NET::KeepBelow);
00774     }
00775     else
00776     {
00777         ni.setState(0, NET::KeepBelow);
00778     }
00779 }
00780 
00781 void Task::toggleKeptBelowOthers()
00782 {
00783     setKeptBelowOthers(!isKeptBelowOthers());
00784 }
00785 
00786 void Task::setFullScreen(bool fullscreen)
00787 {
00788     NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState);
00789 
00790     if (fullscreen)
00791     {
00792         ni.setState(NET::FullScreen, NET::FullScreen);
00793     }
00794     else
00795     {
00796         ni.setState(0, NET::FullScreen);
00797     }
00798 }
00799 
00800 void Task::toggleFullScreen()
00801 {
00802     setFullScreen(!isFullScreen());
00803 }
00804 
00805 void Task::setShaded(bool shade)
00806 {
00807     NETWinInfo ni( QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState);
00808     if(shade)
00809         ni.setState( NET::Shaded, NET::Shaded );
00810     else
00811         ni.setState( 0, NET::Shaded );
00812 }
00813 
00814 void Task::toggleShaded()
00815 {
00816     setShaded( !isShaded() );
00817 }
00818 
00819 void Task::publishIconGeometry(QRect rect)
00820 {
00821     if (rect == d->iconGeometry)
00822     {
00823         return;
00824     }
00825 
00826     d->iconGeometry = rect;
00827     NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), 0);
00828     NETRect r;
00829 
00830     if (rect.isValid())
00831     {
00832         r.pos.x = rect.x();
00833         r.pos.y = rect.y();
00834         r.size.width = rect.width();
00835         r.size.height = rect.height();
00836     }
00837     ni.setIconGeometry(r);
00838 }
00839 
00840 void Task::updateThumbnail()
00841 {
00842     if ( !d->info.valid() ||
00843             !isOnCurrentDesktop() ||
00844             !isActive() ||
00845             !d->grab.isNull() ) // We're already processing one...
00846     {
00847         return;
00848     }
00849 
00850     //
00851     // We do this as a two stage process to remove the delay caused
00852     // by the thumbnail generation. This makes things much smoother
00853     // on slower machines.
00854     //
00855     QWidget *rootWin = qApp->desktop();
00856     QRect geom = d->info.geometry();
00857     d->grab = QPixmap::grabWindow(rootWin->winId(),
00858                                 geom.x(), geom.y(),
00859                                 geom.width(), geom.height());
00860 
00861     if (!d->grab.isNull())
00862     {
00863        QTimer::singleShot(200, this, SLOT(generateThumbnail()));
00864     }
00865 }
00866 
00867 void Task::generateThumbnail()
00868 {
00869    if ( d->grab.isNull() )
00870       return;
00871 
00872    double width = d->grab.width();
00873    double height = d->grab.height();
00874    width = width * d->thumbSize;
00875    height = height * d->thumbSize;
00876 
00877    d->thumb = d->grab.scaled( qRound(width), qRound(height), Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
00878    d->grab = QPixmap(); // Makes grab a null image.
00879 
00880    emit thumbnailChanged();
00881 }
00882 
00883 #ifdef THUMBNAILING_POSSIBLE
00884 QPixmap Task::thumbnail(int maxDimension)
00885 {
00886     if (!KWindowSystem::compositingActive() || !d->windowPixmap)
00887     {
00888         return QPixmap();
00889     }
00890 
00891     Display *dpy = QX11Info::display();
00892 
00893     XWindowAttributes winAttr;
00894     XGetWindowAttributes(dpy, d->frameId, &winAttr);
00895     XRenderPictFormat *format = XRenderFindVisualFormat(dpy, winAttr.visual);
00896 
00897     XRenderPictureAttributes picAttr;
00898     ::memset(&picAttr, 0, sizeof(picAttr));
00899     picAttr.subwindow_mode = IncludeInferiors; // Don't clip child widgets
00900 
00901     Picture picture = XRenderCreatePicture(dpy, d->windowPixmap, format,
00902                                            CPSubwindowMode, &picAttr);
00903 
00904     // Get shaped windows handled correctly.
00905     XserverRegion region = XFixesCreateRegionFromWindow(dpy, d->frameId,
00906                                                         WindowRegionBounding);
00907     XFixesSetPictureClipRegion(dpy, picture, 0, 0, region);
00908     XFixesDestroyRegion(dpy, region);
00909 
00910     double factor;
00911     if (winAttr.width > winAttr.height)
00912     {
00913         factor = (double)maxDimension / (double)winAttr.width;
00914     }
00915     else
00916     {
00917         factor = (double)maxDimension / (double)winAttr.height;
00918     }
00919     int thumbnailWidth = (int)(winAttr.width * factor);
00920     int thumbnailHeight = (int)(winAttr.height * factor);
00921 
00922     QPixmap thumbnail(thumbnailWidth, thumbnailHeight);
00923     thumbnail.fill(QApplication::palette().color(QPalette::Active,QPalette::Background));
00924 
00925 #if 0 // QImage::smoothScale() scaling
00926     QPixmap full(winAttr.width, winAttr.height);
00927     full.fill(QApplication::palette().active().background());
00928 
00929     bool hasAlpha = format->type == PictTypeDirect && format->direct.alphaMask;
00930 
00931     XRenderComposite(dpy,
00932                      hasAlpha ? PictOpOver : PictOpSrc,
00933                      picture, // src
00934                      None, // mask
00935                      full.x11RenderHandle(), // dst
00936                      0, 0, // src offset
00937                      0, 0, // mask offset
00938                      0, 0, // dst offset
00939                      winAttr.width, winAttr.height);
00940 
00941     KPixmapIO io;
00942     QImage image = io.toImage(full);
00943     thumbnail = io.convertToPixmap(image.smoothScale(thumbnailWidth,
00944                                                      thumbnailHeight));
00945 #else // XRENDER scaling
00946     // Scaling matrix
00947     XTransform transformation = {{
00948         { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(     0) },
00949         { XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(     0) },
00950         { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(factor) }
00951     }};
00952 
00953     XRenderSetPictureTransform(dpy, picture, &transformation);
00954     XRenderSetPictureFilter(dpy, picture, FilterBest, 0, 0);
00955 
00956     XRenderComposite(QX11Info::display(),
00957                      PictOpOver, // we're filtering, alpha values are probable
00958                      picture, // src
00959                      None, // mask
00960                      thumbnail.x11PictureHandle(), // dst
00961                      0, 0, // src offset
00962                      0, 0, // mask offset
00963                      0, 0, // dst offset
00964                      thumbnailWidth, thumbnailHeight);
00965 #endif
00966     XRenderFreePicture(dpy, picture);
00967 
00968     return thumbnail;
00969 }
00970 #else // THUMBNAILING_POSSIBLE
00971 QPixmap Task::thumbnail(int /* maxDimension */)
00972 {
00973     return QPixmap();
00974 }
00975 #endif // THUMBNAILING_POSSIBLE
00976 
00977 void Task::updateWindowPixmap()
00978 {
00979 #ifdef THUMBNAILING_POSSIBLE
00980     if (!KWindowSystem::compositingActive() || !isOnCurrentDesktop() ||
00981         isMinimized())
00982     {
00983         return;
00984     }
00985 
00986     Display *dpy = QX11Info::display();
00987 
00988     if (d->windowPixmap)
00989     {
00990         XFreePixmap(dpy, d->windowPixmap);
00991     }
00992 
00993     d->windowPixmap = XCompositeNameWindowPixmap(dpy, d->frameId);
00994 #endif // THUMBNAILING_POSSIBLE
00995 }
00996 
00997 int TaskManager::currentDesktop() const
00998 {
00999     return KWindowSystem::currentDesktop();
01000 }
01001 
01002 TaskDrag::TaskDrag(const TaskList& tasks, QWidget* source)
01003   : QDrag(source),
01004     d(0)
01005 {
01006     QByteArray data;
01007     QDataStream stream(&data, QIODevice::WriteOnly);
01008 
01009     stream.setVersion(QDataStream::Qt_3_1);
01010 
01011     TaskList::const_iterator itEnd = tasks.constEnd();
01012     for (TaskList::const_iterator it = tasks.constBegin(); it != itEnd; ++it)
01013     {
01014         stream << (quint32)(*it)->window();
01015     }
01016 
01017     QMimeData* mimeData = new QMimeData();
01018     mimeData->setData("taskbar/task", data);
01019     setMimeData(mimeData);
01020 }
01021 
01022 TaskDrag::~TaskDrag()
01023 {
01024 }
01025 
01026 bool TaskDrag::canDecode(const QMimeData* e)
01027 {
01028     return e->hasFormat("taskbar/task");
01029 }
01030 
01031 TaskList TaskDrag::decode( const QMimeData* e )
01032 {
01033     QByteArray data(e->data("taskbar/task"));
01034     TaskList tasks;
01035 
01036     if (data.size())
01037     {
01038         QDataStream stream(data);
01039         while (!stream.atEnd())
01040         {
01041             quint32 id;
01042             stream >> id;
01043             if (TaskPtr task = TaskManager::self()->findTask(id))
01044             {
01045                 tasks.append(task);
01046             }
01047         }
01048     }
01049 
01050     return tasks;
01051 }
01052  
01053 } // TaskManager namespace
01054 
01055 #include "task.moc"

libtaskmanager

Skip menu "libtaskmanager"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal