00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "panelview.h"
00021
00022 #include <QApplication>
00023 #include <QDesktopWidget>
00024 #include <QGraphicsLinearLayout>
00025 #include <QTimeLine>
00026 #include <QTimer>
00027 #ifdef Q_WS_X11
00028 #include <X11/Xatom.h>
00029 #include <QX11Info>
00030 #endif
00031
00032 #include <KWindowSystem>
00033 #include <KDebug>
00034
00035 #include <Plasma/Containment>
00036 #include <Plasma/Corona>
00037 #include <Plasma/Plasma>
00038 #include <Plasma/PopupApplet>
00039 #include <Plasma/Svg>
00040 #include <Plasma/Theme>
00041
00042 #include "panelappletoverlay.h"
00043 #include "panelcontroller.h"
00044 #include "plasmaapp.h"
00045
00046 #include <kephal/screens.h>
00047
00048 class GlowBar : public QWidget
00049 {
00050 public:
00051 GlowBar(Plasma::Direction direction, const QRect &triggerZone)
00052 : QWidget(0),
00053 m_strength(0.3),
00054 m_svg(new Plasma::Svg(this)),
00055 m_direction(direction)
00056 {
00057 KWindowSystem::setOnAllDesktops(winId(), true);
00058 unsigned long state = NET::Sticky | NET::StaysOnTop | NET::KeepAbove;
00059 KWindowSystem::setState(winId(), state);
00060 KWindowSystem::setType(winId(), NET::Dock);
00061 m_svg->setImagePath("widgets/glowbar");
00062
00063 QRect glowGeom = triggerZone;
00064 QSize s = sizeHint();
00065 switch (m_direction) {
00066 case Plasma::Up:
00067 glowGeom.setY(glowGeom.y() - s.height() + 1);
00068
00069 case Plasma::Down:
00070 glowGeom.setHeight(s.height());
00071 break;
00072 case Plasma::Left:
00073 glowGeom.setX(glowGeom.x() - s.width() + 1);
00074
00075 case Plasma::Right:
00076 glowGeom.setWidth(s.width());
00077 break;
00078 }
00079
00080
00081 setGeometry(glowGeom);
00082 m_buffer = QPixmap(size());
00083 }
00084
00085 void paintEvent(QPaintEvent* e)
00086 {
00087 Q_UNUSED(e)
00088 QPixmap l, r, c;
00089 const QSize glowRadius = m_svg->elementSize("hint-glow-radius");
00090 QPoint pixmapPosition(0, 0);
00091
00092 m_buffer.fill(QColor(0, 0, 0, int(qreal(255)*m_strength)));
00093 QPainter p(&m_buffer);
00094 p.setCompositionMode(QPainter::CompositionMode_SourceIn);
00095
00096 switch (m_direction) {
00097 case Plasma::Down:
00098 l = m_svg->pixmap("bottomleft");
00099 r = m_svg->pixmap("bottomright");
00100 c = m_svg->pixmap("bottom");
00101 pixmapPosition = QPoint(0, -glowRadius.height());
00102 break;
00103 case Plasma::Up:
00104 l = m_svg->pixmap("topleft");
00105 r = m_svg->pixmap("topright");
00106 c = m_svg->pixmap("top");
00107 break;
00108 case Plasma::Right:
00109 l = m_svg->pixmap("topright");
00110 r = m_svg->pixmap("bottomright");
00111 c = m_svg->pixmap("right");
00112 pixmapPosition = QPoint(-glowRadius.width(), 0);
00113 break;
00114 case Plasma::Left:
00115 l = m_svg->pixmap("topleft");
00116 r = m_svg->pixmap("bottomleft");
00117 c = m_svg->pixmap("left");
00118 break;
00119 }
00120
00121 if (m_direction == Plasma::Left || m_direction == Plasma::Right) {
00122 p.drawPixmap(QPoint(0, 0), l);
00123 p.drawTiledPixmap(QRect(0, l.height(), c.width(), height() - l.height() - r.height()), c);
00124 p.drawPixmap(QPoint(0, height() - r.height()), r);
00125 } else {
00126 p.drawPixmap(pixmapPosition, l);
00127 p.drawTiledPixmap(QRect(l.width(), pixmapPosition.y(), width() - l.width() - r.width(), c.height()), c);
00128 p.drawPixmap(QPoint(width() - r.width(), pixmapPosition.y()), r);
00129 }
00130
00131 p.end();
00132 p.begin(this);
00133 p.drawPixmap(QPoint(0, 0), m_buffer);
00134 }
00135
00136 QSize sizeHint() const
00137 {
00138 return m_svg->elementSize("bottomright") - m_svg->elementSize("hint-glow-radius");
00139 }
00140
00141 bool event(QEvent *event)
00142 {
00143 if (event->type() == QEvent::Paint) {
00144 QPainter p(this);
00145 p.setCompositionMode(QPainter::CompositionMode_Source);
00146 p.fillRect(rect(), Qt::transparent);
00147 }
00148 return QWidget::event(event);
00149 }
00150
00151 void updateStrength(QPoint point)
00152 {
00153 QPoint localPoint = mapFromGlobal(point);
00154
00155 qreal newStrength;
00156 switch (m_direction) {
00157 case Plasma::Up:
00158 newStrength = 1 - qreal(-localPoint.y())/m_triggerDistance;
00159 break;
00160 case Plasma::Right:
00161 newStrength = 1 - qreal(localPoint.x())/m_triggerDistance;
00162 break;
00163 case Plasma::Left:
00164 newStrength = 1 - qreal(-localPoint.x())/m_triggerDistance;
00165 break;
00166 case Plasma::Down:
00167 default:
00168 newStrength = 1- qreal(localPoint.y())/m_triggerDistance;
00169 break;
00170 }
00171 if (qAbs(newStrength - m_strength) > 0.01 && newStrength >= 0 && newStrength <= 1) {
00172 m_strength = newStrength;
00173 update();
00174 }
00175 }
00176
00177
00178 private:
00179 static const int m_triggerDistance = 30;
00180 qreal m_strength;
00181 Plasma::Svg *m_svg;
00182 Plasma::Direction m_direction;
00183 QPixmap m_buffer;
00184 };
00185
00186 PanelView::PanelView(Plasma::Containment *panel, int id, QWidget *parent)
00187 : Plasma::View(panel, id, parent),
00188 m_panelController(0),
00189 m_glowBar(0),
00190 m_mousePollTimer(0),
00191 m_timeLine(0),
00192 m_spacer(0),
00193 m_spacerIndex(-1),
00194 #ifdef Q_WS_X11
00195 m_unhideTrigger(None),
00196 #endif
00197 m_visibilityMode(NormalPanel),
00198 m_lastHorizontal(true),
00199 m_editting(false),
00200 m_firstPaint(true),
00201 m_triggerEntered(false)
00202 {
00203 Q_ASSERT(qobject_cast<Plasma::Corona*>(panel->scene()));
00204 KConfigGroup viewConfig = config();
00205
00206 m_offset = viewConfig.readEntry("Offset", 0);
00207 m_alignment = alignmentFilter((Qt::Alignment)viewConfig.readEntry("Alignment", (int)Qt::AlignLeft));
00208 setVisibilityMode((VisibilityMode)viewConfig.readEntry("panelVisibility", (int)m_visibilityMode));
00209
00210
00211 QRect screenRect = Kephal::ScreenUtils::screenGeometry(containment()->screen());
00212 m_lastHorizontal = isHorizontal();
00213 KConfigGroup sizes = KConfigGroup(&viewConfig, "Sizes");
00214 m_lastSeenSize = sizes.readEntry("lastsize", m_lastHorizontal ? screenRect.width() : screenRect.height());
00215 pinchContainment(screenRect);
00216 m_lastMin = containment()->minimumSize();
00217 m_lastMax = containment()->maximumSize();
00218
00219 if (panel) {
00220 connect(panel, SIGNAL(destroyed(QObject*)), this, SLOT(panelDeleted()));
00221 connect(panel, SIGNAL(toolBoxToggled()), this, SLOT(togglePanelController()));
00222 kDebug() << "Panel geometry is" << panel->geometry();
00223 }
00224
00225 connect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(updatePanelGeometry()));
00226
00227
00228 setFrameStyle(QFrame::NoFrame);
00229
00230
00231
00232 setInteractive(true);
00233 setAcceptDrops(true);
00234 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00235 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00236
00237 QPalette pal = palette();
00238 pal.setBrush(backgroundRole(), Qt::transparent);
00239 setPalette(pal);
00240
00241
00242 KWindowSystem::setOnAllDesktops(winId(), true);
00243
00244 #ifdef Q_WS_WIN
00245 registerAccessBar(true);
00246 #endif
00247
00248 updateStruts();
00249
00250 Kephal::Screens *screens = Kephal::Screens::self();
00251 connect(screens, SIGNAL(screenResized(Kephal::Screen *, QSize, QSize)),
00252 this, SLOT(pinchContainmentToCurrentScreen()));
00253 connect(screens, SIGNAL(screenMoved(Kephal::Screen *, QPoint, QPoint)),
00254 this, SLOT(updatePanelGeometry()));
00255 }
00256
00257 PanelView::~PanelView()
00258 {
00259 delete m_glowBar;
00260 destroyUnhideTrigger();
00261 #ifdef Q_WS_WIN
00262 registerAccessBar(false);
00263 #endif
00264 }
00265
00266 void PanelView::setLocation(Plasma::Location location)
00267 {
00268 Plasma::Containment *c = containment();
00269 QSizeF s = c->size();
00270 QSizeF min = c->minimumSize();
00271 QSizeF max = c->maximumSize();
00272 qreal panelWidth = s.width();
00273 qreal panelHeight = s.height();
00274
00275 Plasma::FormFactor formFactor = c->formFactor();
00276 bool wasHorizontal = formFactor == Plasma::Horizontal;
00277 bool wasFullSize = m_lastSeenSize == (wasHorizontal ? s.width() : s.height());
00278
00279 if (location == Plasma::TopEdge || location == Plasma::BottomEdge) {
00280 if (!wasHorizontal) {
00281
00282 panelHeight = s.width();
00283 if (wasFullSize) {
00284 QRect screenGeom = Kephal::ScreenUtils::screenGeometry(c->screen());
00285 panelWidth = screenGeom.width();
00286 } else {
00287 panelWidth = s.height();
00288 }
00289 min = QSizeF(panelWidth, min.width());
00290 max = QSizeF(panelWidth, max.width());
00291 }
00292
00293 formFactor = Plasma::Horizontal;
00294 } else {
00295 if (wasHorizontal) {
00296
00297
00298 if (wasFullSize) {
00299 QRect screenGeom = Kephal::ScreenUtils::screenGeometry(c->screen());
00300 panelHeight = screenGeom.height();
00301 } else {
00302 panelHeight = s.width();
00303 }
00304
00305 panelWidth = s.height();
00306 min = QSizeF(min.height(), panelHeight);
00307 max = QSizeF(max.height(), panelHeight);
00308 }
00309
00310 formFactor = Plasma::Vertical;
00311 }
00312
00313
00314 disconnect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(updatePanelGeometry()));
00315 c->setFormFactor(formFactor);
00316 c->setLocation(location);
00317
00318 c->setMinimumSize(0, 0);
00319 c->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
00320 c->resize(panelWidth, panelHeight);
00321 c->setMinimumSize(min);
00322 c->setMaximumSize(max);
00323 #ifdef Q_WS_WIN
00324 appBarPosChanged();
00325 #endif
00326 QRect screenRect = Kephal::ScreenUtils::screenGeometry(c->screen());
00327 pinchContainment(screenRect);
00328 KWindowSystem::setOnAllDesktops(winId(), true);
00329
00330 connect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(updatePanelGeometry()));
00331 }
00332
00333 Plasma::Location PanelView::location() const
00334 {
00335 return containment()->location();
00336 }
00337
00338 void PanelView::setVisibilityMode(PanelView::VisibilityMode mode)
00339 {
00340 unsigned long state = NET::Sticky;
00341
00342 delete m_mousePollTimer;
00343 m_mousePollTimer = 0;
00344 delete m_glowBar;
00345 m_glowBar = 0;
00346
00347 KWindowSystem::setType(winId(), NET::Dock);
00348 if (mode == LetWindowsCover) {
00349 createUnhideTrigger();
00350 KWindowSystem::clearState(winId(), NET::StaysOnTop | NET::KeepAbove);
00351 state |= NET::KeepBelow;
00352 } else {
00353
00354 state |= NET::StaysOnTop;
00355 }
00356
00357 if (mode == NormalPanel) {
00358
00359 destroyUnhideTrigger();
00360 }
00361
00362 if (mode != AutoHide) {
00363 updatePanelGeometry();
00364 show();
00365 }
00366
00367
00368 KWindowSystem::setState(winId(), state);
00369 KWindowSystem::setOnAllDesktops(winId(), true);
00370
00371 m_visibilityMode = mode;
00372 config().writeEntry("panelVisibility", (int)mode);
00373 }
00374
00375 PanelView::VisibilityMode PanelView::visibilityMode() const
00376 {
00377 return m_visibilityMode;
00378 }
00379
00380 Plasma::Corona *PanelView::corona() const
00381 {
00382 return qobject_cast<Plasma::Corona*>(scene());
00383 }
00384
00385 void PanelView::updatePanelGeometry()
00386 {
00387 Plasma::Containment *c = containment();
00388 kDebug() << "New panel geometry is" << c->geometry();
00389
00390 QSize size = c->size().toSize();
00391 QRect geom(QPoint(0,0), size);
00392 int screen = c->screen();
00393
00394 if (screen < 0) {
00395
00396 screen = 0;
00397 }
00398
00399 QRect screenGeom = Kephal::ScreenUtils::screenGeometry(screen);
00400
00401 if (m_alignment != Qt::AlignCenter) {
00402 m_offset = qMax(m_offset, 0);
00403 }
00404
00405
00406 switch (location()) {
00407 case Plasma::TopEdge:
00408 case Plasma::BottomEdge:
00409 if (m_alignment != Qt::AlignCenter) {
00410 m_offset = qMax(m_offset, 0);
00411 }
00412
00413 if (geom.width() > screenGeom.width()) {
00414 geom.setWidth(screenGeom.width());
00415 }
00416
00417
00418 if (m_alignment == Qt::AlignLeft) {
00419 if (m_offset + geom.width() > screenGeom.width() + 1) {
00420 m_offset = screenGeom.width() - geom.width();
00421 }
00422 } else if (m_alignment == Qt::AlignRight) {
00423 if (screenGeom.width() - m_offset - geom.width() < -1 ) {
00424 m_offset = screenGeom.width() - geom.width();
00425 }
00426 } else if (m_alignment == Qt::AlignCenter) {
00427 if (screenGeom.center().x() - screenGeom.x() + m_offset + geom.width()/2 > screenGeom.width() + 1) {
00428 m_offset = screenGeom.width() - geom.width()/2 - (screenGeom.center().x() - screenGeom.x());
00429 } else if (screenGeom.center().x() - screenGeom.x() + m_offset - geom.width()/2 < -1) {
00430 m_offset = (screenGeom.center().x() - screenGeom.x()) - geom.width()/2;
00431 }
00432 }
00433 break;
00434
00435 case Plasma::LeftEdge:
00436 case Plasma::RightEdge:
00437 if (m_alignment != Qt::AlignCenter) {
00438 m_offset = qMax(m_offset, 0);
00439 }
00440
00441 if (geom.height() > screenGeom.height()) {
00442 geom.setHeight(screenGeom.height());
00443 }
00444
00445
00446
00447 if (m_alignment == Qt::AlignLeft) {
00448 if (m_offset + geom.height() > screenGeom.height() + 1) {
00449 m_offset = screenGeom.height() - geom.height();
00450 }
00451 } else if (m_alignment == Qt::AlignRight) {
00452 if (screenGeom.height() - m_offset - geom.height() < -1) {
00453 m_offset = screenGeom.height() - geom.height();
00454 }
00455 } else if (m_alignment == Qt::AlignCenter) {
00456 if (screenGeom.center().y() - screenGeom.top() + m_offset + geom.height()/2 > screenGeom.height() + 1) {
00457 m_offset = screenGeom.height() - geom.height()/2 - (screenGeom.center().y() - screenGeom.top());
00458 } else if (screenGeom.center().y() - screenGeom.top() + m_offset - geom.height()/2 < -1) {
00459 m_offset = (screenGeom.center().y() - screenGeom.top()) - geom.width()/2;
00460 }
00461 }
00462 break;
00463
00464
00465 default:
00466 break;
00467 }
00468
00469
00470 switch (location()) {
00471 case Plasma::TopEdge:
00472 if (m_alignment == Qt::AlignLeft) {
00473 geom.moveTopLeft(QPoint(m_offset + screenGeom.left(), screenGeom.top()));
00474 } else if (m_alignment == Qt::AlignRight) {
00475 geom.moveTopRight(QPoint(screenGeom.right() - m_offset, screenGeom.top()));
00476 } else if (m_alignment == Qt::AlignCenter) {
00477 geom.moveTopLeft(QPoint(screenGeom.center().x() - geom.width()/2 + 1 - geom.width()%2 + m_offset, screenGeom.top()));
00478 }
00479
00480
00481
00482 break;
00483
00484 case Plasma::LeftEdge:
00485 if (m_alignment == Qt::AlignLeft) {
00486 geom.moveTopLeft(QPoint(screenGeom.left(), m_offset + screenGeom.top()));
00487 } else if (m_alignment == Qt::AlignRight) {
00488 geom.moveBottomLeft(QPoint(screenGeom.left(), screenGeom.bottom() - m_offset));
00489 } else if (m_alignment == Qt::AlignCenter) {
00490 geom.moveTopLeft(QPoint(screenGeom.left(), screenGeom.center().y() - geom.height()/2 + 1 - geom.height()%2 + m_offset));
00491 }
00492
00493
00494
00495 break;
00496
00497 case Plasma::RightEdge:
00498 if (m_alignment == Qt::AlignLeft) {
00499 geom.moveTopRight(QPoint(screenGeom.right(), m_offset + screenGeom.top()));
00500 } else if (m_alignment == Qt::AlignRight) {
00501 geom.moveBottomRight(QPoint(screenGeom.right(), screenGeom.bottom() - m_offset));
00502 } else if (m_alignment == Qt::AlignCenter) {
00503 geom.moveTopRight(QPoint(screenGeom.right(), screenGeom.center().y() - geom.height()/2 + 1 - geom.height()%2 + m_offset));
00504 }
00505
00506
00507
00508 break;
00509
00510 case Plasma::BottomEdge:
00511 default:
00512 if (m_alignment == Qt::AlignLeft) {
00513 geom.moveBottomLeft(QPoint(m_offset + screenGeom.left(), screenGeom.bottom()));
00514 } else if (m_alignment == Qt::AlignRight) {
00515 geom.moveBottomRight(QPoint(screenGeom.right() - m_offset, screenGeom.bottom()));
00516 } else if (m_alignment == Qt::AlignCenter) {
00517 geom.moveBottomLeft(QPoint(screenGeom.center().x() - geom.width()/2 + 1 - geom.width()%2 + m_offset, screenGeom.bottom()));
00518 }
00519
00520
00521
00522 break;
00523 }
00524
00525 kDebug() << (QObject*)this << "thinks its panel is at " << geom << "was" << geometry();
00526 if (geom == geometry()) {
00527
00528
00529 updateStruts();
00530 } else {
00531 setGeometry(geom);
00532 }
00533
00534 m_lastMin = c->minimumSize();
00535 m_lastMax = c->maximumSize();
00536
00537
00538 if (m_panelController) {
00539 m_panelController->setLocation(c->location());
00540
00541 if (m_panelController->isVisible()) {
00542 m_panelController->resize(m_panelController->sizeHint());
00543 m_panelController->move(m_panelController->positionForPanelGeometry(geometry()));
00544 }
00545
00546 foreach (PanelAppletOverlay *o, m_moveOverlays) {
00547 o->syncOrientation();
00548 }
00549 }
00550 }
00551
00552 bool PanelView::isHorizontal() const
00553 {
00554 return location() == Plasma::BottomEdge ||
00555 location() == Plasma::TopEdge;
00556 }
00557
00558 void PanelView::pinchContainmentToCurrentScreen()
00559 {
00560 QRect screenRect = Kephal::ScreenUtils::screenGeometry(containment()->screen());
00561 pinchContainment(screenRect);
00562 }
00563
00564 void PanelView::pinchContainment(const QRect &screenGeom)
00565 {
00566 kDebug() << "**************************** pinching" << screenGeom << m_lastSeenSize;
00567 bool horizontal = isHorizontal();
00568
00569 int sw = screenGeom.width();
00570 int sh = screenGeom.height();
00571
00572 Plasma::Containment *c = containment();
00573 QSizeF min = c->minimumSize();
00574 QSizeF max = c->maximumSize();
00575
00576 KConfigGroup sizes = config();
00577 sizes = KConfigGroup(&sizes, "Sizes");
00578
00579 if (m_lastHorizontal != horizontal ||
00580 m_lastSeenSize != (horizontal ? sw : sh)) {
00581
00582 KConfigGroup lastSize(&sizes, (m_lastHorizontal ? "Horizontal" : "Vertical") +
00583 QString::number(m_lastSeenSize));
00584 lastSize.writeEntry("size", size());
00585 lastSize.writeEntry("offset", m_offset);
00586 lastSize.writeEntry("min", m_lastMin);
00587 lastSize.writeEntry("max", m_lastMax);
00588
00589 QString last = (horizontal ? "Horizontal" : "Vertical") +
00590 QString::number(horizontal ? sw : sh);
00591 if (sizes.hasGroup(last)) {
00592 KConfigGroup thisSize(&sizes, last);
00593
00594
00595
00596
00597
00598
00599
00600
00601 c->setMinimumSize(0, 0);
00602 c->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
00603 c->resize(thisSize.readEntry("size", c->geometry().size()));
00604 c->setMinimumSize(thisSize.readEntry("min", min));
00605 c->setMaximumSize(thisSize.readEntry("max", max));
00606 m_offset = thisSize.readEntry("offset", 0);
00607 } else if (m_lastSeenSize < (horizontal ? sw : sh) &&
00608 (horizontal ? c->geometry().width() :
00609 c->geometry().height()) >= m_lastSeenSize) {
00610
00611 if (horizontal) {
00612 c->setMaximumSize(sw, max.height());
00613 c->resize(sw, c->geometry().height());
00614 } else {
00615 c->setMaximumSize(max.width(), sh);
00616 c->resize(c->geometry().width(), sh);
00617 }
00618 }
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628 if (horizontal) {
00629
00630 if (m_offset + min.width() > sw) {
00631
00632 if (min.width() > sw) {
00633 c->setMinimumSize(sw, min.height());
00634 } else {
00635 m_offset = sw - int(min.width());
00636 }
00637 }
00638
00639 if (m_offset + max.width() > sw) {
00640
00641 if (max.width() > sw) {
00642 c->setMaximumSize(sw, max.height());
00643 } else {
00644 m_offset = sw - int(max.width());
00645 }
00646 }
00647 } else {
00648 if (m_offset + min.height() > sh) {
00649
00650 if (min.height() > sh) {
00651 c->setMinimumSize(min.width(), sh);
00652 } else {
00653 m_offset = sh - int(min.height());
00654 }
00655 }
00656
00657 if (m_offset + max.height() > sh) {
00658
00659 if (max.height() > sh) {
00660 c->setMaximumSize(max.width(), sh);
00661 } else {
00662 m_offset = sh - int(max.height());
00663 }
00664 }
00665 }
00666
00667 if (m_lastHorizontal != horizontal ||
00668 m_lastSeenSize != (horizontal ? sw : sh)) {
00669 m_lastHorizontal = horizontal;
00670 m_lastSeenSize = (horizontal ? sw : sh);
00671 sizes.writeEntry("lastsize", m_lastSeenSize);
00672 }
00673
00674 updatePanelGeometry();
00675
00676 if (m_panelController) {
00677 m_panelController->setContainment(c);
00678 m_panelController->setOffset(m_offset);
00679 }
00680
00681 kDebug() << "Done pinching, containement's geom" << c->geometry() << "own geom" << geometry();
00682 }
00683
00684 void PanelView::setOffset(int newOffset)
00685 {
00686 m_offset = newOffset;
00687 KConfigGroup viewConfig = config();
00688 viewConfig.writeEntry("Offset", m_offset);
00689
00690 containment()->update();
00691
00692
00693
00694 updatePanelGeometry();
00695 }
00696
00697 int PanelView::offset() const
00698 {
00699 return m_offset;
00700 }
00701
00702 void PanelView::setAlignment(Qt::Alignment align)
00703 {
00704 m_alignment = alignmentFilter(align);
00705 KConfigGroup viewConfig = config();
00706 viewConfig.writeEntry("Alignment", (int)m_alignment);
00707 }
00708
00709 Qt::Alignment PanelView::alignment() const
00710 {
00711 return m_alignment;
00712 }
00713
00714 void PanelView::togglePanelController()
00715 {
00716
00717 m_editting = false;
00718 if (containment()->immutability() != Plasma::Mutable) {
00719 delete m_panelController;
00720 m_panelController = 0;
00721 return;
00722 }
00723
00724 if (!m_panelController) {
00725 m_panelController = new PanelController(this);
00726 m_panelController->setContainment(containment());
00727 m_panelController->setLocation(containment()->location());
00728 m_panelController->setAlignment(m_alignment);
00729 m_panelController->setOffset(m_offset);
00730 m_panelController->setVisibilityMode(m_visibilityMode);
00731
00732 connect(m_panelController, SIGNAL(destroyed(QObject*)), this, SLOT(edittingComplete()));
00733 connect(m_panelController, SIGNAL(offsetChanged(int)), this, SLOT(setOffset(int)));
00734 connect(m_panelController, SIGNAL(alignmentChanged(Qt::Alignment)), this, SLOT(setAlignment(Qt::Alignment)));
00735 connect(m_panelController, SIGNAL(locationChanged(Plasma::Location)), this, SLOT(setLocation(Plasma::Location)));
00736 connect(m_panelController, SIGNAL(panelVisibilityModeChanged(PanelView::VisibilityMode)), this, SLOT(setVisibilityMode(PanelView::VisibilityMode)));
00737
00738 if (dynamic_cast<QGraphicsLinearLayout*>(containment()->layout())) {
00739
00740 QColor overlayColor(Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor));
00741 QBrush overlayBrush(overlayColor);
00742 QPalette p(palette());
00743 p.setBrush(QPalette::Window, overlayBrush);
00744 foreach (Plasma::Applet *applet, containment()->applets()) {
00745 PanelAppletOverlay *moveOverlay = new PanelAppletOverlay(applet, this);
00746 moveOverlay->setPalette(p);
00747 moveOverlay->show();
00748 moveOverlay->raise();
00749 m_moveOverlays << moveOverlay;
00750
00751 }
00752
00753 setTabOrder(0, m_panelController);
00754 QWidget *prior = m_panelController;
00755 foreach (PanelAppletOverlay *w, m_moveOverlays) {
00756 setTabOrder(prior, w);
00757 prior = w;
00758 }
00759 }
00760 }
00761
00762 if (!m_panelController->isVisible()) {
00763 m_editting = true;
00764 m_panelController->resize(m_panelController->sizeHint());
00765 m_panelController->move(m_panelController->positionForPanelGeometry(geometry()));
00766 m_panelController->show();
00767 } else {
00768 m_panelController->close();
00769 updateStruts();
00770 }
00771 }
00772
00773 void PanelView::edittingComplete()
00774 {
00775
00776 m_panelController = 0;
00777 m_editting = false;
00778 qDeleteAll(m_moveOverlays);
00779 m_moveOverlays.clear();
00780 containment()->closeToolBox();
00781 updateStruts();
00782 m_firstPaint = true;
00783
00784
00785
00786 PlasmaApp::self()->corona()->requestConfigSync();
00787 }
00788
00789 Qt::Alignment PanelView::alignmentFilter(Qt::Alignment align) const
00790 {
00791
00792 if (align == Qt::AlignLeft || align == Qt::AlignRight || align == Qt::AlignCenter) {
00793 return align;
00794 } else {
00795 return Qt::AlignLeft;
00796 }
00797 }
00798
00799 void PanelView::updateStruts()
00800 {
00801 NETExtendedStrut strut;
00802
00803 if (m_visibilityMode == NormalPanel) {
00804 QRect thisScreen = Kephal::ScreenUtils::screenGeometry(containment()->screen());
00805 QRect wholeScreen = Kephal::ScreenUtils::desktopGeometry();
00806
00807
00808 int leftOffset = wholeScreen.x() - thisScreen.x();
00809 int rightOffset = wholeScreen.right() - thisScreen.right();
00810 int bottomOffset = wholeScreen.bottom() - thisScreen.bottom();
00811 int topOffset = wholeScreen.top() - thisScreen.top();
00812 kDebug() << "screen l/r/b/t offsets are:" << leftOffset << rightOffset << bottomOffset << topOffset << location();
00813
00814 switch (location())
00815 {
00816 case Plasma::TopEdge:
00817 strut.top_width = height() + topOffset;
00818 strut.top_start = x();
00819 strut.top_end = x() + width() - 1;
00820 break;
00821
00822 case Plasma::BottomEdge:
00823 strut.bottom_width = height() + bottomOffset;
00824 strut.bottom_start = x();
00825 strut.bottom_end = x() + width() - 1;
00826
00827
00828 break;
00829
00830 case Plasma::RightEdge:
00831 strut.right_width = width() + rightOffset;
00832 strut.right_start = y();
00833 strut.right_end = y() + height() - 1;
00834 break;
00835
00836 case Plasma::LeftEdge:
00837 strut.left_width = width() + leftOffset;
00838 strut.left_start = y();
00839 strut.left_end = y() + height() - 1;
00840 break;
00841
00842 default:
00843
00844 break;
00845 }
00846 }
00847
00848 KWindowSystem::setExtendedStrut(winId(), strut.left_width,
00849 strut.left_start,
00850 strut.left_end,
00851 strut.right_width,
00852 strut.right_start,
00853 strut.right_end,
00854 strut.top_width,
00855 strut.top_start,
00856 strut.top_end,
00857 strut.bottom_width,
00858 strut.bottom_start,
00859 strut.bottom_end);
00860 }
00861
00862 void PanelView::moveEvent(QMoveEvent *event)
00863 {
00864
00865 QWidget::moveEvent(event);
00866 updateStruts();
00867 recreateUnhideTrigger();
00868 }
00869
00870 void PanelView::resizeEvent(QResizeEvent *event)
00871 {
00872
00873 QWidget::resizeEvent(event);
00874 recreateUnhideTrigger();
00875 updateStruts();
00876 #ifdef Q_WS_WIN
00877 appBarPosChanged();
00878 #endif
00879 }
00880
00881 QTimeLine *PanelView::timeLine()
00882 {
00883 if (!m_timeLine) {
00884 m_timeLine = new QTimeLine(200, this);
00885 m_timeLine->setCurveShape(QTimeLine::EaseOutCurve);
00886 m_timeLine->setUpdateInterval(10);
00887 connect(m_timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animateHide(qreal)));
00888 }
00889
00890 return m_timeLine;
00891 }
00892
00893 void PanelView::hideMousePoll()
00894 {
00895 QPoint mousePos = QCursor::pos();
00896 if (!geometry().contains(mousePos) && !hasPopup()) {
00897 startAutoHide();
00898 }
00899 }
00900
00901 void PanelView::unhideHintMousePoll()
00902 {
00903 #ifdef Q_WS_X11
00904 QPoint mousePos = QCursor::pos();
00905 m_glowBar->updateStrength(mousePos);
00906
00907 if (!m_unhideTriggerGeom.contains(mousePos)) {
00908 unhintHide();
00909 XMoveResizeWindow(QX11Info::display(), m_unhideTrigger, m_unhideTriggerGeom.x(), m_unhideTriggerGeom.y(), m_unhideTriggerGeom.width(), m_unhideTriggerGeom.height());
00910 }
00911 #endif
00912 }
00913
00914 QRect PanelView::unhideHintGeometry() const
00915 {
00916 #ifdef Q_WS_X11
00917 return m_unhideTriggerGeom;
00918 #else
00919 return QRect();
00920 #endif
00921 }
00922
00923 bool PanelView::hintOrUnhide(const QPoint &point, bool dueToDnd)
00924 {
00925 #ifdef Q_WS_X11
00926 if (m_visibilityMode != LetWindowsCover && isVisible()) {
00927 return false;
00928 }
00929
00930 if (!shouldHintHide()) {
00931
00932 unhide(!dueToDnd);
00933 return true;
00934 }
00935
00936
00937
00938
00939 if (m_triggerZone.contains(point)) {
00940
00941 unhide(!dueToDnd);
00942 return true;
00943 } else if (!m_glowBar) {
00944 Plasma::Direction direction = Plasma::locationToDirection(location());
00945 m_glowBar = new GlowBar(direction, m_triggerZone);
00946 m_glowBar->show();
00947 XMoveResizeWindow(QX11Info::display(), m_unhideTrigger, m_triggerZone.x(), m_triggerZone.y(), m_triggerZone.width(), m_triggerZone.height());
00948
00949
00950 if (!m_mousePollTimer) {
00951 m_mousePollTimer = new QTimer(this);
00952 }
00953
00954 connect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(unhideHintMousePoll()));
00955 m_mousePollTimer->start(200);
00956 }
00957
00958 return false;
00959 #else
00960 return false;
00961 #endif
00962 }
00963
00964 void PanelView::unhintHide()
00965 {
00966
00967 if (m_mousePollTimer) {
00968 m_mousePollTimer->stop();
00969 disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(unhideHintMousePoll()));
00970 }
00971
00972 delete m_glowBar;
00973 m_glowBar = 0;
00974 }
00975
00976 bool PanelView::hasPopup()
00977 {
00978 if (QApplication::activePopupWidget() || m_panelController) {
00979 return true;
00980 }
00981
00982 if (containment()) {
00983 foreach (Plasma::Applet *applet, containment()->applets()) {
00984 if (applet->isPopupShowing()) {
00985 return true;
00986 }
00987 }
00988 }
00989
00990 return false;
00991 }
00992
00993 void PanelView::unhide(bool destroyTrigger)
00994 {
00995
00996 unhintHide();
00997 if (destroyTrigger) {
00998 destroyUnhideTrigger();
00999 } else {
01000 if (!m_mousePollTimer) {
01001 m_mousePollTimer = new QTimer(this);
01002 }
01003
01004 disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(hideMousePoll()));
01005 connect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(hideMousePoll()));
01006 m_mousePollTimer->start(200);
01007 }
01008
01009
01010
01011 QTimeLine * tl = timeLine();
01012 tl->setDirection(QTimeLine::Backward);
01013 tl->setDuration(100);
01014
01015 if (m_visibilityMode == AutoHide) {
01016
01017
01018 show();
01019 }
01020
01021 KWindowSystem::setOnAllDesktops(winId(), true);
01022 unsigned long state = NET::Sticky;
01023 KWindowSystem::setState(winId(), state);
01024
01025 if (m_visibilityMode == LetWindowsCover) {
01026 m_triggerEntered = true;
01027 KWindowSystem::raiseWindow(winId());
01028 QTimer::singleShot(0, this, SLOT(resetTriggerEnteredSuppression()));
01029 } else if (shouldHintHide()) {
01030 if (tl->state() == QTimeLine::NotRunning) {
01031 tl->start();
01032 }
01033 } else {
01034
01035 viewport()->move(0,0);
01036 }
01037 }
01038
01039 void PanelView::resetTriggerEnteredSuppression()
01040 {
01041 m_triggerEntered = false;
01042 }
01043
01044 void PanelView::startAutoHide()
01045 {
01046
01047
01048 if (m_mousePollTimer) {
01049 m_mousePollTimer->stop();
01050 disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(hideMousePoll()));
01051 }
01052
01053 QTimeLine *tl = timeLine();
01054 tl->setDirection(QTimeLine::Forward);
01055 tl->setDuration(200);
01056
01057 if (shouldHintHide()) {
01058 if (tl->state() == QTimeLine::NotRunning) {
01059 tl->start();
01060 }
01061 } else {
01062 animateHide(1.0);
01063 }
01064 }
01065
01066 void PanelView::leaveEvent(QEvent *event)
01067 {
01068 if (m_visibilityMode == LetWindowsCover) {
01069 if (m_triggerEntered) {
01070
01071 m_triggerEntered = false;
01072 } else {
01073 createUnhideTrigger();
01074 }
01075 } else if (m_visibilityMode == AutoHide && !m_editting) {
01076
01077 if (hasPopup()) {
01078
01079 if (!m_mousePollTimer) {
01080 m_mousePollTimer = new QTimer(this);
01081 }
01082
01083 disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(hideMousePoll()));
01084 connect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(hideMousePoll()));
01085 m_mousePollTimer->start(200);
01086 } else {
01087 startAutoHide();
01088 }
01089 }
01090
01091 Plasma::View::leaveEvent(event);
01092 }
01093
01094 void PanelView::drawBackground(QPainter *painter, const QRectF &rect)
01095 {
01096 if (PlasmaApp::hasComposite()) {
01097 painter->setCompositionMode(QPainter::CompositionMode_Source);
01098 painter->fillRect(rect.toAlignedRect(), Qt::transparent);
01099 } else {
01100 Plasma::View::drawBackground(painter, rect);
01101 }
01102 }
01103
01104 void PanelView::paintEvent(QPaintEvent *event)
01105 {
01106 Plasma::View::paintEvent(event);
01107 if (m_firstPaint) {
01108
01109 if (m_visibilityMode == AutoHide) {
01110 QTimeLine * tl = timeLine();
01111 tl->setDirection(QTimeLine::Forward);
01112 if (tl->state() == QTimeLine::NotRunning) {
01113 tl->start();
01114 }
01115 }
01116
01117 m_firstPaint = false;
01118 }
01119 }
01120
01121 bool PanelView::event(QEvent *event)
01122 {
01123 if (event->type() == QEvent::Paint) {
01124 QPainter p(this);
01125 p.setCompositionMode(QPainter::CompositionMode_Source);
01126 p.fillRect(rect(), Qt::transparent);
01127 }
01128
01129 return Plasma::View::event(event);
01130 }
01131
01132 void PanelView::animateHide(qreal progress)
01133 {
01134 if (m_visibilityMode == AutoHide && shouldHintHide()) {
01135 int margin = 0;
01136 Plasma::Location loc = location();
01137
01138 if (loc == Plasma::TopEdge || loc == Plasma::BottomEdge) {
01139 margin = int(progress * height());
01140 } else {
01141 margin = int(progress * width());
01142 }
01143
01144 int xtrans = 0;
01145 int ytrans = 0;
01146
01147 switch (loc) {
01148 case Plasma::TopEdge:
01149 ytrans = -margin;
01150 break;
01151 case Plasma::BottomEdge:
01152 ytrans = margin;
01153 break;
01154 case Plasma::RightEdge:
01155 xtrans = margin;
01156 break;
01157 case Plasma::LeftEdge:
01158 xtrans = -margin;
01159 break;
01160 default:
01161
01162 return;
01163 break;
01164 }
01165
01166
01167 viewport()->move(xtrans, ytrans);
01168 }
01169
01170 QTimeLine *tl = timeLine();
01171 if (qFuzzyCompare(qreal(1.0), progress) && tl->direction() == QTimeLine::Forward) {
01172
01173 createUnhideTrigger();
01174 hide();
01175 } else if (qFuzzyCompare(qreal(1.0), qreal(progress + 1.0)) && tl->direction() == QTimeLine::Backward) {
01176
01177
01178 viewport()->move(0,0);
01179 }
01180 }
01181
01182 bool PanelView::shouldHintHide() const
01183 {
01184 return m_visibilityMode == AutoHide && PlasmaApp::hasComposite();
01185 }
01186
01187 void PanelView::recreateUnhideTrigger()
01188 {
01189 #ifdef Q_WS_X11
01190 if (m_unhideTrigger == None) {
01191 return;
01192 }
01193
01194 XDestroyWindow(QX11Info::display(), m_unhideTrigger);
01195 m_unhideTrigger = None;
01196 createUnhideTrigger();
01197 #endif
01198 }
01199
01200 void PanelView::createUnhideTrigger()
01201 {
01202 #ifdef Q_WS_X11
01203
01204 if (m_unhideTrigger != None) {
01205 return;
01206 }
01207
01208 bool fancy = shouldHintHide();
01209 int actualWidth = 1;
01210 int actualHeight = 1;
01211 int triggerWidth = fancy ? 30 : 1;
01212 int triggerHeight = fancy ? 30 : 1;
01213
01214 QPoint actualTriggerPoint = pos();
01215 QPoint triggerPoint = pos();
01216
01217 switch (location()) {
01218 case Plasma::TopEdge:
01219 actualWidth = triggerWidth = width();
01220
01221 if (fancy) {
01222 triggerWidth += 30;
01223 triggerPoint.setX(qMax(0, triggerPoint.x() - 15));
01224 }
01225 break;
01226 case Plasma::BottomEdge:
01227 actualWidth = triggerWidth = width();
01228 actualTriggerPoint = triggerPoint = geometry().bottomLeft();
01229
01230 if (fancy) {
01231 triggerWidth += 30;
01232 triggerPoint.setX(qMax(0, triggerPoint.x() - 15));
01233 triggerPoint.setY(qMax(0, triggerPoint.y() - 29));
01234 }
01235 break;
01236 case Plasma::RightEdge:
01237 actualHeight = triggerHeight = height();
01238 actualTriggerPoint = triggerPoint = geometry().topRight();
01239
01240 if (fancy) {
01241 triggerHeight += 30;
01242 triggerPoint.setY(qMax(0, triggerPoint.y() - 15));
01243 triggerPoint.setX(qMax(0, triggerPoint.x() - 29));
01244 }
01245 break;
01246 case Plasma::LeftEdge:
01247 actualHeight = triggerHeight = height();
01248
01249 if (fancy) {
01250 triggerHeight += 30;
01251 triggerPoint.setY(qMax(0, triggerPoint.y() - 15));
01252 }
01253 break;
01254 default:
01255
01256 return;
01257 break;
01258 }
01259
01260
01261 XSetWindowAttributes attributes;
01262 attributes.override_redirect = True;
01263 attributes.event_mask = EnterWindowMask;
01264
01265
01266 attributes.event_mask = EnterWindowMask | LeaveWindowMask | PointerMotionMask |
01267 KeyPressMask | KeyPressMask | ButtonPressMask |
01268 ButtonReleaseMask | ButtonMotionMask |
01269 KeymapStateMask | VisibilityChangeMask |
01270 StructureNotifyMask | ResizeRedirectMask |
01271 SubstructureNotifyMask |
01272 SubstructureRedirectMask | FocusChangeMask |
01273 PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask;
01274
01275 unsigned long valuemask = CWOverrideRedirect | CWEventMask;
01276 m_unhideTrigger = XCreateWindow(QX11Info::display(), QX11Info::appRootWindow(),
01277 triggerPoint.x(), triggerPoint.y(), triggerWidth, triggerHeight,
01278 0, CopyFromParent, InputOnly, CopyFromParent,
01279 valuemask, &attributes);
01280
01281 XChangeProperty(QX11Info::display(), m_unhideTrigger, PlasmaApp::self()->m_XdndAwareAtom,
01282 XA_WINDOW, 32, PropModeReplace, (unsigned char *)&PlasmaApp::self()->m_XdndVersionAtom, 1);
01283 XMapWindow(QX11Info::display(), m_unhideTrigger);
01284 m_unhideTriggerGeom = QRect(triggerPoint, QSize(triggerWidth, triggerHeight));
01285 m_triggerZone = QRect(actualTriggerPoint, QSize(actualWidth, actualHeight));
01286 #endif
01287
01288 PlasmaApp::self()->panelHidden(true);
01289 }
01290
01291 void PanelView::destroyUnhideTrigger()
01292 {
01293 #ifdef Q_WS_X11
01294 if (m_unhideTrigger == None) {
01295 return;
01296 }
01297
01298
01299 XDestroyWindow(QX11Info::display(), m_unhideTrigger);
01300 m_unhideTrigger = None;
01301 m_triggerZone = m_unhideTriggerGeom = QRect();
01302 #endif
01303
01304
01305 PlasmaApp::self()->panelHidden(false);
01306 }
01307
01308 void PanelView::panelDeleted()
01309 {
01310 if (!QApplication::closingDown()) {
01311
01312 KConfigGroup c = config();
01313 c.deleteGroup();
01314 }
01315
01316 deleteLater();
01317 }
01318
01319 void PanelView::positionSpacer(const QPoint pos)
01320 {
01321 if (!containment()) {
01322 return;
01323 }
01324
01325 QGraphicsLinearLayout *lay = dynamic_cast<QGraphicsLinearLayout*>(containment()->layout());
01326
01327 if (!lay) {
01328 return;
01329 }
01330
01331 Plasma::FormFactor f = containment()->formFactor();
01332 int insertIndex = -1;
01333
01334
01335 for (int i = 0; i < lay->count(); ++i) {
01336 QRectF siblingGeometry = lay->itemAt(i)->geometry();
01337
01338 if (f == Plasma::Horizontal) {
01339 qreal middle = (siblingGeometry.left() + siblingGeometry.right()) / 2.0;
01340 if (pos.x() < middle) {
01341 insertIndex = i;
01342 break;
01343 } else if (pos.x() <= siblingGeometry.right()) {
01344 insertIndex = i + 1;
01345 break;
01346 }
01347 } else {
01348 qreal middle = (siblingGeometry.top() + siblingGeometry.bottom()) / 2.0;
01349 if (pos.y() < middle) {
01350 insertIndex = i;
01351 break;
01352 } else if (pos.y() <= siblingGeometry.bottom()) {
01353 insertIndex = i + 1;
01354 break;
01355 }
01356 }
01357 }
01358
01359 m_spacerIndex = insertIndex;
01360 if (insertIndex != -1) {
01361 if (!m_spacer) {
01362 m_spacer = new QGraphicsWidget(containment());
01363
01364 }
01365 lay->removeItem(m_spacer);
01366 m_spacer->show();
01367 lay->insertItem(insertIndex, m_spacer);
01368 }
01369 }
01370
01371 void PanelView::dragEnterEvent(QDragEnterEvent *event)
01372 {
01373 Plasma::Containment *c = containment();
01374 if (c && c->immutability() == Plasma::Mutable &&
01375 (event->mimeData()->hasFormat(static_cast<Plasma::Corona*>(scene())->appletMimeType()) ||
01376 KUrl::List::canDecode(event->mimeData()))) {
01377 containment()->showDropZone(event->pos());
01378 }
01379
01380
01381 Plasma::View::dragEnterEvent(event);
01382 }
01383
01384 void PanelView::dragMoveEvent(QDragMoveEvent *event)
01385 {
01386 Plasma::Containment *c = containment();
01387 if (c && c->immutability() == Plasma::Mutable &&
01388 (event->mimeData()->hasFormat(static_cast<Plasma::Corona*>(scene())->appletMimeType()) ||
01389 KUrl::List::canDecode(event->mimeData()))) {
01390 containment()->showDropZone(event->pos());
01391 }
01392
01393 Plasma::View::dragMoveEvent(event);
01394 }
01395
01396 void PanelView::dragLeaveEvent(QDragLeaveEvent *event)
01397 {
01398 if (containment()) {
01399 containment()->showDropZone(QPoint());
01400 }
01401
01402 Plasma::View::dragLeaveEvent(event);
01403 }
01404
01405 void PanelView::dropEvent(QDropEvent *event)
01406 {
01407 Plasma::View::dropEvent(event);
01408
01409 if (containment()) {
01410 containment()->showDropZone(QPoint());
01411 }
01412 }
01413
01414
01415 #include "panelview.moc"
01416