//=========================================== // Lumina-DE source code // Copyright (c) 2012-2015, Ken Moore // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== #include "LSysTray.h" #include "../../LSession.h" LSysTray::LSysTray(QWidget *parent, QString id, bool horizontal) : LPPlugin(parent, id, horizontal){ frame = new QFrame(this); frame->setContentsMargins(0,0,0,0); //frame->setStyleSheet("QFrame{ background: transparent; border: 1px solid transparent; border-radius: 3px; }"); LI = new QBoxLayout( this->layout()->direction()); frame->setLayout(LI); LI->setAlignment(Qt::AlignCenter); LI->setSpacing(0); LI->setContentsMargins(0,0,0,0); this->layout()->addWidget(frame); this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); //TrayID=0; upTimer = new QTimer(this); upTimer->setInterval(300000); //maximum time between refreshes is 5 minutes connect(upTimer, SIGNAL(timeout()), this, SLOT(checkAll()) ); isRunning = false; stopping = false; checking = false; pending = false; QTimer::singleShot(100, this, SLOT(start()) ); //Also do one extra check a minute or so after startup (just in case something got missed in the initial flood of registrations) QTimer::singleShot(90000,this, SLOT(checkAll()) ); connect(LSession::handle(), SIGNAL(TrayListChanged()), this, SLOT(checkAll()) ); connect(LSession::handle(), SIGNAL(TrayIconChanged(WId)), this, SLOT(UpdateTrayWindow(WId)) ); connect(LSession::handle(), SIGNAL(VisualTrayAvailable()), this, SLOT(start()) ); } LSysTray::~LSysTray(){ if(isRunning){ this->stop(); } } void LSysTray::start(){ if(isRunning || stopping){ return; } //already running isRunning = LSession::handle()->registerVisualTray(this->winId()); qDebug() << "Visual Tray Started:" << this->type() << isRunning; if(isRunning){ //upTimer->start(); QTimer::singleShot(0,this, SLOT(checkAll()) ); } } void LSysTray::stop(){ if(!isRunning){ return; } stopping = true; upTimer->stop(); //Now close down the system tray registry qDebug() << "Stop visual system tray:" << this->type(); //LX11::closeSystemTray(TrayID); //TrayID = 0; disconnect(this); //remove any signals/slots isRunning = false; //Release all the tray applications and delete the containers if( !LSession::handle()->currentTrayApps(this->winId()).isEmpty() ){ qDebug() << " - Remove tray applications"; //This overall system tray is not closed down - go ahead and release them here for(int i=(trayIcons.length()-1); i>=0; i--){ trayIcons[i]->detachApp(); TrayIcon *cont = trayIcons.takeAt(i); LI->removeWidget(cont); cont->deleteLater(); } } //Now let some other visual tray take over LSession::handle()->unregisterVisualTray(this->winId()); qDebug() << "Done stopping visual tray"; } // ======================== // PRIVATE FUNCTIONS // ======================== void LSysTray::checkAll(){ if(!isRunning || stopping || checking){ pending = true; return; } //Don't check if not running at the moment checking = true; pending = false; bool listChanged = false; //Make sure this tray should handle the windows (was not disabled in the backend) bool TrayRunning = LSession::handle()->registerVisualTray(this->winId()); //qDebug() << "System Tray: Check tray apps"; QList wins = LSession::handle()->currentTrayApps(this->winId()); for(int i=0; iappID()); if(index < 0){ //Tray Icon no longer exists: remove it qDebug() << " - Visual System Tray: Remove Icon:" << trayIcons[i]->appID(); TrayIcon *cont = trayIcons.takeAt(i); cont->cleanup(); LI->removeWidget(cont); cont->deleteLater(); i--; //List size changed listChanged = true; //Re-adjust the maximum widget size to account for what is left if(this->layout()->direction()==QBoxLayout::LeftToRight){ this->setMaximumSize( trayIcons.length()*this->height(), 10000); }else{ this->setMaximumSize(10000, trayIcons.length()*this->width()); } }else{ //Tray Icon already exists //qDebug() << " - SysTray: Update Icon"; //trayIcons[i]->repaint(); wins.removeAt(index); //Already found - remove from the list } } //Now go through any remaining windows and add them for(int i=0; iaddWidget(cont); //qDebug() << " - Update tray layout"; if(this->layout()->direction()==QBoxLayout::LeftToRight){ int sz = this->height()-2-2*frame->frameWidth(); if(sz>64){ sz = 64; } cont->setSizeSquare(sz); //horizontal tray this->setMaximumSize( trayIcons.length()*this->height(), 10000); }else{ int sz = this->width()-2-2*frame->frameWidth(); if(sz>64){ sz = 64; } cont->setSizeSquare(sz); //vertical tray this->setMaximumSize(10000, trayIcons.length()*this->width()); } //LSession::processEvents(); //qDebug() << " - Attach tray app"; cont->attachApp(wins[i]); if(cont->appID()==0){ //could not attach window - remove the widget qDebug() << " - Invalid Tray App: Could Not Embed:"; trayIcons.takeAt(trayIcons.length()-1); //Always at the end LI->removeWidget(cont); cont->deleteLater(); continue; } LI->update(); //make sure there is no blank space in the layout listChanged = true; } if(listChanged){ //Icons got moved around: be sure to re-draw all of them to fix visuals for(int i=0; irepaint(); } } //qDebug() << " - System Tray: check done"; checking = false; if(pending){ QTimer::singleShot(0,this, SLOT(checkAll()) ); } } void LSysTray::UpdateTrayWindow(WId win){ if(!isRunning || stopping || checking){ return; } for(int i=0; iappID()==win){ //qDebug() << "System Tray: Update Window " << win; trayIcons[i]->repaint(); //don't use update() because we need an instant repaint (not a cached version) return; //finished now } } //Could not find tray in the list, run the checkall routine to make sure we are not missing any //qDebug() << "System Tray: Missing Window - check all"; QTimer::singleShot(0,this, SLOT(checkAll()) ); }