diff options
-rw-r--r-- | libLumina/LuminaX11.cpp | 27 | ||||
-rw-r--r-- | libLumina/LuminaX11.h | 1 | ||||
-rw-r--r-- | lumina-desktop/LPanel.cpp | 4 | ||||
-rw-r--r-- | lumina-desktop/LSession.cpp | 99 | ||||
-rw-r--r-- | lumina-desktop/LXcbEventFilter.cpp | 10 | ||||
-rw-r--r-- | lumina-desktop/LXcbEventFilter.h | 4 | ||||
-rw-r--r-- | lumina-desktop/main.cpp | 2 | ||||
-rw-r--r-- | lumina-desktop/panel-plugins/LPPlugin.h | 8 | ||||
-rw-r--r-- | lumina-desktop/panel-plugins/systemtray/LSysTray.cpp | 197 | ||||
-rw-r--r-- | lumina-desktop/panel-plugins/systemtray/LSysTray.h | 7 | ||||
-rw-r--r-- | lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp | 4 |
11 files changed, 129 insertions, 234 deletions
diff --git a/libLumina/LuminaX11.cpp b/libLumina/LuminaX11.cpp index 51df70d5..05a03631 100644 --- a/libLumina/LuminaX11.cpp +++ b/libLumina/LuminaX11.cpp @@ -906,6 +906,7 @@ void LXCB::RegisterVirtualRoots(QList<WId> roots){ // === WindowClass() === QString LXCB::WindowClass(WId win){ QString out; + if(win==0){ return ""; } xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_class_unchecked(QX11Info::connection(), win); if(cookie.sequence == 0){ return out; } xcb_icccm_get_wm_class_reply_t value; @@ -919,6 +920,7 @@ QString LXCB::WindowClass(WId win){ // === WindowWorkspace() === unsigned int LXCB::WindowWorkspace(WId win){ //qDebug() << "Get Window Workspace"; + if(win==0){ return 0; } uint32_t wkspace = 0; xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_desktop_unchecked(&EWMH, win); if(cookie.sequence == 0){ return wkspace; } @@ -930,6 +932,7 @@ unsigned int LXCB::WindowWorkspace(WId win){ // === WindowGeometry() === QRect LXCB::WindowGeometry(WId win, bool includeFrame){ QRect geom; + if(win==0){ return geom; } xcb_get_geometry_cookie_t cookie = xcb_get_geometry(QX11Info::connection(), win); xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(QX11Info::connection(), cookie, NULL); //qDebug() << "Get Window Geometry:" << reply; @@ -972,6 +975,7 @@ QRect LXCB::WindowGeometry(WId win, bool includeFrame){ // === WindowState() === LXCB::WINDOWSTATE LXCB::WindowState(WId win){ + if(win==0){ return IGNORE; } xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_state_unchecked(&EWMH, win); if(cookie.sequence == 0){ return IGNORE; } xcb_ewmh_get_atoms_reply_t states; @@ -1014,6 +1018,7 @@ LXCB::WINDOWSTATE LXCB::WindowState(WId win){ // === WindowVisibleIconName() === QString LXCB::WindowVisibleIconName(WId win){ //_NET_WM_VISIBLE_ICON_NAME + if(win==0){ return ""; } QString out; xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_icon_name_unchecked(&EWMH, win); if(cookie.sequence == 0){ return out; } @@ -1026,6 +1031,7 @@ QString LXCB::WindowVisibleIconName(WId win){ //_NET_WM_VISIBLE_ICON_NAME // === WindowIconName() === QString LXCB::WindowIconName(WId win){ //_NET_WM_ICON_NAME + if(win==0){ return ""; } QString out; xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_name_unchecked(&EWMH, win); if(cookie.sequence == 0){ return out; } @@ -1038,6 +1044,7 @@ QString LXCB::WindowIconName(WId win){ //_NET_WM_ICON_NAME // === WindowVisibleName() === QString LXCB::WindowVisibleName(WId win){ //_NET_WM_VISIBLE_NAME + if(win==0){ return ""; } QString out; xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_name_unchecked(&EWMH, win); if(cookie.sequence == 0){ return out; } @@ -1050,6 +1057,7 @@ QString LXCB::WindowVisibleName(WId win){ //_NET_WM_VISIBLE_NAME // === WindowName() === QString LXCB::WindowName(WId win){ //_NET_WM_NAME + if(win==0){ return ""; } QString out; xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name_unchecked(&EWMH, win); if(cookie.sequence == 0){ return out; } @@ -1062,6 +1070,7 @@ QString LXCB::WindowName(WId win){ //_NET_WM_NAME // === OldWindowName() === QString LXCB::OldWindowName(WId win){ //WM_NAME (old standard) + if(win==0){ return ""; } xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_name_unchecked(QX11Info::connection(), win); xcb_icccm_get_text_property_reply_t reply; if(1 == xcb_icccm_get_wm_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){ @@ -1075,6 +1084,7 @@ QString LXCB::OldWindowName(WId win){ //WM_NAME (old standard) // === OldWindowIconName() === QString LXCB::OldWindowIconName(WId win){ //WM_ICON_NAME (old standard) + if(win==0){ return ""; } xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_icon_name_unchecked(QX11Info::connection(), win); xcb_icccm_get_text_property_reply_t reply; if(1 == xcb_icccm_get_wm_icon_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){ @@ -1088,6 +1098,7 @@ QString LXCB::OldWindowIconName(WId win){ //WM_ICON_NAME (old standard) // === WindowIsMaximized() === bool LXCB::WindowIsMaximized(WId win){ + if(win==0){ return ""; } //See if the _NET_WM_STATE_MAXIMIZED_[VERT/HORZ] flags are set on the window xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_state_unchecked(&EWMH, win); if(cookie.sequence == 0){ return false; } @@ -1108,6 +1119,7 @@ bool LXCB::WindowIsMaximized(WId win){ QIcon LXCB::WindowIcon(WId win){ //Fetch the _NET_WM_ICON for the window and return it as a QIcon QIcon icon; + if(win==0){ return icon; } xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_unchecked(&EWMH, win); xcb_ewmh_get_wm_icon_reply_t reply; if(1 == xcb_ewmh_get_wm_icon_reply(&EWMH, cookie, &reply, NULL)){ @@ -1136,6 +1148,7 @@ QIcon LXCB::WindowIcon(WId win){ // === SetAsSticky() === void LXCB::SetAsSticky(WId win){ + if(win==0){ return; } //Need to send a client message event for the window so the WM picks it up xcb_client_message_event_t event; event.response_type = XCB_CLIENT_MESSAGE; @@ -1157,6 +1170,7 @@ void LXCB::SetAsSticky(WId win){ // === SetAsPanel() === void LXCB::SetAsPanel(WId win){ + if(win==0){ return; } //Disable Input focus (panel activation ruins task manager window detection routines) // - Disable Input flag in WM_HINTS xcb_icccm_wm_hints_t hints; @@ -1237,11 +1251,19 @@ void LXCB::SetAsPanel(WId win){ // === CloseWindow() === void LXCB::CloseWindow(WId win){ + if(win==0){ return; } + //This will close the specified window (might not close the entire application) xcb_ewmh_request_close_window(&EWMH, 0, win, QX11Info::getTimestamp(), XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER); } +void LXCB::KillClient(WId win){ + if(win==0){ return; } + //This will forcibly close the application which created WIN + xcb_kill_client(QX11Info::connection(), win); +} // === MinimizeWindow() === void LXCB::MinimizeWindow(WId win){ //request that the window be unmapped/minimized + if(win==0){ return; } //Note: Fluxbox completely removes this window from the open list if unmapped manually // xcb_unmap_window(QX11Info::connection(), win); //xcb_flush(QX11Info::connection()); //make sure the command is sent out right away @@ -1263,6 +1285,7 @@ void LXCB::MinimizeWindow(WId win){ //request that the window be unmapped/minimi // === ActivateWindow() === void LXCB::ActivateWindow(WId win){ //request that the window become active + if(win==0){ return; } //First need to get the currently active window xcb_get_property_cookie_t cookie = xcb_ewmh_get_active_window_unchecked(&EWMH, 0); xcb_window_t actwin; @@ -1289,7 +1312,7 @@ void LXCB::ActivateWindow(WId win){ //request that the window become active // === MaximizeWindow() === void LXCB::MaximizeWindow(WId win, bool flagsonly){ //request that the window become maximized - + if(win==0){ return; } if(flagsonly){ //Directly set the flags on the window (bypassing the WM) xcb_atom_t list[2]; @@ -1316,6 +1339,7 @@ void LXCB::MaximizeWindow(WId win, bool flagsonly){ //request that the window be // === MoveResizeWindow() === void LXCB::MoveResizeWindow(WId win, QRect geom){ + if(win==0){ return; } //NOTE: geom needs to be in root/absolute coordinates! //qDebug() << "MoveResize Window:" << geom.x() << geom.y() << geom.width() << geom.height(); @@ -1381,6 +1405,7 @@ bool LXCB::EmbedWindow(WId win, WId container){ // === Unembed Window() === bool LXCB::UnembedWindow(WId win){ + if(win==0){ return false; } //Display *disp = QX11Info::display(); //Remove redirects //XSelectInput(disp, win, NoEventMask); diff --git a/libLumina/LuminaX11.h b/libLumina/LuminaX11.h index 2c34c6f5..4ce279f4 100644 --- a/libLumina/LuminaX11.h +++ b/libLumina/LuminaX11.h @@ -146,6 +146,7 @@ public: void SetAsSticky(WId); //Stick to all workspaces void SetAsPanel(WId); //Adjust all the window flags for a proper panel (cannot be done through Qt) void CloseWindow(WId); //request that the window be closed + void KillClient(WId); //Force the application that created the window to close void MinimizeWindow(WId); //request that the window be unmapped/minimized void ActivateWindow(WId); //request that the window become active void MaximizeWindow(WId win, bool flagsonly = false); //request that the window become maximized diff --git a/lumina-desktop/LPanel.cpp b/lumina-desktop/LPanel.cpp index f979ea15..1f59ba8b 100644 --- a/lumina-desktop/LPanel.cpp +++ b/lumina-desktop/LPanel.cpp @@ -67,9 +67,7 @@ LPanel::~LPanel(){ void LPanel::prepareToClose(){ //Go through and remove all the plugins for(int i=0; i<PLUGINS.length(); i++){ - if( PLUGINS[i]->type().startsWith("systemtray---") ){ - static_cast<LSysTray*>(PLUGINS[i])->stop(); - } + PLUGINS[i]->AboutToClose(); //any last cleanup for this plugin layout->takeAt(i); //remove from the layout delete PLUGINS.takeAt(i); //delete the actual widget LSession::processEvents(); diff --git a/lumina-desktop/LSession.cpp b/lumina-desktop/LSession.cpp index bce1d607..8f6da9ff 100644 --- a/lumina-desktop/LSession.cpp +++ b/lumina-desktop/LSession.cpp @@ -24,7 +24,7 @@ #include <X11/extensions/Xdamage.h> #ifndef DEBUG -#define DEBUG 1 +#define DEBUG 0 #endif XCBEventFilter *evFilter = 0; @@ -44,6 +44,7 @@ LSession::LSession(int &argc, char ** argv) : QApplication(argc, argv){ TrayDmgEvent = 0; TrayDmgError = 0; cleansession = true; + TrayStopping = false; for(int i=1; i<argc; i++){ if( QString::fromLocal8Bit(argv[i]) == "--noclean" ){ cleansession = false; break; } } @@ -133,20 +134,20 @@ void LSession::setupSession(){ void LSession::CleanupSession(){ //Close any running applications and tray utilities (Make sure to keep the UI interactive) LSession::processEvents(); + QDateTime time = QDateTime::currentDateTime(); + qDebug() << "Start closing down the session: " << time.toString( Qt::SystemLocaleShortDate); //Start the logout chimes (if necessary) - if( sessionsettings->value("PlayLogoutAudio",true).toBool() ){ - playAudioFile(LOS::LuminaShare()+"Logout.ogg"); - } - + bool playaudio = sessionsettings->value("PlayLogoutAudio",true).toBool(); + if( playaudio ){ playAudioFile(LOS::LuminaShare()+"Logout.ogg"); } + //Stop the background system tray (detaching/closing apps as necessary) + stopSystemTray(!cleansession); + //Now perform any other cleanup if(cleansession){ - //Close any Tray Apps - for(int i=0; i<RunningTrayApps.length(); i++){ - XCB->CloseWindow(RunningTrayApps[i]); - LSession::processEvents(); - } //Close any open windows + //qDebug() << " - Closing any open windows"; QList<WId> WL = XCB->WindowList(true); for(int i=0; i<WL.length(); i++){ + qDebug() << " - Closing window:" << XCB->WindowClass(WL[i]) << WL[i]; XCB->CloseWindow(WL[i]); LSession::processEvents(); } @@ -155,20 +156,33 @@ void LSession::CleanupSession(){ //Kill any remaining windows WL = XCB->WindowList(true); //all workspaces for(int i=0; i<WL.length(); i++){ - LX11::KillWindow(WL[i]); + qDebug() << " - Window did not close, killing application:" << XCB->WindowClass(WL[i]) << WL[i]; + XCB->KillClient(WL[i]); LSession::processEvents(); } } + evFilter->StopEventHandling(); //Stop the window manager + qDebug() << " - Stopping the window manager"; WM->stopWM(); //Now close down the desktop + qDebug() << " - Closing down the desktop elements"; for(int i=0; i<DESKTOPS.length(); i++){ DESKTOPS[i]->prepareToClose(); //don't actually close them yet - that will happen when the session exits // this will leave the wallpapers up for a few moments (preventing black screens) } //Now wait a moment for things to close down before quitting - for(int i=0; i<20; i++){ LSession::processEvents(); usleep(25); } //1/2 second pause + if(playaudio){ + //wait a max of 3 seconds for audio to finish + bool waitmore = true; + for(int i=0; i<6 && waitmore; i++){ + waitmore = !audioThread->wait(500); + LSession::processEvents(); + } + }else{ + for(int i=0; i<20; i++){ LSession::processEvents(); usleep(25); } //1/2 second pause + } } int LSession::VersionStringToNumber(QString version){ @@ -224,7 +238,7 @@ void LSession::launchStartupApps(){ if(vol>=0){ LOS::setAudioVolume(vol); } LSession::playAudioFile(LOS::LuminaShare()+"Login.ogg"); } - if(sessionsettings->value("EnableNumlock",true).toBool()){ + if(sessionsettings->value("EnableNumlock",false).toBool()){ QProcess::startDetached("numlockx on"); } //Now get any XDG startup applications and launch them @@ -383,7 +397,7 @@ void LSession::adjustWindowGeom(WId win, bool maximize){ //Quick hack for making sure that new windows are not located underneath any panels // Get the window location QRect geom = XCB->WindowGeometry(win, true); //always include the frame if possible - if(DEBUG){ qDebug() << "Adjust Window Geometry:" << XCB->WindowClass(win) << !geom.isNull(); } + if(DEBUG){ qDebug() << "Check Window Geometry:" << XCB->WindowClass(win) << !geom.isNull(); } if(geom.isNull()){ return; } //Could not get geometry //Get the available geometry for the screen the window is on QRect desk; @@ -397,15 +411,15 @@ void LSession::adjustWindowGeom(WId win, bool maximize){ } //Adjust the window location if necessary if(maximize){ - if(DEBUG){ qDebug() << "Maximizing New Window:" << desk.width() << desk.height(); } + if(DEBUG){ qDebug() << " - Maximizing New Window:" << desk.width() << desk.height(); } geom = desk; //Use the full screen XCB->MoveResizeWindow(win, geom); XCB->MaximizeWindow(win, true); //directly set the appropriate "maximized" flags (bypassing WM) }else if(!desk.contains(geom) ){ if(DEBUG){ - qDebug() << "Desk:" << desk.x() << desk.y() << desk.width() << desk.height(); - qDebug() << "Geom:" << geom.x() << geom.y() << geom.width() << geom.height(); + qDebug() << " - Desk:" << desk.x() << desk.y() << desk.width() << desk.height(); + qDebug() << " - Geom:" << geom.x() << geom.y() << geom.width() << geom.height(); } //Adjust origin point for left/top margins if(geom.y() < desk.y()){ geom.moveTop(desk.y()); } //move down to the edge (top panel) @@ -414,15 +428,14 @@ void LSession::adjustWindowGeom(WId win, bool maximize){ // if(geom.right() > desk.right() && (geom.width() > 100)){ geom.setRight(desk.right()); } if(geom.bottom() > desk.bottom() && geom.height() > 100){ geom.setBottom(desk.bottom()); } //Now move/resize the window - if(DEBUG){ qDebug() << "New Geom:" << geom.x() << geom.y() << geom.width() << geom.height(); } + if(DEBUG){ qDebug() << " - New Geom:" << geom.x() << geom.y() << geom.width() << geom.height(); } XCB->MoveResizeWindow(win, geom); } } void LSession::SessionEnding(){ - audioThread->wait(3000); //wait a max of 3 seconds for the audio thread to finish - stopSystemTray(); + stopSystemTray(); //just in case it was not stopped properly earlier } //=============== @@ -454,27 +467,22 @@ void LSession::systemWindow(){ //Play System Audio void LSession::playAudioFile(QString filepath){ //Setup the audio output systems for the desktop - //return; //Disable this for now: too many issues with Phonon at the moment (hangs the session) bool init = false; if(DEBUG){ qDebug() << "Play Audio File"; } if(audioThread==0){ qDebug() << " - Initialize audio systems"; audioThread = new QThread(); init = true; } - //if(mediaObj==0){ qDebug() << " - Initialize Phonon media Object"; mediaObj = new Phonon::MediaObject(); init = true;} if(mediaObj==0){ qDebug() << " - Initialize media player"; mediaObj = new QMediaPlayer(); init = true;} - //if(audioOut==0){ qDebug() << " - Initialize Phonon audio output"; audioOut = new Phonon::AudioOutput(); init=true;} if(mediaObj && init){ //in case it errors for some reason - //qDebug() << " -- Create path between audio objects"; - //Phonon::createPath(mediaObj, audioOut); qDebug() << " -- Move audio objects to separate thread"; mediaObj->moveToThread(audioThread); - //audioOut->moveToThread(audioThread); audioThread->start(); } - if(mediaObj !=0 ){//&& audioOut!=0){ - //mediaObj->setCurrentSource(QUrl(filepath)); + if(mediaObj !=0 ){ + if(DEBUG){ qDebug() << " - starting playback:" << filepath; } mediaObj->setMedia(QUrl::fromLocalFile(filepath)); mediaObj->setVolume(100); mediaObj->play(); - //audioThread->start(); + if(!audioThread->isRunning()){ audioThread->start(); } + LSession::processEvents(); } if(DEBUG){ qDebug() << " - Done with Audio File"; } } @@ -488,7 +496,7 @@ void LSession::WindowPropertyEvent(){ //New Window found LSession::restoreOverrideCursor(); //restore the mouse cursor back to normal (new window opened?) //Perform sanity checks on any new window geometries - for(int i=0; i<newapps.length(); i++){ + for(int i=0; i<newapps.length() && !TrayStopping; i++){ if(!RunningApps.contains(newapps[i])){ adjustWindowGeom(newapps[i]); } } } @@ -505,14 +513,17 @@ void LSession::WindowPropertyEvent(WId win){ } void LSession::SysTrayDockRequest(WId win){ + if(TrayStopping){ return; } attachTrayWindow(win); //Check to see if the window is already registered } void LSession::WindowClosedEvent(WId win){ + if(TrayStopping){ return; } removeTrayWindow(win); //Check to see if the window is a tray app } void LSession::WindowConfigureEvent(WId win){ + if(TrayStopping){ return; } for(int i=0; i<RunningTrayApps.length(); i++){ if(win==RunningTrayApps[i]){ if(DEBUG){ qDebug() << "SysTray: Configure Event"; } @@ -523,6 +534,7 @@ void LSession::WindowConfigureEvent(WId win){ } void LSession::WindowDamageEvent(WId win){ + if(TrayStopping){ return; } for(int i=0; i<RunningTrayApps.length(); i++){ if(win==RunningTrayApps[i]){ if(DEBUG){ qDebug() << "SysTray: Damage Event"; } @@ -533,7 +545,7 @@ void LSession::WindowDamageEvent(WId win){ } void LSession::WindowSelectionClearEvent(WId win){ - if(win==SystemTrayID){ + if(win==SystemTrayID && !TrayStopping){ qDebug() << "Stopping system tray"; stopSystemTray(true); //make sure to detach all windows } @@ -546,7 +558,8 @@ void LSession::WindowSelectionClearEvent(WId win){ 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; } + if(TrayStopping){ return false; } + else if(VisualTrayID==0){ VisualTrayID = visualTray; return true; } else if(VisualTrayID==visualTray){ return true; } else{ return false; } } @@ -555,7 +568,7 @@ void LSession::unregisterVisualTray(WId visualTray){ if(VisualTrayID==visualTray){ qDebug() << "Unregistered Visual Tray"; VisualTrayID=0; - emit VisualTrayAvailable(); + if(!TrayStopping){ emit VisualTrayAvailable(); } } } @@ -584,17 +597,29 @@ void LSession::startSystemTray(){ } void LSession::stopSystemTray(bool detachall){ + if(TrayStopping){ return; } //already run + qDebug() << "Stopping system tray..."; 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]); } + QList<WId> tmpApps = RunningTrayApps; + RunningTrayApps.clear(); //clear this ahead of time so tray's do not attempt to re-access the apps + if(!detachall){ + for(int i=0; i<tmpApps.length(); i++){ + qDebug() << " - Stopping tray app:" << XCB->WindowClass(tmpApps[i]); + //XCB->CloseWindow(RunningTrayApps[i]); + //Tray apps are special and closing the window does not close the app + XCB->KillClient(tmpApps[i]); + LSession::processEvents(); + } } + //Now close down the tray backend LX11::closeSystemTray(SystemTrayID); SystemTrayID = 0; TrayDmgEvent = 0; TrayDmgError = 0; - RunningTrayApps.clear(); + evFilter->setTrayDamageFlag(0); //turn off tray event handling emit TrayListChanged(); + LSession::processEvents(); } void LSession::attachTrayWindow(WId win){ @@ -608,7 +633,7 @@ void LSession::attachTrayWindow(WId win){ } void LSession::removeTrayWindow(WId win){ - if(TrayStopping || SystemTrayID==0){ return; } + if(SystemTrayID==0){ return; } for(int i=0; i<RunningTrayApps.length(); i++){ if(win==RunningTrayApps[i]){ RunningTrayApps.removeAt(i); diff --git a/lumina-desktop/LXcbEventFilter.cpp b/lumina-desktop/LXcbEventFilter.cpp index fe79d6d5..32190d55 100644 --- a/lumina-desktop/LXcbEventFilter.cpp +++ b/lumina-desktop/LXcbEventFilter.cpp @@ -16,6 +16,7 @@ XCBEventFilter::XCBEventFilter(LSession *sessionhandle) : QAbstractNativeEventFilter(){ session = sessionhandle; //save this for interaction with the session later TrayDmgFlag = 0; + stopping = false; InitAtoms(); } @@ -27,6 +28,7 @@ void XCBEventFilter::setTrayDamageFlag(int flag){ //This function format taken directly from the Qt5.3 documentation bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE { + if(stopping){ return false; } //don't do any parsing //qDebug() << "New Event"; if(eventType=="xcb_generic_event_t"){ //Convert to known event type (for X11 systems) @@ -55,7 +57,7 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag //qDebug() << "Client Message Event"; //qDebug() << " - Root Window:" << QX11Info::appRootWindow(); //qDebug() << " - Given Window:" << ((xcb_client_message_event_t*)ev)->window; - if( ((xcb_client_message_event_t*)ev)->type == _NET_SYSTEM_TRAY_OPCODE && ((xcb_client_message_event_t*)ev)->format == 32){ + if( TrayDmgFlag!=0 && ((xcb_client_message_event_t*)ev)->type == _NET_SYSTEM_TRAY_OPCODE && ((xcb_client_message_event_t*)ev)->format == 32){ //data32[0] is timestamp, [1] is opcode, [2] is window handle if(SYSTEM_TRAY_REQUEST_DOCK == ((xcb_client_message_event_t*)ev)->data.data32[1]){ session->SysTrayDockRequest( ((xcb_client_message_event_t*)ev)->data.data32[2] ); @@ -92,8 +94,10 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag break; //============================== default: - if( (ev->response_type & ~0x80)==TrayDmgFlag){ - session->WindowDamageEvent( ((xcb_damage_notify_event_t*)ev)->drawable ); + if(TrayDmgFlag!=0){ + if( (ev->response_type & ~0x80)==TrayDmgFlag){ + session->WindowDamageEvent( ((xcb_damage_notify_event_t*)ev)->drawable ); + } }/*else{ qDebug() << "Default Event:" << (ev->response_type & ~0x80); }*/ diff --git a/lumina-desktop/LXcbEventFilter.h b/lumina-desktop/LXcbEventFilter.h index dafb3212..c56471c9 100644 --- a/lumina-desktop/LXcbEventFilter.h +++ b/lumina-desktop/LXcbEventFilter.h @@ -61,6 +61,7 @@ private: xcb_atom_t _NET_SYSTEM_TRAY_OPCODE; QList<xcb_atom_t> WinNotifyAtoms, SysNotifyAtoms; int TrayDmgFlag; //internal damage event offset value for the system tray + bool stopping; void InitAtoms(){ //Initialize any special atoms that we need to save/use regularly @@ -93,7 +94,8 @@ private: public: XCBEventFilter(LSession *sessionhandle); void setTrayDamageFlag(int flag); - + void StopEventHandling(){ stopping = true; } + //This function format taken directly from the Qt5.3 documentation virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE; diff --git a/lumina-desktop/main.cpp b/lumina-desktop/main.cpp index 357fd14c..adf96181 100644 --- a/lumina-desktop/main.cpp +++ b/lumina-desktop/main.cpp @@ -90,7 +90,7 @@ int main(int argc, char ** argv) LUtils::LoadTranslation(&a, "lumina-desktop"); //a.LoadLocale(QLocale().name()); //Start launching external applications - QTimer::singleShot(2000, &a, SLOT(launchStartupApps()) ); //wait a couple seconds first + QTimer::singleShot(3000, &a, SLOT(launchStartupApps()) ); //wait a couple seconds first if(DEBUG){ qDebug() << "Exec Time:" << timer->elapsed(); delete timer;} int retCode = a.exec(); //qDebug() << "Stopping the window manager"; diff --git a/lumina-desktop/panel-plugins/LPPlugin.h b/lumina-desktop/panel-plugins/LPPlugin.h index dc1c490e..dd869bf6 100644 --- a/lumina-desktop/panel-plugins/LPPlugin.h +++ b/lumina-desktop/panel-plugins/LPPlugin.h @@ -46,6 +46,11 @@ public: QString type(){ return plugintype; } + + virtual void AboutToClose(){ + //This needs to be re-implemented in the subclasses plugin + //This is for any last-minute cleanup before the plugin gets deleted + } public slots: virtual void LocaleChange(){ @@ -61,9 +66,6 @@ public slots: //This is where any horizontal/vertical orientations can be changed appropriately } - /*virtual void ResetMouseFocus(){ - // - }*/ }; #endif
\ No newline at end of file diff --git a/lumina-desktop/panel-plugins/systemtray/LSysTray.cpp b/lumina-desktop/panel-plugins/systemtray/LSysTray.cpp index 2472d064..bdd605d0 100644 --- a/lumina-desktop/panel-plugins/systemtray/LSysTray.cpp +++ b/lumina-desktop/panel-plugins/systemtray/LSysTray.cpp @@ -56,22 +56,6 @@ void LSysTray::start(){ //upTimer->start(); QTimer::singleShot(0,this, SLOT(checkAll()) ); } - //Make sure we catch all events right away - /*connect(LSession::instance(),SIGNAL(aboutToQuit()),this,SLOT(closeAll()) ); - connect(LSession::instance(),SIGNAL(TrayEvent(XEvent*)), this, SLOT(checkXEvent(XEvent*)) ); - isRunning = true; - TrayID = LX11::startSystemTray(0); //LSession::desktop()->screenNumber(this)); - if(TrayID!=0){ - XSelectInput(QX11Info::display(), TrayID, InputOutput); //make sure TrayID events get forwarded here - XDamageQueryExtension( QX11Info::display(), &dmgEvent, &dmgError); - //Now connect the session logout signal to the close function - qDebug() << "System Tray Started Successfully"; - upTimer->start(); - //QTimer::singleShot(100, this, SLOT(initialTrayIconDetect()) ); - }else{ - disconnect(this); - } - isRunning = (TrayID!=0);*/ } void LSysTray::stop(){ @@ -79,95 +63,35 @@ void LSysTray::stop(){ stopping = true; upTimer->stop(); //Now close down the system tray registry - qDebug() << "Stop system Tray:" << this->type(); + 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 - qDebug() << " - Remove tray applications"; - for(int i=(trayIcons.length()-1); i>=0; i--){ - trayIcons[i]->detachApp(); - TrayIcon *cont = trayIcons.takeAt(i); - LI->removeWidget(cont); - delete cont; + 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); + delete cont; + } } //Now let some other visual tray take over LSession::handle()->unregisterVisualTray(this->winId()); - qDebug() << "Done stopping system tray"; + qDebug() << "Done stopping visual tray"; } // ======================== // PRIVATE FUNCTIONS // ======================== -/*void LSysTray::checkXEvent(XEvent *event){ - if(!isRunning){ return; } - switch(event->type){ - // ------------------------- - case ClientMessage: - //Only check if the client is the system tray, otherwise ignore - if(event->xany.window == TrayID){ - //qDebug() << "SysTray: ClientMessage"; - switch(event->xclient.data.l[1]){ - case SYSTEM_TRAY_REQUEST_DOCK: - addTrayIcon(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 == TrayID){ - //qDebug() << "SysTray: Selection Clear"; - this->stop(); //de-activate this system tray (release all embeds) - } - break; - case DestroyNotify: - //qDebug() << "SysTray: DestroyNotify"; - removeTrayIcon(event->xany.window); //Check for removing an icon - break; - - case ConfigureNotify: - for(int i=0; i<trayIcons.length(); i++){ - if(event->xany.window==trayIcons[i]->appID()){ - //qDebug() << "SysTray: Configure Event" << trayIcons[i]->appID(); - trayIcons[i]->update(); //trigger a repaint event - break; - } - } - default: - if(event->type == dmgEvent+XDamageNotify){ - WId ID = reinterpret_cast<XDamageNotifyEvent*>(event)->drawable; - //qDebug() << "SysTray: Damage Event"; - for(int i=0; i<trayIcons.length(); i++){ - if(ID==trayIcons[i]->appID()){ - //qDebug() << "SysTray: Damage Event" << ID; - trayIcons[i]->update(); //trigger a repaint event - break; - } - } - } - - }//end of switch over event type -} - -void LSysTray::closeAll(){ - //Actually close all the tray apps (not just unembed) - //This is used when the desktop is shutting everything down - for(int i=0; i<trayIcons.length(); i++){ - LX11::CloseWindow(trayIcons[i]->appID()); - } - -} -*/ void LSysTray::checkAll(){ if(!isRunning || stopping || checking){ return; } //Don't check if not running at the moment checking = true; + //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"; bool listChanged = false; QList<WId> wins = LSession::handle()->currentTrayApps(this->winId()); @@ -175,7 +99,7 @@ void LSysTray::checkAll(){ int index = wins.indexOf(trayIcons[i]->appID()); if(index < 0){ //Tray Icon no longer exists: remove it - //qDebug() << " - SysTray: Remove Icon"; + qDebug() << " - Visual System Tray: Remove Icon"; TrayIcon *cont = trayIcons.takeAt(i); LI->removeWidget(cont); delete cont; @@ -195,8 +119,8 @@ void LSysTray::checkAll(){ } } //Now go through any remaining windows and add them - for(int i=0; i<wins.length(); i++){ - //qDebug() << " - SysTray: Add Icon"; + for(int i=0; i<wins.length() && TrayRunning; i++){ + qDebug() << " - Visual System Tray: Add Icon"; TrayIcon *cont = new TrayIcon(this); LSession::processEvents(); trayIcons << cont; @@ -245,93 +169,4 @@ void LSysTray::UpdateTrayWindow(WId win){ } } -/*void LSysTray::initialTrayIconDetect(){ - // WARNING: This is still experimental and should be disabled by default!! - QList<WId> wins = LX11::findOrphanTrayWindows(); - for(int i=0; i<wins.length(); i++){ - //addTrayIcon(wins[i]); - qDebug() << "Initial Tray Window:" << wins[i] << LX11::WindowClass(wins[i]); - } -}*/ - -/*void LSysTray::addTrayIcon(WId win){ - if(win == 0 || !isRunning){ return; } - //qDebug() << "System Tray: Add Tray Icon:" << win; - bool exists = false; - for(int i=0; i<trayIcons.length(); i++){ - if(trayIcons[i]->appID() == win){ exists=true; break; } - } - if(!exists){ - //qDebug() << " - New Icon Window:" << win; - TrayIcon *cont = new TrayIcon(this); - QCoreApplication::processEvents(); - connect(cont, SIGNAL(AppClosed()), this, SLOT(trayAppClosed()) ); - connect(cont, SIGNAL(AppAttached()), this, SLOT(updateStatus()) ); - trayIcons << cont; - LI->addWidget(cont); - //qDebug() << " - Update tray layout"; - if(this->layout()->direction()==QBoxLayout::LeftToRight){ - cont->setSizeSquare(this->height()-2*frame->frameWidth()); //horizontal tray - this->setMaximumSize( trayIcons.length()*this->height(), 10000); - }else{ - cont->setSizeSquare(this->width()-2*frame->frameWidth()); //vertical tray - this->setMaximumSize(10000, trayIcons.length()*this->width()); - } - LSession::processEvents(); - //qDebug() << " - Attach tray app"; - cont->attachApp(win); - LI->update(); //make sure there is no blank space - } -}*/ - -/*void LSysTray::removeTrayIcon(WId win){ - //This function only runs when the tray app was closed externally - if(win==0 || !isRunning){ return; } - for(int i=0; i<trayIcons.length(); i++){ - if(trayIcons[i]->appID()==win){ - //qDebug() << " - Remove Icon Window:" << win; - //Remove it from the layout and keep going - TrayIcon *cont = trayIcons.takeAt(i); - LI->removeWidget(cont); - delete cont; - i--; //make sure we don't miss an item when we continue - QCoreApplication::processEvents(); - } - } - //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()); - } - LI->update(); //update the layout (no gaps) - this->update(); //update the main widget appearance -}*/ - -/*void LSysTray::updateStatus(){ - qDebug() << "System Tray: Client Attached"; - LI->update(); //make sure there is no blank space - //qDebug() << " - Items:" << trayIcons.length(); -} -void LSysTray::trayAppClosed(){ - if(!isRunning){ return; } - for(int i=0; i<trayIcons.length(); i++){ - if(trayIcons[i]->appID() == 0){ - qDebug() << "System Tray: Removing icon"; - TrayIcon *cont = trayIcons.takeAt(i); - LI->removeWidget(cont); - delete cont; - QCoreApplication::processEvents(); - } - } - //Re-adjust the maximum widget size - if(this->layout()->direction()==QBoxLayout::LeftToRight){ - this->setMaximumSize( trayIcons.length()*this->height(), 10000); - }else{ - this->setMaximumSize(10000, trayIcons.length()*this->width()); - } - LI->update(); //update the layout (no gaps) - this->update(); -} -*/ diff --git a/lumina-desktop/panel-plugins/systemtray/LSysTray.h b/lumina-desktop/panel-plugins/systemtray/LSysTray.h index 1b482ef7..786ca730 100644 --- a/lumina-desktop/panel-plugins/systemtray/LSysTray.h +++ b/lumina-desktop/panel-plugins/systemtray/LSysTray.h @@ -1,6 +1,6 @@ //=========================================== // Lumina-DE source code -// Copyright (c) 2012, Ken Moore +// Copyright (c) 2012-2015, Ken Moore // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== @@ -12,7 +12,6 @@ #include <QHBoxLayout> #include <QDebug> #include <QX11Info> -//#include <QX11EmbedContainer> #include <QCoreApplication> //Local includes @@ -30,6 +29,10 @@ public: LSysTray(QWidget *parent = 0, QString id="systemtray", bool horizontal=true); ~LSysTray(); + virtual void AboutToClose(){ + this->stop(); + } + private: bool isRunning, stopping, checking; QList<TrayIcon*> trayIcons; diff --git a/lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp b/lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp index e5cc17df..8d0cacb3 100644 --- a/lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp +++ b/lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp @@ -24,9 +24,9 @@ TrayIcon::TrayIcon(QWidget *parent) : QWidget(parent){ } TrayIcon::~TrayIcon(){ - if(AID!=0){ + /*if(AID!=0){ detachApp(); - } + }*/ } WId TrayIcon::appID(){ |