1 //===========================================
2 // Lumina-DE source code
3 // Copyright (c) 2012-2015, Ken Moore
4 // Available under the 3-clause BSD license
5 // See the LICENSE file for full details
6 //===========================================
7 #include "LSysTray.h"
8 #include "../../LSession.h"
9
LSysTray(QWidget * parent,QString id,bool horizontal)10 LSysTray::LSysTray(QWidget *parent, QString id, bool horizontal) : LPPlugin(parent, id, horizontal){
11 frame = new QFrame(this);
12 frame->setContentsMargins(0,0,0,0);
13 //frame->setStyleSheet("QFrame{ background: transparent; border: 1px solid transparent; border-radius: 3px; }");
14 LI = new QBoxLayout( this->layout()->direction());
15 frame->setLayout(LI);
16 LI->setAlignment(Qt::AlignCenter);
17 LI->setSpacing(0);
18 LI->setContentsMargins(0,0,0,0);
19 this->layout()->addWidget(frame);
20 this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
21 //TrayID=0;
22 upTimer = new QTimer(this);
23 upTimer->setInterval(300000); //maximum time between refreshes is 5 minutes
24 connect(upTimer, SIGNAL(timeout()), this, SLOT(checkAll()) );
25 isRunning = false; stopping = false; checking = false; pending = false;
26 QTimer::singleShot(100, this, SLOT(start()) );
27 //Also do one extra check a minute or so after startup (just in case something got missed in the initial flood of registrations)
28 QTimer::singleShot(90000,this, SLOT(checkAll()) );
29 connect(LSession::handle(), SIGNAL(TrayListChanged()), this, SLOT(checkAll()) );
30 connect(LSession::handle(), SIGNAL(TrayIconChanged(WId)), this, SLOT(UpdateTrayWindow(WId)) );
31 connect(LSession::handle(), SIGNAL(VisualTrayAvailable()), this, SLOT(start()) );
32 }
33
~LSysTray()34 LSysTray::~LSysTray(){
35 if(isRunning){
36 this->stop();
37 }
38 }
39
start()40 void LSysTray::start(){
41 if(isRunning || stopping){ return; } //already running
42 isRunning = LSession::handle()->registerVisualTray(this->winId());
43 qDebug() << "Visual Tray Started:" << this->type() << isRunning;
44 if(isRunning){
45 //upTimer->start();
46 QTimer::singleShot(0,this, SLOT(checkAll()) );
47 }
48 }
49
stop()50 void LSysTray::stop(){
51 if(!isRunning){ return; }
52 stopping = true;
53 upTimer->stop();
54 //Now close down the system tray registry
55 qDebug() << "Stop visual system tray:" << this->type();
56 //LX11::closeSystemTray(TrayID);
57 //TrayID = 0;
58 disconnect(this); //remove any signals/slots
59 isRunning = false;
60 //Release all the tray applications and delete the containers
61 if( !LSession::handle()->currentTrayApps(this->winId()).isEmpty() ){
62 qDebug() << " - Remove tray applications";
63 //This overall system tray is not closed down - go ahead and release them here
64 for(int i=(trayIcons.length()-1); i>=0; i--){
65 trayIcons[i]->detachApp();
66 TrayIcon *cont = trayIcons.takeAt(i);
67 LI->removeWidget(cont);
68 cont->deleteLater();
69 }
70 }
71 //Now let some other visual tray take over
72 LSession::handle()->unregisterVisualTray(this->winId());
73 qDebug() << "Done stopping visual tray";
74 }
75
76 // ========================
77 // PRIVATE FUNCTIONS
78 // ========================
checkAll()79 void LSysTray::checkAll(){
80 if(!isRunning || stopping || checking){ pending = true; return; } //Don't check if not running at the moment
81 checking = true;
82 pending = false;
83 bool listChanged = false;
84 //Make sure this tray should handle the windows (was not disabled in the backend)
85 bool TrayRunning = LSession::handle()->registerVisualTray(this->winId());
86 //qDebug() << "System Tray: Check tray apps";
87 QList<WId> wins = LSession::handle()->currentTrayApps(this->winId());
88 for(int i=0; i<trayIcons.length(); i++){
89 int index = wins.indexOf(trayIcons[i]->appID());
90 if(index < 0){
91 //Tray Icon no longer exists: remove it
92 qDebug() << " - Visual System Tray: Remove Icon:" << trayIcons[i]->appID();
93 TrayIcon *cont = trayIcons.takeAt(i);
94 cont->cleanup();
95 LI->removeWidget(cont);
96 cont->deleteLater();
97 i--; //List size changed
98 listChanged = true;
99 //Re-adjust the maximum widget size to account for what is left
100 if(this->layout()->direction()==QBoxLayout::LeftToRight){
101 this->setMaximumSize( trayIcons.length()*this->height(), 10000);
102 }else{
103 this->setMaximumSize(10000, trayIcons.length()*this->width());
104 }
105 }else{
106 //Tray Icon already exists
107 //qDebug() << " - SysTray: Update Icon";
108 //trayIcons[i]->repaint();
109 wins.removeAt(index); //Already found - remove from the list
110 }
111 }
112 //Now go through any remaining windows and add them
113 for(int i=0; i<wins.length() && TrayRunning; i++){
114 qDebug() << " - Visual System Tray: Add Icon:" << wins[i];
115 TrayIcon *cont = new TrayIcon(this);
116 connect(cont, SIGNAL(BadIcon()), this, SLOT(checkAll()) );
117 //LSession::processEvents();
118 trayIcons << cont;
119 LI->addWidget(cont);
120 //qDebug() << " - Update tray layout";
121 if(this->layout()->direction()==QBoxLayout::LeftToRight){
122 int sz = this->height()-2-2*frame->frameWidth();
123 if(sz>64){ sz = 64; }
124 cont->setSizeSquare(sz); //horizontal tray
125 this->setMaximumSize( trayIcons.length()*this->height(), 10000);
126 }else{
127 int sz = this->width()-2-2*frame->frameWidth();
128 if(sz>64){ sz = 64; }
129 cont->setSizeSquare(sz); //vertical tray
130 this->setMaximumSize(10000, trayIcons.length()*this->width());
131 }
132 //LSession::processEvents();
133 //qDebug() << " - Attach tray app";
134 cont->attachApp(wins[i]);
135 if(cont->appID()==0){
136 //could not attach window - remove the widget
137 qDebug() << " - Invalid Tray App: Could Not Embed:";
138 trayIcons.takeAt(trayIcons.length()-1); //Always at the end
139 LI->removeWidget(cont);
140 cont->deleteLater();
141 continue;
142 }
143 LI->update(); //make sure there is no blank space in the layout
144 listChanged = true;
145 }
146 if(listChanged){
147 //Icons got moved around: be sure to re-draw all of them to fix visuals
148 for(int i=0; i<trayIcons.length(); i++){
149 trayIcons[i]->repaint();
150 }
151 }
152 //qDebug() << " - System Tray: check done";
153 checking = false;
154 if(pending){ QTimer::singleShot(0,this, SLOT(checkAll()) ); }
155 }
156
UpdateTrayWindow(WId win)157 void LSysTray::UpdateTrayWindow(WId win){
158 if(!isRunning || stopping || checking){ return; }
159 for(int i=0; i<trayIcons.length(); i++){
160 if(trayIcons[i]->appID()==win){
161 //qDebug() << "System Tray: Update Window " << win;
162 trayIcons[i]->repaint(); //don't use update() because we need an instant repaint (not a cached version)
163 return; //finished now
164 }
165 }
166 //Could not find tray in the list, run the checkall routine to make sure we are not missing any
167 //qDebug() << "System Tray: Missing Window - check all";
168 QTimer::singleShot(0,this, SLOT(checkAll()) );
169 }
170