/*********************************************************************************** * Window List: Plasmoid to show list of opened windows. * Copyright (C) 2009 Michal Dutkiewicz aka Emdek * * 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 "WindowList.h" #include #include #include #include #include #include #include #include #include #include #include #include K_EXPORT_PLASMA_APPLET(windowlist, WindowList) WindowList::WindowList(QObject *parent, const QVariantList &args) : Plasma::Applet(parent, args) { setAspectRatioMode(Plasma::ConstrainedSquare); const int iconSize = IconSize(KIconLoader::Desktop); resize((iconSize * 2), (iconSize * 2)); } WindowList::~WindowList() { qDeleteAll(m_listMenu->actions()); delete m_listMenu; } void WindowList::init() { Plasma::IconWidget *icon = new Plasma::IconWidget(KIcon("preferences-system-windows"), QString(), this); m_listMenu = new KWindowListMenu; m_listMenu->installEventFilter(this); registerAsDragHandle(icon); QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addItem(icon); Plasma::ToolTipManager::self()->setContent(this, Plasma::ToolTipContent(i18n("Window list"), i18n("Show list of opened windows"), KIcon("preferences-system-windows").pixmap(IconSize(KIconLoader::Desktop)))); connect(this, SIGNAL(activate()), this, SLOT(showMenu())); connect(this, SIGNAL(destroyed()), m_listMenu, SLOT(deleteLater())); connect(icon, SIGNAL(clicked()), this, SLOT(showMenu())); connect(m_listMenu, SIGNAL(triggered(QAction*)), this, SLOT(triggered(QAction*))); } void WindowList::mousePressEvent(QGraphicsSceneMouseEvent *event) { Applet::mousePressEvent(event); if (event->button() == Qt::MidButton) { event->accept(); } } void WindowList::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Applet::mouseReleaseEvent(event); if (event->button() == Qt::MidButton) { showMenu(true); } } void WindowList::wheelEvent(QGraphicsSceneWheelEvent *event) { QList windows = KWindowSystem::windows(); if (windows.count() < 2) { return; } int position = windows.indexOf(KWindowSystem::activeWindow()); if (event->delta() > 0) { ++position; if (position >= windows.count()) { position = 0; } } else { --position; if (position < 0) { position = (windows.count() - 1); } } KWindowSystem::activateWindow(windows.at(position)); } bool WindowList::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::ContextMenu) { KMenu *menu = qobject_cast(object); if (menu && menu->activeAction() && menu->activeAction()->data().type() == QVariant::ULongLong) { QContextMenuEvent *cmEvent = static_cast(event); QList actionList; TaskManager::TaskItem item(this, TaskManager::TaskManager::self()->findTask((WId)menu->activeAction()->data().toULongLong())); TaskManager::GroupManager groupManager(this); TaskManager::BasicMenu taskMenu(NULL, &item, &groupManager, actionList); if (taskMenu.exec(cmEvent->globalPos())) { m_listMenu->hide(); } return true; } } else if (event->type() == QEvent::MouseButtonPress) { QMouseEvent *mouseEvent = static_cast(event); if (mouseEvent->button() != Qt::LeftButton) { return false; } KMenu *menu = static_cast(object); if (menu && menu->activeAction() && menu->activeAction()->data().type() == QVariant::ULongLong) { m_dragStartPosition = mouseEvent->pos(); } } else if (event->type() == QEvent::MouseMove) { QMouseEvent *mouseEvent = static_cast(event); if (!(mouseEvent->buttons() & Qt::LeftButton) || (mouseEvent->pos() - m_dragStartPosition).manhattanLength() < QApplication::startDragDistance()) { return false; } KMenu *menu = static_cast(object); if (menu && menu->activeAction() && menu->activeAction()->data().type() == QVariant::ULongLong) { QDrag *drag = new QDrag(menu); QMimeData *mimeData = new QMimeData; QByteArray data; WId window = (WId)menu->activeAction()->data().toULongLong(); data.resize(sizeof(WId)); memcpy(data.data(), &window, sizeof(WId)); mimeData->setData("windowsystem/winid", data); drag->setMimeData(mimeData); drag->setPixmap(menu->activeAction()->icon().pixmap(32, 32)); m_listMenu->hide(); drag->exec(); return true; } } return QObject::eventFilter(object, event); } void WindowList::showMenu(bool onlyCurrentDesktop) { QList windows = KWindowSystem::windows(); QList actionList; QList< QList > windowList; int amount = 0; int number = 0; qDeleteAll(m_listMenu->actions()); //m_listMenu->clear(); if (!onlyCurrentDesktop) { m_listMenu->addTitle(i18n("Actions")); QAction *unclutterAction = m_listMenu->addAction(i18n("Unclutter Windows")); QAction *cascadeAction = m_listMenu->addAction(i18n("Cascade Windows")); connect(unclutterAction, SIGNAL(triggered()), m_listMenu, SLOT(slotUnclutterWindows())); connect(cascadeAction, SIGNAL(triggered()), m_listMenu, SLOT(slotCascadeWindows())); } for (int i = 0; i <= KWindowSystem::numberOfDesktops(); ++i) { windowList.append(QList()); } for (int i = 0; i < windows.count(); ++i) { KWindowInfo window = KWindowSystem::windowInfo(windows.at(i), (NET::WMGeometry | NET::WMFrameExtents | NET::WMWindowType | NET::WMDesktop | NET::WMState | NET::XAWMState | NET::WMVisibleName)); NET::WindowType type = window.windowType(NET::NormalMask | NET::DialogMask | NET::UtilityMask | NET::DesktopMask | NET::DockMask | NET::SplashMask | NET::ToolbarMask | NET::MenuMask); if ((onlyCurrentDesktop && !window.isOnDesktop(KWindowSystem::currentDesktop())) || type == NET::Desktop || type == NET::Dock || type == NET::Splash || type == NET::Menu || type == NET::Toolbar || window.hasState(NET::SkipPager)) { windows.removeAt(i); --i; continue; } ++amount; QAction *action = new QAction(QIcon(KWindowSystem::icon(windows.at(i))), window.visibleName(), this); action->setData((unsigned long long) windows.at(i)); QString window_title = QString(action->text()); window_title.truncate(55); action->setText(window_title); QFont font = QFont(action->font()); if (window.isMinimized()) { font.setItalic(true); } else if (KWindowSystem::activeWindow() == windows.at(i)) { font.setUnderline(true); font.setBold(true); } action->setFont(font); number = ((onlyCurrentDesktop || window.onAllDesktops()) ? 0 : window.desktop()); QList subList = windowList.value(number); subList.append(action); windowList.replace(number, subList); } const bool useSubMenus = (!onlyCurrentDesktop && KWindowSystem::numberOfDesktops() > 1 && (amount / KWindowSystem::numberOfDesktops()) > 5); if (amount && useSubMenus) { m_listMenu->addTitle(i18n("Desktops")); } for (int i = 0; i <= KWindowSystem::numberOfDesktops(); ++i) { if (windowList.value(i).isEmpty()) { continue; } KMenu *subMenu = NULL; QAction *subMenuAction = NULL; QString title = (i ? KWindowSystem::desktopName(i) : (onlyCurrentDesktop ? i18n("Current desktop") : i18n("On all desktops"))); if (useSubMenus) { subMenuAction = m_listMenu->addAction(title); subMenu = new KMenu(m_listMenu); subMenu->installEventFilter(this); } else { m_listMenu->addTitle(title); } for (int j = 0; j < windowList.value(i).count(); ++j) { if (useSubMenus) { subMenu->addAction(windowList.value(i).value(j)); } else { m_listMenu->addAction(windowList.value(i).value(j)); } } if (useSubMenus) { subMenuAction->setMenu(subMenu); } } if (!amount) { qDeleteAll(m_listMenu->actions()); m_listMenu->clear(); QAction *noWindows = m_listMenu->addAction(i18n("No windows")); noWindows->setEnabled(false); } if (formFactor() == Plasma::Vertical || formFactor() == Plasma::Horizontal) { m_listMenu->popup(popupPosition(m_listMenu->sizeHint())); } else { m_listMenu->popup(QCursor::pos()); } } void WindowList::triggered(QAction *action) { if (action->data().type() == QVariant::ULongLong) { if (KWindowSystem::activeWindow() == (WId)action->data().toULongLong()) { KWindowSystem::minimizeWindow((WId)action->data().toULongLong()); } else { KWindowSystem::activateWindow((WId)action->data().toULongLong()); } } } #include "moc_WindowList.cpp"