aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/lumina-desktop/panel-plugins/taskmanager
diff options
context:
space:
mode:
authorKen Moore <moorekou@gmail.com>2016-04-25 13:08:12 -0400
committerKen Moore <moorekou@gmail.com>2016-04-25 13:08:12 -0400
commited5ecf7ea7a482b4649e66ecb35fbc60af680684 (patch)
treeacc0fa17d228259e847f55c678db9fb0a9b50f0c /src-qt5/core/lumina-desktop/panel-plugins/taskmanager
parentMerge branch 'master' of github.com:pcbsd/lumina (diff)
downloadlumina-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')
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp238
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.h70
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp129
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.h71
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
bgstack15