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

Plasma

panelview.cpp

Go to the documentation of this file.
00001 /*
00002 *   Copyright 2007 by Matt Broadstone <mbroadst@kde.org>
00003 *   Copyright 2007 by Robert Knight <robertknight@gmail.com>
00004 *
00005 *   This program is free software; you can redistribute it and/or modify
00006 *   it under the terms of the GNU Library General Public License version 2,
00007 *   or (at your option) any later version.
00008 *
00009 *   This program is distributed in the hope that it will be useful,
00010 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *   GNU General Public License for more details
00013 *
00014 *   You should have received a copy of the GNU Library General Public
00015 *   License along with this program; if not, write to the
00016 *   Free Software Foundation, Inc.,
00017 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
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                 // fallthrough
00069             case Plasma::Down:
00070                 glowGeom.setHeight(s.height());
00071                 break;
00072             case Plasma::Left:
00073                 glowGeom.setX(glowGeom.x() - s.width() + 1);
00074                 // fallthrough
00075             case Plasma::Right:
00076                 glowGeom.setWidth(s.width());
00077                 break;
00078         }
00079 
00080         //kDebug() << "glow geom is" << glowGeom << "from" << triggerZone;
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: // when the panel is at the bottom.
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: // when the panel is right-aligned
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     // pinchContainment calls updatePanelGeometry for us
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     // Graphics view setup
00228     setFrameStyle(QFrame::NoFrame);
00229     //setAutoFillBackground(true);
00230     //setDragMode(QGraphicsView::RubberBandDrag);
00231     //setCacheMode(QGraphicsView::CacheBackground);
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     // KWin setup
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             // we're switching! swap the sizes about
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             // we're switching! swap the sizes about
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     //kDebug() << "!!!!!!!!!!!!!!!!!! about to set to" << location << panelHeight << formFactor;
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     //updatePanelGeometry();
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         //kDebug() << "panel shouldn't let windows cover it!";
00354         state |= NET::StaysOnTop;
00355     }
00356 
00357     if (mode == NormalPanel) {
00358         // we need to kill the input window if it exists!
00359         destroyUnhideTrigger();
00360     }
00361 
00362     if (mode != AutoHide) {
00363         updatePanelGeometry();
00364         show();
00365     }
00366 
00367     //kDebug() << "panel state set to" << state << NET::Sticky;
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         //TODO: is there a valid use for -1 with a panel? floating maybe?
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     //Sanity controls
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         //resize the panel if is too large
00413         if (geom.width() > screenGeom.width()) {
00414             geom.setWidth(screenGeom.width());
00415         }
00416 
00417         //move the panel left/right if there is not enough room
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         //resize the panel if is too tall
00441         if (geom.height() > screenGeom.height()) {
00442             geom.setHeight(screenGeom.height());
00443         }
00444 
00445         //move the panel bottom if there is not enough room
00446         //FIXME: still using alignleft/alignright is simpler and less error prone, but aligntop/alignbottom is more correct?
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     //TODO: floating panels (probably they will save their own geometry)
00465     default:
00466         break;
00467     }
00468 
00469     //Actual movement
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         //enable borders if needed
00481         //c->setGeometry(QRect(geom.left(), c->geometry().top(), geom.width(), geom.height()));
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         //enable borders if needed
00494         //c->setGeometry(QRect(c->geometry().left(), geom.top(), geom.width(), geom.height()));
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         //enable borders if needed
00507         //c->setGeometry(QRect(c->geometry().left(), geom.top(), geom.width(), geom.height()));
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         //enable borders if needed
00521         //c->setGeometry(QRect(geom.left(), c->geometry().top(), geom.width(), geom.height()));
00522         break;
00523     }
00524 
00525     kDebug() << (QObject*)this << "thinks its panel is at " << geom << "was" << geometry();
00526     if (geom == geometry()) {
00527         // our geometry is the same, but the panel moved around
00528         // so make sure our struts are still valid
00529         updateStruts();
00530     } else {
00531         setGeometry(geom);
00532     }
00533 
00534     m_lastMin = c->minimumSize();
00535     m_lastMax = c->maximumSize();
00536 
00537     //update the panel controller location position and size
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         // we're adjusting size. store the current size now
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             kDebug() << "has saved properties..." << last
00596                      << thisSize.readEntry("min", min)
00597                      << thisSize.readEntry("max", max)
00598                      << thisSize.readEntry("size", c->geometry().size())
00599                      << thisSize.readEntry("offset", 0);
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             // we are moving from a smaller space where we are 100% to a larger one
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     // Pinching strategy:
00622     // if our containment is too big for the size of the screen we are now on,
00623     // then we first try and limit the offset and then if that still doesn't
00624     // give us enough room, we limit the size of the panel itself by setting
00625     // the minimum and maximum sizes.
00626 
00627     //kDebug() << "checking panel" << c->geometry() << "against" << screenGeom;
00628     if (horizontal) {
00629         //kDebug() << "becoming horizontal with" << m_offset << min.width() << max.width() << sw;
00630         if (m_offset + min.width() > sw) {
00631             //kDebug() << "min size is too wide!";
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             //kDebug() << "max size is too wide!";
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             //kDebug() << "min size is too tall!";
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             //kDebug() << "max size is too tall!";
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     //TODO: do we ever need to worry about pinching here, or
00693     //      do we just assume that the offset is always < screenSize - containmentSize?
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     //kDebug();
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             // we only support mouse over drags for panels with linear layouts
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                 //kDebug() << moveOverlay << moveOverlay->geometry();
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     //kDebug();
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; // triggers autohide
00783 
00784     // not overly efficient since we may not have changed any settings,
00785     // but ensures that if we have, a config sync will occur
00786     PlasmaApp::self()->corona()->requestConfigSync();
00787 }
00788 
00789 Qt::Alignment PanelView::alignmentFilter(Qt::Alignment align) const
00790 {
00791     //If it's not a supported alignment default to Qt::AlignLeft
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         // extended struts are to the combined screen geoms, not the single screen
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                 //kDebug() << "setting bottom edge to" << strut.bottom_width
00827                 //         << strut.bottom_start << strut.bottom_end;
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                 //kDebug() << "where are we?";
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     //kDebug();
00865     QWidget::moveEvent(event);
00866     updateStruts();
00867     recreateUnhideTrigger();
00868 }
00869 
00870 void PanelView::resizeEvent(QResizeEvent *event)
00871 {
00872     //kDebug() << event->oldSize() << event->size();
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         //kDebug() << "should not hint hide";
00932         unhide(!dueToDnd);
00933         return true;
00934     }
00935 
00936     //kDebug() << point << m_triggerZone;
00937 //    if (point == QPoint()) {
00938         //kDebug() << "enter, we should start glowing!";
00939     if (m_triggerZone.contains(point)) {
00940         //kDebug() << "unhide!" << point;
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         //FIXME: This is ugly as hell but well, yeah
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     //kDebug() << "hide the glow";
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     //kDebug() << destroyTrigger;
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     // with composite, we can quite do some nice animations with transparent
01010     // backgrounds; without it we can't so we just show/hide
01011     QTimeLine * tl = timeLine();
01012     tl->setDirection(QTimeLine::Backward);
01013     tl->setDuration(100);
01014 
01015     if (m_visibilityMode == AutoHide) {
01016         // LetWindowsCover panels are always shown, so don't bother and prevent
01017         // some unsightly flickers
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         //if the hide before  compositing was active now the view is wrong
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     // with composite, we can quite do some nice animations with transparent
01047     // backgrounds; without it we can't so we just show/hide
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             //kDebug() << "not creating!";
01071             m_triggerEntered = false;
01072         } else {
01073             createUnhideTrigger();
01074         }
01075     } else if (m_visibilityMode == AutoHide && !m_editting) {
01076         // try not to hide if we have an associated popup or window about
01077         if (hasPopup()) {
01078             // don't hide yet, but start polling to see when we should
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         // set up our auothide system after we paint it visibly to the user
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                 // no hiding unless we're on an edge.
01162                 return;
01163                 break;
01164         }
01165 
01166     //kDebug() << progress << xtrans << ytransLetWindowsCover;
01167         viewport()->move(xtrans, ytrans);
01168     }
01169 
01170     QTimeLine *tl = timeLine();
01171     if (qFuzzyCompare(qreal(1.0), progress) && tl->direction() == QTimeLine::Forward) {
01172         //kDebug() << "**************** hide complete" << triggerPoint << triggerWidth << triggerHeight;
01173         createUnhideTrigger();
01174         hide();
01175     } else if (qFuzzyCompare(qreal(1.0), qreal(progress + 1.0)) && tl->direction() == QTimeLine::Backward) {
01176         //if the show before accel was off now viewport position is wrong, so ensure it's visible
01177         //kDebug() << "show complete";
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     //kDebug() << m_unhideTrigger << None;
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             // no hiding unless we're on an edge.
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     //kDebug() << m_unhideTrigger;
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     //kDebug();
01299     XDestroyWindow(QX11Info::display(), m_unhideTrigger);
01300     m_unhideTrigger = None;
01301     m_triggerZone = m_unhideTriggerGeom = QRect();
01302 #endif
01303 
01304     //kDebug();
01305     PlasmaApp::self()->panelHidden(false);
01306 }
01307 
01308 void PanelView::panelDeleted()
01309 {
01310     if (!QApplication::closingDown()) {
01311         // the panel was removed at runtime; clean up our configuration object as well
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     //FIXME: needed in two places, make it a function?
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 { // Plasma::Vertical
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             //m_spacer->panel = this;
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     //the containment will do the last decision whether accept it or not
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 

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

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