diff options
author | Ken Moore <moorekou@gmail.com> | 2016-04-25 13:08:12 -0400 |
---|---|---|
committer | Ken Moore <moorekou@gmail.com> | 2016-04-25 13:08:12 -0400 |
commit | ed5ecf7ea7a482b4649e66ecb35fbc60af680684 (patch) | |
tree | acc0fa17d228259e847f55c678db9fb0a9b50f0c /src-qt5/core/lumina-desktop/panel-plugins/taskmanager | |
parent | Merge branch 'master' of github.com:pcbsd/lumina (diff) | |
download | lumina-ed5ecf7ea7a482b4649e66ecb35fbc60af680684.tar.gz lumina-ed5ecf7ea7a482b4649e66ecb35fbc60af680684.tar.bz2 lumina-ed5ecf7ea7a482b4649e66ecb35fbc60af680684.zip |
Rearrange the Lumina source tree quite a bit:
Now the utilites are arranged by category (core, core-utils, desktop-utils), so all the -utils may be excluded by a package system (or turned into separate packages) as needed.
Diffstat (limited to 'src-qt5/core/lumina-desktop/panel-plugins/taskmanager')
4 files changed, 508 insertions, 0 deletions
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp new file mode 100644 index 00000000..a67ef5d6 --- /dev/null +++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp @@ -0,0 +1,238 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2014, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "LTaskButton.h" +#include "LSession.h" + +#ifndef DEBUG +#define DEBUG 0 +#endif + +LTaskButton::LTaskButton(QWidget *parent, bool smallDisplay) : LTBWidget(parent){ + actMenu = new QMenu(this); + winMenu = new QMenu(this); + UpdateMenus(); + showText = !smallDisplay; + this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + this->setAutoRaise(false); //make sure these always look like buttons + this->setContextMenuPolicy(Qt::CustomContextMenu); + this->setFocusPolicy(Qt::NoFocus); + this->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + winMenu->setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(openActionMenu()) ); + connect(this, SIGNAL(clicked()), this, SLOT(buttonClicked()) ); + connect(winMenu, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(openActionMenu()) ); + connect(winMenu, SIGNAL(triggered(QAction*)), this, SLOT(winClicked(QAction*)) ); + connect(winMenu, SIGNAL(aboutToHide()), this, SIGNAL(MenuClosed())); + connect(actMenu, SIGNAL(aboutToHide()), this, SIGNAL(MenuClosed())); +} + +LTaskButton::~LTaskButton(){ + +} + +//=========== +// PUBLIC +//=========== +QList<WId> LTaskButton::windows(){ + QList<WId> list; + for(int i=0; i<WINLIST.length(); i++){ + list << WINLIST[i].windowID(); + } + return list; +} + +QString LTaskButton::classname(){ + return cname; +} + +bool LTaskButton::isActive(){ + return cstate == LXCB::ACTIVE; +} + +void LTaskButton::addWindow(WId win){ + WINLIST << LWinInfo(win); + UpdateButton(); +} + +void LTaskButton::rmWindow(WId win){ + for(int i=0; i<WINLIST.length(); i++){ + if(WINLIST[i].windowID() == win){ + WINLIST.removeAt(i); + break; + } + } + UpdateButton(); +} + +//========== +// PRIVATE +//========== +LWinInfo LTaskButton::currentWindow(){ + if(WINLIST.length() == 1 || cWin.windowID()==0){ + return WINLIST[0]; //only 1 window - this must be it + }else{ + return cWin; + } +} + +//============= +// PUBLIC SLOTS +//============= +void LTaskButton::UpdateButton(){ + if(winMenu->isVisible()){ return; } //skip this if the window menu is currently visible for now + bool statusOnly = (WINLIST.length() == LWINLIST.length()); + LWINLIST = WINLIST; + + winMenu->clear(); + LXCB::WINDOWVISIBILITY showstate = LXCB::IGNORE; + for(int i=0; i<WINLIST.length(); i++){ + if(WINLIST[i].windowID() == 0){ + WINLIST.removeAt(i); + i--; + continue; + } + if(i==0 && !statusOnly){ + //Update the button visuals from the first window + this->setIcon(WINLIST[i].icon(noicon)); + cname = WINLIST[i].Class(); + if(cname.isEmpty()){ + //Special case (chrome/chromium does not register *any* information with X except window title) + cname = WINLIST[i].text(); + if(cname.contains(" - ")){ cname = cname.section(" - ",-1); } + } + this->setToolTip(cname); + } + bool junk; + QAction *tmp = winMenu->addAction( WINLIST[i].icon(junk), WINLIST[i].text() ); + tmp->setData(i); //save which number in the WINLIST this entry is for + LXCB::WINDOWVISIBILITY stat = WINLIST[i].status(true); //update the saved state for the window + if(stat<LXCB::ACTIVE && WINLIST[i].windowID() == LSession::handle()->activeWindow()){ stat = LXCB::ACTIVE; } + if(stat > showstate){ showstate = stat; } //higher priority + } + //Now setup the button appropriately + // - visibility + if(showstate == LXCB::IGNORE || WINLIST.length() < 1){ this->setVisible(false); } + else{ this->setVisible(true); } + // - functionality + if(WINLIST.length() == 1){ + //single window + this->setPopupMode(QToolButton::DelayedPopup); + this->setMenu(actMenu); + if(showText){ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText( WINLIST[0].text()); } + else if(noicon){ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText( cname ); } + else{ this->setToolButtonStyle(Qt::ToolButtonIconOnly); this->setText(""); } + this->setToolTip(WINLIST[0].text()); + }else if(WINLIST.length() > 1){ + //multiple windows + this->setPopupMode(QToolButton::InstantPopup); + this->setMenu(winMenu); + this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + if(noicon || showText){ "("+QString::number(WINLIST.length())+") "+cname; } + else{ this->setText("("+QString::number(WINLIST.length())+")"); } + } + this->setState(showstate); //Make sure this is after the button setup so that it properly sets the margins/etc + cstate = showstate; //save this for later +} + +void LTaskButton::UpdateMenus(){ + //Action menu should be auto-created for the state of the current window (cWin/cstate) + actMenu->clear(); + if(cstate!=LXCB::ACTIVE){ + actMenu->addAction( LXDG::findIcon("edit-select",""), tr("Activate Window"), this, SLOT(triggerWindow()) ); + } + if(cstate!=LXCB::INVISIBLE){ + actMenu->addAction( LXDG::findIcon("view-close",""), tr("Minimize Window"), this, SLOT(minimizeWindow()) ); + if(LSession::handle()->XCB->WindowIsMaximized(cWin.windowID()) ){ + actMenu->addAction( LXDG::findIcon("view-restore",""), tr("Restore Window"), this, SLOT(maximizeWindow()) ); + }else{ + actMenu->addAction( LXDG::findIcon("view-fullscreen",""), tr("Maximize Window"), this, SLOT(maximizeWindow()) ); + } + } + actMenu->addAction( LXDG::findIcon("window-close",""), tr("Close Window"), this, SLOT(closeWindow()) ); +} + +//============= +// PRIVATE SLOTS +//============= +void LTaskButton::buttonClicked(){ + if(WINLIST.length() > 1){ + winMenu->popup(QCursor::pos()); + }else{ + triggerWindow(); + } +} + +void LTaskButton::closeWindow(){ + if(DEBUG){ qDebug() << "Close Window:" << this->text(); } + if(winMenu->isVisible()){ winMenu->hide(); } + LWinInfo win = currentWindow(); + LSession::handle()->XCB->CloseWindow(win.windowID()); + cWin = LWinInfo(); //clear the current +} + +void LTaskButton::maximizeWindow(){ + if(DEBUG){ qDebug() << "Maximize Window:" << this->text(); } + if(winMenu->isVisible()){ winMenu->hide(); } + LWinInfo win = currentWindow(); + LSession::handle()->XCB->MaximizeWindow(win.windowID()); + //LSession::handle()->adjustWindowGeom(win.windowID(), true); //run this for now until the WM works properly + cWin = LWinInfo(); //clear the current +} + +void LTaskButton::minimizeWindow(){ + if(DEBUG){ qDebug() << "Minimize Window:" << this->text(); } + if(winMenu->isVisible()){ winMenu->hide(); } + LWinInfo win = currentWindow(); + LSession::handle()->XCB->MinimizeWindow(win.windowID()); + cWin = LWinInfo(); //clear the current + QTimer::singleShot(100, this, SLOT(UpdateButton()) ); //make sure to update this button if losing active status +} + +void LTaskButton::triggerWindow(){ + LWinInfo win = currentWindow(); + //Check which state the window is currently in and flip it to the other + //LXCB::WINDOWSTATE state = cstate; + //if(DEBUG){ qDebug() << "Window State: " << state; } + if(cstate == LXCB::ACTIVE){ + if(DEBUG){ qDebug() << "Minimize Window:" << this->text(); } + LSession::handle()->XCB->MinimizeWindow(win.windowID()); + QTimer::singleShot(100, this, SLOT(UpdateButton()) ); //make sure to update this button if losing active status + }else{ + if(DEBUG){ qDebug() << "Activate Window:" << this->text(); } + LSession::handle()->XCB->ActivateWindow(win.windowID()); + } + cWin = LWinInfo(); //clear the current +} + +void LTaskButton::winClicked(QAction* act){ + //Get the window from the action + if(act->data().toInt() < WINLIST.length()){ + cWin = WINLIST[act->data().toInt()]; + cstate = cWin.status(); + }else{ cWin = LWinInfo(); } //clear it + //Now trigger the window + triggerWindow(); +} + +void LTaskButton::openActionMenu(){ + //Get the Window the mouse is currently over + QPoint curpos = QCursor::pos(); + QAction *act = winMenu->actionAt(winMenu->mapFromGlobal(curpos)); + //qDebug() << "Button Context Menu:" << curpos.x() << curpos.y() << winMenu->geometry().x() << winMenu->geometry().y() << winMenu->geometry().width() << winMenu->geometry().height(); + cWin = WINLIST[0]; //default to the first window + if( act != 0 && winMenu->isVisible() ){ + //Get the window from the action + //qDebug() << "Found Action:" << act->data().toInt(); + if(act->data().toInt() < WINLIST.length()){ + cWin = WINLIST[act->data().toInt()]; + } + } + cstate = cWin.status(); + //Now show the action menu + UpdateMenus(); + actMenu->popup(QCursor::pos()); +} diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.h b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.h new file mode 100644 index 00000000..43dbaa90 --- /dev/null +++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.h @@ -0,0 +1,70 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2014, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_DESKTOP_TASK_BUTTON_H +#define _LUMINA_DESKTOP_TASK_BUTTON_H + +// Qt includes +#include <QWidget> +#include <QList> +#include <QIcon> +#include <QCursor> +#include <QMenu> +#include <QEvent> +#include <QAction> + +// libLumina includes +#include <LuminaXDG.h> +#include <LuminaX11.h> + +// Local includes +#include "../../LWinInfo.h" +#include "../LTBWidget.h" + +class LTaskButton : public LTBWidget{ + Q_OBJECT +public: + LTaskButton(QWidget *parent=0, bool smallDisplay = true); + ~LTaskButton(); + + //Window Information + QList<WId> windows(); + QString classname(); + bool isActive(); + + //Window Management + void addWindow(WId win); //Add a window to this button + void rmWindow(WId win); //Remove a window from this button + +private: + QList<LWinInfo> WINLIST; + QList<LWinInfo> LWINLIST; + QMenu *actMenu; // action menu (custom context menu) + QMenu *winMenu; // window menu (if more than 1) + LWinInfo cWin; + QString cname; //class name for the entire button + bool noicon, showText; + + LWinInfo currentWindow(); //For getting the currently-active window + LXCB::WINDOWVISIBILITY cstate; //current state of the button + +public slots: + void UpdateButton(); //re-sync the current window infomation + void UpdateMenus(); //re-create the menus (text + icons) + +private slots: + void buttonClicked(); + void closeWindow(); //send the signal to close a window + void maximizeWindow(); //send the signal to maximize/restore a window + void minimizeWindow(); //send the signal to minimize a window (iconify) + void triggerWindow(); //change b/w visible and invisible + void winClicked(QAction*); + void openActionMenu(); + +signals: + void MenuClosed(); +}; +#endif diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp new file mode 100644 index 00000000..3e31a534 --- /dev/null +++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp @@ -0,0 +1,129 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2014, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "LTaskManagerPlugin.h" +#include "../../LSession.h" + +LTaskManagerPlugin::LTaskManagerPlugin(QWidget *parent, QString id, bool horizontal) : LPPlugin(parent, id, horizontal){ + timer = new QTimer(this); + timer->setSingleShot(true); + timer->setInterval(10); // 1/100 second + connect(timer, SIGNAL(timeout()), this, SLOT(UpdateButtons()) ); + usegroups = true; //backwards-compatible default value + if(id.contains("-nogroups")){ usegroups = false; } + connect(LSession::handle(), SIGNAL(WindowListEvent()), this, SLOT(checkWindows()) ); + connect(LSession::handle(), SIGNAL(WindowListEvent(WId)), this, SLOT(UpdateButton(WId)) ); + this->layout()->setContentsMargins(0,0,0,0); + QTimer::singleShot(0,this, SLOT(UpdateButtons()) ); //perform an initial sync + //QTimer::singleShot(100,this, SLOT(OrientationChange()) ); //perform an initial sync +} + +LTaskManagerPlugin::~LTaskManagerPlugin(){ + +} + +//============== +// PRIVATE SLOTS +//============== +void LTaskManagerPlugin::UpdateButtons(){ + updating = QDateTime::currentDateTime(); //global time stamp + QDateTime ctime = updating; //current thread time stamp + + //Get the current window list + QList<WId> winlist = LSession::handle()->XCB->WindowList(); + //Do not change the status of the previously active window if it just changed to a non-visible window + //WId activeWin = LSession::handle()->XCB->ActiveWindow(); + //bool skipActive = !winlist.contains(activeWin); + //qDebug() << "Update Buttons:" << winlist; + if(updating > ctime){ return; } //another thread kicked off already - stop this one + //Now go through all the current buttons first + for(int i=0; i<BUTTONS.length(); i++){ + //Get the windows managed in this button + QList<WId> WI = BUTTONS[i]->windows(); + bool updated=false; + if(updating > ctime){ return; } //another thread kicked off already - stop this one + //Loop over all the windows for this button + for(int w=0; w<WI.length(); w++){ + if(updating > ctime){ return; } //another thread kicked off already - stop this one + if( winlist.contains( WI[w] ) ){ + //Still current window - update it later + winlist.removeAll(WI[w] ); //remove this window from the list since it is done + }else{ + //Window was closed - remove it + if(WI.length()==1){ + //Remove the entire button + //qDebug() << "Window Closed: Remove Button" ; + this->layout()->takeAt(i); //remove from the layout + BUTTONS.takeAt(i)->deleteLater(); + i--; + updated = true; //prevent updating a removed button + break; //break out of the button->window loop + }else{ + //qDebug() << "Window Closed: Remove from button:" << WI[w].windowID() << "Button:" << w; + BUTTONS[i]->rmWindow(WI[w]); // one of the multiple windows for the button + WI.removeAt(w); //remove this window from the list + w--; + } + updated=true; //button already changed + } + if(updating > ctime){ return; } //another thread kicked off already - stop this one + } + if(!updated){ + //qDebug() << "Update Button:" << i; + if(updating > ctime){ return; } //another thread kicked off already - stop this one + //if(!skipActive || !BUTTONS[i]->isActive()){ + QTimer::singleShot(1,BUTTONS[i], SLOT(UpdateButton()) ); //keep moving on + //} + } + } + //Now go through the remaining windows + for(int i=0; i<winlist.length(); i++){ + //New windows, create buttons for each (add grouping later) + if(updating > ctime){ return; } //another thread kicked off already - stop this one + //Check for a button that this can just be added to + QString ctxt = LSession::handle()->XCB->WindowClass(winlist[i]); + bool found = false; + for(int b=0; b<BUTTONS.length(); b++){ + if(updating > ctime){ return; } //another thread kicked off already - stop this one + if(BUTTONS[b]->classname()== ctxt && usegroups){ + //This adds a window to an existing group + found = true; + //qDebug() << "Add Window to Button:" << b; + BUTTONS[b]->addWindow(winlist[i]); + break; + } + } + if(!found){ + if(updating > ctime){ return; } //another thread kicked off already - stop this one + //No group, create a new button + //qDebug() << "New Button"; + LTaskButton *but = new LTaskButton(this, usegroups); + but->addWindow( winlist[i] ); + if(this->layout()->direction()==QBoxLayout::LeftToRight){ + but->setIconSize(QSize(this->height(), this->height())); + }else{ + but->setIconSize(QSize(this->width(), this->width())); + } + this->layout()->addWidget(but); + connect(but, SIGNAL(MenuClosed()), this, SIGNAL(MenuClosed())); + BUTTONS << but; + } + } +} + +void LTaskManagerPlugin::UpdateButton(WId win){ + for(int i=0; i<BUTTONS.length(); i++){ + if(BUTTONS[i]->windows().contains(win)){ + qDebug() << "Update Task Manager Button (single window ping)"; + QTimer::singleShot(0,BUTTONS[i], SLOT(UpdateButton()) ); + break; + } + } +} + +void LTaskManagerPlugin::checkWindows(){ + timer->start(); +} diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.h b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.h new file mode 100644 index 00000000..e6371f34 --- /dev/null +++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.h @@ -0,0 +1,71 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2014, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_DESKTOP_TASK_MANAGER_PLUGIN_H +#define _LUMINA_DESKTOP_TASK_MANAGER_PLUGIN_H + +// Qt includes +#include <QWidget> +#include <QList> +#include <QString> +#include <QDebug> +#include <QTimer> +#include <QEvent> +#include <QDateTime> + +// libLumina includes +#include <LuminaX11.h> + +// Local includes +#include "LTaskButton.h" +#include "LWinInfo.h" +#include "../LPPlugin.h" + +class LTaskManagerPlugin : public LPPlugin{ + Q_OBJECT +public: + LTaskManagerPlugin(QWidget *parent=0, QString id="taskmanager", bool horizontal=true); + ~LTaskManagerPlugin(); + +private: + QList<LTaskButton*> BUTTONS; //to keep track of the current buttons + QTimer *timer; + QDateTime updating; //quick flag for if it is currently working + bool usegroups; + +private slots: + void UpdateButtons(); + void UpdateButton(WId win); + void checkWindows(); + +public slots: + void LocaleChange(){ + UpdateButtons(); + } + void ThemeChange(){ + UpdateButtons(); + } + void OrientationChange(){ + if(this->layout()->direction()==QBoxLayout::LeftToRight){ //horizontal + this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + this->layout()->setAlignment(Qt::AlignLeft); + QSize sz(this->height(), this->height()); + for(int i=0; i<BUTTONS.length(); i++){ + BUTTONS[i]->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + BUTTONS[i]->setIconSize(sz); + } + }else{ //vertical + this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + this->layout()->setAlignment(Qt::AlignTop); + QSize sz(this->width(), this->width()); + for(int i=0; i<BUTTONS.length(); i++){ + BUTTONS[i]->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); + BUTTONS[i]->setIconSize(sz); + } + } + } +}; +#endif
\ No newline at end of file |