diff options
author | Ken Moore <ken@pcbsd.org> | 2014-10-17 08:41:49 -0400 |
---|---|---|
committer | Ken Moore <ken@pcbsd.org> | 2014-10-17 08:41:49 -0400 |
commit | 0394411a5c589b3c19fd3ecd2a6b4836f1a74a88 (patch) | |
tree | 8990178419840553011e2bf38fa079c5f50fc538 /lumina-desktop/LSession.cpp | |
parent | Add a quick "make-linux-distro.sh" script to change the linux template file u... (diff) | |
download | lumina-0394411a5c589b3c19fd3ecd2a6b4836f1a74a88.tar.gz lumina-0394411a5c589b3c19fd3ecd2a6b4836f1a74a88.tar.bz2 lumina-0394411a5c589b3c19fd3ecd2a6b4836f1a74a88.zip |
Adjust how the backend for the system tray works:
1) Now the Lumina session registeres the system-wide tray, and just keeps track of the windows that should be visible (preventing any loss of service or apps starting up before the tray is registered).
2) The system tray plugin is now just a "visual tray" for embedding the applications in the panel. The Session only allows a single visual tray to be registered at a time, but sends out signals whenever there is an opening for a visual tray (allowing near-instant transfer of tray applications from one visual tray to another).
Also fix a quick bug in lumina-config where the save button was getting activated simply by changing the appearance/plugins tab in the panel configuration (without actually changing anything).
Diffstat (limited to 'lumina-desktop/LSession.cpp')
-rw-r--r-- | lumina-desktop/LSession.cpp | 160 |
1 files changed, 155 insertions, 5 deletions
diff --git a/lumina-desktop/LSession.cpp b/lumina-desktop/LSession.cpp index bd7d49fb..0507f920 100644 --- a/lumina-desktop/LSession.cpp +++ b/lumina-desktop/LSession.cpp @@ -16,9 +16,9 @@ #include <X11/Xutil.h> #include <X11/Xatom.h> #include <X11/extensions/Xrender.h> +#include <X11/extensions/Xdamage.h> //Private/global variables (for static function access) -//static WId LuminaSessionTrayID; static AppMenu *appmenu; static SettingsMenu *settingsmenu; static QTranslator *currTranslator; @@ -37,7 +37,9 @@ LSession::LSession(int &argc, char ** argv) : QApplication(argc, argv){ this->setEffectEnabled( Qt::UI_AnimateCombo, true); this->setEffectEnabled( Qt::UI_AnimateTooltip, true); //this->setStyle( new MenuProxyStyle); //QMenu icon size override - //LuminaSessionTrayID = 0; + SystemTrayID = 0; VisualTrayID = 0; + TrayDmgEvent = 0; + TrayDmgError = 0; } LSession::~LSession(){ @@ -68,7 +70,10 @@ void LSession::setupSession(){ qDebug() << " - Launching Fluxbox"; WM = new WMProcess(); WM->startWM(); - + + //Start the background system tray + startSystemTray(); + //Initialize the desktops updateDesktops(); @@ -233,11 +238,11 @@ void LSession::updateDesktops(){ void LSession::SessionEnding(){ audioThread->wait(3000); //wait a max of 3 seconds for the audio thread to finish + stopSystemTray(); } bool LSession::x11EventFilter(XEvent *event){ //Detect X Event types and send the appropriate signal(s) - emit TrayEvent(event); //Make sure the tray also can check this event switch(event->type){ // ------------------------- case PropertyNotify: @@ -253,7 +258,61 @@ bool LSession::x11EventFilter(XEvent *event){ emit WindowListEvent(); } break; - } + //------------------------------ + // System Tray Events + //------------------------------ + case ClientMessage: + //Only check if the client is the system tray, otherwise ignore + if(event->xany.window == SystemTrayID){ + //qDebug() << "SysTray: ClientMessage"; + switch(event->xclient.data.l[1]){ + case SYSTEM_TRAY_REQUEST_DOCK: + attachTrayWindow(event->xclient.data.l[2]); //Window ID + break; + //case SYSTEM_TRAY_BEGIN_MESSAGE: + //Let the window manager handle the pop-up messages for now + //break; + //case SYSTEM_TRAY_CANCEL_MESSAGE: + //Let the window manager handle the pop-up messages for now + //break; + } + } + break; + case SelectionClear: + if(event->xany.window == SystemTrayID){ + //qDebug() << "SysTray: Selection Clear"; + stopSystemTray(); //de-activate this system tray (release all embeds) + } + break; + case DestroyNotify: + //qDebug() << "SysTray: DestroyNotify"; + removeTrayWindow(event->xany.window); //Check for removing an icon + break; + + case ConfigureNotify: + for(int i=0; i<RunningTrayApps.length(); i++){ + if(event->xany.window==RunningTrayApps[i]){ + //qDebug() << "SysTray: Configure Event" << trayIcons[i]->appID(); + emit TrayIconChanged(RunningTrayApps[i]); //trigger a repaint event + break; + } + } + default: + if(SystemTrayID!=0){ //Only do this if the system tray is available + if(event->type == TrayDmgEvent+XDamageNotify){ + WId ID = reinterpret_cast<XDamageNotifyEvent*>(event)->drawable; + //qDebug() << "SysTray: Damage Event"; + for(int i=0; i<RunningTrayApps.length(); i++){ + if(ID==RunningTrayApps[i]){ + //qDebug() << "SysTray: Damage Event" << ID; + emit TrayIconChanged(ID); //trigger a repaint event + break; + } + } + } + } + + } //end event type switch // ----------------------- //Now continue on with the event handling (don't change it) return false; @@ -306,3 +365,94 @@ void LSession::playAudioFile(QString filepath){ audioThread->start(); } } + +//====================== +// SYSTEM TRAY FUNCTIONS +//====================== +bool LSession::registerVisualTray(WId visualTray){ + //Only one visual tray can be registered at a time + // (limitation of how tray apps are embedded) + if(VisualTrayID==0){ VisualTrayID = visualTray; return true; } + else if(VisualTrayID==visualTray){ return true; } + else{ return false; } +} + +void LSession::unregisterVisualTray(WId visualTray){ + if(VisualTrayID==visualTray){ + qDebug() << "Unregistered Visual Tray"; + VisualTrayID=0; + emit VisualTrayAvailable(); + } +} + +QList<WId> LSession::currentTrayApps(WId visualTray){ + if(visualTray==VisualTrayID){ + return RunningTrayApps; + }else if( registerVisualTray(visualTray) ){ + return RunningTrayApps; + }else{ + return QList<WId>(); + } +} + +void LSession::startSystemTray(){ + if(SystemTrayID!=0){ return; } + RunningTrayApps.clear(); //nothing running yet + SystemTrayID = LX11::startSystemTray(0); + TrayStopping = false; + if(SystemTrayID!=0){ + XSelectInput(QX11Info::display(), SystemTrayID, InputOutput); //make sure TrayID events get forwarded here + XDamageQueryExtension( QX11Info::display(), &TrayDmgEvent, &TrayDmgError); + qDebug() << "System Tray Started Successfully"; + } +} + +void LSession::stopSystemTray(bool detachall){ + TrayStopping = true; //make sure the internal list does not modified during this + //Close all the running Tray Apps + for(int i=0; i<RunningTrayApps.length(); i++){ + if(!detachall){ LX11::CloseWindow(RunningTrayApps[i]); } + } + LX11::closeSystemTray(SystemTrayID); + SystemTrayID = 0; + TrayDmgEvent = 0; + TrayDmgError = 0; + RunningTrayApps.clear(); + emit TrayListChanged(); +} + +void LSession::attachTrayWindow(WId win){ + //static int appnum = 0; + if(TrayStopping){ return; } + if(RunningTrayApps.contains(win)){ return; } //already managed + RunningTrayApps << win; + emit TrayListChanged(); + /*//Now try to embed the window into the tray + qDebug() << "Attach Tray App:" << appnum; + WId cont = LX11::CreateWindow( SystemTrayID, QRect(appnum*64, 0, 64, 64) ); + if( LX11::EmbedWindow(win, cont) ){ + appnum++; + //Successful embed, now set it up for damage report notifications + XDamageCreate( QX11Info::display(), win, XDamageReportRawRectangles ); + //LX11::ResizeWindow(win, 64, 64); //Always use 64x64 if possible (can shrink, not expand later) + LX11::RestoreWindow(win); + //Add it to the tray list + RunningTrayApps << win; + TrayAppContainers << cont; + //Emit that the list has changed + emit TrayListChanged(); + }else{ + LX11::DestroyWindow(cont); //clean up + }*/ +} + +void LSession::removeTrayWindow(WId win){ + if(TrayStopping || SystemTrayID==0){ return; } + for(int i=0; i<RunningTrayApps.length(); i++){ + if(win==RunningTrayApps[i]){ + RunningTrayApps.removeAt(i); + emit TrayListChanged(); + break; + } + } +}
\ No newline at end of file |