/* * Copyright 2007 Aaron Seigo * Copyright 2007 Matt Broadstone * Copyright (c) 2009 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 version 2 as * published by the Free Software Foundation * * 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 "desktopview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dashboardview.h" #include "desktopcorona.h" #include "plasmaapp.h" #include "plasma-shell-desktop.h" DesktopView::DesktopView(Plasma::Containment *containment, int id, QWidget *parent) : Plasma::View(containment, id, parent), m_dashboard(0), m_dashboardFollowsDesktop(true), m_init(false) { setAttribute(Qt::WA_TranslucentBackground, false); //setCacheMode(QGraphicsView::CacheNone); /*FIXME: Work around for a (maybe) Qt bug: * QApplication::focusWidget() can't track focus change in QGraphicsProxyWidget * wrapped normal widget (eg. QLineEdit), if the QGraphicsView has called * setFocusPolicy(Qt::NoFocus) * I've created a bug report to Qt Software. * There is also a simple reproduce program in case you're interested in this bug: * ftp://fearee:public@public.sjtu.edu.cn/reproduce.tar.gz */ //setFocusPolicy(Qt::NoFocus); setWindowFlags(windowFlags() | Qt::FramelessWindowHint); checkDesktopAffiliation(); KWindowSystem::setType(winId(), NET::Desktop); lower(); /* const int w = 25; QPixmap tile(w * 2, w * 2); tile.fill(palette().base().color()); QPainter pt(&tile); QColor color = palette().mid().color(); color.setAlphaF(.6); pt.fillRect(0, 0, w, w, color); pt.fillRect(w, w, w, w, color); pt.end(); QBrush b(tile); setBackgroundBrush(tile); */ KConfigGroup cg = config(); const uint dashboardContainmentId = cg.readEntry("DashboardContainment", uint(0)); m_dashboardFollowsDesktop = dashboardContainmentId == 0; // since Plasma::View has a delayed init we need to // put a delay also for this call in order to be sure // to have correct information set (e.g. screen()) if (containment) { QRect geom = PlasmaApp::self()->corona()->screenGeometry(containment->screen()); setGeometry(geom); } Kephal::Screens *screens = Kephal::Screens::self(); connect(screens, SIGNAL(screenResized(Kephal::Screen*,QSize,QSize)), this, SLOT(screenResized(Kephal::Screen*))); connect(screens, SIGNAL(screenMoved(Kephal::Screen*,QPoint,QPoint)), this, SLOT(screenMoved(Kephal::Screen*))); } DesktopView::~DesktopView() { delete m_dashboard; } void DesktopView::checkDesktopAffiliation() { if (AppSettings::perVirtualDesktopViews()) { m_desktop = containment() ? containment()->desktop() + 1 : -1; kDebug() << "setting to desktop" << m_desktop; KWindowSystem::setOnDesktop(winId(), m_desktop); } else { m_desktop = -1; KWindowSystem::setOnAllDesktops(winId(), true); } } void DesktopView::toggleDashboard() { kDebug() << "toggling dashboard for screen" << screen() << "and destop" << desktop() << (m_dashboard ? (m_dashboard->isVisible() ? "visible" : "hidden") : "non-existent"); prepDashboard(); if (m_dashboard) { m_dashboard->toggleVisibility(); kDebug() << "toggling dashboard for screen" << screen() << "and destop" << desktop() << m_dashboard->isVisible(); } } void DesktopView::showDashboard(bool show) { if (!show && (!m_dashboard || !m_dashboard->isVisible())) { return; } prepDashboard(); if (m_dashboard) { m_dashboard->showDashboard(show); } } void DesktopView::prepDashboard() { if (!m_dashboard) { if (!containment()) { return; } KConfigGroup cg = config(); Plasma::Containment *dc = dashboardContainment(); m_dashboardFollowsDesktop = dc == 0; if (dc) { dc->resize(size()); dc->enableAction("remove", false); } else { dc = containment(); } m_dashboard = new DashboardView(dc, this); connect(m_dashboard, SIGNAL(dashboardClosed()), this, SIGNAL(dashboardClosed())); m_dashboard->addActions(actions()); } //If a separate dashboard is used we must use the screen of this containment instead of the dashboard one if (!m_dashboardFollowsDesktop && containment()) { m_dashboard->setGeometry(PlasmaApp::self()->corona()->screenGeometry(containment()->screen())); } } Plasma::Containment *DesktopView::dashboardContainment() const { KConfigGroup cg = config(); Plasma::Containment *dc = 0; const uint containmentId = cg.readEntry("DashboardContainment", uint(0)); if (containmentId > 0) { foreach (Plasma::Containment *c, PlasmaApp::self()->corona()->containments()) { if (c->id() == containmentId) { dc = c; break; } } } return dc; } void DesktopView::setDashboardContainment(Plasma::Containment *containment) { if (containment) { config().writeEntry("DashboardContainment", containment->id()); if (m_dashboard) { m_dashboard->setContainment(containment); } } else { Plasma::Containment *dc = 0; if (dashboardContainment()) { dc = dashboardContainment(); } config().deleteEntry("DashboardContainment"); if (m_dashboard) { m_dashboard->setContainment(View::containment()); } //destroy this after changing the containment, makes sure the view won't receive the destroyed signal if (dc) { dc->destroy(false); } } m_dashboardFollowsDesktop = containment == 0; } void DesktopView::screenResized(Kephal::Screen *s) { if (s->id() == screen()) { kDebug() << screen(); adjustSize(); } } void DesktopView::screenMoved(Kephal::Screen *s) { if (s->id() == screen()) { kDebug() << screen(); adjustSize(); } } void DesktopView::adjustSize() { // adapt to screen resolution changes QRect geom = PlasmaApp::self()->corona()->screenGeometry(screen()); kDebug() << "screen" << screen() << "geom" << geom; setGeometry(geom); if (containment()) { containment()->resize(geom.size()); kDebug() << "Containment's geom after resize" << containment()->geometry(); } if (m_dashboard) { m_dashboard->setGeometry(geom); } kDebug() << "Done" << screen() << geometry(); } bool DesktopView::isDashboardVisible() const { return m_dashboard && m_dashboard->isVisible(); } bool DesktopView::dashboardFollowsDesktop() const { return m_dashboardFollowsDesktop; } void DesktopView::setContainment(Plasma::Containment *containment) { Plasma::Containment *oldContainment = this->containment(); if (m_init && containment == oldContainment) { //kDebug() << "initialized and containment is the same, aborting"; return; } PlasmaApp::self()->prepareContainment(containment); m_init = true; if (m_dashboard && m_dashboardFollowsDesktop) { m_dashboard->setContainment(containment); } KConfigGroup viewIds(KGlobal::config(), "ViewIds"); if (oldContainment) { disconnect(oldContainment, SIGNAL(toolBoxVisibilityChanged(bool)), this, SLOT(toolBoxOpened(bool))); disconnect(oldContainment, SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(showWidgetExplorer())); viewIds.deleteEntry(QString::number(oldContainment->id())); } if (containment) { connect(containment, SIGNAL(toolBoxVisibilityChanged(bool)), this, SLOT(toolBoxOpened(bool))); connect(containment, SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(showWidgetExplorer())); viewIds.writeEntry(QString::number(containment->id()), id()); if (containment->corona()) { containment->corona()->requestConfigSync(); } } View::setContainment(containment); } void DesktopView::toolBoxOpened(bool open) { if (isDashboardVisible()) { return; } NETRootInfo info(QX11Info::display(), NET::Supported); if (!info.isSupported(NET::WM2ShowingDesktop)) { return; } if (open) { connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(showDesktopUntoggled(WId))); } else { disconnect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(showDesktopUntoggled(WId))); } info.setShowingDesktop(open); } void DesktopView::showWidgetExplorer() { if (isDashboardVisible()) { return; } Plasma::Containment *c = containment(); if (c) { PlasmaApp::self()->showWidgetExplorer(screen(), c); } } void DesktopView::showDesktopUntoggled(WId id) { if (isDashboardVisible()) { return; } Plasma::Containment *c = containment(); if (c) { c->setToolBoxOpen(false); } KWindowSystem::activateWindow(id); } void DesktopView::screenOwnerChanged(int wasScreen, int isScreen, Plasma::Containment* newContainment) { if (PlasmaApp::isPanelContainment(newContainment)) { // we don't care about panel containments changing screens on us return; } /* kDebug() << "was:" << wasScreen << "is:" << isScreen << "my screen:" << screen() << "containment:" << (QObject *)newContainment << newContainment->activity() << "current containment" << (QObject *)containment() << "myself:" << (QObject *)this << "containment desktop:" << newContainment->desktop() << "my desktop:" << m_desktop; */ if (containment() == newContainment && wasScreen == screen() && (isScreen != wasScreen || AppSettings::perVirtualDesktopViews())) { //kDebug() << "nulling out containment"; setContainment(0); } if (isScreen > -1 && isScreen == screen() && (!AppSettings::perVirtualDesktopViews() || newContainment->desktop() == m_desktop - 1) ) { //kDebug() << "setting new containment"; setContainment(newContainment); } } #include "moc_desktopview.cpp"