delay a few things on startup, such as setting the visibility mode, which ensures...
[personal-kdebase.git] / workspace / plasma / shells / desktop / plasmaapp.cpp
blobf77c40f4ef3a67f4c43c2beb1cebe260e1a9d1ad
1 /*
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"
22 #ifdef Q_WS_WIN
23 #ifdef _WIN32_WINNT
24 #undef _WIN32_WINNT
25 #endif
26 #define _WIN32_WINNT 0x0500
27 #include <windows.h>
28 #endif
30 #include <unistd.h>
32 #ifndef _SC_PHYS_PAGES
33 #ifdef Q_OS_FREEBSD
34 #include <sys/types.h>
35 #include <sys/sysctl.h>
36 #endif
38 #ifdef Q_OS_NETBSD
39 #include <sys/param.h>
40 #include <sys/sysctl.h>
41 #endif
42 #endif
44 #include <QApplication>
45 #include <QDesktopWidget>
46 #include <QPixmapCache>
47 #include <QTimer>
48 #include <QtDBus/QtDBus>
50 #include <KAction>
51 #include <KCrash>
52 #include <KDebug>
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>
71 #ifdef Q_WS_X11
72 #include <X11/Xlib.h>
73 #include <X11/extensions/Xrender.h>
75 Display* dpy = 0;
76 Colormap colormap = 0;
77 Visual *visual = 0;
78 #endif
80 void checkComposite()
82 #ifdef Q_WS_X11
83 dpy = XOpenDisplay(0); // open default display
84 if (!dpy) {
85 kError() << "Cannot connect to the X server" << endl;
86 return;
88 if( qgetenv( "KDE_SKIP_ARGB_VISUALS" ) == "1" )
89 return;
91 int screen = DefaultScreen(dpy);
92 int eventBase, errorBase;
94 if (XRenderQueryExtension(dpy, &eventBase, &errorBase)) {
95 int nvi;
96 XVisualInfo templ;
97 templ.screen = screen;
98 templ.depth = 32;
99 templ.c_class = TrueColor;
100 XVisualInfo *xvi = XGetVisualInfo(dpy,
101 VisualScreenMask | VisualDepthMask | VisualClassMask,
102 &templ, &nvi);
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);
108 break;
111 XFree(xvi);
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;
117 #endif
120 PlasmaApp* PlasmaApp::self()
122 if (!kapp) {
123 checkComposite();
124 #ifdef Q_WS_X11
125 return new PlasmaApp(dpy, visual ? Qt::HANDLE(visual) : 0, colormap ? Qt::HANDLE(colormap) : 0);
126 #else
127 return new PlasmaApp(0, 0, 0);
128 #endif
131 return qobject_cast<PlasmaApp*>(kapp);
134 PlasmaApp::PlasmaApp(Display* display, Qt::HANDLE visual, Qt::HANDLE colormap)
135 #ifdef Q_WS_X11
136 : KUniqueApplication(display, visual, colormap),
137 #else
138 : KUniqueApplication(),
139 #endif
140 m_corona(0),
141 m_appletBrowser(0),
142 m_zoomLevel(Plasma::DesktopZoom),
143 m_panelHidden(0)
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.
156 int cacheSize = 0;
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;
171 #else
172 #ifdef Q_OS_FREEBSD
173 int sysctlbuf[2];
174 size_t size = sizeof(sysctlbuf);
175 int memorySize;
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];
186 #endif
187 #ifdef Q_OS_NETBSD
188 size_t memorySize;
189 size_t len;
190 static int mib[] = { CTL_HW, HW_PHYSMEM };
192 len = sizeof(memorySize);
193 sysctl(mib, 2, &memorySize, &len, NULL, 0);
194 memorySize /= 1024;
195 #endif
196 #ifdef Q_WS_WIN
197 size_t memorySize;
199 MEMORYSTATUSEX statex;
200 statex.dwLength = sizeof (statex);
201 GlobalMemoryStatusEx (&statex);
203 memorySize = (statex.ullTotalPhys/1024) + (statex.ullTotalPageFile/1024);
204 #endif
205 // If you have no suitable sysconf() interface and are not FreeBSD,
206 // then you are out of luck and get a compile error.
207 #endif
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()
236 #ifdef Q_WS_X11
237 Atom atoms[5];
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;
247 #endif
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.
255 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!
261 notifyStartup(true);
264 void PlasmaApp::cleanup()
266 if (m_corona) {
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;
288 m_desktops.clear();
289 qDeleteAll(desktops);
291 QList<PanelView*> panels = m_panels;
292 m_panels.clear();
293 qDeleteAll(panels);
295 QHash<Plasma::Containment *, BackgroundDialog *> dialogs = m_configDialogs;
296 m_configDialogs.clear();
297 qDeleteAll(dialogs);
299 delete m_corona;
301 //TODO: This manual sync() should not be necessary. Remove it when
302 // KConfig was fixed
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);
324 if (!view) {
325 kWarning() << "we don't have a DesktopView for the current screen!" << currentScreen << currentDesktop;
326 return;
329 view->toggleDashboard();
332 void PlasmaApp::panelHidden(bool hidden)
334 if (hidden) {
335 ++m_panelHidden;
336 //kDebug() << "panel hidden" << m_panelHidden;
337 } else {
338 --m_panelHidden;
339 if (m_panelHidden < 0) {
340 kDebug() << "panelHidden(false) called too many times!";
341 m_panelHidden = 0;
343 //kDebug() << "panel unhidden" << m_panelHidden;
347 Plasma::ZoomLevel PlasmaApp::desktopZoomLevel() const
349 return m_zoomLevel;
352 QList<PanelView*> PlasmaApp::panelViews() const
354 return m_panels;
357 void PlasmaApp::compositingChanged()
359 #ifdef Q_WS_X11
360 foreach (PanelView *panel, m_panels) {
361 panel->recreateUnhideTrigger();
363 #endif
366 #ifdef Q_WS_X11
367 PanelView *PlasmaApp::findPanelForTrigger(WId trigger) const
369 foreach (PanelView *panel, m_panels) {
370 if (panel->unhideTrigger() == trigger) {
371 return panel;
375 return 0;
378 bool PlasmaApp::x11EventFilter(XEvent *event)
380 if (m_panelHidden &&
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;
395 if (!dndEnter) {
396 dndPosition = event->xclient.message_type == m_XdndPositionAtom;
397 if (!dndPosition) {
398 //kDebug() << "FAIL!";
399 return KUniqueApplication::x11EventFilter(event);
401 } else {
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");
408 if (panel) {
409 if (dndEnter || dndPosition) {
410 QPoint p;
412 const unsigned long *l = (const unsigned long *)event->xclient.data.l;
413 if (dndPosition) {
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;
427 } else {
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) {
441 panel->unhintHide();
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));
449 return true;
453 return KUniqueApplication::x11EventFilter(event);
455 #endif
457 void PlasmaApp::screenRemoved(int id)
459 kDebug() << 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);
468 it.remove();
469 delete view;
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) {
481 delete panel;
482 it.remove();
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)) {
493 return view;
497 return 0;
500 Plasma::Corona* PlasmaApp::corona()
502 if (!m_corona) {
503 QTime t;
504 t.start();
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*)));
515 m_corona = c;
516 c->setItemIndexMethod(QGraphicsScene::NoIndex);
517 c->initializeLayout();
518 c->checkScreens();
519 kDebug() << " ------------------------------------------>" << t.elapsed();
522 return m_corona;
525 void PlasmaApp::showAppletBrowser()
527 Plasma::Containment *containment = dynamic_cast<Plasma::Containment *>(sender());
529 if (!containment) {
530 return;
533 foreach (DesktopView *view, m_desktops) {
534 if (view->containment() == containment && view->isDashboardVisible()) {
535 // the dashboard will pick this one up!
536 return;
540 showAppletBrowser(containment);
543 void PlasmaApp::showAppletBrowser(Plasma::Containment *containment)
545 if (!containment) {
546 return;
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()));
557 } else {
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()
568 m_appletBrowser = 0;
571 bool PlasmaApp::hasComposite()
573 // return true;
574 #ifdef Q_WS_X11
575 return colormap && KWindowSystem::compositingActive();
576 #else
577 return false;
578 #endif
581 void PlasmaApp::notifyStartup(bool completed)
583 org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
585 const QString startupID("workspace desktop");
586 if (completed) {
587 ksmserver.resumeStartup(startupID);
588 } else {
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);
607 WId viewWindow = 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;
615 panelView->show();
616 break;
618 default:
619 if (containment->screen() > -1 &&
620 containment->screen() < Kephal::ScreenUtils::numScreens()) {
621 DesktopView *view = viewForScreen(containment->screen(), containment->desktop());
622 if (view) {
623 kDebug() << "had a view for" << containment->screen() << containment->desktop();
624 // we already have a view for this screen
625 return;
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();
635 if (m_corona) {
636 connect(m_corona, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)),
637 view, SLOT(screenOwnerChanged(int,int,Plasma::Containment*)));
640 m_desktops.append(view);
641 view->show();
643 break;
646 #ifdef Q_WS_X11
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
650 if (viewWindow) {
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);
656 #endif
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();
682 } else {
683 const QSize resolution = QApplication::desktop()->screenGeometry(containment->screen()).size();
684 Plasma::View *view = viewForScreen(containment->screen(), containment->desktop());
686 if (!view) {
687 view = viewForScreen(desktop()->screenNumber(QCursor::pos()), containment->desktop());
689 if (!view) {
690 if (m_desktops.count() < 1) {
691 return;
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);
719 return;
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) {
732 zoomIn(containment);
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;
761 bool zoomIn = true;
762 bool zoomOut = true;
763 bool addSibling = isMutable;
764 bool lock = false;
765 bool remove = false;
767 if (m_zoomLevel == Plasma::GroupZoom) {
768 m_zoomLevel = Plasma::DesktopZoom;
769 containment->closeToolBox();
770 addSibling = false;
771 zoomIn = false;
772 lock = true;
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) {
781 continue;
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;
796 bool zoomIn = true;
797 bool zoomOut = true;
798 bool addSibling = isMutable && true;
799 bool lock = false;
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;
806 zoomOut = false;
807 addWidgets = false;
810 //make sure everybody can zoom out again
811 foreach (Plasma::Containment *c, m_corona->containments()) {
812 if (c->containmentType() == Plasma::Containment::PanelContainment) {
813 continue;
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()) {
834 it.next();
835 if (it.value() == (BackgroundDialog*)dialog) {
836 it.remove();
841 #include "plasmaapp.moc"