2 * Copyright 2006 Aaron Seigo <aseigo@kde.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2, or
7 * (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 "plasmaapp.h"
26 #define _WIN32_WINNT 0x0500
32 #ifndef _SC_PHYS_PAGES
34 #include <sys/types.h>
35 #include <sys/sysctl.h>
39 #include <sys/param.h>
40 #include <sys/sysctl.h>
44 #include <QApplication>
45 #include <QDesktopWidget>
46 #include <QPixmapCache>
48 #include <QtDBus/QtDBus>
53 #include <KCmdLineArgs>
54 #include <KWindowSystem>
56 #include <ksmserver_interface.h>
58 #include <Plasma/Containment>
59 #include <Plasma/Theme>
61 #include "appletbrowser.h"
62 #include "appadaptor.h"
63 #include "backgrounddialog.h"
64 #include "desktopcorona.h"
65 #include "desktopview.h"
66 #include "panelview.h"
67 #include "plasma-shell-desktop.h"
69 #include <kephal/screens.h>
73 #include <X11/extensions/Xrender.h>
76 Colormap colormap
= 0;
83 dpy
= XOpenDisplay(0); // open default display
85 kError() << "Cannot connect to the X server" << endl
;
88 if( qgetenv( "KDE_SKIP_ARGB_VISUALS" ) == "1" )
91 int screen
= DefaultScreen(dpy
);
92 int eventBase
, errorBase
;
94 if (XRenderQueryExtension(dpy
, &eventBase
, &errorBase
)) {
97 templ
.screen
= screen
;
99 templ
.c_class
= TrueColor
;
100 XVisualInfo
*xvi
= XGetVisualInfo(dpy
,
101 VisualScreenMask
| VisualDepthMask
| VisualClassMask
,
103 for (int i
= 0; i
< nvi
; ++i
) {
104 XRenderPictFormat
*format
= XRenderFindVisualFormat(dpy
, xvi
[i
].visual
);
105 if (format
->type
== PictTypeDirect
&& format
->direct
.alphaMask
) {
106 visual
= xvi
[i
].visual
;
107 colormap
= XCreateColormap(dpy
, RootWindow(dpy
, screen
), visual
, AllocNone
);
114 kDebug() << (colormap
? "Plasma has an argb visual" : "Plasma lacks an argb visual") << visual
<< colormap
;
115 kDebug() << ((KWindowSystem::compositingActive() && colormap
) ? "Plasma can use COMPOSITE for effects"
116 : "Plasma is COMPOSITE-less") << "on" << dpy
;
120 PlasmaApp
* PlasmaApp::self()
125 return new PlasmaApp(dpy
, visual
? Qt::HANDLE(visual
) : 0, colormap
? Qt::HANDLE(colormap
) : 0);
127 return new PlasmaApp(0, 0, 0);
131 return qobject_cast
<PlasmaApp
*>(kapp
);
134 PlasmaApp::PlasmaApp(Display
* display
, Qt::HANDLE visual
, Qt::HANDLE colormap
)
136 : KUniqueApplication(display
, visual
, colormap
),
138 : KUniqueApplication(),
142 m_zoomLevel(Plasma::DesktopZoom
),
145 KGlobal::locale()->insertCatalog("libplasma");
146 KGlobal::locale()->insertCatalog("plasma-shells-common");
147 KCrash::setFlags(KCrash::AutoRestart
);
149 new PlasmaAppAdaptor(this);
150 QDBusConnection::sessionBus().registerObject("/App", this);
151 notifyStartup(false);
153 // Enlarge application pixmap cache
154 // Calculate the size required to hold background pixmaps for all screens.
155 // Add 10% so that other (smaller) pixmaps can also be cached.
157 for (int i
= 0; i
< Kephal::ScreenUtils::numScreens(); i
++) {
158 QSize size
= Kephal::ScreenUtils::screenSize(i
);
159 cacheSize
+= 4 * size
.width() * size
.height() / 1024;
161 cacheSize
+= cacheSize
/ 10;
163 // Calculate the size of physical system memory; _SC_PHYS_PAGES *
164 // _SC_PAGESIZE is documented to be able to overflow 32-bit integers,
165 // so apply a 10-bit shift. FreeBSD 6-STABLE doesn't have _SC_PHYS_PAGES
166 // (it is documented in FreeBSD 7-STABLE as "Solaris and Linux extension")
167 // so use sysctl in those cases.
168 #if defined(_SC_PHYS_PAGES)
169 int memorySize
= sysconf(_SC_PHYS_PAGES
);
170 memorySize
*= sysconf(_SC_PAGESIZE
) / 1024;
174 size_t size
= sizeof(sysctlbuf
);
176 // This could actually use hw.physmem instead, but I can't find
177 // reliable documentation on how to read the value (which may
178 // not fit in a 32 bit integer).
179 if (!sysctlbyname("vm.stats.vm.v_page_size", sysctlbuf
, &size
, NULL
, 0)) {
180 memorySize
= sysctlbuf
[0] / 1024;
181 size
= sizeof(sysctlbuf
);
182 if (!sysctlbyname("vm.stats.vm.v_page_count", sysctlbuf
, &size
, NULL
, 0)) {
183 memorySize
*= sysctlbuf
[0];
190 static int mib
[] = { CTL_HW
, HW_PHYSMEM
};
192 len
= sizeof(memorySize
);
193 sysctl(mib
, 2, &memorySize
, &len
, NULL
, 0);
199 MEMORYSTATUSEX statex
;
200 statex
.dwLength
= sizeof (statex
);
201 GlobalMemoryStatusEx (&statex
);
203 memorySize
= (statex
.ullTotalPhys
/1024) + (statex
.ullTotalPageFile
/1024);
205 // If you have no suitable sysconf() interface and are not FreeBSD,
206 // then you are out of luck and get a compile error.
209 // Increase the pixmap cache size to 1% of system memory if it isn't already
210 // larger so as to maximize cache usage. 1% of 1GB ~= 10MB.
211 if (cacheSize
< memorySize
/ 100) {
212 cacheSize
= memorySize
/ 100;
215 kDebug() << "Setting the pixmap cache size to" << cacheSize
<< "kilobytes";
216 QPixmapCache::setCacheLimit(cacheSize
);
218 //TODO: Make the shortcut configurable
219 KAction
*showAction
= new KAction( this );
220 showAction
->setText( i18n( "Show Dashboard" ) );
221 showAction
->setObjectName( "Show Dashboard" ); // NO I18N
222 showAction
->setGlobalShortcut( KShortcut( Qt::CTRL
+ Qt::Key_F12
) );
223 connect( showAction
, SIGNAL( triggered() ), this, SLOT( toggleDashboard() ) );
225 connect(this, SIGNAL(aboutToQuit()), this, SLOT(cleanup()));
226 QTimer::singleShot(0, this, SLOT(setupDesktop()));
229 PlasmaApp::~PlasmaApp()
231 delete m_appletBrowser
;
234 void PlasmaApp::setupDesktop()
238 const char *atomNames
[] = {"XdndAware", "XdndEnter", "XdndFinished", "XdndPosition", "XdndStatus"};
239 XInternAtoms(QX11Info::display(), const_cast<char **>(atomNames
), 5, False
, atoms
);
240 m_XdndAwareAtom
= atoms
[0];
241 m_XdndEnterAtom
= atoms
[1];
242 m_XdndFinishedAtom
= atoms
[2];
243 m_XdndPositionAtom
= atoms
[3];
244 m_XdndStatusAtom
= atoms
[4];
245 const int xdndversion
= 5;
246 m_XdndVersionAtom
= (Atom
)xdndversion
;
249 // intialize the default theme and set the font
250 Plasma::Theme
*theme
= Plasma::Theme::defaultTheme();
251 theme
->setFont(AppSettings::desktopFont());
252 connect(theme
, SIGNAL(themeChanged()), this, SLOT(compositingChanged()));
254 // this line initializes the corona.
257 Kephal::Screens
*screens
= Kephal::Screens::self();
258 connect(screens
, SIGNAL(screenRemoved(int)), SLOT(screenRemoved(int)));
260 // and now, let everyone know we're ready!
264 void PlasmaApp::cleanup()
267 m_corona
->saveLayout();
270 // save the mapping of Views to Containments at the moment
271 // of application exit so we can restore that when we start again.
272 KConfigGroup
viewIds(KGlobal::config(), "ViewIds");
273 viewIds
.deleteGroup();
275 foreach (PanelView
*v
, m_panels
) {
276 if (v
->containment()) {
277 viewIds
.writeEntry(QString::number(v
->containment()->id()), v
->id());
281 foreach (DesktopView
*v
, m_desktops
) {
282 if (v
->containment()) {
283 viewIds
.writeEntry(QString::number(v
->containment()->id()), v
->id());
287 QList
<DesktopView
*> desktops
= m_desktops
;
289 qDeleteAll(desktops
);
291 QList
<PanelView
*> panels
= m_panels
;
295 QHash
<Plasma::Containment
*, BackgroundDialog
*> dialogs
= m_configDialogs
;
296 m_configDialogs
.clear();
301 //TODO: This manual sync() should not be necessary. Remove it when
303 KGlobal::config()->sync();
306 void PlasmaApp::syncConfig()
308 KGlobal::config()->sync();
311 void PlasmaApp::toggleDashboard()
313 int currentScreen
= 0;
314 if (Kephal::ScreenUtils::numScreens() > 1) {
315 currentScreen
= Kephal::ScreenUtils::screenId(QCursor::pos());
318 int currentDesktop
= -1;
319 if (AppSettings::perVirtualDesktopViews()) {
320 currentDesktop
= KWindowSystem::currentDesktop();
323 DesktopView
*view
= viewForScreen(currentScreen
, currentDesktop
);
325 kWarning() << "we don't have a DesktopView for the current screen!" << currentScreen
<< currentDesktop
;
329 view
->toggleDashboard();
332 void PlasmaApp::panelHidden(bool hidden
)
336 //kDebug() << "panel hidden" << m_panelHidden;
339 if (m_panelHidden
< 0) {
340 kDebug() << "panelHidden(false) called too many times!";
343 //kDebug() << "panel unhidden" << m_panelHidden;
347 Plasma::ZoomLevel
PlasmaApp::desktopZoomLevel() const
352 QList
<PanelView
*> PlasmaApp::panelViews() const
357 void PlasmaApp::compositingChanged()
360 foreach (PanelView
*panel
, m_panels
) {
361 panel
->recreateUnhideTrigger();
367 PanelView
*PlasmaApp::findPanelForTrigger(WId trigger
) const
369 foreach (PanelView
*panel
, m_panels
) {
370 if (panel
->unhideTrigger() == trigger
) {
378 bool PlasmaApp::x11EventFilter(XEvent
*event
)
381 (event
->type
== ClientMessage
||
382 (event
->xany
.send_event
!= True
&& (event
->type
== EnterNotify
||
383 event
->type
== MotionNotify
)))) {
386 if (event->type == ClientMessage) {
387 kDebug() << "client message with" << event->xclient.message_type << m_XdndEnterAtom << event->xcrossing.window;
391 bool dndEnter
= false;
392 bool dndPosition
= false;
393 if (event
->type
== ClientMessage
) {
394 dndEnter
= event
->xclient
.message_type
== m_XdndEnterAtom
;
396 dndPosition
= event
->xclient
.message_type
== m_XdndPositionAtom
;
398 //kDebug() << "FAIL!";
399 return KUniqueApplication::x11EventFilter(event
);
402 //kDebug() << "on enter" << event->xclient.data.l[0];
406 PanelView
*panel
= findPanelForTrigger(event
->xcrossing
.window
);
407 //kDebug() << "panel?" << panel << ((dndEnter || dndPosition) ? "Drag and drop op" : "Mouse move op");
409 if (dndEnter
|| dndPosition
) {
412 const unsigned long *l
= (const unsigned long *)event
->xclient
.data
.l
;
414 p
= QPoint((l
[2] & 0xffff0000) >> 16, l
[2] & 0x0000ffff);
417 XClientMessageEvent response
;
418 response
.type
= ClientMessage
;
419 response
.window
= l
[0];
420 response
.format
= 32;
421 response
.data
.l
[0] = panel
->winId(); //event->xcrossing.window;
423 if (panel
->hintOrUnhide(p
, true)) {
424 response
.message_type
= m_XdndFinishedAtom
;
425 response
.data
.l
[1] = 0; // flags
426 response
.data
.l
[2] = XNone
;
428 response
.message_type
= m_XdndStatusAtom
;
429 response
.data
.l
[1] = 0; // flags
430 response
.data
.l
[2] = 0; // x, y
431 response
.data
.l
[3] = 0; // w, h
432 response
.data
.l
[4] = 0; // action
435 XSendEvent(QX11Info::display(), l
[0], False
, NoEventMask
, (XEvent
*)&response
);
436 } else if (event
->type
== EnterNotify
) {
437 panel
->hintOrUnhide(QPoint(-1, -1));
438 //kDebug() << "entry";
439 //FIXME: this if it was possible to avoid the polling
440 /*} else if (event->type == LeaveNotify) {
443 } else if (event
->type
== MotionNotify
) {
444 XMotionEvent
*motion
= (XMotionEvent
*)event
;
445 //kDebug() << "motion" << motion->x << motion->y << panel->location();
446 panel
->hintOrUnhide(QPoint(motion
->x_root
, motion
->y_root
));
453 return KUniqueApplication::x11EventFilter(event
);
457 void PlasmaApp::screenRemoved(int id
)
460 QMutableListIterator
<DesktopView
*> it(m_desktops
);
461 while (it
.hasNext()) {
462 DesktopView
*view
= it
.next();
463 if (view
->screen() == id
) {
464 // the screen was removed, so we'll destroy the
465 // corresponding view
466 kDebug() << "removing the view for screen" << id
;
467 view
->setContainment(0);
474 TODO: remove panels when screen goes away.
475 first, however, we need to be able to reserve and restore the panelsettings
476 even when the view itself goes away
477 QMutableListIterator<PanelView*> it(m_panels);
478 while (it.hasNext()) {
479 PanelView *panel = it.next();
480 if (panel->screen() == i) {
488 DesktopView
* PlasmaApp::viewForScreen(int screen
, int desktop
) const
490 foreach (DesktopView
*view
, m_desktops
) {
491 //kDebug() << "comparing" << view->screen() << screen;
492 if (view
->screen() == screen
&& (desktop
< 0 || view
->desktop() == desktop
)) {
500 Plasma::Corona
* PlasmaApp::corona()
505 DesktopCorona
*c
= new DesktopCorona(this);
506 connect(c
, SIGNAL(containmentAdded(Plasma::Containment
*)),
507 this, SLOT(containmentAdded(Plasma::Containment
*)));
508 connect(c
, SIGNAL(configSynced()), this, SLOT(syncConfig()));
510 foreach (DesktopView
*view
, m_desktops
) {
511 connect(c
, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment
*)),
512 view
, SLOT(screenOwnerChanged(int,int,Plasma::Containment
*)));
516 c
->setItemIndexMethod(QGraphicsScene::NoIndex
);
517 c
->initializeLayout();
519 kDebug() << " ------------------------------------------>" << t
.elapsed();
525 void PlasmaApp::showAppletBrowser()
527 Plasma::Containment
*containment
= dynamic_cast<Plasma::Containment
*>(sender());
533 foreach (DesktopView
*view
, m_desktops
) {
534 if (view
->containment() == containment
&& view
->isDashboardVisible()) {
535 // the dashboard will pick this one up!
540 showAppletBrowser(containment
);
543 void PlasmaApp::showAppletBrowser(Plasma::Containment
*containment
)
549 if (!m_appletBrowser
) {
550 m_appletBrowser
= new Plasma::AppletBrowser();
551 m_appletBrowser
->setContainment(containment
);
552 m_appletBrowser
->setApplication();
553 m_appletBrowser
->setAttribute(Qt::WA_DeleteOnClose
);
554 m_appletBrowser
->setWindowTitle(i18n("Add Widgets"));
555 m_appletBrowser
->setWindowIcon(KIcon("plasmagik"));
556 connect(m_appletBrowser
, SIGNAL(destroyed()), this, SLOT(appletBrowserDestroyed()));
558 m_appletBrowser
->setContainment(containment
);
561 KWindowSystem::setOnDesktop(m_appletBrowser
->winId(), KWindowSystem::currentDesktop());
562 m_appletBrowser
->show();
563 KWindowSystem::activateWindow(m_appletBrowser
->winId());
566 void PlasmaApp::appletBrowserDestroyed()
571 bool PlasmaApp::hasComposite()
575 return colormap
&& KWindowSystem::compositingActive();
581 void PlasmaApp::notifyStartup(bool completed
)
583 org::kde::KSMServerInterface
ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
585 const QString
startupID("workspace desktop");
587 ksmserver
.resumeStartup(startupID
);
589 ksmserver
.suspendStartup(startupID
);
593 void PlasmaApp::createView(Plasma::Containment
*containment
)
595 kDebug() << "Containment name:" << containment
->name()
596 << "| type" << containment
->containmentType()
597 << "| screen:" << containment
->screen()
598 << "| desktop:" << containment
->desktop()
599 << "| geometry:" << containment
->geometry()
600 << "| zValue:" << containment
->zValue();
602 // find the mapping of View to Containment, if any,
603 // so we can restore things on start.
604 KConfigGroup
viewIds(KGlobal::config(), "ViewIds");
605 int id
= viewIds
.readEntry(QString::number(containment
->id()), 0);
609 switch (containment
->containmentType()) {
610 case Plasma::Containment::PanelContainment
: {
611 PanelView
*panelView
= new PanelView(containment
, id
);
612 viewWindow
= panelView
->winId();
613 connect(panelView
, SIGNAL(destroyed(QObject
*)), this, SLOT(panelRemoved(QObject
*)));
614 m_panels
<< panelView
;
619 if (containment
->screen() > -1 &&
620 containment
->screen() < Kephal::ScreenUtils::numScreens()) {
621 DesktopView
*view
= viewForScreen(containment
->screen(), containment
->desktop());
623 kDebug() << "had a view for" << containment
->screen() << containment
->desktop();
624 // we already have a view for this screen
628 kDebug() << "creating a new view for" << containment
->screen() << containment
->desktop()
629 << "and we have" << Kephal::ScreenUtils::numScreens() << "screens";
632 // we have a new screen. neat.
633 view
= new DesktopView(containment
, id
, 0);
634 viewWindow
= view
->winId();
636 connect(m_corona
, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment
*)),
637 view
, SLOT(screenOwnerChanged(int,int,Plasma::Containment
*)));
640 m_desktops
.append(view
);
647 //FIXME: if argb visuals enabled Qt will always set WM_CLASS as "qt-subapplication" no matter what
648 //the application name is we set the proper XClassHint here, hopefully won't be necessary anymore when
649 //qapplication will manage apps with argvisuals in a better way
651 XClassHint classHint
;
652 classHint
.res_name
= const_cast<char*>("Plasma");
653 classHint
.res_class
= const_cast<char*>("Plasma");
654 XSetClassHint(QX11Info::display(), viewWindow
, &classHint
);
659 void PlasmaApp::containmentAdded(Plasma::Containment
*containment
)
661 createView(containment
);
662 disconnect(containment
, 0, this, 0);
663 connect(containment
, SIGNAL(zoomRequested(Plasma::Containment
*,Plasma::ZoomDirection
)),
664 this, SLOT(zoom(Plasma::Containment
*,Plasma::ZoomDirection
)));
665 connect(containment
, SIGNAL(showAddWidgetsInterface(QPointF
)), this, SLOT(showAppletBrowser()));
666 connect(containment
, SIGNAL(configureRequested(Plasma::Containment
*)),
667 this, SLOT(configureContainment(Plasma::Containment
*)));
669 if (containment
->containmentType() != Plasma::Containment::PanelContainment
) {
670 connect(containment
, SIGNAL(addSiblingContainment(Plasma::Containment
*)),
671 this, SLOT(addContainment(Plasma::Containment
*)));
675 void PlasmaApp::configureContainment(Plasma::Containment
*containment
)
677 BackgroundDialog
*configDialog
= 0;
679 if (m_configDialogs
.contains(containment
)) {
680 configDialog
= m_configDialogs
.value(containment
);
681 configDialog
->reloadConfig();
683 const QSize resolution
= QApplication::desktop()->screenGeometry(containment
->screen()).size();
684 Plasma::View
*view
= viewForScreen(containment
->screen(), containment
->desktop());
687 view
= viewForScreen(desktop()->screenNumber(QCursor::pos()), containment
->desktop());
690 if (m_desktops
.count() < 1) {
694 view
= m_desktops
.at(0);
699 configDialog
= new BackgroundDialog(resolution
, containment
, view
);
700 configDialog
->setAttribute(Qt::WA_DeleteOnClose
);
701 connect(configDialog
, SIGNAL(destroyed(QObject
*)),
702 this, SLOT(configDialogRemoved(QObject
*)));
705 configDialog
->show();
706 KWindowSystem::setOnDesktop(configDialog
->winId(), KWindowSystem::currentDesktop());
707 KWindowSystem::activateWindow(configDialog
->winId());
710 void PlasmaApp::addContainment(Plasma::Containment
*fromContainment
)
712 QString plugin
= fromContainment
? fromContainment
->pluginName() : QString();
713 Plasma::Containment
*c
= m_corona
->addContainment(plugin
);
715 if (c
&& fromContainment
) {
716 foreach (DesktopView
*view
, m_desktops
) {
717 if (view
->containment() == c
){
718 view
->setContainment(c
);
723 // if we reach here, the containment isn't going to be taken over by the view,
724 // so we're going to resize it ourselves!
725 c
->resize(fromContainment
->size());
729 void PlasmaApp::zoom(Plasma::Containment
*containment
, Plasma::ZoomDirection direction
)
731 if (direction
== Plasma::ZoomIn
) {
733 foreach (DesktopView
*view
, m_desktops
) {
734 view
->zoomIn(m_zoomLevel
);
737 if (m_zoomLevel
== Plasma::DesktopZoom
) {
738 int currentDesktop
= -1;
739 if (AppSettings::perVirtualDesktopViews()) {
740 currentDesktop
= KWindowSystem::currentDesktop();
743 DesktopView
*view
= viewForScreen(desktop()->screenNumber(QCursor::pos()), currentDesktop
);
745 if (view
&& view
->containment() != containment
) {
746 // zooming in all the way, so lets swap containments about if need be
747 view
->setContainment(containment
);
750 } else if (direction
== Plasma::ZoomOut
) {
751 zoomOut(containment
);
752 foreach (DesktopView
*view
, m_desktops
) {
753 view
->zoomOut(m_zoomLevel
);
758 void PlasmaApp::zoomIn(Plasma::Containment
*containment
)
760 bool isMutable
= m_corona
->immutability() == Plasma::Mutable
;
763 bool addSibling
= isMutable
;
767 if (m_zoomLevel
== Plasma::GroupZoom
) {
768 m_zoomLevel
= Plasma::DesktopZoom
;
769 containment
->closeToolBox();
773 } else if (m_zoomLevel
== Plasma::OverviewZoom
) {
774 m_zoomLevel
= Plasma::GroupZoom
;
775 remove
= isMutable
&& true;
778 //make sure everybody can zoom out again
779 foreach (Plasma::Containment
*c
, m_corona
->containments()) {
780 if (c
->containmentType() == Plasma::Containment::PanelContainment
) {
784 c
->enableAction("zoom in", zoomIn
);
785 c
->enableAction("zoom out", zoomOut
);
786 c
->enableAction("add sibling containment", addSibling
);
787 c
->enableAction("lock widgets", lock
);
788 c
->enableAction("remove", remove
&& (c
->screen() == -1));
789 c
->enableAction("add widgets", isMutable
);
793 void PlasmaApp::zoomOut(Plasma::Containment
*)
795 bool isMutable
= m_corona
->immutability() == Plasma::Mutable
;
798 bool addSibling
= isMutable
&& true;
800 bool addWidgets
= isMutable
&& true;
802 if (m_zoomLevel
== Plasma::DesktopZoom
) {
803 m_zoomLevel
= Plasma::GroupZoom
;
804 } else if (m_zoomLevel
== Plasma::GroupZoom
) {
805 m_zoomLevel
= Plasma::OverviewZoom
;
810 //make sure everybody can zoom out again
811 foreach (Plasma::Containment
*c
, m_corona
->containments()) {
812 if (c
->containmentType() == Plasma::Containment::PanelContainment
) {
816 c
->enableAction("zoom in", zoomIn
);
817 c
->enableAction("zoom out", zoomOut
);
818 c
->enableAction("add sibling containment", addSibling
);
819 c
->enableAction("lock widgets", lock
);
820 c
->enableAction("remove", isMutable
&& c
->screen() == -1);
821 c
->enableAction("add widgets", addWidgets
);
825 void PlasmaApp::panelRemoved(QObject
* panel
)
827 m_panels
.removeAll((PanelView
*)panel
);
830 void PlasmaApp::configDialogRemoved(QObject
* dialog
)
832 QMutableHashIterator
<Plasma::Containment
*, BackgroundDialog
*> it(m_configDialogs
);
833 while (it
.hasNext()) {
835 if (it
.value() == (BackgroundDialog
*)dialog
) {
841 #include "plasmaapp.moc"