/* * Copyright 2007 by Matt Broadstone * Copyright 2007 by Robert Knight * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "panelview.h" #include #include #include #include #include #ifdef Q_WS_X11 #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include "desktopcorona.h" #include "desktoptracker.h" #include "panelappletoverlay.h" #include "panelcontroller.h" #include "panelshadows.h" #include "plasmaapp.h" class GlowBar : public QWidget { public: GlowBar(Plasma::Direction direction, const QRect &triggerZone) : QWidget(0), m_strength(0.3), m_svg(new Plasma::Svg(this)), m_direction(direction) { setAttribute(Qt::WA_TranslucentBackground); KWindowSystem::setOnAllDesktops(winId(), true); KWindowSystem::setType(winId(), NET::Dock); m_svg->setImagePath("widgets/glowbar"); QPalette pal = palette(); pal.setColor(backgroundRole(), Qt::transparent); setPalette(pal); #ifdef Q_WS_X11 QRegion region(QRect(0,0,1,1)); XShapeCombineRegion(QX11Info::display(), winId(), ShapeInput, 0, 0, region.handle(), ShapeSet); #endif QRect glowGeom = triggerZone; QSize s = sizeHint(); switch (m_direction) { case Plasma::Up: glowGeom.setY(glowGeom.y() - s.height() + 1); // fallthrough case Plasma::Down: glowGeom.setHeight(s.height()); break; case Plasma::Left: glowGeom.setX(glowGeom.x() - s.width() + 1); // fallthrough case Plasma::Right: glowGeom.setWidth(s.width()); break; } //kDebug() << "glow geom is" << glowGeom << "from" << triggerZone; setGeometry(glowGeom); m_buffer = QPixmap(size()); } void paintEvent(QPaintEvent* e) { Q_UNUSED(e) QPixmap l, r, c; const QSize glowRadius = m_svg->elementSize("hint-glow-radius"); QPoint pixmapPosition(0, 0); m_buffer.fill(QColor(0, 0, 0, int(qreal(255)*m_strength))); QPainter p(&m_buffer); p.setCompositionMode(QPainter::CompositionMode_SourceIn); switch (m_direction) { case Plasma::Down: l = m_svg->pixmap("bottomleft"); r = m_svg->pixmap("bottomright"); c = m_svg->pixmap("bottom"); pixmapPosition = QPoint(0, -glowRadius.height()); break; case Plasma::Up: l = m_svg->pixmap("topleft"); r = m_svg->pixmap("topright"); c = m_svg->pixmap("top"); break; case Plasma::Right: l = m_svg->pixmap("topright"); r = m_svg->pixmap("bottomright"); c = m_svg->pixmap("right"); pixmapPosition = QPoint(-glowRadius.width(), 0); break; case Plasma::Left: l = m_svg->pixmap("topleft"); r = m_svg->pixmap("bottomleft"); c = m_svg->pixmap("left"); break; } if (m_direction == Plasma::Left || m_direction == Plasma::Right) { p.drawPixmap(pixmapPosition, l); p.drawTiledPixmap(QRect(pixmapPosition.x(), l.height(), c.width(), height() - l.height() - r.height()), c); p.drawPixmap(QPoint(pixmapPosition.x(), height() - r.height()), r); } else { p.drawPixmap(pixmapPosition, l); p.drawTiledPixmap(QRect(l.width(), pixmapPosition.y(), width() - l.width() - r.width(), c.height()), c); p.drawPixmap(QPoint(width() - r.width(), pixmapPosition.y()), r); } p.end(); p.begin(this); p.drawPixmap(QPoint(0, 0), m_buffer); } QSize sizeHint() const { return m_svg->elementSize("bottomright") - m_svg->elementSize("hint-glow-radius"); } void updateStrength(QPoint point) { QPoint localPoint = mapFromGlobal(point); qreal newStrength; switch (m_direction) { case Plasma::Up: // when the panel is at the bottom. newStrength = 1 - qreal(-localPoint.y())/m_triggerDistance; break; case Plasma::Right: newStrength = 1 - qreal(localPoint.x())/m_triggerDistance; break; case Plasma::Left: // when the panel is right-aligned newStrength = 1 - qreal(-localPoint.x())/m_triggerDistance; break; case Plasma::Down: default: newStrength = 1- qreal(localPoint.y())/m_triggerDistance; break; } if (qAbs(newStrength - m_strength) > 0.01 && newStrength >= 0 && newStrength <= 1) { m_strength = newStrength; update(); } } private: static const int m_triggerDistance = 30; qreal m_strength; Plasma::Svg *m_svg; Plasma::Direction m_direction; QPixmap m_buffer; }; PanelView::PanelView(Plasma::Containment *panel, int id, QWidget *parent) : Plasma::View(panel, id, parent), m_panelController(0), m_glowBar(0), m_mousePollTimer(0), m_strutsTimer(new QTimer(this)), m_rehideAfterAutounhideTimer(new QTimer(this)), m_spacer(0), m_spacerIndex(-1), #ifdef Q_WS_X11 m_unhideTrigger(None), #endif m_visibilityMode(NormalPanel), m_lastHorizontal(true), m_editing(false), m_triggerEntered(false), m_respectStatus(true) { setAttribute(Qt::WA_TranslucentBackground); PlasmaApp::self()->panelShadows()->addWindow(this); // KWin setup KWindowSystem::setOnAllDesktops(winId(), true); KWindowSystem::setType(winId(), NET::Dock); setWindowRole(QString("panel_%1").arg(id)); m_strutsTimer->setSingleShot(true); connect(m_strutsTimer, SIGNAL(timeout()), this, SLOT(updateStruts())); // this timer controls checks to re-hide a panel after it's been unhidden // for the user because, e.g., something is demanding attention m_rehideAfterAutounhideTimer->setSingleShot(true); connect(m_rehideAfterAutounhideTimer, SIGNAL(timeout()), this, SLOT(checkAutounhide())); // Graphics view setup setFrameStyle(QFrame::NoFrame); setInteractive(true); setAcceptDrops(true); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QPalette pal = palette(); pal.setBrush(backgroundRole(), Qt::transparent); setPalette(pal); KConfigGroup viewConfig = config(); KConfigGroup sizes = KConfigGroup(&viewConfig, "Sizes"); m_lastHorizontal = isHorizontal(); const bool onScreen = panel->screen() < PlasmaApp::self()->corona()->numScreens(); const QRect screenRect = onScreen ? PlasmaApp::self()->corona()->screenGeometry(panel->screen()) : QRect(); const int sw = screenRect.width(); const int sh = screenRect.height(); m_lastSeenSize = sizes.readEntry("lastsize", m_lastHorizontal ? sw : sh); if (onScreen) { const QString last = m_lastHorizontal ? QString::fromLatin1("Horizontal%1").arg(QString::number(sw)) : QString::fromLatin1("Vertical%1").arg(QString::number(sh)); if (sizes.hasGroup(last)) { KConfigGroup thisSize(&sizes, last); resize(thisSize.readEntry("size", m_lastHorizontal ? QSize(sw, 27) : QSize(27, sh))); } } else { resize(panel->size().toSize()); } m_alignment = alignmentFilter((Qt::Alignment)viewConfig.readEntry("Alignment", (int)Qt::AlignLeft)); KConfigGroup sizeConfig(&viewConfig, (m_lastHorizontal ? "Horizontal" : "Vertical") + QString::number(m_lastSeenSize)); m_offset = sizeConfig.readEntry("offset", 0); setVisibilityMode((VisibilityMode)viewConfig.readEntry("panelVisibility", (int)m_visibilityMode)); connect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(pinchContainmentToCurrentScreen())); connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(pinchContainmentToCurrentScreen())); DesktopTracker *tracker = DesktopTracker::self(); connect(tracker, SIGNAL(screenMoved(DesktopTracker::Screen)), this, SLOT(updatePanelGeometry())); connect(tracker, SIGNAL(screenAdded(DesktopTracker::Screen)), this, SLOT(updateStruts())); connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeChanged()), Qt::QueuedConnection); } PanelView::~PanelView() { if (m_panelController) { disconnect(m_panelController, 0, this, 0); delete m_panelController; } delete m_glowBar; destroyUnhideTrigger(); } void PanelView::setContainment(Plasma::Containment *containment) { kDebug() << "Panel geometry is" << containment->geometry(); Plasma::Containment *oldContainment = this->containment(); if (oldContainment) { disconnect(oldContainment); } PlasmaApp::self()->prepareContainment(containment); connect(containment, SIGNAL(newStatus(Plasma::ItemStatus)), this, SLOT(statusUpdated(Plasma::ItemStatus))); connect(containment, SIGNAL(destroyed(QObject*)), this, SLOT(panelDeleted())); connect(containment, SIGNAL(toolBoxToggled()), this, SLOT(togglePanelController())); connect(containment, SIGNAL(appletAdded(Plasma::Applet*,QPointF)), this, SLOT(appletAdded(Plasma::Applet*))); connect(containment, SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(showWidgetExplorer())); connect(containment, SIGNAL(screenChanged(int,int,Plasma::Containment*)), this, SLOT(pinchContainmentToCurrentScreen())); connect(containment, SIGNAL(immutabilityChanged(Plasma::ImmutabilityType)), this, SLOT(immutabilityChanged(Plasma::ImmutabilityType))); KConfigGroup viewIds(KGlobal::config(), "ViewIds"); if (oldContainment) { viewIds.deleteEntry(QString::number(oldContainment->id())); } if (containment) { viewIds.writeEntry(QString::number(containment->id()), id()); if (containment->corona()) { containment->corona()->requestConfigSync(); } } // ensure we aren't overlapping other panels const QRect screenRect = PlasmaApp::self()->corona()->screenGeometry(containment->screen()); View::setContainment(containment); // pinchContainment calls updatePanelGeometry for us pinchContainment(screenRect); m_lastMin = containment->minimumSize(); m_lastMax = containment->maximumSize(); kDebug() << "about to set the containment" << (QObject*)containment; updateStruts(); // if we are an autohiding panel, then see if the status mandates we do something about it if (m_visibilityMode != NormalPanel && m_visibilityMode != WindowsGoBelow) { checkUnhide(containment->status()); } // disable removing widgets from the context menu containment->setProperty("hideCloseAppletInContextMenu", true); } void PanelView::themeChanged() { recreateUnhideTrigger(); } void PanelView::setPanelDragPosition(const QPoint &point) { QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(containment()->screen()); QRect geom = geometry(); geom.translate(-point); if (screenGeom.contains(geom)) { move(pos() - point); if (m_panelController) { m_panelController->move(m_panelController->pos() - point); } } } void PanelView::setLocation(Plasma::Location location) { Plasma::Containment *c = containment(); QSizeF s = c->size(); QSizeF min = c->minimumSize(); QSizeF max = c->maximumSize(); qreal panelWidth = s.width(); qreal panelHeight = s.height(); Plasma::FormFactor formFactor = c->formFactor(); bool wasHorizontal = formFactor == Plasma::Horizontal; bool wasFullSize = m_lastSeenSize == (wasHorizontal ? s.width() : s.height()); if (location == Plasma::TopEdge || location == Plasma::BottomEdge) { if (!wasHorizontal) { // we're switching! swap the sizes about panelHeight = s.width(); if (wasFullSize) { QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(c->screen()); panelWidth = screenGeom.width(); } else { panelWidth = s.height(); } min = QSizeF(panelWidth, min.width()); max = QSizeF(panelWidth, max.width()); } formFactor = Plasma::Horizontal; } else { if (wasHorizontal) { // we're switching! swap the sizes about if (wasFullSize) { QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(c->screen()); panelHeight = screenGeom.height(); } else { panelHeight = s.width(); } panelWidth = s.height(); min = QSizeF(min.height(), panelHeight); max = QSizeF(max.height(), panelHeight); } formFactor = Plasma::Vertical; } //kDebug() << "!!!!!!!!!!!!!!!!!! about to set to" << location << panelHeight << formFactor; disconnect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(pinchContainmentToCurrentScreen())); c->setFormFactor(formFactor); c->setLocation(location); c->setMinimumSize(0, 0); c->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); c->resize(panelWidth, panelHeight); c->setMinimumSize(min); c->setMaximumSize(max); const QRect screenRect = PlasmaApp::self()->corona()->screenGeometry(c->screen()); pinchContainment(screenRect); KWindowSystem::setOnAllDesktops(winId(), true); connect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(pinchContainmentToCurrentScreen())); } Plasma::Location PanelView::location() const { if (containment()) { return containment()->location(); } else { return Plasma::BottomEdge; } } void PanelView::setVisibilityMode(PanelView::VisibilityMode mode) { m_visibilityMode = mode; if (mode == LetWindowsCover) { KWindowSystem::setState(winId(), NET::KeepBelow); } else { KWindowSystem::clearState(winId(), NET::KeepBelow); } //life is vastly simpler if we ensure we're visible now unhide(); disconnect(containment(), SIGNAL(activate()), this, SLOT(unhide())); disconnect(containment(), SIGNAL(newStatus(Plasma::ItemStatus)), this, SLOT(checkUnhide(Plasma::ItemStatus))); if (mode == NormalPanel || mode == WindowsGoBelow) { //remove the last remnants of hide/unhide delete m_mousePollTimer; m_mousePollTimer = 0; } else { connect(containment(), SIGNAL(activate()), this, SLOT(unhide())); connect(containment(), SIGNAL(newStatus(Plasma::ItemStatus)), this, SLOT(checkUnhide(Plasma::ItemStatus))); } config().writeEntry("panelVisibility", (int)mode); //if the user didn't cause this, hide again in a bit if (!m_editing) { updateStruts(); if (mode == AutoHide || mode == LetWindowsCover) { if (m_mousePollTimer) { m_mousePollTimer->stop(); } QTimer::singleShot(2000, this, SLOT(startAutoHide())); } } KWindowSystem::setOnAllDesktops(winId(), true); } PanelView::VisibilityMode PanelView::visibilityMode() const { return m_visibilityMode; } void PanelView::updatePanelGeometry() { Plasma::Containment *c = containment(); if (!c) { return; } kDebug() << "New panel geometry is" << c->geometry(); QSize size = c->size().expandedTo(c->minimumSize()).toSize(); QRect geom(QPoint(0,0), size); int screen = c->screen(); if (screen < 0) { //TODO: is there a valid use for -1 with a panel? floating maybe? screen = 0; } QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(screen); if (m_alignment != Qt::AlignCenter) { m_offset = qMax(m_offset, 0); } //Sanity controls switch (location()) { case Plasma::TopEdge: case Plasma::BottomEdge: //resize the panel if is too large if (geom.width() > screenGeom.width()) { geom.setWidth(screenGeom.width()); } //move the panel left/right if there is not enough room if (m_alignment == Qt::AlignLeft) { if (m_offset + geom.width() > screenGeom.width() + 1) { m_offset = screenGeom.width() - geom.width(); } } else if (m_alignment == Qt::AlignRight) { if (screenGeom.width() - m_offset - geom.width() < -1 ) { m_offset = screenGeom.width() - geom.width(); } } else if (m_alignment == Qt::AlignCenter) { if (screenGeom.center().x() - screenGeom.x() + m_offset + geom.width()/2 > screenGeom.width() + 1) { m_offset = screenGeom.width() - geom.width()/2 - (screenGeom.center().x() - screenGeom.x()); } else if (screenGeom.center().x() - screenGeom.x() + m_offset - geom.width()/2 < -1) { m_offset = (screenGeom.center().x() - screenGeom.x()) - geom.width()/2; } } break; case Plasma::LeftEdge: case Plasma::RightEdge: //resize the panel if is too tall if (geom.height() > screenGeom.height()) { geom.setHeight(screenGeom.height()); } //move the panel bottom if there is not enough room //FIXME: still using alignleft/alignright is simpler and less error prone, but aligntop/alignbottom is more correct? if (m_alignment == Qt::AlignLeft) { if (m_offset + geom.height() > screenGeom.height() + 1) { m_offset = screenGeom.height() - geom.height(); } } else if (m_alignment == Qt::AlignRight) { if (screenGeom.height() - m_offset - geom.height() < -1) { m_offset = screenGeom.height() - geom.height(); } } else if (m_alignment == Qt::AlignCenter) { if (screenGeom.center().y() - screenGeom.top() + m_offset + geom.height()/2 > screenGeom.height() + 1) { m_offset = screenGeom.height() - geom.height()/2 - (screenGeom.center().y() - screenGeom.top()); } else if (screenGeom.center().y() - screenGeom.top() + m_offset - geom.height()/2 < -1) { m_offset = (screenGeom.center().y() - screenGeom.top()) - geom.width()/2; } } break; //TODO: floating panels (probably they will save their own geometry) default: break; } //Actual movement switch (location()) { case Plasma::TopEdge: if (m_alignment == Qt::AlignLeft) { geom.moveTopLeft(QPoint(m_offset + screenGeom.left(), screenGeom.top())); } else if (m_alignment == Qt::AlignRight) { geom.moveTopRight(QPoint(screenGeom.right() - m_offset, screenGeom.top())); } else if (m_alignment == Qt::AlignCenter) { geom.moveTopLeft(QPoint(screenGeom.center().x() - geom.width()/2 + 1 - geom.width()%2 + m_offset, screenGeom.top())); } break; case Plasma::LeftEdge: if (m_alignment == Qt::AlignLeft) { geom.moveTopLeft(QPoint(screenGeom.left(), m_offset + screenGeom.top())); } else if (m_alignment == Qt::AlignRight) { geom.moveBottomLeft(QPoint(screenGeom.left(), screenGeom.bottom() - m_offset)); } else if (m_alignment == Qt::AlignCenter) { geom.moveTopLeft(QPoint(screenGeom.left(), screenGeom.center().y() - geom.height()/2 + 1 - geom.height()%2 + m_offset)); } break; case Plasma::RightEdge: if (m_alignment == Qt::AlignLeft) { geom.moveTopRight(QPoint(screenGeom.right(), m_offset + screenGeom.top())); } else if (m_alignment == Qt::AlignRight) { geom.moveBottomRight(QPoint(screenGeom.right(), screenGeom.bottom() - m_offset)); } else if (m_alignment == Qt::AlignCenter) { geom.moveTopRight(QPoint(screenGeom.right(), screenGeom.center().y() - geom.height()/2 + 1 - geom.height()%2 + m_offset)); } break; case Plasma::BottomEdge: default: if (m_alignment == Qt::AlignLeft) { geom.moveBottomLeft(QPoint(m_offset + screenGeom.left(), screenGeom.bottom())); } else if (m_alignment == Qt::AlignRight) { geom.moveBottomRight(QPoint(screenGeom.right() - m_offset, screenGeom.bottom())); } else if (m_alignment == Qt::AlignCenter) { geom.moveBottomLeft(QPoint(screenGeom.center().x() - geom.width()/2 + 1 - geom.width()%2 + m_offset, screenGeom.bottom())); } break; } kDebug() << (QObject*)this << "thinks its panel is at " << geom << "was" << geometry(); if (geom == geometry()) { // our geometry is the same, but the panel moved around // so make sure our struts are still valid m_strutsTimer->stop(); m_strutsTimer->start(STRUTSTIMERDELAY); // this is probably papering over some real bug, but it fixes bug 283974 setGeometry(geom); } else { if (m_panelController && QPoint(pos() - geom.topLeft()).manhattanLength() > 100) { resize(geom.size()); QPropertyAnimation *panelAnimation = new QPropertyAnimation(this, "pos", this); panelAnimation->setEasingCurve(QEasingCurve::InOutQuad); panelAnimation->setDuration(300); panelAnimation->setStartValue(pos()); panelAnimation->setEndValue(geom.topLeft()); panelAnimation->start(QAbstractAnimation::DeleteWhenStopped); QPropertyAnimation *controllerAnimation = new QPropertyAnimation(m_panelController, "pos", m_panelController); controllerAnimation->setEasingCurve(QEasingCurve::InOutQuad); controllerAnimation->setDuration(300); controllerAnimation->setStartValue(m_panelController->pos()); controllerAnimation->setEndValue(m_panelController->positionForPanelGeometry(geom)); controllerAnimation->start(QAbstractAnimation::DeleteWhenStopped); } else { setGeometry(geom); } } m_lastMin = c->minimumSize(); m_lastMax = c->maximumSize(); //update the panel controller location position and size if (m_panelController) { m_panelController->setLocation(c->location()); foreach (PanelAppletOverlay *o, m_appletOverlays) { o->syncOrientation(); } } recreateUnhideTrigger(); } bool PanelView::isHorizontal() const { return location() == Plasma::BottomEdge || location() == Plasma::TopEdge; } void PanelView::pinchContainmentToCurrentScreen() { kDebug() << "pinching to current screen"; const QRect screenRect = PlasmaApp::self()->corona()->screenGeometry(containment()->screen()); pinchContainment(screenRect); } void PanelView::pinchContainment(const QRect &screenGeom) { kDebug() << "**************************** pinching" << screenGeom << m_lastSeenSize; disconnect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(pinchContainmentToCurrentScreen())); bool horizontal = isHorizontal(); const int oldOffset = m_offset; const int sw = screenGeom.width(); const int sh = screenGeom.height(); Plasma::Containment *c = containment(); QSizeF min = c->minimumSize(); QSizeF max = c->maximumSize(); KConfigGroup sizes = config(); sizes = KConfigGroup(&sizes, "Sizes"); if (m_lastHorizontal != horizontal || m_lastSeenSize != (horizontal ? sw : sh)) { // we're adjusting size. store the current size now KConfigGroup lastSize(&sizes, (m_lastHorizontal ? "Horizontal" : "Vertical") + QString::number(m_lastSeenSize)); lastSize.writeEntry("size", size()); lastSize.writeEntry("offset", m_offset); lastSize.writeEntry("min", m_lastMin); lastSize.writeEntry("max", m_lastMax); configNeedsSaving(); const QString last = horizontal ? QString::fromLatin1("Horizontal%1").arg(QString::number(sw)) : QString::fromLatin1("Vertical%1").arg(QString::number(sh)); if (sizes.hasGroup(last)) { KConfigGroup thisSize(&sizes, last); /* kDebug() << "has saved properties..." << last << thisSize.readEntry("min", min) << thisSize.readEntry("max", max) << thisSize.readEntry("size", c->geometry().size()) << thisSize.readEntry("offset", 0); */ c->setMinimumSize(0, 0); c->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); c->resize(thisSize.readEntry("size", c->geometry().size())); c->setMinimumSize(thisSize.readEntry("min", min)); c->setMaximumSize(thisSize.readEntry("max", max)); m_offset = thisSize.readEntry("offset", 0); } if (m_lastSeenSize < (horizontal ? sw : sh) && (horizontal ? c->geometry().width() : c->geometry().height()) >= m_lastSeenSize) { // we are moving from a smaller space where we are 100% to a larger one kDebug() << "we are moving from a smaller space where we are 100% to a larger one"; c->setMinimumSize(0, 0); c->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); if (horizontal) { c->setMaximumSize(sw, max.height()); c->resize(sw, c->geometry().height()); if (min.width() == max.width()) { c->setMinimumSize(sw, min.height()); } } else { c->setMaximumSize(max.width(), sh); c->resize(c->geometry().width(), sh); if (min.height() == max.height()) { c->setMinimumSize(min.width(), sh); } } } else if (m_lastSeenSize > (horizontal ? sw : sh) && (m_offset + (horizontal ? c->geometry().width() : c->geometry().height())) > (horizontal ? sw : sh)) { kDebug() << "we are moving from a bigger space to a smaller one where the panel won't fit!!"; if ((horizontal ? c->geometry().width() : c->geometry().height()) > (horizontal ? sw : sh)) { kDebug() << "panel is larger than screen, adjusting panel size"; setOffset(0); c->setMinimumSize(0, 0); c->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); if (horizontal) { c->setMaximumSize(sw, max.height()); c->resize(sw, c->geometry().height()); if (min.width() == max.width()) { c->setMinimumSize(sw, min.height()); } } else { c->setMaximumSize(max.width(), sh); c->resize(c->geometry().width(), sh); if (min.height() == max.height()) { c->setMinimumSize(min.width(), sh); } } } else { kDebug() << "reducing offset so the panel fits in screen"; setOffset((horizontal ? sw : sh) - (horizontal ? c->geometry().width() : c->geometry().height())); } } } // Pinching strategy: // if our containment is too big for the size of the screen we are now on, // then we first try and limit the offset and then if that still doesn't // give us enough room, we limit the size of the panel itself by setting // the minimum and maximum sizes. //kDebug() << "checking panel" << c->geometry() << "against" << screenGeom; // resize to max if for some reason the size is empty // otherwise its not possible to interact with the panel at all if (c->size().isEmpty()) { c->resize(max); } // write to the config file if the size has changed, or if we haven't recorded the lastsize // previously which ensures we'll always have a value even after first run const bool writeConfig = m_lastSeenSize != (horizontal ? sw : sh) || !sizes.hasKey("lastsize"); m_lastHorizontal = horizontal; m_lastSeenSize = (horizontal ? sw : sh); if (writeConfig) { sizes.writeEntry("lastsize", m_lastSeenSize); configNeedsSaving(); } updatePanelGeometry(); if (m_offset != oldOffset) { sizes.writeEntry("offset", m_lastSeenSize); configNeedsSaving(); } if (m_panelController) { m_panelController->setOffset(m_offset); } connect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(pinchContainmentToCurrentScreen())); recreateUnhideTrigger(); kDebug() << "Done pinching, containment's geom" << c->geometry() << "own geom" << geometry(); } void PanelView::setOffset(int newOffset) { m_offset = newOffset; //TODO: do we ever need to worry about pinching here, or // do we just assume that the offset is always < screenSize - containmentSize? updatePanelGeometry(); KConfigGroup viewConfig = config(); viewConfig = KConfigGroup(&viewConfig, (m_lastHorizontal ? "Horizontal" : "Vertical") + QString::number(m_lastSeenSize)); viewConfig.writeEntry("offset", m_offset); configNeedsSaving(); } int PanelView::offset() const { return m_offset; } void PanelView::setAlignment(Qt::Alignment align) { m_alignment = alignmentFilter(align); KConfigGroup viewConfig = config(); viewConfig.writeEntry("Alignment", (int)m_alignment); configNeedsSaving(); } Qt::Alignment PanelView::alignment() const { return m_alignment; } void PanelView::immutabilityChanged(Plasma::ImmutabilityType immutability) { if (immutability != Plasma::Mutable) { delete m_panelController; m_panelController = 0; } } void PanelView::togglePanelController() { //kDebug(); m_editing = false; if (containment()->immutability() != Plasma::Mutable) { delete m_panelController; m_panelController = 0; return; } if (!m_panelController) { m_panelController = new PanelController(0); m_panelController->setContainment(containment()); m_panelController->setLocation(containment()->location()); m_panelController->setAlignment(m_alignment); m_panelController->setOffset(m_offset); m_panelController->setVisibilityMode(m_visibilityMode); connect(m_panelController, SIGNAL(destroyed(QObject*)), this, SLOT(editingComplete())); connect(m_panelController, SIGNAL(offsetChanged(int)), this, SLOT(setOffset(int))); connect(m_panelController, SIGNAL(partialMove(QPoint)), this, SLOT(setPanelDragPosition(QPoint))); connect(m_panelController, SIGNAL(alignmentChanged(Qt::Alignment)), this, SLOT(setAlignment(Qt::Alignment))); connect(m_panelController, SIGNAL(locationChanged(Plasma::Location)), this, SLOT(setLocation(Plasma::Location))); connect(m_panelController, SIGNAL(panelVisibilityModeChanged(PanelView::VisibilityMode)), this, SLOT(setVisibilityMode(PanelView::VisibilityMode))); if (containment()->containmentType() == Plasma::Containment::PanelContainment && dynamic_cast(containment()->layout())) { setTabOrder(0, m_panelController); QWidget *prior = m_panelController; // we only support mouse over drags for panels with linear layouts QColor overlayColor(Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor)); QBrush overlayBrush(overlayColor); QPalette p(palette()); p.setBrush(QPalette::Window, overlayBrush); foreach (Plasma::Applet *applet, containment()->applets()) { PanelAppletOverlay *moveOverlay = new PanelAppletOverlay(applet, this); connect(moveOverlay, SIGNAL(removedWithApplet(PanelAppletOverlay*)), this, SLOT(overlayDestroyed(PanelAppletOverlay*))); connect(moveOverlay, SIGNAL(moved(PanelAppletOverlay*)), this, SLOT(overlayMoved(PanelAppletOverlay*))); moveOverlay->setPalette(p); moveOverlay->show(); moveOverlay->raise(); m_appletOverlays << moveOverlay; //kDebug() << moveOverlay << moveOverlay->geometry(); setTabOrder(prior, moveOverlay); prior = moveOverlay; } } } if (m_panelController->isVisible()) { if (m_panelController->showingWidgetExplorer()) { m_panelController->switchToController(); m_panelController->move(m_panelController->positionForPanelGeometry(geometry())); } else { Plasma::WindowEffects::slideWindow(m_panelController, location()); m_panelController->close(); updateStruts(); } } else { m_editing = true; m_panelController->resize(m_panelController->sizeHint()); m_panelController->move(m_panelController->positionForPanelGeometry(geometry())); Plasma::WindowEffects::slideWindow(m_panelController, location()); kDebug() << "showing panel controller!" << m_panelController->geometry(); m_panelController->show(); } containment()->setProperty("hideCloseAppletInContextMenu", false); } void PanelView::editingComplete() { //kDebug(); m_panelController = 0; m_editing = false; qDeleteAll(m_appletOverlays); m_appletOverlays.clear(); if (!containment()) { return; } containment()->closeToolBox(); containment()->setProperty("hideCloseAppletInContextMenu", true); updateStruts(); if (m_visibilityMode == LetWindowsCover || m_visibilityMode == AutoHide) { startAutoHide(); } } void PanelView::overlayDestroyed(PanelAppletOverlay *overlay) { m_appletOverlays.remove(overlay); } void PanelView::overlayMoved(PanelAppletOverlay *overlay) { Q_UNUSED(overlay) foreach (PanelAppletOverlay *o, m_appletOverlays) { o->syncIndex(); } } Qt::Alignment PanelView::alignmentFilter(Qt::Alignment align) const { //If it's not a supported alignment default to Qt::AlignLeft if (align == Qt::AlignLeft || align == Qt::AlignRight || align == Qt::AlignCenter) { return align; } else { return Qt::AlignLeft; } } void PanelView::updateStruts() { if (!containment()) { return; } NETExtendedStrut strut; if (m_visibilityMode == NormalPanel) { const QRect thisScreen = PlasmaApp::self()->corona()->screenGeometry(containment()->screen()); const QRect wholeScreen = DesktopTracker::desktopGeometry(); //Extended struts against a screen edge near to another screen are really harmful, so windows maximized under the panel is a lesser pain //TODO: force "windows can cover" in those cases? const int numScreens = PlasmaApp::self()->corona()->numScreens(); for (int i = 0; i < numScreens; ++i) { if (i == containment()->screen()) { continue; } const QRect otherScreen = PlasmaApp::self()->corona()->screenGeometry(i); switch (location()) { case Plasma::TopEdge: if (otherScreen.bottom() <= thisScreen.top()) { KWindowSystem::setExtendedStrut(winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); return; } break; case Plasma::BottomEdge: if (otherScreen.top() >= thisScreen.bottom()) { KWindowSystem::setExtendedStrut(winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); return; } break; case Plasma::RightEdge: if (otherScreen.left() >= thisScreen.right()) { KWindowSystem::setExtendedStrut(winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); return; } break; case Plasma::LeftEdge: if (otherScreen.right() <= thisScreen.left()) { KWindowSystem::setExtendedStrut(winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); return; } break; default: return; } } // extended struts are to the combined screen geoms, not the single screen int leftOffset = wholeScreen.x() - thisScreen.x(); int rightOffset = wholeScreen.right() - thisScreen.right(); int bottomOffset = wholeScreen.bottom() - thisScreen.bottom(); int topOffset = wholeScreen.top() - thisScreen.top(); kDebug() << "screen l/r/b/t offsets are:" << leftOffset << rightOffset << bottomOffset << topOffset << location(); switch (location()) { case Plasma::TopEdge: strut.top_width = height() + topOffset; strut.top_start = x(); strut.top_end = x() + width() - 1; break; case Plasma::BottomEdge: strut.bottom_width = height() + bottomOffset; strut.bottom_start = x(); strut.bottom_end = x() + width() - 1; //kDebug() << "setting bottom edge to" << strut.bottom_width // << strut.bottom_start << strut.bottom_end; break; case Plasma::RightEdge: strut.right_width = width() + rightOffset; strut.right_start = y(); strut.right_end = y() + height() - 1; break; case Plasma::LeftEdge: strut.left_width = width() + leftOffset; strut.left_start = y(); strut.left_end = y() + height() - 1; break; default: //kDebug() << "where are we?"; break; } } KWindowSystem::setExtendedStrut(winId(), strut.left_width, strut.left_start, strut.left_end, strut.right_width, strut.right_start, strut.right_end, strut.top_width, strut.top_start, strut.top_end, strut.bottom_width, strut.bottom_start, strut.bottom_end); if (m_panelController) { m_panelController->setLocation(containment()->location()); if (m_panelController->isVisible()) { m_panelController->resize(m_panelController->sizeHint()); m_panelController->move(m_panelController->positionForPanelGeometry(geometry())); Plasma::WindowEffects::slideWindow(m_panelController, location()); } foreach (PanelAppletOverlay *o, m_appletOverlays) { o->syncOrientation(); } } recreateUnhideTrigger(); } bool PanelView:: migratedFrom(int screenId) const { KConfigGroup cg = config(); const QList migrations = cg.readEntry("Migrations", QList()); return migrations.contains(screenId); } void PanelView::migrateTo(int screenId) { KConfigGroup cg = config(); QList migrations = cg.readEntry("Migrations", QList()); const int index = migrations.indexOf(screenId); if (index == -1) { migrations.append(screenId); } else { migrations = migrations.mid(0, migrations.length() - index - 1); } cg.writeEntry("Migrations", migrations); setScreen(screenId); } void PanelView::showWidgetExplorer() { if (!containment()) { return; } if (!m_panelController) { m_editing = true; ControllerWindow *controller = PlasmaApp::self()->showWidgetExplorer(screen(), containment()); connect(controller, SIGNAL(destroyed(QObject*)), this, SLOT(editingComplete()), Qt::UniqueConnection); } else { m_panelController->showWidgetExplorer(); } containment()->setProperty("hideCloseAppletInContextMenu", false); } void PanelView::moveEvent(QMoveEvent *event) { Plasma::View::moveEvent(event); m_strutsTimer->stop(); m_strutsTimer->start(STRUTSTIMERDELAY); recreateUnhideTrigger(); if (containment()) { foreach (Plasma::Applet *applet, containment()->applets()) { applet->updateConstraints(Plasma::PopupConstraint); } } } void PanelView::resizeEvent(QResizeEvent *event) { //kDebug() << event->oldSize() << event->size(); Plasma::View::resizeEvent(event); recreateUnhideTrigger(); m_strutsTimer->stop(); m_strutsTimer->start(STRUTSTIMERDELAY); if (containment()) { foreach (Plasma::Applet *applet, containment()->applets()) { applet->updateConstraints(Plasma::PopupConstraint); } } } void PanelView::updateHinter() { #ifdef Q_WS_X11 QPoint mousePos = QCursor::pos(); m_glowBar->updateStrength(mousePos); if (!m_unhideTriggerGeom.contains(mousePos)) { hideHinter(); XMoveResizeWindow(QX11Info::display(), m_unhideTrigger, m_unhideTriggerGeom.x(), m_unhideTriggerGeom.y(), m_unhideTriggerGeom.width(), m_unhideTriggerGeom.height()); } #endif } QRect PanelView::unhideHintGeometry() const { #ifdef Q_WS_X11 return m_unhideTriggerGeom; #else return QRect(); #endif } bool PanelView::hintOrUnhide(const QPoint &point, bool dueToDnd) { #ifdef Q_WS_X11 if (m_visibilityMode != LetWindowsCover && isVisible()) { return false; } KWindowInfo activeWindow = KWindowSystem::windowInfo(KWindowSystem::activeWindow(), NET::WMState); if (activeWindow.state() & NET::FullScreen) { return false; } if (!shouldHintHide()) { //kDebug() << "should not hint hide"; unhide(!dueToDnd); return true; } //kDebug() << point << m_triggerZone; if (m_triggerZone.contains(point)) { //kDebug() << "unhide!" << point; unhide(!dueToDnd); return true; } else if (!m_glowBar) { Plasma::Direction direction = Plasma::locationToDirection(location()); m_glowBar = new GlowBar(direction, m_triggerZone); m_glowBar->show(); XMoveResizeWindow(QX11Info::display(), m_unhideTrigger, m_triggerZone.x(), m_triggerZone.y(), m_triggerZone.width(), m_triggerZone.height()); //FIXME: This is ugly as hell but well, yeah if (!m_mousePollTimer) { m_mousePollTimer = new QTimer(this); } connect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(updateHinter()), Qt::UniqueConnection); m_mousePollTimer->start(200); } return false; #else return false; #endif } void PanelView::hideHinter() { //kDebug() << "hide the glow"; if (m_mousePollTimer) { m_mousePollTimer->stop(); disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(updateHinter())); } delete m_glowBar; m_glowBar = 0; } bool PanelView::hasPopup() { if (QApplication::activePopupWidget() || m_panelController) { return true; } if (containment()) { foreach (Plasma::Applet *applet, containment()->applets()) { if (applet->isPopupShowing()) { return true; } } } return false; } void PanelView::unhide(bool destroyTrigger) { //kill the unhide stuff hideHinter(); if (destroyTrigger) { destroyUnhideTrigger(); } //ensure it's visible if (!isVisible()) { Plasma::WindowEffects::slideWindow(this, location()); show(); KWindowSystem::raiseWindow(winId()); } KWindowSystem::setOnAllDesktops(winId(), true); //non-hiding panels stop here if (m_visibilityMode == NormalPanel || m_visibilityMode == WindowsGoBelow) { return; } //set up the re-hiding stuff if (!m_mousePollTimer) { m_mousePollTimer = new QTimer(this); } connect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(startAutoHide()), Qt::UniqueConnection); m_mousePollTimer->start(500); //avoid hide-show loops if (m_visibilityMode == LetWindowsCover) { m_triggerEntered = true; KWindowSystem::clearState(winId(), NET::KeepBelow); KWindowSystem::raiseWindow(winId()); QTimer::singleShot(0, this, SLOT(resetTriggerEnteredSuppression())); } } void PanelView::statusUpdated(Plasma::ItemStatus newStatus) { if (newStatus == Plasma::AcceptingInputStatus) { KWindowSystem::forceActiveWindow(winId()); } } void PanelView::checkUnhide(Plasma::ItemStatus newStatus) { //kDebug() << "================= got a status: " << newStatus << Plasma::ActiveStatus; m_respectStatus = true; if (newStatus > Plasma::ActiveStatus) { unhide(); if (newStatus == Plasma::NeedsAttentionStatus) { //kDebug() << "starting the timer!"; // start our rehide timer, so that the panel doesn't stay up and stuck forever and a day m_rehideAfterAutounhideTimer->start(AUTOUNHIDE_CHECK_DELAY); } } else { //kDebug() << "new status, just autohiding"; startAutoHide(); } } void PanelView::checkAutounhide() { //kDebug() << "***************************" << KIdleTime::instance()->idleTime(); if (KIdleTime::instance()->idleTime() >= AUTOUNHIDE_CHECK_DELAY) { // the user is idle .. let's not hige the panel on them quite yet, but rather given them a // chance to see this thing! connect(KIdleTime::instance(), SIGNAL(resumingFromIdle()), this, SLOT(checkAutounhide()), Qt::UniqueConnection); KIdleTime::instance()->catchNextResumeEvent(); //kDebug() << "exit 1 ***************************"; return; } m_respectStatus = false; //kDebug() << "in to check ... who's resonsible?" << sender() << KIdleTime::instance(); if (sender() == KIdleTime::instance()) { //kDebug() << "doing a 2s wait"; QTimer::singleShot(2000, this, SLOT(startAutoHide())); } else { //kDebug() << "just starting autohide!"; startAutoHide(); } // this line must come after the check on sender() as it *clears* that value! disconnect(KIdleTime::instance(), SIGNAL(resumingFromIdle()), this, SLOT(checkAutounhide())); //kDebug() << "exit 0 ***************************"; } void PanelView::unhide() { unhide(true); } void PanelView::resetTriggerEnteredSuppression() { m_triggerEntered = false; } void PanelView::startAutoHide() { /* kDebug() << m_editing << (containment() ? containment()->status() : 0) << Plasma::ActiveStatus << geometry().adjusted(-10, -10, 10, 10).contains(QCursor::pos()) << hasPopup(); if (containment() && containment()->status() > Plasma::ActiveStatus) { foreach (Plasma::Applet *applet, containment()->applets()) { kDebug() << " " << applet->name() << applet->status(); } } */ if (m_editing || (m_respectStatus && (containment() && containment()->status() > Plasma::ActiveStatus))) { if (m_mousePollTimer) { m_mousePollTimer->stop(); disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(startAutoHide())); } return; } // since we've gotten this far, we don't need to worry about rehiding-after-auto-unhide, so just // stop the timer m_rehideAfterAutounhideTimer->stop(); if (geometry().adjusted(-10, -10, 10, 10).contains(QCursor::pos()) || hasPopup()) { if (!m_mousePollTimer) { leaveEvent(0); } return; } if (m_mousePollTimer) { m_mousePollTimer->stop(); disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(startAutoHide())); } updatePanelGeometry(); if (m_visibilityMode == LetWindowsCover) { KWindowSystem::setState(winId(), NET::KeepBelow); KWindowSystem::lowerWindow(winId()); createUnhideTrigger(); } else { Plasma::WindowEffects::slideWindow(this, location()); createUnhideTrigger(); hide(); } } void PanelView::leaveEvent(QEvent *event) { if (m_visibilityMode == LetWindowsCover && m_triggerEntered) { //this prevents crazy hide-unhide loops that can happen at times m_triggerEntered = false; } else if (containment() && (m_visibilityMode == AutoHide || m_visibilityMode == LetWindowsCover) && !m_editing) { // even if we dont have a popup, we'll start a timer, so // that the panel stays if the mouse only leaves for a // few ms if (!m_mousePollTimer) { m_mousePollTimer = new QTimer(this); } connect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(startAutoHide()), Qt::UniqueConnection); m_mousePollTimer->start(500); } if (event) { // startAutoHide calls this with a null event pointer, so we have to check it Plasma::View::leaveEvent(event); } } void PanelView::appletAdded(Plasma::Applet *applet) { if (m_panelController && containment()->containmentType() == Plasma::Containment::PanelContainment) { QColor overlayColor(Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor)); QBrush overlayBrush(overlayColor); QPalette p(palette()); p.setBrush(QPalette::Window, overlayBrush); PanelAppletOverlay *moveOverlay = new PanelAppletOverlay(applet, this); connect(moveOverlay, SIGNAL(removedWithApplet(PanelAppletOverlay*)), this, SLOT(overlayDestroyed(PanelAppletOverlay*))); moveOverlay->setPalette(p); moveOverlay->show(); moveOverlay->raise(); m_appletOverlays << moveOverlay; QWidget *prior = m_panelController; Plasma::Applet *priorApplet = 0; foreach (Plasma::Applet *otherApplet, containment()->applets()) { if (applet == otherApplet) { break; } priorApplet = otherApplet; } if (priorApplet) { foreach (PanelAppletOverlay *overlay, m_appletOverlays) { if (overlay->applet() == priorApplet) { prior = overlay; break; } } } setTabOrder(prior, moveOverlay); } } bool PanelView::shouldHintHide() const { return m_visibilityMode == AutoHide && KWindowSystem::compositingActive(); } void PanelView::recreateUnhideTrigger() { #ifdef Q_WS_X11 if (m_unhideTrigger == None) { return; } XDestroyWindow(QX11Info::display(), m_unhideTrigger); m_unhideTrigger = None; createUnhideTrigger(); #endif } void PanelView::createUnhideTrigger() { #ifdef Q_WS_X11 //kDebug() << m_unhideTrigger << None; if (m_unhideTrigger != None) { return; } bool fancy = shouldHintHide(); int actualWidth = 1; int actualHeight = 1; int triggerWidth = fancy ? 30 : 1; int triggerHeight = fancy ? 30 : 1; QPoint actualTriggerPoint = pos(); QPoint triggerPoint = pos(); switch (location()) { case Plasma::TopEdge: actualWidth = triggerWidth = width(); if (fancy) { triggerWidth += 30; triggerPoint.setX(qMax(0, triggerPoint.x() - 15)); } break; case Plasma::BottomEdge: actualWidth = triggerWidth = width(); actualTriggerPoint = triggerPoint = geometry().bottomLeft(); if (fancy) { triggerWidth += 30; triggerPoint.setX(qMax(0, triggerPoint.x() - 15)); triggerPoint.setY(qMax(0, triggerPoint.y() - 29)); } break; case Plasma::RightEdge: actualHeight = triggerHeight = height(); actualTriggerPoint = triggerPoint = geometry().topRight(); if (fancy) { triggerHeight += 30; triggerPoint.setY(qMax(0, triggerPoint.y() - 15)); triggerPoint.setX(qMax(0, triggerPoint.x() - 29)); } break; case Plasma::LeftEdge: actualHeight = triggerHeight = height(); if (fancy) { triggerHeight += 30; triggerPoint.setY(qMax(0, triggerPoint.y() - 15)); } break; default: // no hiding unless we're on an edge. return; break; } XSetWindowAttributes attributes; attributes.override_redirect = True; attributes.event_mask = EnterWindowMask; attributes.event_mask = EnterWindowMask | LeaveWindowMask | PointerMotionMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeymapStateMask | VisibilityChangeMask | StructureNotifyMask | ResizeRedirectMask | SubstructureNotifyMask | SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask; unsigned long valuemask = CWOverrideRedirect | CWEventMask; m_unhideTrigger = XCreateWindow(QX11Info::display(), QX11Info::appRootWindow(), triggerPoint.x(), triggerPoint.y(), triggerWidth, triggerHeight, 0, CopyFromParent, InputOnly, CopyFromParent, valuemask, &attributes); XChangeProperty(QX11Info::display(), m_unhideTrigger, PlasmaApp::self()->m_XdndAwareAtom, XA_WINDOW, 32, PropModeReplace, (unsigned char *)&PlasmaApp::self()->m_XdndVersionAtom, 1); XMapWindow(QX11Info::display(), m_unhideTrigger); m_unhideTriggerGeom = QRect(triggerPoint, QSize(triggerWidth, triggerHeight)); m_triggerZone = QRect(actualTriggerPoint, QSize(actualWidth, actualHeight)); #endif //kDebug() << m_unhideTrigger; PlasmaApp::self()->panelHidden(true); } void PanelView::destroyUnhideTrigger() { #ifdef Q_WS_X11 if (m_unhideTrigger == None) { return; } //kDebug(); XDestroyWindow(QX11Info::display(), m_unhideTrigger); m_unhideTrigger = None; m_triggerZone = m_unhideTriggerGeom = QRect(); #endif //kDebug(); PlasmaApp::self()->panelHidden(false); } void PanelView::panelDeleted() { if (!QApplication::closingDown()) { // the panel was removed at runtime; clean up our configuration object as well KConfigGroup c = config(); c.deleteGroup(); configNeedsSaving(); } delete m_mousePollTimer; m_mousePollTimer = 0; m_strutsTimer->stop(); deleteLater(); } void PanelView::positionSpacer(const QPoint pos) { if (!containment()) { return; } QGraphicsLinearLayout *lay = dynamic_cast(containment()->layout()); if (!lay) { return; } Plasma::FormFactor f = containment()->formFactor(); int insertIndex = -1; //FIXME: needed in two places, make it a function? for (int i = 0; i < lay->count(); ++i) { QRectF siblingGeometry = lay->itemAt(i)->geometry(); if (f == Plasma::Horizontal) { qreal middle = (siblingGeometry.left() + siblingGeometry.right()) / 2.0; if (pos.x() < middle) { insertIndex = i; break; } else if (pos.x() <= siblingGeometry.right()) { insertIndex = i + 1; break; } } else { // Plasma::Vertical qreal middle = (siblingGeometry.top() + siblingGeometry.bottom()) / 2.0; if (pos.y() < middle) { insertIndex = i; break; } else if (pos.y() <= siblingGeometry.bottom()) { insertIndex = i + 1; break; } } } m_spacerIndex = insertIndex; if (insertIndex != -1) { if (!m_spacer) { m_spacer = new QGraphicsWidget(containment()); //m_spacer->panel = this; } lay->removeItem(m_spacer); m_spacer->show(); lay->insertItem(insertIndex, m_spacer); } } void PanelView::dragLeaveEvent(QDragLeaveEvent *event) { if (containment()) { containment()->showDropZone(QPoint()); } Plasma::View::dragLeaveEvent(event); } void PanelView::dropEvent(QDropEvent *event) { Plasma::View::dropEvent(event); if (containment()) { containment()->showDropZone(QPoint()); } } #include "moc_panelview.cpp"