00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "task.h"
00027
00028
00029 #include <QMimeData>
00030 #include <QTimer>
00031
00032
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
00092 d->pixmap = KWindowSystem::icon(d->win, 16, 16, true);
00093
00094
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
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
00125 if (d->windowPixmap && QX11Info::display())
00126 {
00127 XFreePixmap(QX11Info::display(), d->windowPixmap);
00128 }
00129 #endif // THUMBNAILING_POSSIBLE
00130 delete d;
00131 }
00132
00133
00134
00135
00136
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);
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
00175 d->pixmap = KWindowSystem::icon(d->win, 16, 16, true);
00176
00177
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
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
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
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
00476
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
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
00498 pixmap = icon( size, size, false );
00499
00500
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
00512 if ( pixmap.isNull() || ( pixmap.width() != size ) || ( pixmap.height() != size ) ) {
00513 pixmap = icon( size, size, true );
00514 isStaticIcon = false;
00515 }
00516
00517
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
00690 KWindowSystem::raiseWindow( d->win );
00691 }
00692
00693 void Task::lower()
00694 {
00695
00696 KWindowSystem::lowerWindow( d->win );
00697 }
00698
00699 void Task::activate()
00700 {
00701
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() )
00846 {
00847 return;
00848 }
00849
00850
00851
00852
00853
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();
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;
00900
00901 Picture picture = XRenderCreatePicture(dpy, d->windowPixmap, format,
00902 CPSubwindowMode, &picAttr);
00903
00904
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,
00934 None,
00935 full.x11RenderHandle(),
00936 0, 0,
00937 0, 0,
00938 0, 0,
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
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,
00958 picture,
00959 None,
00960 thumbnail.x11PictureHandle(),
00961 0, 0,
00962 0, 0,
00963 0, 0,
00964 thumbnailWidth, thumbnailHeight);
00965 #endif
00966 XRenderFreePicture(dpy, picture);
00967
00968 return thumbnail;
00969 }
00970 #else // THUMBNAILING_POSSIBLE
00971 QPixmap Task::thumbnail(int )
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 }
01054
01055 #include "task.moc"