aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libLumina/LuminaX11.cpp27
-rw-r--r--libLumina/LuminaX11.h1
-rw-r--r--libLumina/LuminaXDG.cpp9
-rw-r--r--lumina-desktop/LPanel.cpp4
-rw-r--r--lumina-desktop/LSession.cpp99
-rw-r--r--lumina-desktop/LXcbEventFilter.cpp10
-rw-r--r--lumina-desktop/LXcbEventFilter.h4
-rw-r--r--lumina-desktop/main.cpp2
-rw-r--r--lumina-desktop/panel-plugins/LPPlugin.h8
-rw-r--r--lumina-desktop/panel-plugins/systemtray/LSysTray.cpp197
-rw-r--r--lumina-desktop/panel-plugins/systemtray/LSysTray.h7
-rw-r--r--lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp4
12 files changed, 138 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/libLumina/LuminaXDG.cpp b/libLumina/LuminaXDG.cpp
index dbf08b88..57757fc9 100644
--- a/libLumina/LuminaXDG.cpp
+++ b/libLumina/LuminaXDG.cpp
@@ -88,6 +88,15 @@ XDGDesktop LXDG::loadDesktopFile(QString filePath, bool& ok){
} //end reading file
file.close();
//If there are OnlyShowIn desktops listed, add them to the name
+ if(DF.showInList.contains("lumina", Qt::CaseInsensitive)){
+ //Need to be careful about case insensitivity here - the QList functions don't understand it
+ for(int i=0; i<DF.showInList.length(); i++){
+ if(DF.showInList[i].toLower()=="lumina"){
+ DF.showInList.removeAt(i);
+ i--;
+ }
+ }
+ }
if(!DF.showInList.isEmpty()){
DF.name.append(" ("+DF.showInList.join(", ")+")");
}
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(){
bgstack15