diff --git a/qmlpackages/contour-tablet-homescreen/contents/ui/HomeScreen.qml b/qmlpackages/contour-tablet-homescreen/contents/ui/HomeScreen.qml index 9747dd03..d5919e08 100644 --- a/qmlpackages/contour-tablet-homescreen/contents/ui/HomeScreen.qml +++ b/qmlpackages/contour-tablet-homescreen/contents/ui/HomeScreen.qml @@ -1,267 +1,269 @@ /*************************************************************************** * Copyright 2010 Alexis Menard * * Copyright 2010 Artur Duque de Souza * * Copyright 2010 Marco Martin * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, 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 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 . * ***************************************************************************/ /**Documented API Inherits: Item Imports: QtQuick 1.0 org.kde.plasma.core 0.1 org.kde.plasma.deviceshell 0.1 org.kde.plasma.mobilecomponents 0.1 Description: This is the main component of the Plasma Active tablet shell. It manages the look and feel on how the main containment is shown, and how panels and extra ui pieces (outside containments, such as activity switcher) are loaded and shown. Properties: Item availableScreenRect: an item as big as the usable area of the main containment, make it smaller to prevent the containment to lay out items out of the availableScreenRect geometry. The item can offer four additional properties: - int leftReserved: space reserved at the left edge of the screen. a maximized window will not go over this area of the screen. - int topReserved: space reserved at the top edge of the screen. a maximized window will not go over this area of the screen. - int rightReserved: space reserved at the right edge of the screen. - int bottomReserved: space reserved at the bottom edge of the screen. QGraphicsWidget activeContainment: It's a pointer to the containment that owns the screen and is set by the plasma shell (the qml part must not write it). The qml part should make sure activeContainment is disaplayed in a prominent place, e.g. filling the whole screen. Methods: void addPanel(panel, formFactor, location) panel: pointer to the containment formFactor: formFactor of the panel location: location of the panel Position a new panel in this home screen. The final position can depend from the panel formfactor or location Signals: newActivityRequested(): Ask the shell to show the user interface to create a new activity focusActivityView(): Ask the shell to show the main activity screen, even if it was covered by some application, by raising and focusing its window. **/ import QtQuick 1.0 import org.kde.plasma.core 0.1 as PlasmaCore import org.kde.plasma.deviceshell 0.1 as DeviceShell import org.kde.plasma.mobilecomponents 0.1 as MobileComponents import org.kde.qtextracomponents 0.1 Item { id: homeScreen /***** API ************************/ signal newActivityRequested signal focusActivityView + property bool windowActive: false + //this item will define Corona::availableScreenRegion() for simplicity made by a single rectangle property Item availableScreenRect: Item { parent: homeScreen anchors.fill: parent anchors.topMargin: topEdgePanel.panelHeight anchors.bottomMargin: 4 anchors.leftMargin: 32 anchors.rightMargin: 32 //those properties will define "structs" for reserved screen of the panels property int leftReserved: 0 property int topReserved: anchors.topMargin property int rightReserved: 0 property int bottomReserved: 0 } property QGraphicsWidget activeContainment onActiveContainmentChanged: { activeContainment.visible=true spareSlot.containment = activeContainment activeContainment.parent = spareSlot activeContainment.visible = true activeContainment.x = 0 activeContainment.y = 0 activeContainment.size = width + "x" + height //view the main containment internal.state = "Slide" internal.finishTransition() } /*position a new panel in this home screen. the final position can depend from the panel formfactor or location*/ function addPanel(panel, formFactor, location) { //formFactor is not used in this implementation print("Adding a new panel: "+panel+" Formfactor: "+formFactor +" Location: "+location) switch (location) { case DeviceShell.ContainmentProperties.TopEdge: topEdgePanel.containment = panel break default: print("On this homescreen only top panels are supported") break } } function togglePanel() { if (topEdgePanel.state == "Hidden") { topEdgePanel.state = "Launcher" } else { topEdgePanel.state = "Hidden" } } /*************Implementation***************/ x: 0 y: 0 width: 800 height: 480 Item { id: internal state : "Normal" function finishTransition() { //spareSlot.containment = undefined if (mainSlot.containment) { mainSlot.containment.visible = false } mainSlot.containment = activeContainment activeContainment.parent = mainSlot activeContainment.x = 0 activeContainment.y = 0 //hide the activity switcher if (activityPanel) { activityPanel.x = homeScreen.width activityPanel.state = "hidden" } state = "Normal" } states: [ State { name: "Normal" PropertyChanges { target: spareSlot; x: homeScreen.width } }, State { name: "Slide" PropertyChanges { target: spareSlot; x: 0 } } ] } MobileComponents.Package { id: homeScreenPackage name: "org.kde.active.contour-tablet-homescreen" } MouseEventListener { id: mainSlot; x: 0; y: 0; width: homeScreen.width height: homeScreen.height property QGraphicsWidget containment onPressed: { if (activityPanel && mouse.x < activityPanel.x) { activityPanel.state = "hidden" } if (mouse.x > recommendationsPanel.x+recommendationsPanel.width) { recommendationsPanel.state = "hidden" } } } //acceptsFocus property is costly, delay it after the animation Timer { id: topEdgePanelStateTimer interval: 500 repeat: false running: false onTriggered: { topEdgePanel.state = "Hidden" } } DeviceShell.DevicePanel { id: topSlidingPanel visible: true windowStripEnabled: topEdgePanel.windowStripVisible mainItem: SystrayPanel { id: topEdgePanel } onActiveWindowChanged: { if (acceptsFocus && !activeWindow) { topEdgePanelStateTimer.restart() } } } property Item recommendationsPanel property Item activityPanel Component { id: recommendationsPanelComponent RecommendationsPanel { id: recommendationsPanel anchors { top: parent.top bottom: parent.bottom } x: - width } } Component { id: activityPanelComponent ActivityPanel { id: activityPanel x: parent.width - width } } Item { id : spareSlot x: 0 y: 0 width: homeScreen.width height: homeScreen.height property QGraphicsWidget containment } Component.onCompleted: { homeScreen.recommendationsPanel = recommendationsPanelComponent.createObject(homeScreen) homeScreen.activityPanel = activityPanelComponent.createObject(homeScreen) } } diff --git a/qmlpackages/contour-tablet-homescreen/contents/ui/SlidingDragButton.qml b/qmlpackages/contour-tablet-homescreen/contents/ui/SlidingDragButton.qml index cd33edb8..52781dfc 100644 --- a/qmlpackages/contour-tablet-homescreen/contents/ui/SlidingDragButton.qml +++ b/qmlpackages/contour-tablet-homescreen/contents/ui/SlidingDragButton.qml @@ -1,135 +1,137 @@ /* * Copyright 2011 Marco Martin * * 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. */ import Qt 4.7 import org.kde.plasma.core 0.1 as PlasmaCore import org.kde.plasma.mobilecomponents 0.1 as MobileComponents import org.kde.qtextracomponents 0.1 MouseEventListener { id: panelDragButton property int startY property int startX property int lastY property bool dragging: false property bool dragEnabled: true property int panelHeight property int tasksHeight property bool homeButtonShown: !deviceCapabilitiesSource.data["Input"]["hasHomeButton"] PlasmaCore.Svg { id: iconSvg imagePath: "icons/start" } PlasmaCore.DataSource { id: deviceCapabilitiesSource engine: "org.kde.devicecapabilities" interval: 0 connectedSources: ["Input"] } PlasmaCore.SvgItem { id: iconItem svg: iconSvg elementId: "start-here" width: homeButtonShown ? height : 0 height: theme.mediumIconSize visible: homeButtonShown + enabled: !homeScreen.windowActive + opacity: enabled ? 1 : 0.3 anchors { right: parent.right bottom: parent.bottom bottomMargin: background.margins.bottom } MouseArea { anchors.fill: parent onClicked: homeScreen.focusActivityView() } } Timer { id: disableTimer running: false repeat: false interval: 400 onTriggered: { panelDragButton.dragEnabled = false } } onPressed: { startY = mouse.screenY startX = mouse.screenX lastY = mouse.screenY } onPositionChanged: { if (!panelDragButton.dragEnabled ) { return } //FIXME: why sometimes onPressed doesn't arrive? if (startY < 0 || lastY < 0) { startY = mouse.screenY startX = mouse.screenX lastY = mouse.screenY } //try to avoid vertical scrolling when an horizontal one is in place //this 32 is completely arbitrary if (!dragging && Math.abs(startX - mouse.screenX) > 32) { panelDragButton.dragEnabled = false; } if (Math.abs(startY - lastY) > 32) { dragging = true disableTimer.running = false } if (dragging) { topSlidingPanel.y = Math.min(0, (topSlidingPanel.y + mouse.screenY - lastY)) } lastY = mouse.screenY } onReleased: { panelDragButton.dragEnabled = true disableTimer.running = false dragging = false var oldState = systrayPanel.state systrayPanel.state = "none" // if more than half of pick & launch panel is visible then make it totally visible. if ((topSlidingPanel.y > -(systrayPanel.height - topSlidingPanel.windowListArea.height)/2) ) { //the biggest one, Launcher systrayPanel.state = "Launcher" } else if ((oldState == "Hidden" && systrayPanel.height + topSlidingPanel.y > panelDragButton.tasksHeight/2) || (systrayPanel.height + topSlidingPanel.y > (panelDragButton.tasksHeight / 5) * 6)) { //show only the taskbar: require a smaller quantity of the screen uncovered when the previous state is hidden systrayPanel.state = "Tasks" } else { //Only the small top panel systrayPanel.state = "Hidden" } startY = -1 startX = -1 lastY = -1 } } diff --git a/shell/plasmaapp.cpp b/shell/plasmaapp.cpp index ebc6dc1f..2d29ec46 100644 --- a/shell/plasmaapp.cpp +++ b/shell/plasmaapp.cpp @@ -1,642 +1,650 @@ /*************************************************************************** * Copyright 2006-2008 Aaron Seigo * * Copyright 2009 Marco Martin * * Copyright 2010 Alexis Menard * * Copyright 2010 Artur Duque de Souza * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, 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 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 "busywidget.h" #include "mobview.h" #include "mobcorona.h" #include "mobpluginloader.h" #include "mobileactivitythumbnails/mobileactivitythumbnails.h" #include "widgetsexplorer/mobilewidgetsexplorer.h" #include "activityconfiguration/activityconfiguration.h" #include "panelproxy.h" #include "panelshadows.h" #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 "../components/runnermodel/runnermodel.h" #ifdef Q_WS_X11 #include #include #endif PlasmaApp* PlasmaApp::self() { if (!kapp) { return new PlasmaApp(); } return qobject_cast(kapp); } PlasmaApp::PlasmaApp() : KUniqueApplication(), m_corona(0), m_mainView(0), m_declarativeWidget(0), m_currentContainment(0), m_panelShadows(0), m_isDesktop(false) { KGlobal::locale()->insertCatalog("libplasma"); KGlobal::locale()->insertCatalog("plasma-device"); KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); Nepomuk::ResourceManager::instance()->init(); qmlRegisterType("org.kde.plasma.deviceshell", 0, 1, "DevicePanel"); qmlRegisterUncreatableType("org.kde.plasma.deviceshell", 0, 1, "ContainmentProperties", "ContainmentProperties is just a type holder"); //FIXME: why does not work? //qmlRegisterInterface("Wallpaper"); //qRegisterMetaType("Wallpaper"); bool useGL = args->isSet("opengl"); if (!useGL) { //use plasmarc to share this with plasma-windowed KConfigGroup cg(KSharedConfig::openConfig("plasmarc"), "General"); useGL = cg.readEntry("UseOpenGl", false); } m_mainView = new MobView(0, MobView::mainViewId(), 0); m_mainView->setWindowTitle(i18n("Home Screen")); m_mainView->setUseGL(useGL); bool isDesktop = args->isSet("desktop"); if (isDesktop) { notifyStartup(false); KCrash::setFlags(KCrash::AutoRestart); } int width = 800; int height = 480; if (isDesktop) { QRect rect = QApplication::desktop()->screenGeometry(m_mainView->screen()); width = rect.width(); height = rect.height(); } else { QAction *action = KStandardAction::quit(qApp, SLOT(quit()), m_mainView); m_mainView->addAction(action); QString geom = args->getOption("screen"); int x = geom.indexOf('x'); if (x > 0) { width = qMax(width, geom.left(x).toInt()); height = qMax(height, geom.right(geom.length() - x - 1).toInt()); } } bool isFullScreen = args->isSet("fullscreen"); if (isFullScreen) { m_mainView->showFullScreen(); } setIsDesktop(isDesktop); m_mainView->setFixedSize(width, height); m_mainView->move(0,0); KConfigGroup cg(KSharedConfig::openConfig("plasmarc"), "Theme-plasma-device"); const QString themeName = cg.readEntry("name", "air-mobile"); Plasma::Theme::defaultTheme()->setUseGlobalSettings(false); Plasma::Theme::defaultTheme()->setThemeName(themeName); cg = KConfigGroup(KGlobal::config(), "General"); Plasma::Theme::defaultTheme()->setFont(cg.readEntry("desktopFont", font())); m_pluginLoader = new MobPluginLoader; Plasma::PluginLoader::setPluginLoader(m_pluginLoader); Plasma::ToolTipManager::self()->setState(Plasma::ToolTipManager::Deactivated); // this line initializes the corona and setups the main qml homescreen corona(); connect(this, SIGNAL(aboutToQuit()), this, SLOT(cleanup())); + connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), + this, SLOT(activeWindowChanged(WId))); + if (isDesktop) { notifyStartup(true); } m_startupInfo = new KStartupInfo(KStartupInfo::CleanOnCantDetect, this ); connect(m_startupInfo, SIGNAL(gotNewStartup(KStartupInfoId,KStartupInfoData)), SLOT(gotStartup(KStartupInfoId,KStartupInfoData))); connect(m_startupInfo, SIGNAL(gotStartupChange(KStartupInfoId,KStartupInfoData)), SLOT(gotStartup(KStartupInfoId,KStartupInfoData))); connect(m_startupInfo, SIGNAL(gotRemoveStartup(KStartupInfoId,KStartupInfoData)), SLOT(killStartup(KStartupInfoId))); } PlasmaApp::~PlasmaApp() { } QList PlasmaApp::containments() const { return m_containments.values(); } QList PlasmaApp::panelContainments() const { return m_panelContainments.values(); } PanelShadows *PlasmaApp::panelShadows() { if (!m_panelShadows) { m_panelShadows = new PanelShadows(this); } return m_panelShadows; } void PlasmaApp::cleanup() { if (m_corona) { m_corona->saveLayout(); } delete m_mainView; m_mainView = 0; delete m_corona; m_corona = 0; //TODO: This manual sync() should not be necessary? syncConfig(); } void PlasmaApp::setIsDesktop(bool isDesktop) { m_isDesktop = isDesktop; if (isDesktop) { //FIXME: remove close button *and* window border: possible? KWindowSystem::setType(m_mainView->winId(), NET::Normal); m_mainView->setWindowFlags((m_mainView->windowFlags() | Qt::FramelessWindowHint /*| Qt::CustomizeWindowHint*/) /*& ~Qt::WindowCloseButtonHint*/); KWindowSystem::setOnAllDesktops(m_mainView->winId(), true); m_mainView->show(); } else { m_mainView->setWindowFlags(((m_mainView->windowFlags() | Qt::CustomizeWindowHint) & ~Qt::FramelessWindowHint) & ~Qt::WindowCloseButtonHint); KWindowSystem::setOnAllDesktops(m_mainView->winId(), false); KWindowSystem::setType(m_mainView->winId(), NET::Normal); } } void PlasmaApp::syncConfig() { KGlobal::config()->sync(); } void PlasmaApp::setupHomeScreen() { //The home screen can be set up a single time Q_ASSERT(!m_declarativeWidget); m_declarativeWidget = new Plasma::DeclarativeWidget(); m_corona->addItem(m_declarativeWidget); m_homeScreenPath = m_corona->homeScreenPackage()->filePath("mainscript"); if (m_homeScreenPath.isEmpty()) { kWarning() << "Could not find an home screen, exiting."; QTimer::singleShot(0, QCoreApplication::instance(), SLOT(quit())); return; } kDebug() << "Loading " << m_homeScreenPath; m_declarativeWidget->setQmlPath(m_homeScreenPath); if (!m_declarativeWidget->engine()) { kDebug() << "Invalid main declarative engine, exiting."; QTimer::singleShot(0, QCoreApplication::instance(), SLOT(quit())); return; } m_homeScreen = qobject_cast(m_declarativeWidget->rootObject()); if (!m_homeScreen) { kError() << "Error in creation of the homescreen object, exiting. " << m_homeScreenPath; QTimer::singleShot(0, QCoreApplication::instance(), SLOT(quit())); return; } mainViewGeometryChanged(); connect(m_mainView, SIGNAL(geometryChanged()), this, SLOT(mainViewGeometryChanged())); connect(m_mainView, SIGNAL(containmentActivated()), this, SLOT(mainContainmentActivated())); connect(m_homeScreen, SIGNAL(focusActivityView()), this, SLOT(focusMainView())); KAction *focusHomeAction = new KAction(this); focusHomeAction->setObjectName("Focus Homescreen"); focusHomeAction->setGlobalShortcut( KShortcut(QKeySequence(Qt::Key_HomePage)), KAction::ShortcutTypes(KAction::ActiveShortcut | KAction::DefaultShortcut), KAction::NoAutoloading); connect(focusHomeAction, SIGNAL(triggered()), this, SLOT(focusMainView())); KAction *togglePanelAction = new KAction(this); togglePanelAction->setObjectName("Toggle Panel"); togglePanelAction->setGlobalShortcut( KShortcut(QKeySequence(Qt::Key_Menu)), KAction::ShortcutTypes(KAction::ActiveShortcut | KAction::DefaultShortcut), KAction::NoAutoloading); connect(togglePanelAction, SIGNAL(triggered()), m_homeScreen, SLOT(togglePanel())); connect(m_homeScreen, SIGNAL(newActivityRequested()), this, SLOT(showActivityCreation())); m_mainView->setSceneRect(m_homeScreen->x(), m_homeScreen->y(), m_homeScreen->width(), m_homeScreen->height()); } void PlasmaApp::changeContainment(Plasma::Containment *containment) { QDeclarativeProperty containmentProperty(m_homeScreen, "activeContainment"); containmentProperty.write(QVariant::fromValue(static_cast(containment))); m_oldContainment = m_currentContainment; m_currentContainment = containment; } Plasma::Corona* PlasmaApp::corona() { if (!m_corona) { m_corona = new MobCorona(this); m_corona->setItemIndexMethod(QGraphicsScene::NoIndex); m_corona->setScreenGeometry(QRect(QPoint(0,0), m_mainView->size())); //FIXME libplasma2: qml containments cannot set containmentType before this signal is emitted connect(m_corona, SIGNAL(containmentAdded(Plasma::Containment*)), this, SLOT(manageNewContainment(Plasma::Containment*)), Qt::QueuedConnection); connect(m_corona, SIGNAL(configSynced()), this, SLOT(syncConfig())); connect(m_corona, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)), this, SLOT(containmentScreenOwnerChanged(int,int,Plasma::Containment*))); // setup our QML home screen; setupHomeScreen(); m_corona->initializeLayout(); m_mainView->setScene(m_corona); m_corona->checkActivities(); m_mainView->show(); } return m_corona; } QSize PlasmaApp::defaultScreenSize() { return QSize(1366, 768); } void PlasmaApp::notifyStartup(bool completed) { org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus()); const QString startupID("mobile desktop"); if (completed) { ksmserver.resumeStartup(startupID); } else { ksmserver.suspendStartup(startupID); } } void PlasmaApp::mainContainmentActivated() { const WId id = m_mainView->effectiveWinId(); QWidget * activeWindow = QApplication::activeWindow(); KWindowSystem::raiseWindow(id); if (activeWindow) { KWindowSystem::raiseWindow(activeWindow->effectiveWinId()); m_mainView->activateWindow(); activeWindow->setFocus(); } else { m_mainView->activateWindow(); } } void PlasmaApp::manageNewContainment(Plasma::Containment *containment) { if (m_containments.contains(containment->id()) || m_panelContainments.contains(containment->id())) { return; } QAction *addAction = containment->action("add widgets"); if (addAction) { connect(addAction, SIGNAL(triggered()), this, SLOT(showWidgetsExplorer())); } connect(containment, SIGNAL(configureRequested(Plasma::Containment*)), this, SLOT(showActivityConfiguration(Plasma::Containment*))); //is it a panel? if (containment->location() == Plasma::LeftEdge || containment->location() == Plasma::TopEdge || containment->location() == Plasma::RightEdge || containment->location() == Plasma::BottomEdge) { m_panelContainments.insert(containment->id(), containment); //add the panel into the QML homescreen m_homeScreen->metaObject()->invokeMethod(m_homeScreen, "addPanel", Q_ARG(QVariant, QVariant::fromValue(containment)), Q_ARG(QVariant, containment->formFactor()), Q_ARG(QVariant, containment->location())); //done, don't need further management return; } // add the containment and it identifier to a hash to enable us // to retrieve it later. m_containments.insert(containment->id(), containment); connect(containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed(QObject*))); containment->resize(m_mainView->size()); //FIXME: avoidable all this disk access at startup? QString path = KStandardDirs::locateLocal("data", QString("plasma/activities-screenshots/%1.png").arg(containment->context()->currentActivityId())); if (!QFile::exists(path)) { m_pluginLoader->activityThumbnails()->snapshotContainment(containment); } // we need our homescreen to show something! if (containment->config().readEntry("excludeFromActivities", false)) { //Do nothing! //Don't remove this empty branch } else if (containment->screen() > -1) { changeContainment(containment); } else { containment->setPos(m_mainView->width(), m_mainView->height()); // containment->setVisible(false); } KConfigGroup cg = containment->config(); cg = KConfigGroup(&cg, "General"); } void PlasmaApp::focusMainView() { if (m_mainView) { KWindowSystem::forceActiveWindow(m_mainView->winId()); } } +void PlasmaApp::activeWindowChanged(WId id) +{ + m_homeScreen->setProperty("windowActive", (id == m_mainView->winId())); +} + void PlasmaApp::mainViewGeometryChanged() { if (m_declarativeWidget) { //sometimes a geometry change arives very early in the ctor corona(); m_declarativeWidget->resize(m_mainView->size()); //m_declarativeWidget->setPos(m_mainView->mapToScene(QPoint(0,0))); m_declarativeWidget->setGeometry(m_mainView->mapToScene(QRect(QPoint(0,0), m_mainView->size())).boundingRect()); QRect availableScreenRect(QPoint(0,0), m_mainView->size()); QDeclarativeItem *availableScreenRectItem = m_homeScreen->property("availableScreenRect").value(); //is there an item that defines the screen geometry? if (availableScreenRectItem) { availableScreenRect = QRect((int)availableScreenRectItem->property("x").toReal(), (int)availableScreenRectItem->property("y").toReal(), (int)availableScreenRectItem->property("width").toReal(), (int)availableScreenRectItem->property("height").toReal()); const int left = availableScreenRectItem->property("leftReserved").toInt(); const int top = availableScreenRectItem->property("topReserved").toInt(); const int right = availableScreenRectItem->property("rightReserved").toInt(); const int bottom = availableScreenRectItem->property("bottomReserved").toInt(); reserveStruts(left, top, right, bottom); } m_corona->setScreenGeometry(QRect(QPoint(0, 0), m_mainView->size())); m_corona->setAvailableScreenRegion(availableScreenRect); if (m_currentContainment) { m_currentContainment->resize(m_mainView->size()); } if (m_widgetsExplorer) { m_widgetsExplorer.data()->setGeometry(m_declarativeWidget->geometry()); } } } void PlasmaApp::reserveStruts(const int left, const int top, const int right, const int bottom) { if (!m_mainView) { return; } if (!m_isDesktop) { KWindowSystem::setExtendedStrut(m_mainView->winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); return; } NETExtendedStrut strut; if (left) { strut.left_width = left; strut.left_start = m_mainView->y(); strut.left_end = m_mainView->y() + m_mainView->height() - 1; } if (right) { strut.right_width = right; strut.right_start = m_mainView->y(); strut.right_end = m_mainView->y() + m_mainView->height() - 1; } if (top) { strut.top_width = top; strut.top_start = m_mainView->x(); strut.top_end = m_mainView->x() + m_mainView->width() - 1; } if (bottom) { strut.bottom_width = bottom; strut.bottom_start = m_mainView->x(); strut.bottom_end = m_mainView->x() + m_mainView->width() - 1; } const QPoint oldPos = m_mainView->pos(); KWindowSystem::setExtendedStrut(m_mainView->winId(), strut.left_width, strut.left_start, strut.left_end, strut.right_width, strut.right_start, strut.right_end, strut.top_width, strut.top_start, strut.top_end, strut.bottom_width, strut.bottom_start, strut.bottom_end); //ensure the main view is at the proper position too m_mainView->move(oldPos); } void PlasmaApp::showWidgetsExplorer() { if (!m_widgetsExplorer) { m_widgetsExplorer = new MobileWidgetsExplorer(0); m_widgetsExplorer.data()->setZValue(1000); m_corona->addItem(m_widgetsExplorer.data()); } m_widgetsExplorer.data()->setContainment(m_currentContainment); if (m_declarativeWidget) { m_widgetsExplorer.data()->setGeometry(m_declarativeWidget->geometry()); } m_widgetsExplorer.data()->show(); } void PlasmaApp::showActivityCreation() { showActivityConfiguration(0); } void PlasmaApp::showActivityConfiguration(Plasma::Containment *containment) { if (!m_activityConfiguration) { m_activityConfiguration = new ActivityConfiguration(); connect(m_activityConfiguration.data(), SIGNAL(containmentWallpaperChanged(Plasma::Containment*)), this, SLOT(containmentWallpaperChanged(Plasma::Containment*))); m_activityConfiguration.data()->setZValue(1000); m_corona->addItem(m_activityConfiguration.data()); } m_activityConfiguration.data()->setContainment(containment); if (m_declarativeWidget) { m_activityConfiguration.data()->setGeometry(m_declarativeWidget->geometry()); } m_activityConfiguration.data()->show(); } void PlasmaApp::containmentWallpaperChanged(Plasma::Containment *containment) { if (m_pluginLoader->activityThumbnails()) { m_pluginLoader->activityThumbnails()->snapshotContainment(containment); } } void PlasmaApp::containmentDestroyed(QObject *object) { Plasma::Containment *cont = qobject_cast(object); if (cont) { m_containments.remove(cont->id()); } } void PlasmaApp::containmentScreenOwnerChanged(int wasScreen, int isScreen, Plasma::Containment *cont) { Q_UNUSED(wasScreen) bool excludeFromActivities = cont->config().readEntry("excludeFromActivities", false); if (!excludeFromActivities && isScreen >= 0 && (cont->location() == Plasma::Desktop || cont->location() == Plasma::Floating)) { changeContainment(cont); } } void PlasmaApp::gotStartup(const KStartupInfoId &id, const KStartupInfoData &data) { Q_UNUSED(id) Q_UNUSED(data) if (!m_busyWidget) { m_busyWidget = new BusyWidget(); } m_busyWidget.data()->setGeometry(m_mainView->geometry().center().x() - 128, m_mainView->geometry().bottom() - 78, 256, 78); KWindowSystem::setState(m_busyWidget.data()->winId(), NET::SkipTaskbar | NET::KeepAbove); Plasma::WindowEffects::slideWindow(m_busyWidget.data(), Plasma::BottomEdge); m_busyWidget.data()->show(); KWindowSystem::activateWindow(m_busyWidget.data()->winId(), 500); KWindowSystem::raiseWindow(m_busyWidget.data()->winId()); } void PlasmaApp::killStartup(const KStartupInfoId &id) { Q_UNUSED(id) if (!m_busyWidget) { return; } Plasma::WindowEffects::slideWindow(m_busyWidget.data(), Plasma::BottomEdge); m_busyWidget.data()->hide(); m_busyWidget.data()->deleteLater(); } #include "plasmaapp.moc" diff --git a/shell/plasmaapp.h b/shell/plasmaapp.h index d99b6929..910413b4 100644 --- a/shell/plasmaapp.h +++ b/shell/plasmaapp.h @@ -1,173 +1,174 @@ /*************************************************************************** * Copyright 2006-2008 Aaron Seigo * * Copyright 2009 Marco Martin * * Copyright 2010 Alexis Menard * * Copyright 2010 Artur Duque de Souza * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, 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 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 . * ***************************************************************************/ #ifndef PLASMA_APP_H #define PLASMA_APP_H #include #include #include #include #include #ifdef Q_WS_X11 #include #include #endif class ActivityConfiguration; class MobView; class MobCorona; class MobileWidgetsExplorer; class MobPluginLoader; class PanelShadows; class BusyWidget; class KStartupInfo; namespace Plasma { class Applet; class Containment; class Corona; class DeclarativeWidget; } // namespace Plasma class ContainmentProperties : public QObject { Q_OBJECT Q_ENUMS(Location) Q_ENUMS(FormFactor) public: /** * The Location enumeration describes where on screen an element, such as an * Applet or its managing container, is positioned on the screen. **/ enum Location { Floating = 0, /**< Free floating. Neither geometry or z-ordering is described precisely by this value. */ Desktop, /**< On the planar desktop layer, extending across the full screen from edge to edge */ FullScreen, /**< Full screen */ TopEdge, /**< Along the top of the screen*/ BottomEdge, /**< Along the bottom of the screen*/ LeftEdge, /**< Along the left side of the screen */ RightEdge /**< Along the right side of the screen */ }; /** * The FormFactor enumeration describes how a Plasma::Applet should arrange * itself. The value is derived from the container managing the Applet * (e.g. in Plasma, a Corona on the desktop or on a panel). **/ enum FormFactor { Planar = 0, /**< The applet lives in a plane and has two degrees of freedom to grow. Optimize for desktop, laptop or tablet usage: a high resolution screen 1-3 feet distant from the viewer. */ MediaCenter, /**< As with Planar, the applet lives in a plane but the interface should be optimized for medium-to-high resolution screens that are 5-15 feet distant from the viewer. Sometimes referred to as a "ten foot interface".*/ Horizontal, /**< The applet is constrained vertically, but can expand horizontally. */ Vertical /**< The applet is constrained horizontally, but can expand vertically. */ }; private: ContainmentProperties(QObject *parent = 0) : QObject(parent) {} }; class PlasmaApp : public KUniqueApplication { Q_OBJECT public: PlasmaApp(); ~PlasmaApp(); static PlasmaApp* self(); static QSize defaultScreenSize(); void notifyStartup(bool completed); Plasma::Corona* corona(); QList containments() const; QList panelContainments() const; PanelShadows *panelShadows(); protected: void setIsDesktop(bool isDesktop); void setupHomeScreen(); void setupContainment(Plasma::Containment *containment); void changeContainment(Plasma::Containment *containment); void reserveStruts(const int left, const int top, const int right, const int bottom); private Q_SLOTS: void cleanup(); void mainContainmentActivated(); void manageNewContainment(Plasma::Containment *containment); void containmentDestroyed(QObject *); void containmentScreenOwnerChanged(int wasScreen, int isScreen, Plasma::Containment *cont); void syncConfig(); void showWidgetsExplorer(); void showActivityConfiguration(Plasma::Containment *containment); void showActivityCreation(); void mainViewGeometryChanged(); void containmentWallpaperChanged(Plasma::Containment *containment); void gotStartup(const KStartupInfoId& id, const KStartupInfoData& data); void killStartup(const KStartupInfoId& id); void focusMainView(); + void activeWindowChanged(WId id); private: MobCorona *m_corona; MobView *m_mainView; //the main declarative scene loader Plasma::DeclarativeWidget *m_declarativeWidget; QDeclarativeItem *m_homeScreen; Plasma::Containment *m_currentContainment; QWeakPointer m_oldContainment; QMap m_containments; QHash m_panelContainments; MobPluginLoader *m_pluginLoader; PanelShadows *m_panelShadows; QString m_homeScreenPath; QWeakPointer m_widgetsExplorer; QWeakPointer m_activityConfiguration; bool m_isDesktop; KStartupInfo *m_startupInfo; QWeakPointer m_busyWidget; }; #endif // multiple inclusion guard