2
* Copyright 2007 by Matt Broadstone <mbroadst@kde.org>
3
* Copyright 2007 by Robert Knight <robertknight@gmail.com>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU Library General Public License version 2,
7
* or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details
14
* You should have received a copy of the GNU Library General Public
15
* License along with this program; if not, write to the
16
* Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
#include "panelview.h"
22
#include <QApplication>
23
#include <QGraphicsLinearLayout>
24
#include <QPropertyAnimation>
27
#include <X11/Xatom.h>
29
#include <X11/extensions/shape.h>
34
#include <KWindowSystem>
36
#include <Plasma/Containment>
37
#include <Plasma/Corona>
38
#include <Plasma/Plasma>
39
#include <Plasma/PopupApplet>
41
#include <Plasma/Theme>
42
#include <Plasma/WindowEffects>
44
#include <kephal/screens.h>
46
#include "desktopcorona.h"
47
#include "panelappletoverlay.h"
48
#include "panelcontroller.h"
49
#include "panelshadows.h"
50
#include "plasmaapp.h"
52
class GlowBar : public QWidget
55
GlowBar(Plasma::Direction direction, const QRect &triggerZone)
58
m_svg(new Plasma::Svg(this)),
59
m_direction(direction)
61
setAttribute(Qt::WA_TranslucentBackground);
62
KWindowSystem::setOnAllDesktops(winId(), true);
63
KWindowSystem::setType(winId(), NET::Dock);
64
m_svg->setImagePath("widgets/glowbar");
66
QPalette pal = palette();
67
pal.setColor(backgroundRole(), Qt::transparent);
71
QRegion region(QRect(0,0,1,1));
72
XShapeCombineRegion(QX11Info::display(), winId(), ShapeInput, 0, 0,
73
region.handle(), ShapeSet);
76
QRect glowGeom = triggerZone;
78
switch (m_direction) {
80
glowGeom.setY(glowGeom.y() - s.height() + 1);
83
glowGeom.setHeight(s.height());
86
glowGeom.setX(glowGeom.x() - s.width() + 1);
89
glowGeom.setWidth(s.width());
93
//kDebug() << "glow geom is" << glowGeom << "from" << triggerZone;
94
setGeometry(glowGeom);
95
m_buffer = QPixmap(size());
98
void paintEvent(QPaintEvent* e)
102
const QSize glowRadius = m_svg->elementSize("hint-glow-radius");
103
QPoint pixmapPosition(0, 0);
105
m_buffer.fill(QColor(0, 0, 0, int(qreal(255)*m_strength)));
106
QPainter p(&m_buffer);
107
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
109
switch (m_direction) {
111
l = m_svg->pixmap("bottomleft");
112
r = m_svg->pixmap("bottomright");
113
c = m_svg->pixmap("bottom");
114
pixmapPosition = QPoint(0, -glowRadius.height());
117
l = m_svg->pixmap("topleft");
118
r = m_svg->pixmap("topright");
119
c = m_svg->pixmap("top");
122
l = m_svg->pixmap("topright");
123
r = m_svg->pixmap("bottomright");
124
c = m_svg->pixmap("right");
125
pixmapPosition = QPoint(-glowRadius.width(), 0);
128
l = m_svg->pixmap("topleft");
129
r = m_svg->pixmap("bottomleft");
130
c = m_svg->pixmap("left");
134
if (m_direction == Plasma::Left || m_direction == Plasma::Right) {
135
p.drawPixmap(pixmapPosition, l);
136
p.drawTiledPixmap(QRect(pixmapPosition.x(), l.height(), c.width(), height() - l.height() - r.height()), c);
137
p.drawPixmap(QPoint(pixmapPosition.x(), height() - r.height()), r);
139
p.drawPixmap(pixmapPosition, l);
140
p.drawTiledPixmap(QRect(l.width(), pixmapPosition.y(), width() - l.width() - r.width(), c.height()), c);
141
p.drawPixmap(QPoint(width() - r.width(), pixmapPosition.y()), r);
146
p.drawPixmap(QPoint(0, 0), m_buffer);
149
QSize sizeHint() const
151
return m_svg->elementSize("bottomright") - m_svg->elementSize("hint-glow-radius");
154
bool event(QEvent *event)
156
if (event->type() == QEvent::Paint) {
158
p.setCompositionMode(QPainter::CompositionMode_Source);
159
p.fillRect(rect(), Qt::transparent);
161
return QWidget::event(event);
164
void updateStrength(QPoint point)
166
QPoint localPoint = mapFromGlobal(point);
169
switch (m_direction) {
170
case Plasma::Up: // when the panel is at the bottom.
171
newStrength = 1 - qreal(-localPoint.y())/m_triggerDistance;
174
newStrength = 1 - qreal(localPoint.x())/m_triggerDistance;
176
case Plasma::Left: // when the panel is right-aligned
177
newStrength = 1 - qreal(-localPoint.x())/m_triggerDistance;
181
newStrength = 1- qreal(localPoint.y())/m_triggerDistance;
184
if (qAbs(newStrength - m_strength) > 0.01 && newStrength >= 0 && newStrength <= 1) {
185
m_strength = newStrength;
192
static const int m_triggerDistance = 30;
195
Plasma::Direction m_direction;
199
PanelView::PanelView(Plasma::Containment *panel, int id, QWidget *parent)
200
: Plasma::View(panel, id, parent),
201
m_panelController(0),
204
m_strutsTimer(new QTimer(this)),
205
m_rehideAfterAutounhideTimer(new QTimer(this)),
209
m_unhideTrigger(None),
211
m_visibilityMode(NormalPanel),
212
m_lastHorizontal(true),
214
m_triggerEntered(false),
215
m_respectStatus(true)
217
PlasmaApp::self()->panelShadows()->addWindow(this);
220
KWindowSystem::setOnAllDesktops(winId(), true);
221
KWindowSystem::setType(winId(), NET::Dock);
222
setWindowRole(QString("panel_%1").arg(id));
224
m_strutsTimer->setSingleShot(true);
225
connect(m_strutsTimer, SIGNAL(timeout()), this, SLOT(updateStruts()));
227
// this timer controls checks to re-hide a panel after it's been unhidden
228
// for the user because, e.g., something is demanding attention
229
m_rehideAfterAutounhideTimer->setSingleShot(true);
230
connect(m_rehideAfterAutounhideTimer, SIGNAL(timeout()), this, SLOT(checkAutounhide()));
232
// Graphics view setup
233
setFrameStyle(QFrame::NoFrame);
234
setInteractive(true);
235
setAcceptDrops(true);
236
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
237
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
239
QPalette pal = palette();
240
pal.setBrush(backgroundRole(), Qt::transparent);
244
registerAccessBar(true);
247
KConfigGroup viewConfig = config();
248
KConfigGroup sizes = KConfigGroup(&viewConfig, "Sizes");
249
m_lastHorizontal = isHorizontal();
251
const bool onScreen = panel->screen() < PlasmaApp::self()->corona()->numScreens();
252
const QRect screenRect = onScreen ? PlasmaApp::self()->corona()->screenGeometry(panel->screen()) : QRect();
253
const int sw = screenRect.width();
254
const int sh = screenRect.height();
255
m_lastSeenSize = sizes.readEntry("lastsize", m_lastHorizontal ? sw : sh);
258
const QString last = m_lastHorizontal ? QString::fromLatin1("Horizontal%1").arg(QString::number(sw)) :
259
QString::fromLatin1("Vertical%1").arg(QString::number(sh));
260
if (sizes.hasGroup(last)) {
261
KConfigGroup thisSize(&sizes, last);
262
resize(thisSize.readEntry("size", m_lastHorizontal ? QSize(sw, 27) : QSize(27, sh)));
265
resize(panel->size().toSize());
268
m_alignment = alignmentFilter((Qt::Alignment)viewConfig.readEntry("Alignment", (int)Qt::AlignLeft));
269
KConfigGroup sizeConfig(&viewConfig, (m_lastHorizontal ? "Horizontal" : "Vertical") +
270
QString::number(m_lastSeenSize));
271
m_offset = sizeConfig.readEntry("offset", 0);
272
setVisibilityMode((VisibilityMode)viewConfig.readEntry("panelVisibility", (int)m_visibilityMode));
274
connect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(pinchContainmentToCurrentScreen()));
276
Kephal::Screens *screens = Kephal::Screens::self();
277
connect(screens, SIGNAL(screenResized(Kephal::Screen *, QSize, QSize)),
278
this, SLOT(pinchContainmentToCurrentScreen()));
279
connect(screens, SIGNAL(screenMoved(Kephal::Screen *, QPoint, QPoint)),
280
this, SLOT(updatePanelGeometry()));
281
connect(screens, SIGNAL(screenAdded(Kephal::Screen *)),
282
this, SLOT(updateStruts()));
283
connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeChanged()), Qt::QueuedConnection);
286
PanelView::~PanelView()
288
if (m_panelController) {
289
disconnect(m_panelController, 0, this, 0);
290
delete m_panelController;
294
destroyUnhideTrigger();
296
registerAccessBar(false);
300
void PanelView::setContainment(Plasma::Containment *containment)
302
kDebug() << "Panel geometry is" << containment->geometry();
304
Plasma::Containment *oldContainment = this->containment();
305
if (oldContainment) {
306
disconnect(oldContainment);
309
connect(containment, SIGNAL(newStatus(Plasma::ItemStatus)), this, SLOT(statusUpdated(Plasma::ItemStatus)));
310
connect(containment, SIGNAL(destroyed(QObject*)), this, SLOT(panelDeleted()));
311
connect(containment, SIGNAL(toolBoxToggled()), this, SLOT(togglePanelController()));
312
connect(containment, SIGNAL(appletAdded(Plasma::Applet *, const QPointF &)), this, SLOT(appletAdded(Plasma::Applet *)));
313
connect(containment, SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(showWidgetExplorer()));
314
connect(containment, SIGNAL(screenChanged(int,int,Plasma::Containment*)), this, SLOT(pinchContainmentToCurrentScreen()));
315
connect(containment, SIGNAL(immutabilityChanged(Plasma::ImmutabilityType)), this, SLOT(immutabilityChanged(Plasma::ImmutabilityType)));
317
KConfigGroup viewIds(KGlobal::config(), "ViewIds");
319
if (oldContainment) {
320
viewIds.deleteEntry(QString::number(oldContainment->id()));
324
viewIds.writeEntry(QString::number(containment->id()), id());
325
if (containment->corona()) {
326
containment->corona()->requestConfigSync();
330
// ensure we aren't overlapping other panels
331
const QRect screenRect = PlasmaApp::self()->corona()->screenGeometry(containment->screen());
333
View::setContainment(containment);
335
// pinchContainment calls updatePanelGeometry for us
336
pinchContainment(screenRect);
337
m_lastMin = containment->minimumSize();
338
m_lastMax = containment->maximumSize();
340
kDebug() << "about to set the containment" << (QObject*)containment;
344
// if we are an autohiding panel, then see if the status mandates we do something about it
345
if (m_visibilityMode != NormalPanel && m_visibilityMode != WindowsGoBelow) {
346
checkUnhide(containment->status());
350
void PanelView::themeChanged()
352
recreateUnhideTrigger();
355
void PanelView::setPanelDragPosition(const QPoint &point)
357
QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(containment()->screen());
358
QRect geom = geometry();
359
geom.translate(-point);
360
if (screenGeom.contains(geom)) {
362
if (m_panelController) {
363
m_panelController->move(m_panelController->pos() - point);
368
void PanelView::setLocation(Plasma::Location location)
370
Plasma::Containment *c = containment();
371
QSizeF s = c->size();
372
QSizeF min = c->minimumSize();
373
QSizeF max = c->maximumSize();
374
qreal panelWidth = s.width();
375
qreal panelHeight = s.height();
377
Plasma::FormFactor formFactor = c->formFactor();
378
bool wasHorizontal = formFactor == Plasma::Horizontal;
379
bool wasFullSize = m_lastSeenSize == (wasHorizontal ? s.width() : s.height());
381
if (location == Plasma::TopEdge || location == Plasma::BottomEdge) {
382
if (!wasHorizontal) {
383
// we're switching! swap the sizes about
384
panelHeight = s.width();
386
QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(c->screen());
387
panelWidth = screenGeom.width();
389
panelWidth = s.height();
391
min = QSizeF(panelWidth, min.width());
392
max = QSizeF(panelWidth, max.width());
395
formFactor = Plasma::Horizontal;
398
// we're switching! swap the sizes about
401
QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(c->screen());
402
panelHeight = screenGeom.height();
404
panelHeight = s.width();
407
panelWidth = s.height();
408
min = QSizeF(min.height(), panelHeight);
409
max = QSizeF(max.height(), panelHeight);
412
formFactor = Plasma::Vertical;
415
//kDebug() << "!!!!!!!!!!!!!!!!!! about to set to" << location << panelHeight << formFactor;
416
disconnect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(pinchContainmentToCurrentScreen()));
417
c->setFormFactor(formFactor);
418
c->setLocation(location);
420
c->setMinimumSize(0, 0);
421
c->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
422
c->resize(panelWidth, panelHeight);
423
c->setMinimumSize(min);
424
c->setMaximumSize(max);
428
const QRect screenRect = PlasmaApp::self()->corona()->screenGeometry(c->screen());
429
pinchContainment(screenRect);
430
KWindowSystem::setOnAllDesktops(winId(), true);
431
connect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(pinchContainmentToCurrentScreen()));
434
Plasma::Location PanelView::location() const
437
return containment()->location();
439
return Plasma::BottomEdge;
443
void PanelView::setVisibilityMode(PanelView::VisibilityMode mode)
445
m_visibilityMode = mode;
447
if (mode == LetWindowsCover) {
448
KWindowSystem::setState(winId(), NET::KeepBelow);
450
KWindowSystem::clearState(winId(), NET::KeepBelow);
452
//life is vastly simpler if we ensure we're visible now
455
disconnect(containment(), SIGNAL(activate()), this, SLOT(unhide()));
456
disconnect(containment(), SIGNAL(newStatus(Plasma::ItemStatus)), this, SLOT(checkUnhide(Plasma::ItemStatus)));
457
if (mode == NormalPanel || mode == WindowsGoBelow) {
458
//remove the last remnants of hide/unhide
459
delete m_mousePollTimer;
460
m_mousePollTimer = 0;
462
connect(containment(), SIGNAL(activate()), this, SLOT(unhide()));
463
connect(containment(), SIGNAL(newStatus(Plasma::ItemStatus)), this, SLOT(checkUnhide(Plasma::ItemStatus)));
466
config().writeEntry("panelVisibility", (int)mode);
468
//if the user didn't cause this, hide again in a bit
469
if ((mode == AutoHide || mode == LetWindowsCover) && !m_editing) {
470
if (m_mousePollTimer) {
471
m_mousePollTimer->stop();
474
QTimer::singleShot(2000, this, SLOT(startAutoHide()));
477
KWindowSystem::setOnAllDesktops(winId(), true);
480
PanelView::VisibilityMode PanelView::visibilityMode() const
482
return m_visibilityMode;
485
void PanelView::updatePanelGeometry()
487
Plasma::Containment *c = containment();
493
kDebug() << "New panel geometry is" << c->geometry();
495
QSize size = c->size().expandedTo(c->minimumSize()).toSize();
496
QRect geom(QPoint(0,0), size);
497
int screen = c->screen();
500
//TODO: is there a valid use for -1 with a panel? floating maybe?
504
QRect screenGeom = PlasmaApp::self()->corona()->screenGeometry(screen);
506
if (m_alignment != Qt::AlignCenter) {
507
m_offset = qMax(m_offset, 0);
511
switch (location()) {
512
case Plasma::TopEdge:
513
case Plasma::BottomEdge:
514
//resize the panel if is too large
515
if (geom.width() > screenGeom.width()) {
516
geom.setWidth(screenGeom.width());
519
//move the panel left/right if there is not enough room
520
if (m_alignment == Qt::AlignLeft) {
521
if (m_offset + geom.width() > screenGeom.width() + 1) {
522
m_offset = screenGeom.width() - geom.width();
524
} else if (m_alignment == Qt::AlignRight) {
525
if (screenGeom.width() - m_offset - geom.width() < -1 ) {
526
m_offset = screenGeom.width() - geom.width();
528
} else if (m_alignment == Qt::AlignCenter) {
529
if (screenGeom.center().x() - screenGeom.x() + m_offset + geom.width()/2 > screenGeom.width() + 1) {
530
m_offset = screenGeom.width() - geom.width()/2 - (screenGeom.center().x() - screenGeom.x());
531
} else if (screenGeom.center().x() - screenGeom.x() + m_offset - geom.width()/2 < -1) {
532
m_offset = (screenGeom.center().x() - screenGeom.x()) - geom.width()/2;
537
case Plasma::LeftEdge:
538
case Plasma::RightEdge:
539
//resize the panel if is too tall
540
if (geom.height() > screenGeom.height()) {
541
geom.setHeight(screenGeom.height());
544
//move the panel bottom if there is not enough room
545
//FIXME: still using alignleft/alignright is simpler and less error prone, but aligntop/alignbottom is more correct?
546
if (m_alignment == Qt::AlignLeft) {
547
if (m_offset + geom.height() > screenGeom.height() + 1) {
548
m_offset = screenGeom.height() - geom.height();
550
} else if (m_alignment == Qt::AlignRight) {
551
if (screenGeom.height() - m_offset - geom.height() < -1) {
552
m_offset = screenGeom.height() - geom.height();
554
} else if (m_alignment == Qt::AlignCenter) {
555
if (screenGeom.center().y() - screenGeom.top() + m_offset + geom.height()/2 > screenGeom.height() + 1) {
556
m_offset = screenGeom.height() - geom.height()/2 - (screenGeom.center().y() - screenGeom.top());
557
} else if (screenGeom.center().y() - screenGeom.top() + m_offset - geom.height()/2 < -1) {
558
m_offset = (screenGeom.center().y() - screenGeom.top()) - geom.width()/2;
563
//TODO: floating panels (probably they will save their own geometry)
569
switch (location()) {
570
case Plasma::TopEdge:
571
if (m_alignment == Qt::AlignLeft) {
572
geom.moveTopLeft(QPoint(m_offset + screenGeom.left(), screenGeom.top()));
573
} else if (m_alignment == Qt::AlignRight) {
574
geom.moveTopRight(QPoint(screenGeom.right() - m_offset, screenGeom.top()));
575
} else if (m_alignment == Qt::AlignCenter) {
576
geom.moveTopLeft(QPoint(screenGeom.center().x() - geom.width()/2 + 1 - geom.width()%2 + m_offset, screenGeom.top()));
581
case Plasma::LeftEdge:
582
if (m_alignment == Qt::AlignLeft) {
583
geom.moveTopLeft(QPoint(screenGeom.left(), m_offset + screenGeom.top()));
584
} else if (m_alignment == Qt::AlignRight) {
585
geom.moveBottomLeft(QPoint(screenGeom.left(), screenGeom.bottom() - m_offset));
586
} else if (m_alignment == Qt::AlignCenter) {
587
geom.moveTopLeft(QPoint(screenGeom.left(), screenGeom.center().y() - geom.height()/2 + 1 - geom.height()%2 + m_offset));
592
case Plasma::RightEdge:
593
if (m_alignment == Qt::AlignLeft) {
594
geom.moveTopRight(QPoint(screenGeom.right(), m_offset + screenGeom.top()));
595
} else if (m_alignment == Qt::AlignRight) {
596
geom.moveBottomRight(QPoint(screenGeom.right(), screenGeom.bottom() - m_offset));
597
} else if (m_alignment == Qt::AlignCenter) {
598
geom.moveTopRight(QPoint(screenGeom.right(), screenGeom.center().y() - geom.height()/2 + 1 - geom.height()%2 + m_offset));
603
case Plasma::BottomEdge:
605
if (m_alignment == Qt::AlignLeft) {
606
geom.moveBottomLeft(QPoint(m_offset + screenGeom.left(), screenGeom.bottom()));
607
} else if (m_alignment == Qt::AlignRight) {
608
geom.moveBottomRight(QPoint(screenGeom.right() - m_offset, screenGeom.bottom()));
609
} else if (m_alignment == Qt::AlignCenter) {
610
geom.moveBottomLeft(QPoint(screenGeom.center().x() - geom.width()/2 + 1 - geom.width()%2 + m_offset, screenGeom.bottom()));
616
kDebug() << (QObject*)this << "thinks its panel is at " << geom << "was" << geometry();
617
if (geom == geometry()) {
618
// our geometry is the same, but the panel moved around
619
// so make sure our struts are still valid
620
m_strutsTimer->stop();
621
m_strutsTimer->start(STRUTSTIMERDELAY);
623
if (m_panelController && QPoint(pos() - geom.topLeft()).manhattanLength() > 100) {
625
QPropertyAnimation *panelAnimation = new QPropertyAnimation(this, "pos", this);
626
panelAnimation->setEasingCurve(QEasingCurve::InOutQuad);
627
panelAnimation->setDuration(300);
628
panelAnimation->setStartValue(pos());
629
panelAnimation->setEndValue(geom.topLeft());
630
panelAnimation->start(QAbstractAnimation::DeleteWhenStopped);
632
QPropertyAnimation *controllerAnimation = new QPropertyAnimation(m_panelController, "pos", m_panelController);
633
controllerAnimation->setEasingCurve(QEasingCurve::InOutQuad);
634
controllerAnimation->setDuration(300);
635
controllerAnimation->setStartValue(m_panelController->pos());
636
controllerAnimation->setEndValue(m_panelController->positionForPanelGeometry(geom));
637
controllerAnimation->start(QAbstractAnimation::DeleteWhenStopped);
643
m_lastMin = c->minimumSize();
644
m_lastMax = c->maximumSize();
646
//update the panel controller location position and size
647
if (m_panelController) {
648
m_panelController->setLocation(c->location());
650
foreach (PanelAppletOverlay *o, m_appletOverlays) {
651
o->syncOrientation();
655
recreateUnhideTrigger();
658
bool PanelView::isHorizontal() const
660
return location() == Plasma::BottomEdge ||
661
location() == Plasma::TopEdge;
664
void PanelView::pinchContainmentToCurrentScreen()
666
kDebug() << "pinching to current screen";
667
const QRect screenRect = PlasmaApp::self()->corona()->screenGeometry(containment()->screen());
668
pinchContainment(screenRect);
671
void PanelView::pinchContainment(const QRect &screenGeom)
673
kDebug() << "**************************** pinching" << screenGeom << m_lastSeenSize;
674
disconnect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(pinchContainmentToCurrentScreen()));
675
bool horizontal = isHorizontal();
677
const int oldOffset = m_offset;
678
const int sw = screenGeom.width();
679
const int sh = screenGeom.height();
681
Plasma::Containment *c = containment();
682
QSizeF min = c->minimumSize();
683
QSizeF max = c->maximumSize();
685
KConfigGroup sizes = config();
686
sizes = KConfigGroup(&sizes, "Sizes");
688
if (m_lastHorizontal != horizontal || m_lastSeenSize != (horizontal ? sw : sh)) {
689
// we're adjusting size. store the current size now
690
KConfigGroup lastSize(&sizes, (m_lastHorizontal ? "Horizontal" : "Vertical") +
691
QString::number(m_lastSeenSize));
692
lastSize.writeEntry("size", size());
693
lastSize.writeEntry("offset", m_offset);
694
lastSize.writeEntry("min", m_lastMin);
695
lastSize.writeEntry("max", m_lastMax);
698
const QString last = horizontal ? QString::fromLatin1("Horizontal%1").arg(QString::number(sw)) :
699
QString::fromLatin1("Vertical%1").arg(QString::number(sh));
700
if (sizes.hasGroup(last)) {
701
KConfigGroup thisSize(&sizes, last);
704
kDebug() << "has saved properties..." << last
705
<< thisSize.readEntry("min", min)
706
<< thisSize.readEntry("max", max)
707
<< thisSize.readEntry("size", c->geometry().size())
708
<< thisSize.readEntry("offset", 0);
710
c->setMinimumSize(0, 0);
711
c->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
712
c->resize(thisSize.readEntry("size", c->geometry().size()));
713
c->setMinimumSize(thisSize.readEntry("min", min));
714
c->setMaximumSize(thisSize.readEntry("max", max));
715
m_offset = thisSize.readEntry("offset", 0);
716
} else if (m_lastSeenSize < (horizontal ? sw : sh) &&
717
(horizontal ? c->geometry().width() :
718
c->geometry().height()) >= m_lastSeenSize) {
719
// we are moving from a smaller space where we are 100% to a larger one
720
kDebug() << "we are moving from a smaller space where we are 100% to a larger one";
721
c->setMinimumSize(0, 0);
722
c->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
725
c->setMaximumSize(sw, max.height());
726
c->resize(sw, c->geometry().height());
727
if (min.width() == max.width()) {
728
c->setMinimumSize(sw, min.height());
731
c->setMaximumSize(max.width(), sh);
732
c->resize(c->geometry().width(), sh);
733
if (min.height() == max.height()) {
734
c->setMinimumSize(min.width(), sh);
737
} else if (m_lastSeenSize > (horizontal ? sw : sh) &&
738
(m_offset + (horizontal ? c->geometry().width() :
739
c->geometry().height())) > (horizontal ? sw : sh)) {
740
kDebug() << "we are moving from a bigger space to a smaller one where the panel won't fit!!";
741
if ((horizontal ? c->geometry().width() :
742
c->geometry().height()) > (horizontal ? sw : sh)) {
743
kDebug() << "panel is larger than screen, adjusting panel size";
745
c->setMinimumSize(0, 0);
746
c->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
749
c->setMaximumSize(sw, max.height());
750
c->resize(sw, c->geometry().height());
751
if (min.width() == max.width()) {
752
c->setMinimumSize(sw, min.height());
755
c->setMaximumSize(max.width(), sh);
756
c->resize(c->geometry().width(), sh);
757
if (min.height() == max.height()) {
758
c->setMinimumSize(min.width(), sh);
762
kDebug() << "reducing offset so the panel fits in screen";
763
setOffset((horizontal ? sw : sh) -
764
(horizontal ? c->geometry().width() : c->geometry().height()));
769
// Pinching strategy:
770
// if our containment is too big for the size of the screen we are now on,
771
// then we first try and limit the offset and then if that still doesn't
772
// give us enough room, we limit the size of the panel itself by setting
773
// the minimum and maximum sizes.
775
//kDebug() << "checking panel" << c->geometry() << "against" << screenGeom;
777
// resize to max if for some reason the size is empty
778
// otherwise its not possible to interact with the panel at all
779
if (c->size().isEmpty()) {
783
// write to the config file if the size has changed, or if we haven't recorded the lastsize
784
// previously which ensures we'll always have a value even after first run
785
const bool writeConfig = m_lastSeenSize != (horizontal ? sw : sh) || !sizes.hasKey("lastsize");
786
m_lastHorizontal = horizontal;
787
m_lastSeenSize = (horizontal ? sw : sh);
789
sizes.writeEntry("lastsize", m_lastSeenSize);
793
updatePanelGeometry();
795
if (m_offset != oldOffset) {
796
sizes.writeEntry("offset", m_lastSeenSize);
800
if (m_panelController) {
801
m_panelController->setOffset(m_offset);
804
connect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(pinchContainmentToCurrentScreen()));
805
recreateUnhideTrigger();
806
kDebug() << "Done pinching, containment's geom" << c->geometry() << "own geom" << geometry();
809
void PanelView::setOffset(int newOffset)
811
m_offset = newOffset;
813
//TODO: do we ever need to worry about pinching here, or
814
// do we just assume that the offset is always < screenSize - containmentSize?
815
updatePanelGeometry();
817
KConfigGroup viewConfig = config();
818
viewConfig = KConfigGroup(&viewConfig, (m_lastHorizontal ? "Horizontal" : "Vertical") +
819
QString::number(m_lastSeenSize));
820
viewConfig.writeEntry("offset", m_offset);
824
int PanelView::offset() const
829
void PanelView::setAlignment(Qt::Alignment align)
831
m_alignment = alignmentFilter(align);
832
KConfigGroup viewConfig = config();
833
viewConfig.writeEntry("Alignment", (int)m_alignment);
837
Qt::Alignment PanelView::alignment() const
842
void PanelView::immutabilityChanged(Plasma::ImmutabilityType immutability)
844
if (immutability != Plasma::Mutable) {
845
delete m_panelController;
846
m_panelController = 0;
850
void PanelView::togglePanelController()
854
if (containment()->immutability() != Plasma::Mutable) {
855
delete m_panelController;
856
m_panelController = 0;
860
if (!m_panelController) {
861
m_panelController = new PanelController(0);
862
m_panelController->setContainment(containment());
863
m_panelController->setLocation(containment()->location());
864
m_panelController->setAlignment(m_alignment);
865
m_panelController->setOffset(m_offset);
866
m_panelController->setVisibilityMode(m_visibilityMode);
868
connect(m_panelController, SIGNAL(destroyed(QObject*)), this, SLOT(editingComplete()));
869
connect(m_panelController, SIGNAL(offsetChanged(int)), this, SLOT(setOffset(int)));
870
connect(m_panelController, SIGNAL(partialMove(const QPoint&)), this, SLOT(setPanelDragPosition(const QPoint&)));
871
connect(m_panelController, SIGNAL(alignmentChanged(Qt::Alignment)), this, SLOT(setAlignment(Qt::Alignment)));
872
connect(m_panelController, SIGNAL(locationChanged(Plasma::Location)), this, SLOT(setLocation(Plasma::Location)));
873
connect(m_panelController, SIGNAL(panelVisibilityModeChanged(PanelView::VisibilityMode)), this, SLOT(setVisibilityMode(PanelView::VisibilityMode)));
875
if (containment()->containmentType() == Plasma::Containment::PanelContainment &&
876
dynamic_cast<QGraphicsLinearLayout*>(containment()->layout())) {
877
setTabOrder(0, m_panelController);
878
QWidget *prior = m_panelController;
880
// we only support mouse over drags for panels with linear layouts
881
QColor overlayColor(Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor));
882
QBrush overlayBrush(overlayColor);
883
QPalette p(palette());
884
p.setBrush(QPalette::Window, overlayBrush);
885
foreach (Plasma::Applet *applet, containment()->applets()) {
886
PanelAppletOverlay *moveOverlay = new PanelAppletOverlay(applet, this);
887
connect(moveOverlay, SIGNAL(removedWithApplet(PanelAppletOverlay*)),
888
this, SLOT(overlayDestroyed(PanelAppletOverlay*)));
889
connect(moveOverlay, SIGNAL(moved(PanelAppletOverlay*)),
890
this, SLOT(overlayMoved(PanelAppletOverlay*)));
891
moveOverlay->setPalette(p);
893
moveOverlay->raise();
894
m_appletOverlays << moveOverlay;
895
//kDebug() << moveOverlay << moveOverlay->geometry();
896
setTabOrder(prior, moveOverlay);
902
if (m_panelController->isVisible()) {
903
if (m_panelController->showingWidgetExplorer() ||
904
m_panelController->showingActivityManager()) {
905
m_panelController->switchToController();
906
m_panelController->move(m_panelController->positionForPanelGeometry(geometry()));
908
Plasma::WindowEffects::slideWindow(m_panelController, location());
909
m_panelController->close();
914
m_panelController->resize(m_panelController->sizeHint());
915
m_panelController->move(m_panelController->positionForPanelGeometry(geometry()));
916
Plasma::WindowEffects::slideWindow(m_panelController, location());
917
kDebug() << "showing panel controller!" << m_panelController->geometry();
918
m_panelController->show();
922
void PanelView::editingComplete()
925
m_panelController = 0;
927
qDeleteAll(m_appletOverlays);
928
m_appletOverlays.clear();
930
if (!containment()) {
934
containment()->closeToolBox();
937
if (m_visibilityMode == LetWindowsCover || m_visibilityMode == AutoHide) {
942
void PanelView::overlayDestroyed(PanelAppletOverlay *overlay)
944
m_appletOverlays.remove(overlay);
947
void PanelView::overlayMoved(PanelAppletOverlay *overlay)
950
foreach (PanelAppletOverlay *o, m_appletOverlays) {
955
Qt::Alignment PanelView::alignmentFilter(Qt::Alignment align) const
957
//If it's not a supported alignment default to Qt::AlignLeft
958
if (align == Qt::AlignLeft || align == Qt::AlignRight || align == Qt::AlignCenter) {
961
return Qt::AlignLeft;
965
void PanelView::updateStruts()
967
if (!containment()) {
971
NETExtendedStrut strut;
973
if (m_visibilityMode == NormalPanel) {
974
const QRect thisScreen = PlasmaApp::self()->corona()->screenGeometry(containment()->screen());
975
const QRect wholeScreen = Kephal::ScreenUtils::desktopGeometry();
977
//Extended struts against a screen edge near to another screen are really harmful, so windows maximized under the panel is a lesser pain
978
//TODO: force "windows can cover" in those cases?
979
const int numScreens = PlasmaApp::self()->corona()->numScreens();
980
for (int i = 0; i < numScreens; ++i) {
981
if (i == containment()->screen()) {
985
const QRect otherScreen = PlasmaApp::self()->corona()->screenGeometry(i);
989
case Plasma::TopEdge:
990
if (otherScreen.bottom() <= thisScreen.top()) {
991
KWindowSystem::setExtendedStrut(winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
995
case Plasma::BottomEdge:
996
if (otherScreen.top() >= thisScreen.bottom()) {
997
KWindowSystem::setExtendedStrut(winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1001
case Plasma::RightEdge:
1002
if (otherScreen.left() >= thisScreen.right()) {
1003
KWindowSystem::setExtendedStrut(winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1007
case Plasma::LeftEdge:
1008
if (otherScreen.right() <= thisScreen.left()) {
1009
KWindowSystem::setExtendedStrut(winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1017
// extended struts are to the combined screen geoms, not the single screen
1018
int leftOffset = wholeScreen.x() - thisScreen.x();
1019
int rightOffset = wholeScreen.right() - thisScreen.right();
1020
int bottomOffset = wholeScreen.bottom() - thisScreen.bottom();
1021
int topOffset = wholeScreen.top() - thisScreen.top();
1022
kDebug() << "screen l/r/b/t offsets are:" << leftOffset << rightOffset << bottomOffset << topOffset << location();
1026
case Plasma::TopEdge:
1027
strut.top_width = height() + topOffset;
1028
strut.top_start = x();
1029
strut.top_end = x() + width() - 1;
1032
case Plasma::BottomEdge:
1033
strut.bottom_width = height() + bottomOffset;
1034
strut.bottom_start = x();
1035
strut.bottom_end = x() + width() - 1;
1036
//kDebug() << "setting bottom edge to" << strut.bottom_width
1037
// << strut.bottom_start << strut.bottom_end;
1040
case Plasma::RightEdge:
1041
strut.right_width = width() + rightOffset;
1042
strut.right_start = y();
1043
strut.right_end = y() + height() - 1;
1046
case Plasma::LeftEdge:
1047
strut.left_width = width() + leftOffset;
1048
strut.left_start = y();
1049
strut.left_end = y() + height() - 1;
1053
//kDebug() << "where are we?";
1058
KWindowSystem::setExtendedStrut(winId(), strut.left_width,
1071
if (m_panelController) {
1072
m_panelController->setLocation(containment()->location());
1074
if (m_panelController->isVisible()) {
1075
m_panelController->resize(m_panelController->sizeHint());
1076
m_panelController->move(m_panelController->positionForPanelGeometry(geometry()));
1077
Plasma::WindowEffects::slideWindow(m_panelController, location());
1080
foreach (PanelAppletOverlay *o, m_appletOverlays) {
1081
o->syncOrientation();
1085
recreateUnhideTrigger();
1088
bool PanelView:: migratedFrom(int screenId) const
1090
KConfigGroup cg = config();
1091
QList<int> migrations;
1092
migrations = cg.readEntry("Migrations", migrations);
1093
return migrations.contains(screenId);
1096
void PanelView::migrateTo(int screenId)
1098
KConfigGroup cg = config();
1099
QList<int> migrations;
1100
migrations = cg.readEntry("Migrations", migrations);
1102
const int index = migrations.indexOf(screenId);
1104
migrations.append(screenId);
1106
migrations = migrations.mid(0, migrations.length() - index - 1);
1109
cg.writeEntry("Migrations", migrations);
1110
setScreen(screenId);
1113
void PanelView::showWidgetExplorer()
1115
if (!containment()) {
1119
if (!m_panelController) {
1121
ControllerWindow *controller = PlasmaApp::self()->showWidgetExplorer(screen(), containment());
1122
connect(controller, SIGNAL(destroyed(QObject*)), this, SLOT(editingComplete()), Qt::UniqueConnection);
1124
m_panelController->showWidgetExplorer();
1128
void PanelView::moveEvent(QMoveEvent *event)
1130
Plasma::View::moveEvent(event);
1131
m_strutsTimer->stop();
1132
m_strutsTimer->start(STRUTSTIMERDELAY);
1133
recreateUnhideTrigger();
1135
if (containment()) {
1136
foreach (Plasma::Applet *applet, containment()->applets()) {
1137
applet->updateConstraints(Plasma::PopupConstraint);
1142
void PanelView::resizeEvent(QResizeEvent *event)
1144
//kDebug() << event->oldSize() << event->size();
1145
Plasma::View::resizeEvent(event);
1146
recreateUnhideTrigger();
1147
m_strutsTimer->stop();
1148
m_strutsTimer->start(STRUTSTIMERDELAY);
1153
if (containment()) {
1154
foreach (Plasma::Applet *applet, containment()->applets()) {
1155
applet->updateConstraints(Plasma::PopupConstraint);
1160
void PanelView::updateHinter()
1163
QPoint mousePos = QCursor::pos();
1164
m_glowBar->updateStrength(mousePos);
1166
if (!m_unhideTriggerGeom.contains(mousePos)) {
1168
XMoveResizeWindow(QX11Info::display(), m_unhideTrigger, m_unhideTriggerGeom.x(), m_unhideTriggerGeom.y(), m_unhideTriggerGeom.width(), m_unhideTriggerGeom.height());
1173
QRect PanelView::unhideHintGeometry() const
1176
return m_unhideTriggerGeom;
1182
bool PanelView::hintOrUnhide(const QPoint &point, bool dueToDnd)
1185
if (m_visibilityMode != LetWindowsCover && isVisible()) {
1189
KWindowInfo activeWindow = KWindowSystem::windowInfo(KWindowSystem::activeWindow(), NET::WMState);
1190
if (activeWindow.state() & NET::FullScreen) {
1194
if (!shouldHintHide()) {
1195
//kDebug() << "should not hint hide";
1200
//kDebug() << point << m_triggerZone;
1201
if (m_triggerZone.contains(point)) {
1202
//kDebug() << "unhide!" << point;
1205
} else if (!m_glowBar) {
1206
Plasma::Direction direction = Plasma::locationToDirection(location());
1207
m_glowBar = new GlowBar(direction, m_triggerZone);
1209
XMoveResizeWindow(QX11Info::display(), m_unhideTrigger, m_triggerZone.x(), m_triggerZone.y(), m_triggerZone.width(), m_triggerZone.height());
1211
//FIXME: This is ugly as hell but well, yeah
1212
if (!m_mousePollTimer) {
1213
m_mousePollTimer = new QTimer(this);
1216
connect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(updateHinter()), Qt::UniqueConnection);
1217
m_mousePollTimer->start(200);
1226
void PanelView::hideHinter()
1228
//kDebug() << "hide the glow";
1229
if (m_mousePollTimer) {
1230
m_mousePollTimer->stop();
1231
disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(updateHinter()));
1238
bool PanelView::hasPopup()
1240
if (QApplication::activePopupWidget() || m_panelController) {
1244
if (containment()) {
1245
foreach (Plasma::Applet *applet, containment()->applets()) {
1246
if (applet->isPopupShowing()) {
1255
void PanelView::unhide(bool destroyTrigger)
1257
//kill the unhide stuff
1259
if (destroyTrigger) {
1260
destroyUnhideTrigger();
1263
//ensure it's visible
1265
Plasma::WindowEffects::slideWindow(this, location());
1269
KWindowSystem::setOnAllDesktops(winId(), true);
1271
//non-hiding panels stop here
1272
if (m_visibilityMode == NormalPanel || m_visibilityMode == WindowsGoBelow) {
1276
//set up the re-hiding stuff
1277
if (!m_mousePollTimer) {
1278
m_mousePollTimer = new QTimer(this);
1281
connect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(startAutoHide()), Qt::UniqueConnection);
1282
m_mousePollTimer->start(500);
1284
//avoid hide-show loops
1285
if (m_visibilityMode == LetWindowsCover) {
1286
m_triggerEntered = true;
1287
KWindowSystem::clearState(winId(), NET::KeepBelow);
1288
KWindowSystem::raiseWindow(winId());
1289
QTimer::singleShot(0, this, SLOT(resetTriggerEnteredSuppression()));
1293
void PanelView::statusUpdated(Plasma::ItemStatus newStatus)
1295
if (newStatus == Plasma::AcceptingInputStatus) {
1296
KWindowSystem::forceActiveWindow(winId());
1300
void PanelView::checkUnhide(Plasma::ItemStatus newStatus)
1302
//kDebug() << "================= got a status: " << newStatus << Plasma::ActiveStatus;
1303
m_respectStatus = true;
1305
if (newStatus > Plasma::ActiveStatus) {
1307
if (newStatus == Plasma::NeedsAttentionStatus) {
1308
//kDebug() << "starting the timer!";
1309
// start our rehide timer, so that the panel doesn't stay up and stuck forever and a day
1310
m_rehideAfterAutounhideTimer->start(AUTOUNHIDE_CHECK_DELAY);
1313
//kDebug() << "new status, just autohiding";
1318
void PanelView::checkAutounhide()
1320
//kDebug() << "***************************" << KIdleTime::instance()->idleTime();
1321
if (KIdleTime::instance()->idleTime() >= AUTOUNHIDE_CHECK_DELAY) {
1322
// the user is idle .. let's not hige the panel on them quite yet, but rather given them a
1323
// chance to see this thing!
1324
connect(KIdleTime::instance(), SIGNAL(resumingFromIdle()), this, SLOT(checkAutounhide()),
1325
Qt::UniqueConnection);
1326
KIdleTime::instance()->catchNextResumeEvent();
1327
//kDebug() << "exit 1 ***************************";
1331
m_respectStatus = false;
1332
//kDebug() << "in to check ... who's resonsible?" << sender() << KIdleTime::instance();
1333
if (sender() == KIdleTime::instance()) {
1334
//kDebug() << "doing a 2s wait";
1335
QTimer::singleShot(2000, this, SLOT(startAutoHide()));
1337
//kDebug() << "just starting autohide!";
1341
// this line must come after the check on sender() as it *clears* that value!
1342
disconnect(KIdleTime::instance(), SIGNAL(resumingFromIdle()), this, SLOT(checkAutounhide()));
1343
//kDebug() << "exit 0 ***************************";
1346
void PanelView::unhide()
1351
void PanelView::resetTriggerEnteredSuppression()
1353
m_triggerEntered = false;
1356
void PanelView::startAutoHide()
1359
kDebug() << m_editing << (containment() ? containment()->status() : 0) << Plasma::ActiveStatus
1360
<< geometry().adjusted(-10, -10, 10, 10).contains(QCursor::pos()) << hasPopup();
1361
if (containment() && containment()->status() > Plasma::ActiveStatus) {
1362
foreach (Plasma::Applet *applet, containment()->applets()) {
1363
kDebug() << " " << applet->name() << applet->status();
1369
if (m_editing || (m_respectStatus && (containment() && containment()->status() > Plasma::ActiveStatus))) {
1370
if (m_mousePollTimer) {
1371
m_mousePollTimer->stop();
1372
disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(startAutoHide()));
1378
// since we've gotten this far, we don't need to worry about rehiding-after-auto-unhide, so just
1380
m_rehideAfterAutounhideTimer->stop();
1382
if (geometry().adjusted(-10, -10, 10, 10).contains(QCursor::pos()) || hasPopup()) {
1383
if (!m_mousePollTimer) {
1389
if (m_mousePollTimer) {
1390
m_mousePollTimer->stop();
1391
disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(startAutoHide()));
1394
if (m_visibilityMode == LetWindowsCover) {
1395
KWindowSystem::setState(winId(), NET::KeepBelow);
1396
KWindowSystem::lowerWindow(winId());
1397
createUnhideTrigger();
1399
Plasma::WindowEffects::slideWindow(this, location());
1400
createUnhideTrigger();
1405
void PanelView::leaveEvent(QEvent *event)
1407
if (m_visibilityMode == LetWindowsCover && m_triggerEntered) {
1408
//this prevents crazy hide-unhide loops that can happen at times
1409
m_triggerEntered = false;
1410
} else if (containment() &&
1411
(m_visibilityMode == AutoHide || m_visibilityMode == LetWindowsCover) && !m_editing) {
1412
// even if we dont have a popup, we'll start a timer, so
1413
// that the panel stays if the mouse only leaves for a
1415
if (!m_mousePollTimer) {
1416
m_mousePollTimer = new QTimer(this);
1419
connect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(startAutoHide()), Qt::UniqueConnection);
1420
m_mousePollTimer->start(500);
1424
// startAutoHide calls this with a null event pointer, so we have to check it
1425
Plasma::View::leaveEvent(event);
1429
void PanelView::drawBackground(QPainter *painter, const QRectF &rect)
1431
if (PlasmaApp::hasComposite()) {
1432
painter->setCompositionMode(QPainter::CompositionMode_Source);
1433
painter->fillRect(rect.toAlignedRect(), Qt::transparent);
1435
Plasma::View::drawBackground(painter, rect);
1439
void PanelView::paintEvent(QPaintEvent *event)
1441
Plasma::View::paintEvent(event);
1444
bool PanelView::event(QEvent *event)
1446
if (event->type() == QEvent::Paint) {
1448
p.setCompositionMode(QPainter::CompositionMode_Source);
1449
p.fillRect(rect(), Qt::transparent);
1452
return Plasma::View::event(event);
1455
void PanelView::appletAdded(Plasma::Applet *applet)
1457
if (m_panelController && containment()->containmentType() == Plasma::Containment::PanelContainment) {
1458
QColor overlayColor(Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor));
1459
QBrush overlayBrush(overlayColor);
1460
QPalette p(palette());
1461
p.setBrush(QPalette::Window, overlayBrush);
1463
PanelAppletOverlay *moveOverlay = new PanelAppletOverlay(applet, this);
1464
connect(moveOverlay, SIGNAL(removedWithApplet(PanelAppletOverlay*)),
1465
this, SLOT(overlayDestroyed(PanelAppletOverlay*)));
1466
moveOverlay->setPalette(p);
1467
moveOverlay->show();
1468
moveOverlay->raise();
1469
m_appletOverlays << moveOverlay;
1471
QWidget *prior = m_panelController;
1472
Plasma::Applet *priorApplet = 0;
1473
foreach (Plasma::Applet *otherApplet, containment()->applets()) {
1474
if (applet == otherApplet) {
1478
priorApplet = otherApplet;
1482
foreach (PanelAppletOverlay *overlay, m_appletOverlays) {
1483
if (overlay->applet() == priorApplet) {
1490
setTabOrder(prior, moveOverlay);
1494
bool PanelView::shouldHintHide() const
1496
return m_visibilityMode == AutoHide && PlasmaApp::hasComposite();
1499
void PanelView::recreateUnhideTrigger()
1502
if (m_unhideTrigger == None) {
1506
XDestroyWindow(QX11Info::display(), m_unhideTrigger);
1507
m_unhideTrigger = None;
1508
createUnhideTrigger();
1512
void PanelView::createUnhideTrigger()
1515
//kDebug() << m_unhideTrigger << None;
1516
if (m_unhideTrigger != None) {
1520
bool fancy = shouldHintHide();
1521
int actualWidth = 1;
1522
int actualHeight = 1;
1523
int triggerWidth = fancy ? 30 : 1;
1524
int triggerHeight = fancy ? 30 : 1;
1526
QPoint actualTriggerPoint = pos();
1527
QPoint triggerPoint = pos();
1529
switch (location()) {
1530
case Plasma::TopEdge:
1531
actualWidth = triggerWidth = width();
1535
triggerPoint.setX(qMax(0, triggerPoint.x() - 15));
1538
case Plasma::BottomEdge:
1539
actualWidth = triggerWidth = width();
1540
actualTriggerPoint = triggerPoint = geometry().bottomLeft();
1544
triggerPoint.setX(qMax(0, triggerPoint.x() - 15));
1545
triggerPoint.setY(qMax(0, triggerPoint.y() - 29));
1548
case Plasma::RightEdge:
1549
actualHeight = triggerHeight = height();
1550
actualTriggerPoint = triggerPoint = geometry().topRight();
1553
triggerHeight += 30;
1554
triggerPoint.setY(qMax(0, triggerPoint.y() - 15));
1555
triggerPoint.setX(qMax(0, triggerPoint.x() - 29));
1558
case Plasma::LeftEdge:
1559
actualHeight = triggerHeight = height();
1562
triggerHeight += 30;
1563
triggerPoint.setY(qMax(0, triggerPoint.y() - 15));
1567
// no hiding unless we're on an edge.
1573
XSetWindowAttributes attributes;
1574
attributes.override_redirect = True;
1575
attributes.event_mask = EnterWindowMask;
1578
attributes.event_mask = EnterWindowMask | LeaveWindowMask | PointerMotionMask |
1579
KeyPressMask | KeyPressMask | ButtonPressMask |
1580
ButtonReleaseMask | ButtonMotionMask |
1581
KeymapStateMask | VisibilityChangeMask |
1582
StructureNotifyMask | ResizeRedirectMask |
1583
SubstructureNotifyMask |
1584
SubstructureRedirectMask | FocusChangeMask |
1585
PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask;
1587
unsigned long valuemask = CWOverrideRedirect | CWEventMask;
1588
m_unhideTrigger = XCreateWindow(QX11Info::display(), QX11Info::appRootWindow(),
1589
triggerPoint.x(), triggerPoint.y(), triggerWidth, triggerHeight,
1590
0, CopyFromParent, InputOnly, CopyFromParent,
1591
valuemask, &attributes);
1593
XChangeProperty(QX11Info::display(), m_unhideTrigger, PlasmaApp::self()->m_XdndAwareAtom,
1594
XA_WINDOW, 32, PropModeReplace, (unsigned char *)&PlasmaApp::self()->m_XdndVersionAtom, 1);
1595
XMapWindow(QX11Info::display(), m_unhideTrigger);
1596
m_unhideTriggerGeom = QRect(triggerPoint, QSize(triggerWidth, triggerHeight));
1597
m_triggerZone = QRect(actualTriggerPoint, QSize(actualWidth, actualHeight));
1599
//kDebug() << m_unhideTrigger;
1600
PlasmaApp::self()->panelHidden(true);
1603
void PanelView::destroyUnhideTrigger()
1606
if (m_unhideTrigger == None) {
1611
XDestroyWindow(QX11Info::display(), m_unhideTrigger);
1612
m_unhideTrigger = None;
1613
m_triggerZone = m_unhideTriggerGeom = QRect();
1617
PlasmaApp::self()->panelHidden(false);
1620
void PanelView::panelDeleted()
1622
if (!QApplication::closingDown()) {
1623
// the panel was removed at runtime; clean up our configuration object as well
1624
KConfigGroup c = config();
1626
configNeedsSaving();
1629
delete m_mousePollTimer;
1630
m_mousePollTimer = 0;
1631
m_strutsTimer->stop();
1636
void PanelView::positionSpacer(const QPoint pos)
1638
if (!containment()) {
1642
QGraphicsLinearLayout *lay = dynamic_cast<QGraphicsLinearLayout*>(containment()->layout());
1648
Plasma::FormFactor f = containment()->formFactor();
1649
int insertIndex = -1;
1651
//FIXME: needed in two places, make it a function?
1652
for (int i = 0; i < lay->count(); ++i) {
1653
QRectF siblingGeometry = lay->itemAt(i)->geometry();
1655
if (f == Plasma::Horizontal) {
1656
qreal middle = (siblingGeometry.left() + siblingGeometry.right()) / 2.0;
1657
if (pos.x() < middle) {
1660
} else if (pos.x() <= siblingGeometry.right()) {
1661
insertIndex = i + 1;
1664
} else { // Plasma::Vertical
1665
qreal middle = (siblingGeometry.top() + siblingGeometry.bottom()) / 2.0;
1666
if (pos.y() < middle) {
1669
} else if (pos.y() <= siblingGeometry.bottom()) {
1670
insertIndex = i + 1;
1676
m_spacerIndex = insertIndex;
1677
if (insertIndex != -1) {
1679
m_spacer = new QGraphicsWidget(containment());
1680
//m_spacer->panel = this;
1682
lay->removeItem(m_spacer);
1684
lay->insertItem(insertIndex, m_spacer);
1688
void PanelView::dragLeaveEvent(QDragLeaveEvent *event)
1690
if (containment()) {
1691
containment()->showDropZone(QPoint());
1694
Plasma::View::dragLeaveEvent(event);
1697
void PanelView::dropEvent(QDropEvent *event)
1699
Plasma::View::dropEvent(event);
1701
if (containment()) {
1702
containment()->showDropZone(QPoint());
1706
#include "panelview.moc"