2
* Copyright 2006-2008 Aaron Seigo <aseigo@kde.org>
3
* Copyright 2009 Marco Martin <notmart@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 as
7
* published by the Free Software Foundation; either version 2, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details
15
* You should have received a copy of the GNU Library General Public
16
* License along with this program; if not, write to the
17
* Free Software Foundation, Inc.,
18
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
#include "plasmaapp.h"
25
#include <QApplication>
26
#include <QPixmapCache>
28
#include <QtDBus/QtDBus>
32
#include <KCmdLineArgs>
33
#include <KStandardAction>
34
#include <KWindowSystem>
37
#include <ksmserver_interface.h>
39
#include <kephal/screens.h>
41
#include <Plasma/Containment>
42
#include <Plasma/Dialog>
43
#include <Plasma/Theme>
44
#include <Plasma/Wallpaper>
45
#include <Plasma/WindowEffects>
47
#include "netcorona.h"
50
#include "widgetsexplorer/widgetexplorer.h"
51
#include "plasmagenericshell/backgrounddialog.h"
55
#include <X11/extensions/Xrender.h>
56
#include <X11/extensions/shape.h>
59
PlasmaApp* PlasmaApp::self()
62
return new PlasmaApp();
65
return qobject_cast<PlasmaApp*>(kapp);
69
class GlowBar : public QWidget
72
GlowBar(Plasma::Direction direction, const QRect &triggerZone)
75
m_svg(new Plasma::Svg(this)),
76
m_direction(direction)
78
setAttribute(Qt::WA_TranslucentBackground);
79
KWindowSystem::setOnAllDesktops(winId(), true);
80
unsigned long state = NET::Sticky | NET::StaysOnTop | NET::KeepAbove;
81
KWindowSystem::setState(winId(), state);
82
KWindowSystem::setType(winId(), NET::Dock);
83
m_svg->setImagePath("widgets/glowbar");
86
QRegion region(QRect(0,0,1,1));
87
XShapeCombineRegion(QX11Info::display(), winId(), ShapeInput, 0, 0,
88
region.handle(), ShapeSet);
91
QPalette pal = palette();
92
pal.setColor(backgroundRole(), Qt::transparent);
95
QRect glowGeom = triggerZone;
97
switch (m_direction) {
99
glowGeom.setY(glowGeom.y() - s.height() + 1);
102
glowGeom.setHeight(s.height());
105
glowGeom.setX(glowGeom.x() - s.width() + 1);
108
glowGeom.setWidth(s.width());
112
//kDebug() << "glow geom is" << glowGeom << "from" << triggerZone;
113
setGeometry(glowGeom);
114
m_buffer = QPixmap(size());
117
void paintEvent(QPaintEvent* e)
121
const QSize glowRadius = m_svg->elementSize("hint-glow-radius");
122
QPoint pixmapPosition(0, 0);
124
m_buffer.fill(QColor(0, 0, 0, int(qreal(255)*m_strength)));
125
QPainter p(&m_buffer);
126
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
128
switch (m_direction) {
130
pixmap = m_svg->pixmap("bottom");
131
pixmapPosition = QPoint(0, -glowRadius.height());
134
pixmap = m_svg->pixmap("top");
137
pixmap = m_svg->pixmap("right");
138
pixmapPosition = QPoint(-glowRadius.width(), 0);
141
pixmap = m_svg->pixmap("left");
145
if (m_direction == Plasma::Left || m_direction == Plasma::Right) {
146
p.drawTiledPixmap(QRect(0, pixmapPosition.x(), pixmap.width(), height()), pixmap);
148
p.drawTiledPixmap(QRect(0, pixmapPosition.y(), width(), pixmap.height()), pixmap);
153
p.drawPixmap(QPoint(0, 0), m_buffer);
156
QSize sizeHint() const
158
return m_svg->elementSize("bottomright") - m_svg->elementSize("hint-glow-radius");
161
bool event(QEvent *event)
163
if (event->type() == QEvent::Paint) {
165
p.setCompositionMode(QPainter::CompositionMode_Source);
166
p.fillRect(rect(), Qt::transparent);
168
return QWidget::event(event);
171
void updateStrength(QPoint point)
173
QPoint localPoint = mapFromGlobal(point);
176
switch (m_direction) {
177
case Plasma::Up: // when the panel is at the bottom.
178
newStrength = 1 - qreal(-localPoint.y())/m_triggerDistance;
181
newStrength = 1 - qreal(localPoint.x())/m_triggerDistance;
183
case Plasma::Left: // when the panel is right-aligned
184
newStrength = 1 - qreal(-localPoint.x())/m_triggerDistance;
188
newStrength = 1- qreal(localPoint.y())/m_triggerDistance;
191
if (qAbs(newStrength - m_strength) > 0.01 && newStrength >= 0 && newStrength <= 1) {
192
m_strength = newStrength;
199
static const int m_triggerDistance = 30;
202
Plasma::Direction m_direction;
207
class ShadowWindow : public QWidget
210
ShadowWindow(NetView *panel)
215
setAttribute(Qt::WA_TranslucentBackground);
216
setAttribute(Qt::WA_NoSystemBackground, false);
217
setAutoFillBackground(false);
219
QRegion region(QRect(0,0,1,1));
220
XShapeCombineRegion(QX11Info::display(), winId(), ShapeInput, 0, 0,
221
region.handle(), ShapeSet);
224
m_shadow = new Plasma::FrameSvg(this);
227
void setSvg(const QString &path)
229
m_shadow->setImagePath(path);
231
if (!m_shadow->hasElementPrefix("shadow")) {
238
m_shadow->setElementPrefix("shadow");
240
adjustMargins(geometry());
248
void adjustMargins(const QRect &geo)
250
QRect screenRect = Kephal::ScreenUtils::screenGeometry(m_panel->screen());
252
Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders;
254
if (geo.left() <= screenRect.left()) {
255
enabledBorders ^= Plasma::FrameSvg::LeftBorder;
257
if (geo.top() <= screenRect.top()) {
258
enabledBorders ^= Plasma::FrameSvg::TopBorder;
260
if (geo.bottom() >= screenRect.bottom()) {
261
enabledBorders ^= Plasma::FrameSvg::BottomBorder;
263
if (geo.right() >= screenRect.right()) {
264
enabledBorders ^= Plasma::FrameSvg::RightBorder;
267
m_shadow->setEnabledBorders(enabledBorders);
269
qreal left, top, right, bottom;
271
m_shadow->getMargins(left, top, right, bottom);
272
setContentsMargins(left, top, right, bottom);
276
bool event(QEvent *event)
280
if (event->type() == QEvent::Paint) {
282
p.setCompositionMode(QPainter::CompositionMode_Source);
283
p.fillRect(rect(), Qt::transparent);
285
return QWidget::event(event);
288
void resizeEvent(QResizeEvent *event)
290
m_shadow->resizeFrame(event->size());
292
adjustMargins(geometry());
295
void paintEvent(QPaintEvent* e)
300
//p.setCompositionMode(QPainter::CompositionMode_Source);
301
m_shadow->paintFrame(&p);
305
Plasma::FrameSvg *m_shadow;
310
PlasmaApp::PlasmaApp()
311
: KUniqueApplication(),
313
m_widgetExplorerView(0),
320
m_autoHideControlBar(true),
323
m_startupSuspendWaitCount(0)
325
PlasmaApp::suspendStartup(true);
326
KGlobal::locale()->insertCatalog("libplasma");
327
KGlobal::locale()->insertCatalog("plasmagenericshell");
330
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
331
bool isDesktop = args->isSet("desktop");
333
KCrash::setFlags(KCrash::AutoRestart);
336
//TODO: decide how to handle the cache size; possibilities:
337
// * % of ram, as in desktop
338
// * fixed size, hardcoded (uck)
339
// * optional size, specified on command line
340
// * optional size, in a config file
341
// * don't do anything special at all
342
//QPixmapCache::setCacheLimit(cacheSize);
344
KConfigGroup cg(KSharedConfig::openConfig("plasmarc"), "Theme-plasma-netbook");
345
const QString themeName = cg.readEntry("name", "air-netbook");
346
Plasma::Theme::defaultTheme()->setUseGlobalSettings(false);
347
Plasma::Theme::defaultTheme()->setThemeName(themeName);
349
cg = KConfigGroup(KGlobal::config(), "General");
351
Plasma::Theme::defaultTheme()->setFont(cg.readEntry("desktopFont", font()));
353
m_mainView = new NetView(0, NetView::mainViewId(), 0);
356
connect(m_mainView, SIGNAL(containmentActivated()), this, SLOT(mainContainmentActivated()));
357
connect(KWindowSystem::self(), SIGNAL(workAreaChanged()), this, SLOT(positionPanel()));
359
bool useGL = args->isSet("opengl");
360
m_mainView->setUseGL(useGL);
362
connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(controlBarVisibilityUpdate()));
367
QRect rect = Kephal::ScreenUtils::screenGeometry(m_mainView->screen());
368
width = rect.width();
369
height = rect.height();
371
QAction *action = KStandardAction::quit(qApp, SLOT(quit()), m_mainView);
372
m_mainView->addAction(action);
374
QString geom = args->getOption("screen");
375
int x = geom.indexOf('x');
378
width = qMax(width, geom.left(x).toInt());
379
height = qMax(height, geom.right(geom.length() - x - 1).toInt());
383
m_mainView->setFixedSize(width, height);
384
m_mainView->move(0,0);
385
setIsDesktop(isDesktop);
387
// this line initializes the corona.
389
//setIsDesktop(isDesktop);
392
connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(checkShadow()));
393
connect(this, SIGNAL(aboutToQuit()), this, SLOT(cleanup()));
396
PlasmaApp::~PlasmaApp()
400
void PlasmaApp::cleanup()
403
m_corona->saveLayout();
406
if (!m_mainView->containment()) {
410
// save the mapping of Views to Containments at the moment
411
// of application exit so we can restore that when we start again.
412
KConfigGroup viewIds(KGlobal::config(), "ViewIds");
413
viewIds.deleteGroup();
414
viewIds.writeEntry(QString::number(m_mainView->containment()->id()), NetView::mainViewId());
417
viewIds.writeEntry(QString::number(m_controlBar->containment()->id()), NetView::controlBarId());
426
//TODO: This manual sync() should not be necessary?
430
void PlasmaApp::syncConfig()
432
KGlobal::config()->sync();
435
void PlasmaApp::positionPanel()
441
QRect screenRect = Kephal::ScreenUtils::screenGeometry(m_controlBar->screen());
443
screenRect = m_mainView->geometry();
447
controlBarMoved(m_controlBar);
449
if (m_controlBar->formFactor() == Plasma::Horizontal) {
450
m_controlBar->setFixedSize(screenRect.width(), m_controlBar->size().height());
451
} else if (m_controlBar->formFactor() == Plasma::Vertical) {
452
m_controlBar->setFixedSize(m_controlBar->size().width(), screenRect.height());
456
m_controlBar->containment()->setMaximumSize(m_controlBar->size());
457
m_controlBar->containment()->setMinimumSize(m_controlBar->size());
459
if (m_autoHideControlBar && m_controlBar->isVisible()) {
460
destroyUnHideTrigger();
461
createUnhideTrigger();
466
emit controlBarChanged();
469
void PlasmaApp::checkShadow()
475
if (KWindowSystem::compositingActive() && m_controlBar->containment()->property("shadowPath").isValid()) {
476
if (!m_shadowWindow) {
477
m_shadowWindow = new ShadowWindow(m_controlBar);
478
KWindowSystem::setOnAllDesktops(m_controlBar->winId(), true);
480
KWindowSystem::setType(m_shadowWindow->winId(), NET::Dock);
481
KWindowSystem::setState(m_shadowWindow->winId(), NET::KeepBelow);
482
KWindowSystem::setOnAllDesktops(m_shadowWindow->winId(), true);
483
m_shadowWindow->setSvg(m_controlBar->containment()->property("shadowPath").toString());
484
int left, right, top, bottom;
485
m_shadowWindow->adjustMargins(m_controlBar->geometry());
486
m_shadowWindow->getContentsMargins(&left, &top, &right, &bottom);
487
m_shadowWindow->setMinimumSize(-1, -1);
488
m_shadowWindow->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
489
m_shadowWindow->setGeometry(m_controlBar->geometry().adjusted(-left, -top, right, bottom));
490
m_shadowWindow->setFixedSize(m_shadowWindow->size());
491
if (m_shadowWindow->isValid()) {
492
m_shadowWindow->show();
495
m_shadowWindow->deleteLater();
500
void PlasmaApp::mainContainmentActivated()
502
if (m_mainView->containment()) {
503
m_mainView->setWindowTitle(m_mainView->containment()->activity());
507
const WId id = m_mainView->effectiveWinId();
509
QWidget * activeWindow = QApplication::activeWindow();
510
KWindowSystem::raiseWindow(id);
513
KWindowSystem::raiseWindow(activeWindow->effectiveWinId());
514
m_mainView->activateWindow();
515
activeWindow->setFocus();
516
if (m_shadowWindow) {
517
KWindowSystem::clearState(m_shadowWindow->winId(), NET::KeepBelow);
518
KWindowSystem::setState(m_shadowWindow->winId(), NET::KeepAbove);
521
m_mainView->activateWindow();
525
void PlasmaApp::setIsDesktop(bool isDesktop)
527
m_isDesktop = isDesktop;
530
KWindowSystem::setType(m_mainView->winId(), NET::Normal);
531
m_mainView->setWindowFlags(m_mainView->windowFlags() | Qt::FramelessWindowHint);
532
KWindowSystem::setOnAllDesktops(m_mainView->winId(), true);
534
KWindowSystem::setOnAllDesktops(m_controlBar->winId(), true);
538
m_mainView->setWindowFlags(m_mainView->windowFlags() & ~Qt::FramelessWindowHint);
539
KWindowSystem::setOnAllDesktops(m_mainView->winId(), false);
541
KWindowSystem::setOnAllDesktops(m_controlBar->winId(), false);
543
KWindowSystem::setType(m_mainView->winId(), NET::Normal);
547
bool PlasmaApp::isDesktop() const
552
void PlasmaApp::adjustSize(Kephal::Screen *screen)
556
QRect rect = Kephal::ScreenUtils::screenGeometry(m_mainView->screen());
558
int width = rect.width();
559
int height = rect.height();
560
//FIXME: ugly hack there too
561
m_mainView->setFixedSize(width, height);
566
void PlasmaApp::reserveStruts()
572
if (m_autoHideControlBar || !isDesktop()) {
573
KWindowSystem::setExtendedStrut(m_controlBar->winId(),
581
NETExtendedStrut strut;
583
if (!m_autoHideControlBar || hasForegroundWindows()) {
584
switch (m_controlBar->location()) {
585
case Plasma::LeftEdge:
586
strut.left_width = m_controlBar->width();
587
strut.left_start = m_controlBar->y();
588
strut.left_end = m_controlBar->y() + m_controlBar->height() - 1;
590
case Plasma::RightEdge:
591
strut.right_width = m_controlBar->width();
592
strut.right_start = m_controlBar->y();
593
strut.right_end = m_controlBar->y() + m_controlBar->height() - 1;
595
case Plasma::TopEdge:
596
strut.top_width = m_controlBar->height();
597
strut.top_start = m_controlBar->x();
598
strut.top_end = m_controlBar->x() + m_controlBar->width() - 1;
600
case Plasma::BottomEdge:
602
strut.bottom_width = m_controlBar->height();
603
strut.bottom_start = m_controlBar->x();
604
strut.bottom_end = m_controlBar->x() + m_controlBar->width() - 1;
608
KWindowSystem::setExtendedStrut(m_controlBar->winId(),
609
strut.left_width, strut.left_start, strut.left_end,
610
strut.right_width, strut.right_start, strut.right_end,
611
strut.top_width, strut.top_start, strut.top_end,
612
strut.bottom_width, strut.bottom_start, strut.bottom_end);
614
//ensure the main view is at the proper position too
615
QRect screenRect = Kephal::ScreenUtils::screenGeometry(m_controlBar->screen());
616
m_mainView->move(screenRect.topLeft());
619
NetView *PlasmaApp::controlBar() const
624
NetView *PlasmaApp::mainView() const
629
QWidget *PlasmaApp::widgetExplorer() const
631
return m_widgetExplorerView;
634
Plasma::Corona* PlasmaApp::corona()
637
m_corona = new NetCorona(this);
638
connect(m_corona, SIGNAL(containmentAdded(Plasma::Containment*)),
639
this, SLOT(createView(Plasma::Containment*)));
640
connect(m_corona, SIGNAL(configSynced()), this, SLOT(syncConfig()));
642
connect(m_corona, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)),
643
m_mainView, SLOT(screenOwnerChanged(int,int,Plasma::Containment*)));
645
m_corona->setItemIndexMethod(QGraphicsScene::NoIndex);
646
m_corona->initializeLayout();
647
m_corona->processUpdateScripts();
652
foreach (Plasma::Containment *containment, m_corona->containments()) {
653
if (containment->screen() != -1 && containment->wallpaper()) {
654
++m_startupSuspendWaitCount;
655
connect(containment->wallpaper(), SIGNAL(update(QRectF)), this, SLOT(wallpaperCheckedIn()));
659
QTimer::singleShot(5000, this, SLOT(wallpaperCheckInTimeout()));
664
void PlasmaApp::wallpaperCheckInTimeout()
666
if (m_startupSuspendWaitCount > 0) {
667
m_startupSuspendWaitCount = 0;
668
suspendStartup(false);
672
void PlasmaApp::wallpaperCheckedIn()
674
if (m_startupSuspendWaitCount < 1) {
678
--m_startupSuspendWaitCount;
679
if (m_startupSuspendWaitCount < 1) {
680
m_startupSuspendWaitCount = 0;
681
suspendStartup(false);
685
bool PlasmaApp::hasComposite()
687
return KWindowSystem::compositingActive();
690
void PlasmaApp::suspendStartup(bool suspend)
692
org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
694
const QString startupID("netbook desktop");
696
ksmserver.suspendStartup(startupID);
698
ksmserver.resumeStartup(startupID);
702
void PlasmaApp::createView(Plasma::Containment *containment)
704
connect(containment, SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(showWidgetExplorer()));
705
connect(containment, SIGNAL(configureRequested(Plasma::Containment*)),
706
this, SLOT(configureContainment(Plasma::Containment*)));
707
connect(containment, SIGNAL(toolBoxVisibilityChanged(bool)),
708
this, SLOT(updateToolBoxVisibility(bool)));
711
KConfigGroup viewIds(KGlobal::config(), "ViewIds");
713
if (containment->containmentType() == Plasma::Containment::PanelContainment &&
714
(!m_controlBar || m_controlBar->containment() == 0) ) {
715
defaultId = NetView::controlBarId();
716
} else if (containment->containmentType() == Plasma::Containment::PanelContainment &&
717
m_mainView->containment() == 0 ) {
718
defaultId = NetView::mainViewId();
721
int id = viewIds.readEntry(QString::number(containment->id()), defaultId);
724
kDebug() << "new containment" << (QObject*)containment << containment->id() << "view id" << id;
726
//is it a desktop -and- is it active?
727
if ((m_mainView && id == NetView::mainViewId()) ||
728
(containment->containmentType() != Plasma::Containment::PanelContainment &&
729
containment->containmentType() != Plasma::Containment::CustomPanelContainment &&
730
!viewIds.exists() && containment->screen() == 0)) {
731
m_mainView->setContainment(containment);
732
containment->setScreen(0);
734
} else if (id == NetView::controlBarId()) {
736
m_controlBar = new NetView(0, NetView::controlBarId(), 0);
738
Kephal::Screens *screens = Kephal::Screens::self();
739
connect(screens, SIGNAL(screenResized(Kephal::Screen *, QSize, QSize)),
740
this, SLOT(adjustSize(Kephal::Screen *)));
742
m_controlBar->setAutoFillBackground(false);
743
m_controlBar->viewport()->setAutoFillBackground(false);
744
m_controlBar->setAttribute(Qt::WA_TranslucentBackground);
746
connect(m_controlBar, SIGNAL(locationChanged(const NetView *)), this, SLOT(positionPanel()));
747
connect(m_controlBar, SIGNAL(geometryChanged()), this, SLOT(positionPanel()));
748
connect(m_controlBar, SIGNAL(containmentActivated()), this, SLOT(showControlBar()));
749
connect(m_controlBar, SIGNAL(autoHideChanged(bool)), this, SLOT(setAutoHideControlBar(bool)));
752
m_controlBar->setContainment(containment);
754
setControlBarVisible(true);
755
containment->setMaximumSize(m_controlBar->size());
756
containment->setMinimumSize(m_controlBar->size());
757
containment->setImmutability(Plasma::UserImmutable);
759
m_autoHideControlBar = m_controlBar->config().readEntry("panelAutoHide", true);
761
setAutoHideControlBar(m_autoHideControlBar);
762
emit controlBarChanged();
763
setControlBarVisible(true);
765
containment->setScreen(-1);
769
void PlasmaApp::closeWidgetExplorer()
771
if (m_widgetExplorer) {
772
Plasma::WindowEffects::slideWindow(m_widgetExplorerView, m_controlBar->location());
773
m_widgetExplorer->deleteLater();
774
m_widgetExplorerView->deleteLater();
778
void PlasmaApp::updateToolBoxVisibility(bool visible)
780
bool hadToolBoxOpen = false;
782
foreach (Plasma::Containment *cont, m_corona->containments()) {
783
if (cont->isToolBoxOpen()) {
784
hadToolBoxOpen = true;
786
cont->setToolBoxOpen(visible);
789
if (!visible && hadToolBoxOpen) {
790
closeWidgetExplorer();
794
void PlasmaApp::controlBarMoved(const NetView *controlBar)
796
if (!m_controlBar || controlBar != m_controlBar) {
800
QRect screenRect = Kephal::ScreenUtils::screenGeometry(m_controlBar->screen());
802
Plasma::Containment *cont = m_controlBar->containment();
804
switch (controlBar->location()) {
805
case Plasma::LeftEdge:
806
m_controlBar->move(screenRect.topLeft());
808
case Plasma::RightEdge:
809
m_controlBar->move(screenRect.topRight()-QPoint(m_controlBar->size().width(), 0));
811
case Plasma::TopEdge:
812
m_controlBar->move(screenRect.topLeft());
814
case Plasma::BottomEdge:
815
m_controlBar->move(screenRect.bottomLeft()-QPoint(0,m_controlBar->size().height()));
820
//flip height and width
821
if (controlBar->formFactor() == Plasma::Vertical) {
822
if (cont && m_controlBar->size().width() > m_controlBar->size().height()) {
823
cont->setMinimumSize(cont->size().height(), cont->size().width());
824
cont->setMaximumSize(cont->minimumSize());
826
} else if (controlBar->formFactor() == Plasma::Horizontal) {
827
if (cont && m_controlBar->size().width() < m_controlBar->size().height()) {
828
cont->setMinimumSize(cont->size().height(), cont->size().width());
829
cont->setMaximumSize(cont->minimumSize());
836
void PlasmaApp::setAutoHideControlBar(bool autoHide)
843
if (!m_unHideTimer) {
844
m_unHideTimer = new QTimer(this);
845
m_unHideTimer->setSingleShot(true);
846
connect(m_unHideTimer, SIGNAL(timeout()), this, SLOT(controlBarVisibilityUpdate()));
849
m_controlBar->installEventFilter(this);
850
controlBarVisibilityUpdate();
852
m_controlBar->removeEventFilter(this);
853
destroyUnHideTrigger();
854
delete m_unHideTimer;
856
setControlBarVisible(true);
859
m_autoHideControlBar = autoHide;
861
m_controlBar->config().writeEntry("panelAutoHide", autoHide);
864
void PlasmaApp::showWidgetExplorer()
866
Plasma::Containment *containment = dynamic_cast<Plasma::Containment *>(sender());
872
showWidgetExplorer(containment);
875
void PlasmaApp::showWidgetExplorer(Plasma::Containment *containment)
881
containment->setToolBoxOpen(true);
883
if (!m_widgetExplorerView) {
885
m_widgetExplorerView = new Plasma::Dialog();
887
KWindowSystem::setOnAllDesktops(m_widgetExplorerView->winId(), true);
888
m_widgetExplorerView->show();
889
KWindowSystem::activateWindow(m_widgetExplorerView->winId());
890
m_widgetExplorerView->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
891
m_widgetExplorerView->setAttribute(Qt::WA_TranslucentBackground);
892
m_widgetExplorerView->setAttribute(Qt::WA_DeleteOnClose);
893
KWindowSystem::setState(m_widgetExplorerView->winId(), NET::StaysOnTop|NET::KeepAbove);
894
connect(m_widgetExplorerView, SIGNAL(destroyed()), this, SLOT(widgetExplorerDestroyed()));
897
switch (m_controlBar->location()) {
898
case Plasma::TopEdge:
899
m_widgetExplorerView->resize(m_mainView->size().width(), KIconLoader::SizeEnormous);
900
m_widgetExplorerView->move(m_controlBar->geometry().bottomLeft());
902
case Plasma::LeftEdge:
903
m_widgetExplorerView->resize(KIconLoader::SizeEnormous, m_mainView->size().height());
904
m_widgetExplorerView->move(m_controlBar->geometry().topRight());
906
case Plasma::RightEdge:
907
m_widgetExplorerView->resize(KIconLoader::SizeEnormous, m_mainView->size().height());
908
m_widgetExplorerView->move(m_controlBar->geometry().topLeft() - QPoint(m_widgetExplorerView->size().width(), 0));
910
case Plasma::BottomEdge:
912
m_widgetExplorerView->resize(m_mainView->size().width(), KIconLoader::SizeEnormous);
913
m_widgetExplorerView->move(m_controlBar->geometry().topLeft() - QPoint(0, m_widgetExplorerView->size().height()));
917
m_widgetExplorerView->resize(m_mainView->size().width(), KIconLoader::SizeEnormous);
918
m_widgetExplorerView->move(0,0);
923
if (!m_widgetExplorer) {
924
m_widgetExplorer = new Plasma::WidgetExplorer(m_controlBar->containment());
925
connect(m_widgetExplorer, SIGNAL(closeClicked()), this, SLOT(closeWidgetExplorer()));
926
m_widgetExplorer->setContainment(m_mainView->containment());
927
m_widgetExplorer->populateWidgetList();
929
m_corona->addOffscreenWidget(m_widgetExplorer);
931
QSize viewSize = m_widgetExplorerView->size();
932
m_widgetExplorerView->setGraphicsWidget(m_widgetExplorer);
934
m_widgetExplorer->setIconSize(KIconLoader::SizeLarge);
935
m_widgetExplorerView->installEventFilter(this);
938
m_widgetExplorer->setLocation(m_controlBar->location());
940
if (m_widgetExplorer->location() == Plasma::LeftEdge || m_widgetExplorer->location() == Plasma::RightEdge) {
941
m_widgetExplorer->setMinimumWidth(-1);
942
m_widgetExplorer->setMinimumHeight(m_mainView->size().height());
944
m_widgetExplorer->setMinimumWidth(m_mainView->size().width());
945
m_widgetExplorer->setMinimumHeight(-1);
950
m_widgetExplorer->show();
951
Plasma::WindowEffects::slideWindow(m_widgetExplorerView, m_controlBar->location());
952
m_widgetExplorerView->show();
953
emit controlBarChanged();
956
void PlasmaApp::widgetExplorerDestroyed()
958
m_widgetExplorer = 0;
959
m_widgetExplorerView = 0;
961
if (m_mainView->containment()) {
962
m_mainView->containment()->setToolBoxOpen(false);
967
void PlasmaApp::configureContainment(Plasma::Containment *containment)
969
const QString id = "plasma_containment_settings_" + QString::number(containment->id());
970
BackgroundDialog *configDialog = qobject_cast<BackgroundDialog*>(KConfigDialog::exists(id));
971
kDebug() << configDialog;
974
configDialog->reloadConfig();
976
const QSize resolution = Kephal::ScreenUtils::screenGeometry(m_mainView->screen()).size();
979
KConfigSkeleton *nullManager = new KConfigSkeleton(0);
980
configDialog = new BackgroundDialog(resolution, containment, m_mainView, 0, id, nullManager);
981
configDialog->setAttribute(Qt::WA_DeleteOnClose);
983
connect(configDialog, SIGNAL(destroyed(QObject*)), nullManager, SLOT(deleteLater()));
986
configDialog->show();
987
KWindowSystem::setOnDesktop(configDialog->winId(), KWindowSystem::currentDesktop());
988
KWindowSystem::activateWindow(configDialog->winId());
991
bool PlasmaApp::mainViewOnTop() const
995
QSet<WId> ownWindows;
996
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
997
ownWindows.insert(widget->winId());
1000
//search if the main view is actually one of the widgets on top, show the panel only in this case
1001
QList<WId> windows = KWindowSystem::stackingOrder();
1002
for (int i = windows.size() - 1; i >= 0; --i) {
1003
WId window = windows.at(i);
1005
if (window == m_mainView->winId()) {
1008
} else if (!ownWindows.contains(window)) {
1016
bool PlasmaApp::eventFilter(QObject * watched, QEvent *event)
1018
if (watched == m_widgetExplorerView && event->type() == QEvent::KeyPress) {
1019
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
1020
if (keyEvent->key() == Qt::Key_Escape) {
1021
closeWidgetExplorer();
1023
} else if (watched == m_widgetExplorerView && event->type() == QEvent::Resize) {
1024
m_widgetExplorer->resize(m_widgetExplorerView->contentsRect().size());
1025
} else if (!m_isDesktop && watched == m_mainView && event->type() == QEvent::Close) {
1031
bool PlasmaApp::x11EventFilter(XEvent *event)
1034
if (m_controlBar && m_autoHideControlBar && !m_controlBar->isVisible() && event->xcrossing.window == m_unhideTrigger &&
1035
(event->xany.send_event != True && event->type == EnterNotify)) {
1037
if (!m_glowBar && KWindowSystem::compositingActive() && !m_triggerZone.contains(QCursor::pos())) {
1038
Plasma::Direction direction = Plasma::locationToDirection(m_controlBar->location());
1039
m_glowBar = new GlowBar(direction, m_triggerZone);
1041
XMoveResizeWindow(QX11Info::display(), m_unhideTrigger, m_triggerZone.x(), m_triggerZone.y(), m_triggerZone.width(), m_triggerZone.height());
1043
//FIXME: This is ugly as hell but well, yeah
1044
if (!m_mousePollTimer) {
1045
m_mousePollTimer = new QTimer(this);
1048
disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(unhideHintMousePoll()));
1049
connect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(unhideHintMousePoll()));
1050
m_mousePollTimer->start(200);
1052
m_unHideTimer->start(400);
1054
} else if ((event->xany.send_event != True && event->type == FocusOut)) {
1055
QTimer::singleShot(100, this, SLOT(lowerMainView()));
1056
} else if (m_controlBar && m_autoHideControlBar && m_controlBar->isVisible() &&
1057
(event->xany.send_event != True && event->type == LeaveNotify)) {
1058
if (m_unHideTimer) {
1059
m_unHideTimer->start(200);
1063
return KUniqueApplication::x11EventFilter(event);
1066
bool PlasmaApp::hasForegroundWindows() const
1068
return QApplication::activeWindow();
1071
void PlasmaApp::lowerMainView()
1073
if (m_isDesktop && !hasForegroundWindows()) {
1074
KWindowSystem::lowerWindow(m_mainView->winId());
1076
if (m_shadowWindow) {
1077
KWindowSystem::clearState(m_shadowWindow->winId(), NET::KeepAbove);
1078
KWindowSystem::setState(m_shadowWindow->winId(), NET::KeepBelow);
1082
void PlasmaApp::controlBarVisibilityUpdate()
1084
if (!m_controlBar) {
1088
if (!m_autoHideControlBar) {
1089
setControlBarVisible(true);
1091
if (m_shadowWindow && m_shadowWindow->isValid()) {
1092
Plasma::WindowEffects::slideWindow(m_shadowWindow, m_controlBar->location());
1093
m_shadowWindow->show();
1094
if (hasForegroundWindows()) {
1095
KWindowSystem::clearState(m_shadowWindow->winId(), NET::KeepBelow);
1096
KWindowSystem::setState(m_shadowWindow->winId(), NET::KeepAbove);
1098
KWindowSystem::clearState(m_shadowWindow->winId(), NET::KeepAbove);
1099
KWindowSystem::setState(m_shadowWindow->winId(), NET::KeepBelow);
1101
KWindowSystem::setOnAllDesktops(m_shadowWindow->winId(), true);
1105
} else if (m_autoHideControlBar && hasForegroundWindows() && m_controlBar->isVisible()) {
1109
if (sender() != m_unHideTimer) {
1110
m_unHideTimer->start(200);
1114
//would be nice to avoid this
1115
QPoint cursorPos = QCursor::pos();
1117
if (m_triggerZone.adjusted(-1, -1, 1, 1).contains(cursorPos) || hasForegroundWindows()) {
1118
if (!m_controlBar->isVisible()) {
1119
destroyUnHideTrigger();
1120
Plasma::WindowEffects::slideWindow(m_controlBar, m_controlBar->location());
1121
setControlBarVisible(true);
1124
if (m_shadowWindow && m_shadowWindow->isValid()) {
1125
Plasma::WindowEffects::slideWindow(m_shadowWindow, m_controlBar->location());
1126
if (hasForegroundWindows()) {
1127
KWindowSystem::clearState(m_shadowWindow->winId(), NET::KeepBelow);
1128
KWindowSystem::setState(m_shadowWindow->winId(), NET::KeepAbove);
1130
m_shadowWindow->show();
1131
KWindowSystem::setOnAllDesktops(m_shadowWindow->winId(), true);
1133
} else if (!m_controlBar->geometry().contains(cursorPos) && !mainViewOnTop() && !hasForegroundWindows()) {
1134
Plasma::WindowEffects::slideWindow(m_controlBar, m_controlBar->location());
1135
m_controlBar->hide();
1137
if (m_shadowWindow) {
1138
Plasma::WindowEffects::slideWindow(m_shadowWindow, m_controlBar->location());
1139
m_shadowWindow->hide();
1142
createUnhideTrigger();
1146
void PlasmaApp::showControlBar()
1148
setControlBarVisible(true);
1151
void PlasmaApp::hideControlBar()
1153
setControlBarVisible(false);
1156
void PlasmaApp::setControlBarVisible(bool visible)
1158
if (!m_controlBar || m_controlBar->isVisible() == visible) {
1163
destroyUnHideTrigger();
1164
Plasma::WindowEffects::slideWindow(m_controlBar, m_controlBar->location());
1165
m_controlBar->setWindowFlags(m_mainView->windowFlags() | Qt::FramelessWindowHint);
1166
m_controlBar->setFrameShape(QFrame::NoFrame);
1167
m_controlBar->show();
1168
KWindowSystem::setOnAllDesktops(m_controlBar->winId(), m_isDesktop);
1169
unsigned long state = NET::Sticky | NET::StaysOnTop | NET::KeepAbove;
1170
KWindowSystem::setState(m_controlBar->effectiveWinId(), state);
1171
KWindowSystem::setType(m_controlBar->effectiveWinId(), NET::Dock);
1173
if (m_shadowWindow && m_shadowWindow->isValid()) {
1174
Plasma::WindowEffects::slideWindow(m_shadowWindow, m_controlBar->location());
1175
m_shadowWindow->show();
1176
if (!m_autoHideControlBar) {
1177
KWindowSystem::setState(m_shadowWindow->winId(), NET::KeepBelow);
1179
KWindowSystem::setOnAllDesktops(m_shadowWindow->winId(), true);
1181
} else if (!m_autoHideControlBar) {
1182
Plasma::WindowEffects::slideWindow(m_controlBar, m_controlBar->location());
1183
m_controlBar->hide();
1184
createUnhideTrigger();
1186
if (m_shadowWindow) {
1187
Plasma::WindowEffects::slideWindow(m_shadowWindow, m_controlBar->location());
1188
m_shadowWindow->hide();
1193
void PlasmaApp::toggleControlBarVisibility()
1195
setControlBarVisible(!m_controlBar->isVisible());
1198
void PlasmaApp::unhideHintMousePoll()
1201
QPoint mousePos = QCursor::pos();
1202
m_glowBar->updateStrength(mousePos);
1204
if (!m_unhideTriggerGeom.contains(mousePos)) {
1205
//kDebug() << "hide the glow";
1206
if (m_mousePollTimer) {
1207
m_mousePollTimer->stop();
1208
disconnect(m_mousePollTimer, SIGNAL(timeout()), this, SLOT(unhideHintMousePoll()));
1213
XMoveResizeWindow(QX11Info::display(), m_unhideTrigger, m_unhideTriggerGeom.x(), m_unhideTriggerGeom.y(), m_unhideTriggerGeom.width(), m_unhideTriggerGeom.height());
1215
m_unHideTimer->start(0);
1220
void PlasmaApp::createUnhideTrigger()
1223
//kDebug() << m_unhideTrigger << None;
1224
if (!m_autoHideControlBar || m_unhideTrigger != None || !m_controlBar || m_controlBar->isVisible()) {
1228
int actualWidth = 1;
1229
int actualHeight = 1;
1230
int triggerWidth = 1;
1231
int triggerHeight = 1;
1233
if (KWindowSystem::compositingActive()) {
1238
QPoint actualTriggerPoint;
1239
QPoint triggerPoint = actualTriggerPoint = QPoint(qMax(0, m_controlBar->pos().x()), qMax(0, m_controlBar->pos().y()));
1241
switch (m_controlBar->location()) {
1242
case Plasma::TopEdge:
1243
actualWidth = triggerWidth = m_controlBar->width() - 1;
1245
triggerPoint += QPoint(1, 0);
1248
case Plasma::BottomEdge:
1249
actualWidth = triggerWidth = m_controlBar->width() - 1;
1250
actualTriggerPoint = triggerPoint = m_controlBar->geometry().bottomLeft() + QPoint(1, 0);
1253
case Plasma::RightEdge:
1254
actualHeight = triggerHeight = m_controlBar->height() - 1;
1255
actualTriggerPoint = triggerPoint = m_controlBar->geometry().topRight() + QPoint(0, 1);
1258
case Plasma::LeftEdge:
1259
actualHeight = triggerHeight = m_controlBar->height() - 1;
1260
triggerPoint += QPoint(0, -1);
1264
// no hiding unless we're on an edge.
1270
XSetWindowAttributes attributes;
1271
attributes.override_redirect = True;
1272
attributes.event_mask = EnterWindowMask;
1275
attributes.event_mask = EnterWindowMask | LeaveWindowMask | PointerMotionMask |
1276
KeyPressMask | KeyPressMask | ButtonPressMask |
1277
ButtonReleaseMask | ButtonMotionMask |
1278
KeymapStateMask | VisibilityChangeMask |
1279
StructureNotifyMask | ResizeRedirectMask |
1280
SubstructureNotifyMask |
1281
SubstructureRedirectMask | FocusChangeMask |
1282
PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask;
1284
unsigned long valuemask = CWOverrideRedirect | CWEventMask;
1285
m_unhideTrigger = XCreateWindow(QX11Info::display(), QX11Info::appRootWindow(),
1286
triggerPoint.x(), triggerPoint.y(), triggerWidth, triggerHeight,
1287
0, CopyFromParent, InputOnly, CopyFromParent,
1288
valuemask, &attributes);
1290
XMapWindow(QX11Info::display(), m_unhideTrigger);
1291
m_unhideTriggerGeom = QRect(triggerPoint, QSize(triggerWidth, triggerHeight));
1292
m_triggerZone = QRect(actualTriggerPoint, QSize(actualWidth, actualHeight));
1296
void PlasmaApp::destroyUnHideTrigger()
1299
if (m_unhideTrigger != None) {
1300
XDestroyWindow(QX11Info::display(), m_unhideTrigger);
1301
m_unhideTrigger = None;
1302
m_triggerZone = m_unhideTriggerGeom = QRect();
1307
#include "plasmaapp.moc"