00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "pager.h"
00021
00022 #include <math.h>
00023
00024 #include <QApplication>
00025 #include <QPainter>
00026 #include <QStyleOptionGraphicsItem>
00027 #include <QFont>
00028 #include <QGraphicsSceneHoverEvent>
00029 #include <QTimer>
00030 #include <QX11Info>
00031
00032 #include <KDialog>
00033 #include <KColorScheme>
00034 #include <KConfigDialog>
00035 #include <KGlobalSettings>
00036 #include <KSharedConfig>
00037 #include <KWindowSystem>
00038 #include <NETRootInfo>
00039 #include <KToolInvocation>
00040 #include <kmanagerselection.h>
00041
00042 #include <Plasma/Svg>
00043 #include <Plasma/FrameSvg>
00044 #include <Plasma/PaintUtils>
00045 #include <Plasma/Theme>
00046 #include <Plasma/ToolTipManager>
00047 #include <Plasma/Animator>
00048
00049 #include <kephal/screens.h>
00050
00051 #include <taskmanager/task.h>
00052
00053 const int FAST_UPDATE_DELAY = 200;
00054 const int UPDATE_DELAY = 500;
00055 const int DRAG_SWITCH_DELAY = 1000;
00056
00057 Pager::Pager(QObject *parent, const QVariantList &args)
00058 : Plasma::Applet(parent, args),
00059 m_displayedText(None),
00060 m_showWindowIcons(false),
00061 m_showOwnBackground(false),
00062 m_rows(2),
00063 m_columns(0),
00064 m_hoverIndex(-1),
00065 m_colorScheme(0),
00066 m_dragId(0),
00067 m_dirtyDesktop(-1),
00068 m_dragStartDesktop(-1),
00069 m_dragHighlightedDesktop(-1),
00070 m_dragSwitchDesktop(-1)
00071 {
00072 setAcceptsHoverEvents(true);
00073 setAcceptDrops(true);
00074 setHasConfigurationInterface(true);
00075
00076 m_background = new Plasma::FrameSvg(this);
00077 m_background->setImagePath("widgets/pager");
00078 m_background->setCacheAllRenderedFrames(true);
00079
00080
00081 m_desktopCount = KWindowSystem::numberOfDesktops();
00082 m_size = QSizeF(176, 88);
00083 resize(m_size);
00084 }
00085
00086 void Pager::init()
00087 {
00088 createMenu();
00089
00090 KConfigGroup cg = config();
00091 m_displayedText = (DisplayedText)cg.readEntry("displayedText", (int)m_displayedText);
00092 m_showWindowIcons = cg.readEntry("showWindowIcons", m_showWindowIcons);
00093 m_rows = globalConfig().readEntry("rows", m_rows);
00094
00095 if (m_rows < 1) {
00096 m_rows = 1;
00097 } else if (m_rows > m_desktopCount) {
00098 m_rows = m_desktopCount;
00099 }
00100
00101 m_timer = new QTimer(this);
00102 m_timer->setSingleShot(true);
00103 connect(m_timer, SIGNAL(timeout()), this, SLOT(recalculateWindowRects()));
00104
00105 m_dragSwitchTimer = new QTimer(this);
00106 m_dragSwitchTimer->setSingleShot(true);
00107 connect(m_dragSwitchTimer, SIGNAL(timeout()), this, SLOT(dragSwitch()));
00108
00109 connect(KWindowSystem::self(), SIGNAL(currentDesktopChanged(int)), this, SLOT(currentDesktopChanged(int)));
00110 connect(KWindowSystem::self(), SIGNAL(windowAdded(WId)), this, SLOT(windowAdded(WId)));
00111 connect(KWindowSystem::self(), SIGNAL(windowRemoved(WId)), this, SLOT(windowRemoved(WId)));
00112 connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(activeWindowChanged(WId)));
00113 connect(KWindowSystem::self(), SIGNAL(numberOfDesktopsChanged(int)), this, SLOT(numberOfDesktopsChanged(int)));
00114 connect(KWindowSystem::self(), SIGNAL(desktopNamesChanged()), this, SLOT(desktopNamesChanged()));
00115 connect(KWindowSystem::self(), SIGNAL(stackingOrderChanged()), this, SLOT(stackingOrderChanged()));
00116 connect(KWindowSystem::self(), SIGNAL(windowChanged(WId,unsigned int)), this, SLOT(windowChanged(WId,unsigned int)));
00117 connect(KWindowSystem::self(), SIGNAL(showingDesktopChanged(bool)), this, SLOT(showingDesktopChanged(bool)));
00118 connect(Kephal::Screens::self(), SIGNAL(screenAdded(Kephal::Screen *)), SLOT(desktopsSizeChanged()));
00119 connect(Kephal::Screens::self(), SIGNAL(screenRemoved(int)), SLOT(desktopsSizeChanged()));
00120 connect(Kephal::Screens::self(), SIGNAL(screenResized(Kephal::Screen *, QSize, QSize)), SLOT(desktopsSizeChanged()));
00121 connect(Kephal::Screens::self(), SIGNAL(screenMoved(Kephal::Screen *, QPoint, QPoint)), SLOT(desktopsSizeChanged()));
00122
00123 m_desktopLayoutOwner = new KSelectionOwner( QString( "_NET_DESKTOP_LAYOUT_S%1" )
00124 .arg( QX11Info::appScreen()).toLatin1().constData(), QX11Info::appScreen(), this );
00125 connect( m_desktopLayoutOwner, SIGNAL( lostOwnership()), SLOT( lostDesktopLayoutOwner()));
00126 if ( !m_desktopLayoutOwner->claim( false ))
00127 lostDesktopLayoutOwner();
00128
00129 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeRefresh()));
00130
00131 recalculateGeometry();
00132
00133 m_currentDesktop = KWindowSystem::currentDesktop();
00134 }
00135
00136 Pager::~Pager()
00137 {
00138 delete m_colorScheme;
00139 }
00140
00141 void Pager::constraintsEvent(Plasma::Constraints constraints)
00142 {
00143 if (constraints & Plasma::SizeConstraint) {
00144 recalculateGeometry();
00145 recalculateWindowRects();
00146 if (m_background->hasElementPrefix(QString())) {
00147 m_background->setElementPrefix(QString());
00148 m_background->resizeFrame(size());
00149 }
00150 }
00151 if (constraints & Plasma::FormFactorConstraint) {
00152 if (formFactor() == Plasma::Horizontal) {
00153 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
00154 } else if (formFactor() == Plasma::Vertical) {
00155 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
00156 } else {
00157 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00158 }
00159 }
00160 }
00161
00162 KColorScheme *Pager::colorScheme()
00163 {
00164 if (!m_colorScheme) {
00165 m_colorScheme = new KColorScheme(QPalette::Active, KColorScheme::View, Plasma::Theme::defaultTheme()->colorScheme());
00166 }
00167
00168 return m_colorScheme;
00169 }
00170
00171 void Pager::createMenu()
00172 {
00173 QAction* configureDesktop = new QAction(SmallIcon("configure"),i18n("&Configure Desktops..."), this);
00174 m_actions.append(configureDesktop);
00175 connect(configureDesktop, SIGNAL(triggered(bool)), this , SLOT(slotConfigureDesktop()));
00176 }
00177
00178 QList<QAction*> Pager::contextualActions()
00179 {
00180 return m_actions;
00181 }
00182
00183 void Pager::slotConfigureDesktop()
00184 {
00185 QString error;
00186 KToolInvocation::startServiceByDesktopName("desktop", QStringList(), &error);
00187 }
00188
00189 void Pager::createConfigurationInterface(KConfigDialog *parent)
00190 {
00191 QWidget *widget = new QWidget();
00192 ui.setupUi(widget);
00193 parent->addPage(widget, i18n("General"), icon());
00194 connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
00195 connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
00196 connect(ui.configureDesktopsButton, SIGNAL(clicked()), SLOT(slotConfigureDesktop()));
00197
00198 switch (m_displayedText){
00199 case Number:
00200 ui. desktopNumberRadioButton->setChecked(true);
00201 break;
00202
00203 case Name:
00204 ui.desktopNameRadioButton->setChecked(true);
00205 break;
00206
00207 case None:
00208 ui.displayNoneRadioButton->setChecked(true);
00209 break;
00210 }
00211
00212 ui.showWindowIconsCheckBox->setChecked(m_showWindowIcons);
00213 ui.spinRows->setValue(m_rows);
00214 ui.spinRows->setMaximum(m_desktopCount);
00215 }
00216
00217 void Pager::recalculateGeometry()
00218 {
00219 if (!m_rects.isEmpty() && geometry().size() == m_size) {
00220
00221 return;
00222 }
00223
00224 int padding = 2;
00225 int textMargin = 3;
00226 int columns = m_desktopCount / m_rows + m_desktopCount % m_rows;
00227 int rows = m_rows;
00228
00229
00230 if (formFactor() == Plasma::Vertical) {
00231 rows = columns;
00232 columns = m_rows;
00233 }
00234
00235 qreal leftMargin = 0;
00236 qreal topMargin = 0;
00237 qreal rightMargin = 0;
00238 qreal bottomMargin = 0;
00239
00240 if (formFactor() == Plasma::Vertical || formFactor() == Plasma::Horizontal) {
00241 m_background->setElementPrefix(QString());
00242 m_background->getMargins(leftMargin, topMargin, rightMargin, bottomMargin);
00243
00244 qreal ratio = (qreal)Kephal::ScreenUtils::desktopGeometry().width() / (qreal)Kephal::ScreenUtils::desktopGeometry().height();
00245
00246 if (formFactor() == Plasma::Vertical) {
00247 qreal optimalSize = (geometry().width() - KIconLoader::SizeSmall*ratio * columns + padding*(columns-1)) / 2;
00248
00249 if (optimalSize < leftMargin || optimalSize < rightMargin) {
00250 leftMargin = rightMargin = qMax(qreal(0), optimalSize);
00251 m_showOwnBackground = false;
00252 }
00253 } else if (formFactor() == Plasma::Horizontal) {
00254 qreal optimalSize = (geometry().height() - KIconLoader::SizeSmall*rows + padding*(rows-1)) / 2;
00255
00256 if (optimalSize < topMargin || optimalSize < bottomMargin) {
00257 topMargin = bottomMargin = qMax(qreal(0), optimalSize);
00258 m_showOwnBackground = false;
00259 }
00260 } else {
00261 m_showOwnBackground = true;
00262 }
00263 } else {
00264 getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
00265 }
00266
00267 qreal itemHeight;
00268 qreal itemWidth;
00269
00270 if (formFactor() == Plasma::Vertical) {
00271 itemWidth = (contentsRect().width() - leftMargin - rightMargin - padding * (columns - 1)) / columns;
00272 m_widthScaleFactor = itemWidth / Kephal::ScreenUtils::desktopGeometry().width();
00273 itemHeight = Kephal::ScreenUtils::desktopGeometry().height() * m_widthScaleFactor;
00274 m_heightScaleFactor = m_widthScaleFactor;
00275 } else {
00276 itemHeight = (contentsRect().height() - topMargin - bottomMargin - padding * (rows - 1)) / rows;
00277 m_heightScaleFactor = itemHeight / Kephal::ScreenUtils::desktopGeometry().height();
00278 itemWidth = Kephal::ScreenUtils::desktopGeometry().width() * m_heightScaleFactor;
00279 if (m_displayedText == Name) {
00280
00281
00282 for (int i = 0; i < m_desktopCount; i++) {
00283 QFontMetricsF metrics(KGlobalSettings::taskbarFont());
00284 QSizeF textSize = metrics.size(Qt::TextSingleLine, KWindowSystem::desktopName(i+1));
00285 if (textSize.width() + textMargin * 2 > itemWidth) {
00286 itemWidth = textSize.width() + textMargin * 2;
00287 }
00288 }
00289 }
00290 m_widthScaleFactor = itemWidth / Kephal::ScreenUtils::desktopGeometry().width();
00291 }
00292
00293 m_rects.clear();
00294 m_animations.clear();
00295 QRectF itemRect(QPoint(leftMargin, topMargin) , QSize(floor(itemWidth), floor(itemHeight)));
00296 for (int i = 0; i < m_desktopCount; i++) {
00297 itemRect.moveLeft(leftMargin + floor(i % columns * (itemWidth + padding)));
00298 itemRect.moveTop(topMargin + floor(i / columns * (itemHeight + padding)));
00299 m_rects.append(itemRect);
00300 AnimInfo anim;
00301 anim.animId = -1;
00302 anim.fadeIn = true;
00303 anim.alpha = 0;
00304 m_animations.append(anim);
00305 }
00306
00307
00308 if (m_background->hasElementPrefix("normal")) {
00309 m_background->setElementPrefix("normal");
00310 m_background->resizeFrame(itemRect.size());
00311 }
00312
00313 if (m_background->hasElementPrefix("active")) {
00314 m_background->setElementPrefix("active");
00315 m_background->resizeFrame(itemRect.size());
00316 }
00317
00318 if (m_background->hasElementPrefix("hover")) {
00319 m_background->setElementPrefix("hover");
00320 m_background->resizeFrame(itemRect.size());
00321 }
00322
00323 m_size = QSizeF(ceil(columns * itemWidth + padding * (columns - 1) + leftMargin + rightMargin),
00324 ceil(rows * itemHeight + padding * (rows - 1) + topMargin + bottomMargin));
00325
00326
00327
00328 resize(m_size);
00329 setPreferredSize(m_size);
00330 if (m_desktopLayoutOwner && columns != m_columns) {
00331
00332 m_columns = columns;
00333 NET::Orientation orient = NET::OrientationHorizontal;
00334 NETRootInfo i( QX11Info::display(), 0 );
00335 i.setDesktopLayout( orient, columns, rows, NET::DesktopLayoutCornerTopLeft );
00336 }
00337 }
00338
00339 void Pager::recalculateWindowRects()
00340 {
00341 QList<WId> windows = KWindowSystem::stackingOrder();
00342 m_windowRects.clear();
00343 for (int i = 0; i < m_desktopCount; i++) {
00344 m_windowRects.append(QList<QPair<WId, QRect> >());
00345 }
00346 m_activeWindows.clear();
00347 m_windowInfo.clear();
00348 foreach(WId window, windows) {
00349 KWindowInfo info = KWindowSystem::windowInfo(window, NET::WMGeometry | NET::WMFrameExtents | NET::WMWindowType | NET::WMDesktop | NET::WMState | NET::XAWMState | NET::WMVisibleName);
00350 NET::WindowType type = info.windowType(NET::NormalMask | NET::DialogMask | NET::OverrideMask |
00351 NET::UtilityMask | NET::DesktopMask | NET::DockMask |
00352 NET::TopMenuMask | NET::SplashMask | NET::ToolbarMask |
00353 NET::MenuMask);
00354
00355
00356
00357
00358 if (type == NET::Desktop || type == NET::Dock || type == NET::TopMenu ||
00359 type == NET::Splash || type == NET::Menu || type == NET::Toolbar ||
00360 info.hasState(NET::SkipPager) || info.isMinimized()) {
00361 continue;
00362 }
00363
00364 for (int i = 0; i < m_desktopCount; i++) {
00365 if (!info.isOnDesktop(i+1)) {
00366 continue;
00367 }
00368
00369 QRect windowRect = info.frameGeometry();
00370
00371 if (KWindowSystem::mapViewport()) {
00372 windowRect = fixViewportPosition( windowRect );
00373 }
00374
00375 windowRect = QRectF(windowRect.x() * m_widthScaleFactor,
00376 windowRect.y() * m_heightScaleFactor,
00377 windowRect.width() * m_widthScaleFactor,
00378 windowRect.height() * m_heightScaleFactor).toRect();
00379 windowRect.translate(m_rects[i].topLeft().toPoint());
00380 m_windowRects[i].append(QPair<WId, QRect>(window, windowRect));
00381 if (window == KWindowSystem::activeWindow()) {
00382 m_activeWindows.append(windowRect);
00383 }
00384 m_windowInfo.append(info);
00385 }
00386 }
00387
00388 update();
00389 }
00390
00391 void Pager::configAccepted()
00392 {
00393 KConfigGroup cg = config();
00394 bool changed = false;
00395
00396 DisplayedText displayedText;
00397
00398 if (ui.desktopNumberRadioButton->isChecked()){
00399 displayedText = Number;
00400
00401 }else if (ui.desktopNameRadioButton->isChecked()){
00402 displayedText = Name;
00403
00404 }else{
00405 displayedText = None;
00406 }
00407
00408 if ((int)m_displayedText != (int)displayedText) {
00409 m_displayedText = displayedText;
00410 cg.writeEntry("displayedText", (int)m_displayedText);
00411 changed = true;
00412 }
00413
00414 if (m_showWindowIcons != ui.showWindowIconsCheckBox->isChecked()) {
00415 m_showWindowIcons = ui.showWindowIconsCheckBox->isChecked();
00416 cg.writeEntry("showWindowIcons", m_showWindowIcons);
00417 changed = true;
00418 }
00419
00420
00421
00422
00423 if (m_rows != ui.spinRows->value()) {
00424 KConfigGroup globalcg = globalConfig();
00425 m_rows = ui.spinRows->value();
00426 if (m_rows > m_desktopCount) {
00427 m_rows = m_desktopCount;
00428 }
00429 globalcg.writeEntry("rows", m_rows);
00430 changed = true;
00431 }
00432
00433 if (changed) {
00434 configNeedsSaving();
00435
00436 m_columns = 0;
00437 m_size = QSizeF(-1, -1);
00438 recalculateGeometry();
00439 recalculateWindowRects();
00440 update();
00441 }
00442 }
00443
00444 void Pager::currentDesktopChanged(int desktop)
00445 {
00446 if (desktop < 1) {
00447 return;
00448 }
00449
00450 m_currentDesktop = desktop;
00451 m_dirtyDesktop = -1;
00452
00453 if (!m_timer->isActive()) {
00454 m_timer->start(FAST_UPDATE_DELAY);
00455 }
00456 }
00457
00458 void Pager::windowAdded(WId id)
00459 {
00460 Q_UNUSED(id)
00461
00462 KWindowInfo info = KWindowSystem::windowInfo(id, NET::WMGeometry | NET::WMFrameExtents | NET::WMWindowType | NET::WMDesktop | NET::WMState | NET::XAWMState);
00463 m_dirtyDesktop = info.desktop() - 1;
00464
00465 if (!m_timer->isActive()) {
00466 m_timer->start(FAST_UPDATE_DELAY);
00467 }
00468 }
00469
00470 void Pager::windowRemoved(WId id)
00471 {
00472 Q_UNUSED(id)
00473
00474 KWindowInfo info = KWindowSystem::windowInfo(id, NET::WMGeometry | NET::WMFrameExtents | NET::WMWindowType | NET::WMDesktop | NET::WMState | NET::XAWMState);
00475 m_dirtyDesktop = info.desktop() - 1;
00476
00477 if (!m_timer->isActive()) {
00478 m_timer->start(FAST_UPDATE_DELAY);
00479 }
00480 }
00481
00482 void Pager::activeWindowChanged(WId id)
00483 {
00484 Q_UNUSED(id)
00485
00486 KWindowInfo info = KWindowSystem::windowInfo(id, NET::WMGeometry | NET::WMFrameExtents | NET::WMWindowType | NET::WMDesktop | NET::WMState | NET::XAWMState);
00487 m_dirtyDesktop = info.desktop() - 1;
00488
00489 if (!m_timer->isActive()) {
00490 m_timer->start(FAST_UPDATE_DELAY);
00491 }
00492 }
00493
00494 void Pager::numberOfDesktopsChanged(int num)
00495 {
00496 if (num < 1) {
00497 return;
00498 }
00499
00500 m_dirtyDesktop = -1;
00501 m_desktopCount = num;
00502
00503 if (m_rows > m_desktopCount) {
00504 m_rows = m_desktopCount;
00505 }
00506
00507 m_rects.clear();
00508 recalculateGeometry();
00509 recalculateWindowRects();
00510 }
00511
00512 void Pager::desktopNamesChanged()
00513 {
00514 m_dirtyDesktop = -1;
00515
00516 m_rects.clear();
00517 recalculateGeometry();
00518
00519 if (!m_timer->isActive()) {
00520 m_timer->start(UPDATE_DELAY);
00521 }
00522 }
00523
00524 void Pager::stackingOrderChanged()
00525 {
00526 m_dirtyDesktop = -1;
00527
00528 if (!m_timer->isActive()) {
00529 m_timer->start(FAST_UPDATE_DELAY);
00530 }
00531 }
00532
00533 void Pager::windowChanged(WId id, unsigned int properties)
00534 {
00535 Q_UNUSED(id)
00536
00537 if (properties & NET::WMGeometry) {
00538 KWindowInfo info = KWindowSystem::windowInfo(id, NET::WMGeometry | NET::WMFrameExtents | NET::WMWindowType | NET::WMDesktop | NET::WMState | NET::XAWMState);
00539 m_dirtyDesktop = info.desktop() - 1;
00540 } else {
00541 m_dirtyDesktop = -1;
00542 }
00543
00544 if (properties & NET::WMGeometry ||
00545 properties & NET::WMDesktop) {
00546 if (!m_timer->isActive()) {
00547 m_timer->start(UPDATE_DELAY);
00548 }
00549 }
00550 }
00551
00552 void Pager::showingDesktopChanged(bool showing)
00553 {
00554 m_dirtyDesktop = -1;
00555
00556 Q_UNUSED(showing)
00557 if (!m_timer->isActive()) {
00558 m_timer->start(UPDATE_DELAY);
00559 }
00560 }
00561
00562 void Pager::desktopsSizeChanged()
00563 {
00564 m_dirtyDesktop = -1;
00565
00566 m_rects.clear();
00567 recalculateGeometry();
00568
00569 if (!m_timer->isActive()) {
00570 m_timer->start(UPDATE_DELAY);
00571 }
00572 }
00573
00574 void Pager::mousePressEvent(QGraphicsSceneMouseEvent *event)
00575 {
00576 if (event->buttons() != Qt::RightButton)
00577 {
00578 for (int i = 0; i < m_rects.count(); ++i) {
00579 if (m_rects[i].contains(event->pos())) {
00580 m_dragStartDesktop = m_dragHighlightedDesktop = i;
00581 m_dragOriginalPos = m_dragCurrentPos = event->pos();
00582 if (m_dragOriginal.isEmpty()) {
00583 m_dragOriginal = m_rects[i].toRect();
00584 }
00585
00586 update();
00587 return;
00588 }
00589 }
00590 }
00591 Applet::mousePressEvent(event);
00592 }
00593
00594 void Pager::wheelEvent(QGraphicsSceneWheelEvent *e)
00595 {
00596 int newDesk;
00597 int desktops = KWindowSystem::numberOfDesktops();
00598
00599
00600
00601
00602
00603 if (e->delta() < 0) {
00604 newDesk = m_currentDesktop % desktops + 1;
00605 } else {
00606 newDesk = (desktops + m_currentDesktop - 2) % desktops + 1;
00607 }
00608
00609 KWindowSystem::setCurrentDesktop(newDesk);
00610 m_currentDesktop = newDesk;
00611 update();
00612
00613 Applet::wheelEvent(e);
00614 }
00615
00616 void Pager::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00617 {
00618 if (m_dragId > 0) {
00619 m_dragCurrentPos = event->pos();
00620 m_dragHighlightedDesktop = -1;
00621 m_hoverRect = QRectF();
00622 int i = 0;
00623 foreach (const QRectF &rect, m_rects) {
00624 if (rect.contains(event->pos())) {
00625 m_dragHighlightedDesktop = i;
00626 m_hoverRect = rect;
00627 break;
00628 }
00629
00630 ++i;
00631 }
00632 update();
00633 event->accept();
00634 return;
00635 } else if (m_dragStartDesktop != -1 &&
00636 (event->pos() - m_dragOriginalPos).toPoint().manhattanLength() > KGlobalSettings::dndEventDelay()) {
00637 m_dragId = 0;
00638 for (int k = m_windowRects[m_dragStartDesktop].count() - 1; k >= 0 ; k--) {
00639 if (m_windowRects[m_dragStartDesktop][k].second.contains(m_dragOriginalPos.toPoint())) {
00640 m_dragOriginal = m_windowRects[m_dragStartDesktop][k].second;
00641 m_dragId = m_windowRects[m_dragStartDesktop][k].first;
00642 event->accept();
00643 break;
00644 }
00645 }
00646 }
00647
00648 if (m_dragOriginal.isEmpty()) {
00649 Applet::mouseMoveEvent(event);
00650 }
00651 }
00652
00653 void Pager::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00654 {
00655 if (m_dragId) {
00656 if (m_dragHighlightedDesktop != -1) {
00657 QPointF dest = m_dragCurrentPos - m_rects[m_dragHighlightedDesktop].topLeft() - m_dragOriginalPos + m_dragOriginal.topLeft();
00658 dest = QPointF(dest.x()/m_widthScaleFactor, dest.y()/m_heightScaleFactor);
00659
00660 dest = QPointF(qMax(dest.x(), qreal(0.0)), qMax(dest.y(), qreal(0.0)));
00661 if (!KWindowSystem::mapViewport()) {
00662 KWindowInfo info = KWindowSystem::windowInfo(m_dragId, NET::WMDesktop);
00663
00664 if (!info.onAllDesktops()) {
00665 KWindowSystem::setOnDesktop(m_dragId, m_dragHighlightedDesktop+1);
00666 }
00667
00668
00669
00670
00671 if (m_dragHighlightedDesktop == m_dragStartDesktop || info.onAllDesktops()) {
00672
00673 NETRootInfo i( QX11Info::display(), 0 );
00674 int flags = ( 0x20 << 12 ) | ( 0x03 << 8 ) | 1;
00675 i.moveResizeWindowRequest( m_dragId, flags, dest.toPoint().x(), dest.toPoint().y(), 0, 0 );
00676 }
00677 } else {
00678
00679
00680
00681 dest += KWindowSystem::desktopToViewport( m_dragHighlightedDesktop+1, false );
00682 QPoint d = KWindowSystem::constrainViewportRelativePosition( dest.toPoint());
00683 NETRootInfo i( QX11Info::display(), 0 );
00684 int flags = ( 0x20 << 12 ) | ( 0x03 << 8 ) | 1;
00685 i.moveResizeWindowRequest( m_dragId, flags, d.x(), d.y(), 0, 0 );
00686 }
00687 }
00688 m_timer->start();
00689 } else if (m_dragStartDesktop != -1 && m_dragStartDesktop < m_rects.size() &&
00690 m_rects[m_dragStartDesktop].contains(event->pos()) &&
00691 m_currentDesktop != m_dragStartDesktop + 1) {
00692
00693 KWindowSystem::setCurrentDesktop(m_dragStartDesktop + 1);
00694 m_currentDesktop = m_dragStartDesktop + 1;
00695 }
00696
00697 m_dragId = 0;
00698 m_dragOriginal = QRect();
00699 m_dragHighlightedDesktop = -1;
00700 m_dragStartDesktop = -1;
00701 m_dragOriginalPos = m_dragCurrentPos = QPointF();
00702
00703 update();
00704 Applet::mouseReleaseEvent(event);
00705 }
00706
00707
00708
00709 void Pager::handleHoverMove(const QPointF& pos)
00710 {
00711 bool changedHover = !m_hoverRect.contains(pos);
00712 Plasma::Animator *anim = Plasma::Animator::self();
00713
00714 if (changedHover && m_hoverIndex > -1) {
00715 if (m_animations[m_hoverIndex].animId != -1) {
00716 Plasma::Animator::self()->stopCustomAnimation(m_animations[m_hoverIndex].animId);
00717 }
00718 m_animations[m_hoverIndex].fadeIn = false;
00719 m_animations[m_hoverIndex].alpha = 1;
00720 m_animations[m_hoverIndex].animId = anim->customAnimation(40 / (1000 / s_FadeOutDuration), s_FadeOutDuration,Plasma::Animator::EaseOutCurve, this,"animationUpdate");
00721 }
00722
00723 if (!changedHover) {
00724 return;
00725 }
00726
00727 int i = 0;
00728 foreach (const QRectF &rect, m_rects) {
00729 if (rect.contains(pos)) {
00730 if (m_hoverRect != rect) {
00731 m_hoverRect = rect;
00732 m_hoverIndex = i;
00733 if (m_animations[m_hoverIndex].animId != -1) {
00734 anim->stopCustomAnimation(m_animations[i].animId);
00735 }
00736 m_animations[m_hoverIndex].fadeIn = true;
00737 m_animations[m_hoverIndex].alpha = 0;
00738 m_animations[m_hoverIndex].animId = anim->customAnimation(40 / (1000 / s_FadeInDuration), s_FadeInDuration,Plasma::Animator::EaseInCurve, this,"animationUpdate");
00739 update();
00740 updateToolTip();
00741 }
00742 return;
00743 }
00744 ++i;
00745 }
00746 m_hoverIndex = -1;
00747 m_hoverRect = QRectF();
00748 update();
00749 }
00750
00751
00752
00753 void Pager::handleHoverLeave()
00754 {
00755 if (m_hoverRect != QRectF()) {
00756 m_hoverRect = QRectF();
00757 update();
00758 }
00759
00760 if (m_hoverIndex != -1) {
00761 if (m_animations[m_hoverIndex].animId != -1) {
00762 Plasma::Animator::self()->stopCustomAnimation(m_animations[m_hoverIndex].animId);
00763 }
00764 m_animations[m_hoverIndex].fadeIn = false;
00765 m_animations[m_hoverIndex].alpha = 1;
00766 m_animations[m_hoverIndex].animId = Plasma::Animator::self()->customAnimation(40 / (1000 / s_FadeOutDuration), s_FadeOutDuration,Plasma::Animator::EaseOutCurve, this,"animationUpdate");
00767 m_hoverIndex = -1;
00768 }
00769
00770
00771
00772
00773
00774
00775 if (m_dragId || m_dragStartDesktop != -1) {
00776 m_dragId = 0;
00777 m_dragOriginal = QRect();
00778 m_dragHighlightedDesktop = -1;
00779 m_dragStartDesktop = -1;
00780 m_dragOriginalPos = m_dragCurrentPos = QPointF();
00781 update();
00782 }
00783 }
00784
00785 void Pager::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
00786 {
00787 handleHoverMove(event->pos());
00788 Applet::hoverEnterEvent(event);
00789 }
00790
00791 void Pager::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
00792 {
00793 handleHoverMove(event->pos());
00794 }
00795
00796 void Pager::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
00797 {
00798 handleHoverLeave();
00799 Applet::hoverLeaveEvent(event);
00800 }
00801
00802 void Pager::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
00803 {
00804 if (event->mimeData()->hasFormat(TaskManager::Task::mimetype())) {
00805 event->setAccepted(true);
00806 return;
00807 }
00808 else event->setAccepted(false);
00809 handleHoverMove(event->pos());
00810
00811 if (m_hoverIndex != -1) {
00812 m_dragSwitchDesktop = m_hoverIndex;
00813 m_dragSwitchTimer->start(DRAG_SWITCH_DELAY);
00814 }
00815 Applet::dragEnterEvent(event);
00816 }
00817
00818 void Pager::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
00819 {
00820 handleHoverMove(event->pos());
00821
00822 if (m_dragSwitchDesktop != m_hoverIndex && m_hoverIndex != -1) {
00823 m_dragSwitchDesktop = m_hoverIndex;
00824 m_dragSwitchTimer->start(DRAG_SWITCH_DELAY);
00825 } else if (m_hoverIndex == -1) {
00826 m_dragSwitchDesktop = m_hoverIndex;
00827 m_dragSwitchTimer->stop();
00828 }
00829 Applet::dragMoveEvent(event);
00830 }
00831
00832 void Pager::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
00833 {
00834 handleHoverLeave();
00835
00836 m_dragSwitchDesktop = -1;
00837 m_dragSwitchTimer->stop();
00838 Applet::dragLeaveEvent(event);
00839 }
00840
00841 void Pager::dropEvent(QGraphicsSceneDragDropEvent *event)
00842 {
00843 bool ok;
00844 WId id = TaskManager::Task::idFromMimeData(event->mimeData(), &ok);
00845 if (ok) {
00846 for (int i = 0; i < m_rects.count(); ++i) {
00847 if (m_rects[i].contains(event->pos().toPoint())) {
00848 KWindowSystem::setOnDesktop(id, i + 1);
00849 m_dragSwitchDesktop = -1;
00850 break;
00851 }
00852 }
00853 }
00854 }
00855
00856 void Pager::animationUpdate(qreal progress, int animId)
00857 {
00858 int i = 0;
00859 foreach (AnimInfo anim, m_animations) {
00860 if (anim.animId == animId) {
00861 break;
00862 }
00863 i++;
00864 }
00865
00866 if (i >= m_animations.size()) {
00867 return;
00868 }
00869
00870 m_animations[i].alpha = m_animations[i].fadeIn ? progress : 1 - progress;
00871
00872 if (progress == 1) {
00873 m_animations[i].animId = -1;
00874 m_animations[i].fadeIn = true;
00875 }
00876
00877
00878 update();
00879 }
00880
00881 void Pager::dragSwitch()
00882 {
00883 if (m_dragSwitchDesktop == -1) {
00884 return;
00885 }
00886 KWindowSystem::setCurrentDesktop(m_dragSwitchDesktop + 1);
00887 m_currentDesktop = m_dragSwitchDesktop + 1;
00888 }
00889
00890 void Pager::paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
00891 {
00892 Q_UNUSED( option );
00893 Q_UNUSED( contentsRect );
00894
00895 KColorScheme* plasmaColorTheme = colorScheme();
00896 painter->setFont(KGlobalSettings::taskbarFont());
00897
00898
00899 QColor defaultTextColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
00900 QColor hoverColor = defaultTextColor;
00901 hoverColor.setAlpha(64);
00902
00903
00904 QColor drawingColor = plasmaColorTheme->foreground(KColorScheme::InactiveText).color();
00905 drawingColor.setAlpha(45);
00906 QBrush windowBrush(drawingColor);
00907
00908 drawingColor.setAlpha(90);
00909 QBrush windowBrushActiveDesk(drawingColor);
00910
00911
00912 drawingColor = defaultTextColor;
00913 drawingColor.setAlpha(130);
00914 QPen windowPen(drawingColor);
00915
00916
00917 QPen activeWindowPen(defaultTextColor);
00918
00919
00920 drawingColor.setAlpha(130);
00921 QBrush activeWindowBrush(drawingColor);
00922
00923 drawingColor.setAlpha(155);
00924 QBrush activeWindowBrushActiveDesk(drawingColor);
00925
00926 if (m_showOwnBackground && (formFactor() == Plasma::Vertical || formFactor() == Plasma::Horizontal)) {
00927 m_background->setElementPrefix(QString());
00928 m_background->paintFrame(painter);
00929 }
00930
00931
00932 painter->setPen(Qt::NoPen);
00933 if (!m_background->hasElementPrefix("hover")) {
00934 for (int i = 0; i < m_rects.count(); i++) {
00935 if (m_rects[i] == m_hoverRect) {
00936 QColor animHoverColor = hoverColor;
00937 if (m_animations[i].animId > -1) {
00938 animHoverColor.setAlpha(hoverColor.alpha()*m_animations[i].alpha);
00939 }
00940 painter->setBrush(animHoverColor);
00941 painter->drawRect(m_rects[i]);
00942 }
00943 }
00944 }
00945
00946
00947 painter->setPen(windowPen);
00948 for (int i = 0; i < m_windowRects.count(); i++) {
00949 for (int j = 0; j < m_windowRects[i].count(); j++) {
00950 QRect rect = m_windowRects[i][j].second;
00951
00952 if (m_currentDesktop > 0 &&
00953 m_currentDesktop <= m_rects.count() &&
00954 m_rects[m_currentDesktop-1].contains(rect)) {
00955 if (m_activeWindows.contains(rect)) {
00956 painter->setBrush(activeWindowBrushActiveDesk);
00957 painter->setPen(activeWindowPen);
00958 } else {
00959 painter->setBrush(windowBrushActiveDesk);
00960 painter->setPen(windowPen);
00961 }
00962 } else {
00963 if (m_activeWindows.contains(rect)) {
00964 painter->setBrush(activeWindowBrush);
00965 painter->setPen(activeWindowPen);
00966 } else {
00967 painter->setBrush(windowBrush);
00968 painter->setPen(windowPen);
00969 }
00970 }
00971 if (m_dragId == m_windowRects[i][j].first) {
00972 rect.translate((m_dragCurrentPos - m_dragOriginalPos).toPoint());
00973 painter->setClipRect(option->exposedRect);
00974 } else if (i < m_rects.count()) {
00975 painter->setClipRect(m_rects[i].adjusted(1, 1, -1, -1));
00976 }
00977 painter->drawRect(rect);
00978 if ((rect.width() > 16) && (rect.height() > 16) && m_showWindowIcons){
00979 painter->drawPixmap(rect.x() + (rect.width() - 16) / 2, rect.y() + (rect.height() - 16) / 2, 16, 16,
00980 KWindowSystem::icon(m_windowRects[i][j].first, 16, 16, true));
00981 }
00982 }
00983 }
00984
00985
00986 painter->setClipRect(option->exposedRect);
00987 painter->setBrush(Qt::NoBrush);
00988
00989 QString prefix;
00990 for (int i = 0; i < m_rects.count(); i++) {
00991 if (i + 1 == m_currentDesktop || i == m_dragHighlightedDesktop) {
00992 prefix = "active";
00993 } else {
00994 prefix = "normal";
00995 }
00996
00997
00998 if (m_background->hasElementPrefix(prefix)) {
00999 m_background->setElementPrefix(prefix);
01000 if (m_animations[i].animId > -1) {
01001 QPixmap normal = m_background->framePixmap();
01002 m_background->setElementPrefix("hover");
01003 QPixmap result = Plasma::PaintUtils::transition(normal, m_background->framePixmap(), m_animations[i].alpha);
01004 painter->drawPixmap(m_rects[i].topLeft(), result);
01005 } else {
01006
01007 if (m_rects[i] == m_hoverRect) {
01008 m_background->setElementPrefix("hover");
01009 }
01010 m_background->paintFrame(painter, m_rects[i].topLeft());
01011 }
01012 } else {
01013 QPen drawingPen;
01014
01015 if (i + 1 == m_currentDesktop || i == m_dragHighlightedDesktop) {
01016 defaultTextColor.setAlphaF(1);
01017 drawingPen = QPen(defaultTextColor);
01018 } else {
01019 drawingPen = QPen(plasmaColorTheme->foreground(KColorScheme::InactiveText).color());
01020 }
01021
01022 painter->setPen(drawingPen);
01023 painter->drawRect(m_rects[i]);
01024 }
01025
01026
01027 if (m_animations[i].animId == -1) {
01028 defaultTextColor.setAlphaF(1);
01029 }
01030 defaultTextColor.setAlphaF(m_animations[i].alpha / 2 + 0.5);
01031 painter->setPen(defaultTextColor);
01032
01033 QColor shadowColor(Qt::black);
01034 if (defaultTextColor.value() < 128) {
01035 shadowColor = Qt::white;
01036 }
01037
01038 QString desktopText = QString();
01039 if (m_displayedText == Number) {
01040 desktopText = QString::number(i + 1);
01041 } else if (m_displayedText == Name) {
01042 desktopText = KWindowSystem::desktopName(i + 1);
01043 }
01044
01045 if (!desktopText.isEmpty()) {
01046 int radius = 2;
01047 QPixmap result = Plasma::PaintUtils::shadowText(desktopText,
01048 KGlobalSettings::smallestReadableFont(),
01049 defaultTextColor,
01050 shadowColor, QPoint(0, 0), radius);
01051 QRectF target = m_rects[i];
01052
01053
01054 if (target.height() >= result.height() - radius * 2) {
01055 QPointF paintPoint = target.center() - (result.rect().center() + QPoint(radius, radius));
01056
01057 if (paintPoint.x() + radius < target.x() + 1) {
01058 paintPoint.setX(target.x() + 1 - radius);
01059 }
01060
01061 if (paintPoint.y() + radius < target.y() + 1) {
01062 paintPoint.setY(target.y() + 1 - radius);
01063 }
01064
01065 target.moveTopLeft(QPointF(0, 0));
01066 painter->drawPixmap(paintPoint, result, target);
01067 }
01068 }
01069 }
01070 }
01071
01072 void Pager::lostDesktopLayoutOwner()
01073 {
01074 delete m_desktopLayoutOwner;
01075 m_desktopLayoutOwner = NULL;
01076 }
01077
01078
01079
01080
01081 QRect Pager::fixViewportPosition( const QRect& r )
01082 {
01083 QRect desktopGeom = Kephal::ScreenUtils::desktopGeometry();
01084 int x = r.center().x() % desktopGeom.width();
01085 int y = r.center().y() % desktopGeom.height();
01086 if( x < 0 ) {
01087 x = x + desktopGeom.width();
01088 }
01089 if( y < 0 ) {
01090 y = y + desktopGeom.height();
01091 }
01092 return QRect( x - r.width() / 2, y - r.height() / 2, r.width(), r.height());
01093 }
01094
01095 void Pager::themeRefresh()
01096 {
01097 delete m_colorScheme;
01098 m_colorScheme = 0;
01099 }
01100
01101 void Pager::updateToolTip()
01102 {
01103 int hoverDesktopNumber = 0;
01104
01105 for (int i = 0; i < m_desktopCount; i++) {
01106 if (m_rects[i] == m_hoverRect) {
01107 hoverDesktopNumber = i + 1;
01108 }
01109 }
01110
01111 Plasma::ToolTipContent data;
01112 QString subtext = QString();
01113 int taskCounter = 0;
01114 int displayedTaskCounter = 0;
01115
01116 QList<WId> windows;
01117
01118 foreach(KWindowInfo winInfo, m_windowInfo){
01119 if (winInfo.isOnDesktop(hoverDesktopNumber) && !windows.contains(winInfo.win())) {
01120 bool active = (winInfo.win() == KWindowSystem::activeWindow());
01121 if ((taskCounter < 4) || active){
01122 QPixmap icon = KWindowSystem::icon(winInfo.win(), 16, 16, true);
01123 if (icon.isNull()) {
01124 subtext += "<br />•" + winInfo.visibleName();
01125 } else {
01126 data.addResource(Plasma::ToolTipContent::ImageResource, QUrl("wicon://" + QString::number(taskCounter)), QVariant(icon));
01127 subtext += "<br /><img src=\"wicon://" + QString::number(taskCounter) + "\"/>";
01128 }
01129 subtext += (active ? "<u>" : "") + winInfo.visibleName() + (active ? "</u>" : "");
01130
01131 displayedTaskCounter++;
01132 windows.append(winInfo.win());
01133 }
01134 taskCounter++;
01135 }
01136 }
01137
01138 if (taskCounter) {
01139 subtext.prepend(i18np("One window:", "%1 windows:", taskCounter));
01140 }
01141
01142 if (taskCounter - displayedTaskCounter > 0) {
01143 subtext.append("<br>• <i>" + i18np("and 1 other", "and %1 others", taskCounter - displayedTaskCounter) + "</i>");
01144 }
01145
01146 data.setMainText(KWindowSystem::desktopName(hoverDesktopNumber));
01147 data.setSubText(subtext);
01148
01149 Plasma::ToolTipManager::self()->setContent(this, data);
01150 }
01151
01152 #include "pager.moc"