/* * Copyright 2006 Aaron Seigo * Copyright 2010 Chani Armitage * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "plasmaapp.h" #include #ifndef _SC_PHYS_PAGES #if defined(Q_OS_FREEBSD) || defined(Q_OS_DRAGONFLY) #include #include #endif #ifdef Q_OS_NETBSD #include #include #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "appadaptor.h" #include "controllerwindow.h" #include "checkbox.h" #include "desktopcorona.h" #include "desktopview.h" #include "interactiveconsole.h" #include "panelshadows.h" #include "panelview.h" #include "plasma-shell-desktop.h" #include "toolbutton.h" #include "klistconfirmationdialog.h" #include "supportinformation.h" #ifdef Q_WS_X11 #include #include #endif extern QString plasmaLocale; PlasmaApp* PlasmaApp::self() { if (!kapp) { return new PlasmaApp(); } return qobject_cast(kapp); } PlasmaApp::PlasmaApp() : KUniqueApplication(), m_corona(0), m_panelHidden(0), m_mapper(new QSignalMapper(this)), m_startupSuspendWaitCount(0), m_unlockCorona(false) { kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "plasma app ctor start" << "(line:" << __LINE__ << ")"; suspendStartup(true); if (KGlobalSettings::isMultiHead()) { KGlobal::locale()->setLanguage(plasmaLocale, KGlobal::config().data()); } KGlobal::locale()->insertCatalog("libplasma"); KGlobal::locale()->insertCatalog("plasmagenericshell"); KCrash::setFlags(KCrash::AutoRestart); m_panelViewCreationTimer.setSingleShot(true); m_panelViewCreationTimer.setInterval(0); m_desktopViewCreationTimer.setSingleShot(true); m_desktopViewCreationTimer.setInterval(0); new PlasmaAppAdaptor(this); QDBusConnection::sessionBus().registerObject("/App", this); // Enlarge application pixmap cache // Calculate the size required to hold background pixmaps for all screens. // Add 10% so that other (smaller) pixmaps can also be cached. int cacheSize = 0; if (KGlobalSettings::isMultiHead()) { int id = 0; #ifdef Q_WS_X11 Display *dpy = XOpenDisplay(NULL); if (dpy) { id = DefaultScreen(dpy); XCloseDisplay(dpy); } #endif const QSize size = QApplication::desktop()->screenGeometry(id).size(); cacheSize += 4 * size.width() * size.height() / 1024; } else { for (int i = 0; i < QApplication::desktop()->screenCount(); i++) { QSize size = QApplication::desktop()->screenGeometry(i).size(); cacheSize += 4 * size.width() * size.height() / 1024; } } cacheSize += cacheSize / 10; // Calculate the size of physical system memory; _SC_PHYS_PAGES * // _SC_PAGESIZE is documented to be able to overflow 32-bit integers, // so apply a 10-bit shift. FreeBSD 6-STABLE doesn't have _SC_PHYS_PAGES // (it is documented in FreeBSD 7-STABLE as "Solaris and Linux extension") // so use sysctl in those cases. #if defined(_SC_PHYS_PAGES) int memorySize = sysconf(_SC_PHYS_PAGES); memorySize *= sysconf(_SC_PAGESIZE) / 1024; #else #ifdef Q_OS_FREEBSD || defined(Q_OS_DRAGONFLY) int sysctlbuf[2]; size_t size = sizeof(sysctlbuf); int memorySize; // This could actually use hw.physmem instead, but I can't find // reliable documentation on how to read the value (which may // not fit in a 32 bit integer). if (!sysctlbyname("vm.stats.vm.v_page_size", sysctlbuf, &size, NULL, 0)) { memorySize = sysctlbuf[0] / 1024; size = sizeof(sysctlbuf); if (!sysctlbyname("vm.stats.vm.v_page_count", sysctlbuf, &size, NULL, 0)) { memorySize *= sysctlbuf[0]; } } #endif #ifdef Q_OS_NETBSD size_t memorySize; size_t len; static int mib[] = { CTL_HW, HW_PHYSMEM }; len = sizeof(memorySize); sysctl(mib, 2, &memorySize, &len, NULL, 0); memorySize /= 1024; #endif // If you have no suitable sysconf() interface and are not FreeBSD, // then you are out of luck and get a compile error. #endif // Increase the pixmap cache size to 1% of system memory if it isn't already // larger so as to maximize cache usage. 1% of 1GB ~= 10MB. if (cacheSize < memorySize / 100) { cacheSize = memorySize / 100; } kDebug() << "Setting the pixmap cache size to" << cacheSize << "kilobytes"; QPixmapCache::setCacheLimit(cacheSize); KGlobal::setAllowQuit(true); KGlobal::ref(); QTimer::singleShot(0, this, SLOT(setupDesktop())); kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "plasma app ctor end" << "(line:" << __LINE__ << ")"; } PlasmaApp::~PlasmaApp() { } void PlasmaApp::setupDesktop() { #ifdef Q_WS_X11 Atom atoms[5]; const char * const atomNames[] = {"XdndAware", "XdndEnter", "XdndFinished", "XdndPosition", "XdndStatus"}; XInternAtoms(QX11Info::display(), const_cast(atomNames), 5, False, atoms); m_XdndAwareAtom = atoms[0]; m_XdndEnterAtom = atoms[1]; m_XdndFinishedAtom = atoms[2]; m_XdndPositionAtom = atoms[3]; m_XdndStatusAtom = atoms[4]; const int xdndversion = 5; m_XdndVersionAtom = (Atom)xdndversion; #endif // intialize the default theme and set the font Plasma::Theme *theme = Plasma::Theme::defaultTheme(); theme->setFont(AppSettings::desktopFont()); m_panelShadows = new PanelShadows(); // this line initializes the corona. corona(); DesktopTracker *tracker = DesktopTracker::self(); connect(tracker, SIGNAL(screenRemoved(DesktopTracker::Screen)), SLOT(screenRemoved(DesktopTracker::Screen))); connect(tracker, SIGNAL(screenAdded(DesktopTracker::Screen)), SLOT(screenAdded(DesktopTracker::Screen))); // free the memory possibly occupied by the background image of the // root window - login managers will typically set one QPalette palette; palette.setColor(desktop()->backgroundRole(), Qt::black); desktop()->setPalette(palette); connect(this, SIGNAL(aboutToQuit()), this, SLOT(cleanup())); kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Plasma App SetupDesktop()" << "(line:" << __LINE__ << ")"; // now connect up the creation timers and start them to get the views created connect(&m_panelViewCreationTimer, SIGNAL(timeout()), this, SLOT(createWaitingPanels())); connect(&m_desktopViewCreationTimer, SIGNAL(timeout()), this, SLOT(createWaitingDesktops())); m_panelViewCreationTimer.start(); m_desktopViewCreationTimer.start(); } void PlasmaApp::quit() { if (m_corona) { cleanup(); KGlobal::deref(); } } void PlasmaApp::cleanup() { if (!m_corona) { return; } m_corona->saveLayout(KStandardDirs::locateLocal("config", "plasma-desktoprc")); // save the mapping of Views to Containments at the moment // of application exit so we can restore that when we start again. KConfigGroup viewIds(KGlobal::config(), "ViewIds"); viewIds.deleteGroup(); foreach (PanelView *v, m_panels) { if (v->containment()) { viewIds.writeEntry(QString::number(v->containment()->id()), v->id()); } } foreach (DesktopView *v, m_desktops) { if (v->containment()) { viewIds.writeEntry(QString::number(v->containment()->id()), v->id()); } } QList desktops = m_desktops; m_desktops.clear(); qDeleteAll(desktops); QList panels = m_panels; m_panels.clear(); qDeleteAll(panels); delete m_console.data(); delete m_corona; m_corona = 0; delete m_panelShadows; m_panelShadows = 0; //TODO: This manual sync() should not be necessary. Remove it when // KConfig was fixed KGlobal::config()->sync(); } void PlasmaApp::syncConfig() { KGlobal::config()->sync(); } void PlasmaApp::showInteractiveConsole() { if (KGlobal::config()->isImmutable()) { return; } InteractiveConsole *console = m_console.data(); if (!console) { m_console = console = new InteractiveConsole(m_corona); } m_console.data()->setMode(InteractiveConsole::PlasmaConsole); KWindowSystem::setOnDesktop(console->winId(), KWindowSystem::currentDesktop()); console->show(); console->raise(); KWindowSystem::forceActiveWindow(console->winId()); } void PlasmaApp::loadScriptInInteractiveConsole(const QString &script) { showInteractiveConsole(); if (m_console) { m_console.data()->loadScript(script); } } void PlasmaApp::showInteractiveKWinConsole() { showInteractiveConsole(); if (m_console) { m_console.data()->setMode(InteractiveConsole::KWinConsole); } } void PlasmaApp::loadKWinScriptInInteractiveConsole (const QString &script) { showInteractiveKWinConsole(); if (m_console) { m_console.data()->loadScript(script); } } void PlasmaApp::panelHidden(bool hidden) { if (hidden) { ++m_panelHidden; //kDebug() << "panel hidden" << m_panelHidden; } else { --m_panelHidden; if (m_panelHidden < 0) { kDebug() << "panelHidden(false) called too many times!"; m_panelHidden = 0; } //kDebug() << "panel unhidden" << m_panelHidden; } } QList PlasmaApp::panelViews() const { return m_panels; } PanelShadows *PlasmaApp::panelShadows() const { return m_panelShadows; } ControllerWindow *PlasmaApp::showWidgetExplorer(int screen, Plasma::Containment *containment) { return showController(screen, containment, true); } ControllerWindow *PlasmaApp::showController(int screen, Plasma::Containment *containment, bool widgetExplorerMode) { if (!containment) { kDebug() << "no containment"; return 0; } QWeakPointer controllerPtr = m_widgetExplorers.value(screen); ControllerWindow *controller = controllerPtr.data(); if (!controller) { //kDebug() << "controller not found for screen" << screen; controllerPtr = controller = new ControllerWindow(0); m_widgetExplorers.insert(screen, controllerPtr); } controller->setContainment(containment); if (!containment || containment->screen() != screen) { controller->setScreen(screen); } controller->setLocation(containment->location()); if (widgetExplorerMode) { controller->showWidgetExplorer(); } controller->show(); Plasma::WindowEffects::slideWindow(controller, controller->location()); QTimer::singleShot(0, controller, SLOT(activate())); return controller; } void PlasmaApp::hideController(int screen) { QWeakPointer controller = m_widgetExplorers.value(screen); if (controller) { controller.data()->hide(); } } #ifdef Q_WS_X11 PanelView *PlasmaApp::findPanelForTrigger(WId trigger) const { foreach (PanelView *panel, m_panels) { if (panel->unhideTrigger() == trigger) { return panel; } } return 0; } bool PlasmaApp::x11EventFilter(XEvent *event) { if (m_panelHidden > 0 && (event->type == ClientMessage || (event->xany.send_event != True && (event->type == EnterNotify || event->type == MotionNotify)))) { /* if (event->type == ClientMessage) { kDebug() << "client message with" << event->xclient.message_type << m_XdndEnterAtom << event->xcrossing.window; } */ bool dndEnter = false; bool dndPosition = false; if (event->type == ClientMessage) { dndEnter = event->xclient.message_type == m_XdndEnterAtom; if (!dndEnter) { dndPosition = event->xclient.message_type == m_XdndPositionAtom; if (!dndPosition) { //kDebug() << "FAIL!"; return KUniqueApplication::x11EventFilter(event); } } else { //kDebug() << "on enter" << event->xclient.data.l[0]; } } PanelView *panel = findPanelForTrigger(event->xcrossing.window); //kDebug() << "panel?" << panel << ((dndEnter || dndPosition) ? "Drag and drop op" : "Mouse move op"); if (panel) { if (dndEnter || dndPosition) { QPoint p; const unsigned long *l = (const unsigned long *)event->xclient.data.l; if (dndPosition) { p = QPoint((l[2] & 0xffff0000) >> 16, l[2] & 0x0000ffff); } else { p = QCursor::pos(); } XClientMessageEvent response; response.type = ClientMessage; response.window = l[0]; response.format = 32; response.data.l[0] = panel->winId(); //event->xcrossing.window; if (panel->hintOrUnhide(p, true)) { response.message_type = m_XdndFinishedAtom; response.data.l[1] = 0; // flags response.data.l[2] = XNone; } else { response.message_type = m_XdndStatusAtom; response.data.l[1] = 0; // flags response.data.l[2] = 0; // x, y response.data.l[3] = 0; // w, h response.data.l[4] = 0; // action } XSendEvent(QX11Info::display(), l[0], False, NoEventMask, (XEvent*)&response); } else if (event->type == EnterNotify) { panel->hintOrUnhide(QPoint(-1, -1)); //kDebug() << "entry"; //FIXME: this if it was possible to avoid the polling /*} else if (event->type == LeaveNotify) { panel->unhintHide(); */ } else if (event->type == MotionNotify) { XMotionEvent *motion = (XMotionEvent*)event; //kDebug() << "motion" << motion->x << motion->y << panel->location(); panel->hintOrUnhide(QPoint(motion->x_root, motion->y_root)); } } } return KUniqueApplication::x11EventFilter(event); } #endif void PlasmaApp::screenRemoved(const DesktopTracker::Screen &screen) { kDebug() << "@@@@" << screen.id; QMutableListIterator it(m_desktops); while (it.hasNext()) { DesktopView *view = it.next(); if (view->screen() == screen.id) { // the screen was removed, so we'll destroy the // corresponding view kDebug() << "@@@@removing the view for screen" << screen.id; view->setContainment(0); it.remove(); delete view; } } #if 1 /** UPDATE: this was linked to kephal events, which are not optimal, but it seems it may well have been the panel->migrateTo call due to a bug in libplasma fixed in e2108ed. so let's try and re-enable this. NOTE: CURRENTLY UNSAFE DUE TO HOW KEPHAL (or rather, it seems, Qt?) PROCESSES EVENTS DURING XRANDR EVENTS. REVISIT IN 4.8! */ const DesktopTracker::Screen primary = DesktopTracker::self()->primaryScreen(); QList screens = DesktopTracker::self()->screens(); screens.removeAll(primary); // Now we process panels: if there is room on another screen for the panel, // we migrate the panel there, otherwise the view is deleted. The primary // screen is preferred in all cases. QMutableListIterator pIt(m_panels); while (pIt.hasNext()) { PanelView *panel = pIt.next(); if (panel->screen() == screen.id) { DesktopTracker::Screen moveTo; if (canRelocatePanel(panel, primary)) { moveTo = primary; } else { foreach (const DesktopTracker::Screen &screen, screens) { if (canRelocatePanel(panel, screen)) { moveTo = screen; break; } } } if (moveTo.id >= 0) { panel->migrateTo(moveTo.id); } else { pIt.remove(); delete panel; continue; } } panel->updateStruts(); } #else QMutableListIterator pIt(m_panels); while (pIt.hasNext()) { PanelView *panel = pIt.next(); if (panel->screen() == screen.id) { pIt.remove(); delete panel; } } #endif } void PlasmaApp::screenAdded(const DesktopTracker::Screen &screen) { foreach (Plasma::Containment *containment, corona()->containments()) { if (isPanelContainment(containment) && containment->screen() == screen.id) { m_panelsWaiting << containment; m_panelViewCreationTimer.start(); } } foreach (PanelView *view, m_panels) { if (view->migratedFrom(screen.id)) { view->migrateTo(screen.id); } } } bool PlasmaApp::canRelocatePanel(PanelView * view, const DesktopTracker::Screen &screen) { if (!view->containment()) { return false; } QRect newGeom = view->geometry(); switch (view->location()) { case Plasma::TopEdge: newGeom.setY(screen.geom.y()); newGeom.setX(view->offset()); break; case Plasma::BottomEdge: newGeom.setY(screen.geom.bottom() - newGeom.height()); newGeom.setX(view->offset()); break; case Plasma::LeftEdge: newGeom.setX(screen.geom.left()); newGeom.setY(view->offset()); break; case Plasma::RightEdge: newGeom.setX(screen.geom.right() - newGeom.width()); newGeom.setY(view->offset()); break; default: break; } kDebug() << "testing:" << screen.id << view << view->geometry() << view->location() << newGeom; foreach (PanelView *pv, m_panels) { kDebug() << pv << pv->screen() << pv->screen() << pv->location() << pv->geometry(); if (pv != view && pv->screen() == screen.id && pv->location() == view->location() && pv->geometry().intersects(newGeom)) { return false; } } return true; } DesktopView* PlasmaApp::viewForScreen(int screen, int desktop) const { foreach (DesktopView *view, m_desktops) { if (view->containment()) { kDebug() << "comparing" << view->containment()->screen() << screen; } if (view->containment() && view->containment()->screen() == screen && (desktop < 0 || view->containment()->desktop() == desktop)) { return view; } } return 0; } DesktopCorona* PlasmaApp::corona(bool createIfMissing) { if (!m_corona && createIfMissing) { QTime t; t.start(); DesktopCorona *c = new DesktopCorona(this); connect(c, SIGNAL(containmentAdded(Plasma::Containment*)), this, SLOT(containmentAdded(Plasma::Containment*))); connect(c, SIGNAL(configSynced()), this, SLOT(syncConfig())); connect(c, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)), this, SLOT(containmentScreenOwnerChanged(int,int,Plasma::Containment*))); foreach (DesktopView *view, m_desktops) { connect(c, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)), view, SLOT(screenOwnerChanged(int,int,Plasma::Containment*))); } //actions! c->updateShortcuts(); m_corona = c; c->setItemIndexMethod(QGraphicsScene::NoIndex); c->initializeLayout(); foreach (Plasma::Containment *containment, c->containments()) { if (containment->screen() != -1 && containment->wallpaper()) { ++m_startupSuspendWaitCount; connect(containment->wallpaper(), SIGNAL(update(QRectF)), this, SLOT(wallpaperCheckedIn())); } } QTimer::singleShot(5000, this, SLOT(wallpaperCheckInTimeout())); kDebug() << " ------------------------------------------>" << t.elapsed() << m_startupSuspendWaitCount; } return m_corona; } void PlasmaApp::wallpaperCheckInTimeout() { if (m_startupSuspendWaitCount > 0) { m_startupSuspendWaitCount = 0; suspendStartup(false); } } void PlasmaApp::wallpaperCheckedIn() { if (m_startupSuspendWaitCount < 1) { return; } --m_startupSuspendWaitCount; if (m_startupSuspendWaitCount < 1) { m_startupSuspendWaitCount = 0; suspendStartup(false); } } bool PlasmaApp::hasComposite() { // return true; #ifdef Q_WS_X11 return KWindowSystem::compositingActive(); #else return false; #endif } void PlasmaApp::suspendStartup(bool suspend) { org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus()); const QString startupID("workspace desktop"); if (suspend) { ksmserver.suspendStartup(startupID); } else { ksmserver.resumeStartup(startupID); } } bool PlasmaApp::isPanelContainment(Plasma::Containment *containment) { if (!containment) { return false; } Plasma::Containment::Type t = containment->containmentType(); return t == Plasma::Containment::PanelContainment || t == Plasma::Containment::CustomPanelContainment; } void PlasmaApp::createView(Plasma::Containment *containment) { kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Plasma App createView() start" << "(line:" << __LINE__ << ")"; kDebug() << "Containment name:" << containment->name() << "| type" << containment->containmentType() << "| screen:" << containment->screen() << "| desktop:" << containment->desktop() << "| geometry:" << containment->geometry() << "| zValue:" << containment->zValue(); // find the mapping of View to Containment, if any, // so we can restore things on start. if (isPanelContainment(containment)) { m_panelsWaiting << containment; m_panelViewCreationTimer.start(); } else if (containment->screen() > -1 && containment->screen() < m_corona->numScreens()) { m_desktopsWaiting.append(containment); m_desktopViewCreationTimer.start(); } } void PlasmaApp::setWmClass(WId id) { #ifdef Q_WS_X11 //FIXME: if argb visuals enabled Qt will always set WM_CLASS as "qt-subapplication" no matter what //the application name is we set the proper XClassHint here, hopefully won't be necessary anymore when //qapplication will manage apps with argvisuals in a better way XClassHint classHint; classHint.res_name = const_cast("Plasma"); classHint.res_class = const_cast("Plasma"); XSetClassHint(QX11Info::display(), id, &classHint); #endif } void PlasmaApp::createWaitingPanels() { if (m_panelsWaiting.isEmpty()) { return; } const QList > containments = m_panelsWaiting; m_panelsWaiting.clear(); foreach (QWeakPointer containmentPtr, containments) { Plasma::Containment *containment = containmentPtr.data(); if (!containment) { continue; } foreach (PanelView *view, m_panels) { if (view->containment() == containment) { continue; } } if (containment->screen() < 0) { continue; } // try to relocate the panel if it is on a now-non-existent screen if (containment->screen() >= m_corona->numScreens()) { m_panelRelocationCandidates << containment; continue; } createPanelView(containment); } if (!m_panelRelocationCandidates.isEmpty()) { QTimer::singleShot(0, this, SLOT(relocatePanels())); } } void PlasmaApp::relocatePanels() { // we go through relocatables last so that all other panels can be set up first, // preventing panel creation ordering to trip up the canRelocatePanel algorithm const DesktopTracker::Screen primary = DesktopTracker::self()->primaryScreen(); QList screens = DesktopTracker::self()->screens(); screens.removeAll(primary); foreach (QWeakPointer c, m_panelRelocationCandidates) { Plasma::Containment *containment = c.data(); if (!containment) { continue; } DesktopTracker::Screen moveTo; PanelView *panelView = createPanelView(containment); if (canRelocatePanel(panelView, primary)) { moveTo = primary; } else { foreach (const DesktopTracker::Screen &screen, screens) { if (canRelocatePanel(panelView, screen)) { moveTo = screen; break; } } } if (moveTo.id >= 0) { panelView->migrateTo(moveTo.id); } else { m_panels.removeAll(panelView); delete panelView; } } m_panelRelocationCandidates.clear(); } PanelView *PlasmaApp::createPanelView(Plasma::Containment *containment) { KConfigGroup viewIds(KGlobal::config(), "ViewIds"); const int id = viewIds.readEntry(QString::number(containment->id()), 0); PanelView *panelView = new PanelView(containment, id); connect(panelView, SIGNAL(destroyed(QObject*)), this, SLOT(panelRemoved(QObject*))); m_panels << panelView; panelView->show(); setWmClass(panelView->winId()); return panelView; } void PlasmaApp::createWaitingDesktops() { const QList > containments = m_desktopsWaiting; m_desktopsWaiting.clear(); foreach (QWeakPointer weakContainment, containments) { if (weakContainment) { Plasma::Containment *containment = weakContainment.data(); KConfigGroup viewIds(KGlobal::config(), "ViewIds"); const int id = viewIds.readEntry(QString::number(containment->id()), 0); const int screen = containment->screen(); if (screen >= m_corona->numScreens() || screen < 0) { kDebug() << "not creating a view on screen" << screen << "as it does not exist"; continue; } DesktopView *view = viewForScreen(screen, -1); if (view) { kDebug() << "already had a view for" << containment->screen() << containment->desktop(); // we already have a view for this screen continue; } kDebug() << "creating a new view for" << containment->screen() << containment->desktop() << "and we have" << m_corona->numScreens() << "screens"; // we have a new screen. neat. view = new DesktopView(containment, id, 0); if (m_corona) { connect(m_corona, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)), view, SLOT(screenOwnerChanged(int,int,Plasma::Containment*))); } m_desktops.append(view); view->show(); setWmClass(view->winId()); } } } void PlasmaApp::containmentAdded(Plasma::Containment *containment) { if (isPanelContainment(containment)) { foreach (PanelView * panel, m_panels) { if (panel->containment() == containment) { kDebug() << "not creating second PanelView with existing Containment!!"; return; } } } createView(containment); } void PlasmaApp::prepareContainment(Plasma::Containment *containment) { if (!containment) { return; } disconnect(containment, 0, this, 0); connect(containment, SIGNAL(configureRequested(Plasma::Containment*)), this, SLOT(configureContainment(Plasma::Containment*))); if (isPanelContainment(containment)) { return; } if ((containment->containmentType() == Plasma::Containment::DesktopContainment || containment->containmentType() == Plasma::Containment::CustomContainment)) { QAction *a = containment->action("remove"); delete a; //activities handle removal now if (containment->containmentType() == Plasma::Containment::DesktopContainment) { foreach (QAction *action, m_corona->actions()) { containment->addToolBoxAction(action); } } } } void PlasmaApp::containmentScreenOwnerChanged(int wasScreen, int isScreen, Plasma::Containment *containment) { Q_UNUSED(wasScreen) kDebug() << "@@@was" << wasScreen << "is" << isScreen << (QObject*)containment << m_desktops.count(); if (isScreen < 0) { kDebug() << "@@@screen<0"; return; } if (isPanelContainment(containment)) { kDebug() << "@@@isPanel"; return; } foreach (DesktopView *view, m_desktops) { if (view->screen() == isScreen) { kDebug() << "@@@@found view" << view; return; } } kDebug() << "@@@@appending"; m_desktopsWaiting.append(containment); m_desktopViewCreationTimer.start(); } void PlasmaApp::configureContainment(Plasma::Containment *containment) { const QString id = QString::number(containment->id()) + "settings" + containment->name(); BackgroundDialog *configDialog = qobject_cast(KConfigDialog::exists(id)); if (configDialog) { configDialog->reloadConfig(); } else { const QSize resolution = QApplication::desktop()->screenGeometry(containment->screen()).size(); Plasma::View *view = viewForScreen(containment->screen(), containment->desktop()); if (!view) { view = viewForScreen(desktop()->screenNumber(QCursor::pos()), containment->desktop()); if (!view) { if (m_desktops.count() < 1) { return; } view = m_desktops.at(0); } } KConfigSkeleton *nullManager = new KConfigSkeleton(); configDialog = new BackgroundDialog(resolution, containment, view, 0, id, nullManager); configDialog->setAttribute(Qt::WA_DeleteOnClose); connect(configDialog, SIGNAL(destroyed(QObject*)), nullManager, SLOT(deleteLater())); } configDialog->show(); KWindowSystem::setOnDesktop(configDialog->winId(), KWindowSystem::currentDesktop()); KWindowSystem::activateWindow(configDialog->winId()); } void PlasmaApp::panelRemoved(QObject *panel) { m_panels.removeAll((PanelView *)panel); } QString PlasmaApp::supportInformation() const { return SupportInformation::generateSupportInformation(m_corona); } void PlasmaApp::executeCommands(const QList < QVariant > & commands) { foreach (const QVariant & command, commands) { KRun::runCommand(command.toString(), 0); } } #include "moc_plasmaapp.cpp"