|
|
|
/*
|
|
|
|
* Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved.
|
|
|
|
*
|
|
|
|
* This is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This software is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this software; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
|
|
* USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// $Id: traylabelmgr.cpp,v 1.10 2005/02/09 03:38:43 cs19713 Exp $
|
|
|
|
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqmessagebox.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqaction.h>
|
|
|
|
#include <tqpopupmenu.h>
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
#include <tqfiledialog.h>
|
|
|
|
|
|
|
|
#include <tdelocale.h>
|
|
|
|
|
|
|
|
#include "trace.h"
|
|
|
|
#include "traylabelmgr.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
#include <X11/Xmu/WinUtil.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
TrayLabelMgr* TrayLabelMgr::gTrayLabelMgr = NULL;
|
|
|
|
const char *TrayLabelMgr::mOptionString = "+abdefi:lmop:qtw:";
|
|
|
|
|
|
|
|
TrayLabelMgr* TrayLabelMgr::instance(void)
|
|
|
|
{
|
|
|
|
if (gTrayLabelMgr) return gTrayLabelMgr;
|
|
|
|
TRACE("Creating new instance");
|
|
|
|
return (gTrayLabelMgr = new TrayLabelMgr());
|
|
|
|
}
|
|
|
|
|
|
|
|
TrayLabelMgr::TrayLabelMgr() : mReady(false), mHiddenLabelsCount(0)
|
|
|
|
{
|
|
|
|
// Set ourselves up to be called from the application loop
|
|
|
|
TQTimer::singleShot(0, this, SLOT(startup()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TrayLabelMgr::~TrayLabelMgr()
|
|
|
|
{
|
|
|
|
undockAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrayLabelMgr::about(void)
|
|
|
|
{
|
|
|
|
if (TQMessageBox::information(NULL, i18n("About KDocker"),
|
|
|
|
i18n("Bugs/wishes to Girish Ramakrishnan (gramakri@uiuc.edu)\n"
|
|
|
|
"English translation by Girish (gramakri@uiuc.edu)\n\n"
|
|
|
|
"http://kdocker.sourceforge.net for updates"),
|
|
|
|
TQString::null, SHOW_TRACE_TEXT) == 1) SHOW_TRACE();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrayLabelMgr::startup(void)
|
|
|
|
{
|
|
|
|
const int WAIT_TIME = 10;
|
|
|
|
static int wait_time = WAIT_TIME;
|
|
|
|
/*
|
|
|
|
* If it appears that we were launched from some startup script (check whether
|
|
|
|
* stdout is a tty) OR if we are getting restored, wait for WAIT_TIME until
|
|
|
|
* the system tray shows up (before informing the user)
|
|
|
|
*/
|
|
|
|
static bool do_wait = !isatty(fileno(stdout)) || tqApp->isSessionRestored();
|
|
|
|
|
|
|
|
SysTrayState state = sysTrayStatus(TQPaintDevice::x11AppDisplay());
|
|
|
|
|
|
|
|
if (state != SysTrayPresent)
|
|
|
|
{
|
|
|
|
if (wait_time-- > 0 && do_wait)
|
|
|
|
{
|
|
|
|
TRACE("Will check sys tray status after 1 second");
|
|
|
|
TQTimer::singleShot(1000, this, SLOT(startup()));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TQMessageBox::warning(NULL, i18n("KDocker"),
|
|
|
|
i18n(state == SysTrayAbsent ? "No system tray found"
|
|
|
|
: "System tray appears to be hidden"),
|
|
|
|
TQMessageBox::Abort, TQMessageBox::Ignore) == TQMessageBox::Abort)
|
|
|
|
{
|
|
|
|
tqApp->quit();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Things are fine or user with OK with the state of system tray
|
|
|
|
mReady = true;
|
|
|
|
bool ok = false;
|
|
|
|
if (tqApp->isSessionRestored()) ok = restoreSession(tqApp->sessionId());
|
|
|
|
else ok = processCommand(tqApp->argc(), tqApp->argv());
|
|
|
|
// Process the request Q from previous instances
|
|
|
|
|
|
|
|
TRACE("Request queue has %i requests", mRequestQ.count());
|
|
|
|
for(unsigned i=0; i < mRequestQ.count(); i++)
|
|
|
|
ok |= processCommand(mRequestQ[i]);
|
|
|
|
if (!ok) tqApp->quit();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize a TQTrayLabel after its creation
|
|
|
|
void TrayLabelMgr::manageTrayLabel(TQTrayLabel *t)
|
|
|
|
{
|
|
|
|
connect(t, SIGNAL(destroyed(TQObject *)),
|
|
|
|
this, SLOT(trayLabelDestroyed(TQObject *)));
|
|
|
|
connect(t, SIGNAL(undocked(TQTrayLabel *)), t, SLOT(deleteLater()));
|
|
|
|
|
|
|
|
// All TQTrayLabels will emit this signal. We just need one of them
|
|
|
|
if (mTrayLabels.count() == 0)
|
|
|
|
connect(t, SIGNAL(sysTrayDestroyed()), this, SLOT(sysTrayDestroyed()));
|
|
|
|
mTrayLabels.prepend(t);
|
|
|
|
|
|
|
|
TRACE("New TQTrayLabel prepended. Count=%i", mTrayLabels.count());
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrayLabelMgr::dockAnother()
|
|
|
|
{
|
|
|
|
TQTrayLabel *t = selectAndDock();
|
|
|
|
if (t == NULL) return;
|
|
|
|
manageTrayLabel(t);
|
|
|
|
t->withdraw();
|
|
|
|
t->dock();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Undock all the windows
|
|
|
|
void TrayLabelMgr::undockAll()
|
|
|
|
{
|
|
|
|
TRACE("Number of tray labels = %i", mTrayLabels.count());
|
|
|
|
TQPtrListIterator<TQTrayLabel> it(mTrayLabels);
|
|
|
|
TQTrayLabel *t;
|
|
|
|
while ((t = it.current()) != 0)
|
|
|
|
{
|
|
|
|
++it;
|
|
|
|
t->undock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process the command line
|
|
|
|
bool TrayLabelMgr::processCommand(const TQStringList& args)
|
|
|
|
{
|
|
|
|
if (!mReady)
|
|
|
|
{
|
|
|
|
// If we are still looking for system tray, just add it to the Q
|
|
|
|
mRequestQ.append(args);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const int MAX_ARGS = 20;
|
|
|
|
const char *argv[MAX_ARGS];
|
|
|
|
int argc = args.count();
|
|
|
|
if (argc >= MAX_ARGS) argc = MAX_ARGS - 1;
|
|
|
|
|
|
|
|
for(int i =0 ; i<argc; i++)
|
|
|
|
argv[i] = args[i].latin1();
|
|
|
|
|
|
|
|
argv[argc] = NULL; // null terminate the array
|
|
|
|
|
|
|
|
return processCommand(argc, const_cast<char **>(argv));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process the command line
|
|
|
|
bool TrayLabelMgr::processCommand(int argc, char** argv)
|
|
|
|
{
|
|
|
|
TRACE("CommandLine arguments");
|
|
|
|
for(int i = 0; i < argc; i++) TRACE("\t%s", argv[i]);
|
|
|
|
|
|
|
|
if (argc < 1) return false;
|
|
|
|
|
|
|
|
// Restore session (See the comments in KDocker::notifyPreviousInstance()
|
|
|
|
if (qstrcmp(argv[1], "-session") == 0)
|
|
|
|
{
|
|
|
|
TRACE("Restoring session %s (new instance request)", argv[2]);
|
|
|
|
return restoreSession(TQString(argv[2]));
|
|
|
|
}
|
|
|
|
|
|
|
|
int option;
|
|
|
|
Window w = None;
|
|
|
|
const char *icon = NULL;
|
|
|
|
int balloon_timeout = 4000;
|
|
|
|
bool withdraw = true, skip_taskbar = false,
|
|
|
|
auto_launch = false, dock_obscure = false, check_normality = true,
|
|
|
|
enable_sm = true;
|
|
|
|
|
|
|
|
optind = 0; // initialise the getopt static
|
|
|
|
|
|
|
|
while ((option = getopt(argc, argv, mOptionString)) != EOF)
|
|
|
|
{
|
|
|
|
switch (option)
|
|
|
|
{
|
|
|
|
case '?':
|
|
|
|
return false;
|
|
|
|
case 'a':
|
|
|
|
tqDebug("%s", i18n("Girish Ramakrishnan (gramakri@uiuc.edu)").local8Bit().data());
|
|
|
|
return false;
|
|
|
|
case 'b':
|
|
|
|
check_normality = false;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
enable_sm = false;
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
enable_sm = true;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
w = activeWindow(TQPaintDevice::x11AppDisplay());
|
|
|
|
TRACE("Active window is %i", (unsigned) w);
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
icon = optarg;
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
auto_launch = true;
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
withdraw = false;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
dock_obscure = true;
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
balloon_timeout = atoi(optarg) * 1000; // convert to ms
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
balloon_timeout = 0; // same as '-p 0'
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
skip_taskbar = true;
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
if ((optarg[1] == 'x') || (optarg[1] == 'X'))
|
|
|
|
sscanf(optarg, "%x", (unsigned *) &w);
|
|
|
|
else
|
|
|
|
w = (Window) atoi(optarg);
|
|
|
|
if (!isValidWindowId(TQPaintDevice::x11AppDisplay(), w))
|
|
|
|
{
|
|
|
|
tqDebug("Window 0x%x invalid", (unsigned) w);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} // switch (option)
|
|
|
|
} // while (getopt)
|
|
|
|
|
|
|
|
// Launch an application if present in command line. else request from user
|
|
|
|
CustomTrayLabel *t = (CustomTrayLabel *) // this should be dynamic_cast
|
|
|
|
((optind < argc) ? dockApplication(&argv[optind])
|
|
|
|
: selectAndDock(w, check_normality));
|
|
|
|
if (t == NULL) return false;
|
|
|
|
// apply settings and add to tray
|
|
|
|
manageTrayLabel(t);
|
|
|
|
if (icon) t->setTrayIcon(icon);
|
|
|
|
t->setSkipTaskbar(skip_taskbar);
|
|
|
|
t->setBalloonTimeout(balloon_timeout);
|
|
|
|
t->setDockWhenObscured(dock_obscure);
|
|
|
|
if (withdraw) t->withdraw(); else t->map();
|
|
|
|
t->enableSessionManagement(enable_sm);
|
|
|
|
t->dock();
|
|
|
|
t->setLaunchOnStartup(auto_launch);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Request user to make a window selection if necessary. Dock the window.
|
|
|
|
*/
|
|
|
|
TQTrayLabel *TrayLabelMgr::selectAndDock(Window w, bool checkNormality)
|
|
|
|
{
|
|
|
|
if (w == None)
|
|
|
|
{
|
|
|
|
tqDebug("%s", i18n("Select the application/window to dock with button1.").local8Bit().data());
|
|
|
|
tqDebug("%s", i18n("Click any other button to abort\n").local8Bit().data());
|
|
|
|
|
|
|
|
const char *err = NULL;
|
|
|
|
|
|
|
|
if ((w = selectWindow(TQPaintDevice::x11AppDisplay(), &err)) == None)
|
|
|
|
{
|
|
|
|
if (err) TQMessageBox::critical(NULL, i18n("KDocker"), i18n(err));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (checkNormality && !isNormalWindow(TQPaintDevice::x11AppDisplay(), w))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Abort should be the only option here really. "Ignore" is provided here
|
|
|
|
* for the curious user who wants to screw himself very badly
|
|
|
|
*/
|
|
|
|
if (TQMessageBox::warning(NULL, i18n("KDocker"),
|
|
|
|
i18n("The window you are attempting to dock does not seem to be a"
|
|
|
|
" normal window."), TQMessageBox::Abort,
|
|
|
|
TQMessageBox::Ignore) == TQMessageBox::Abort)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isWindowDocked(w)) return new CustomTrayLabel(w);
|
|
|
|
|
|
|
|
TRACE("0x%x is not docked", (unsigned) w);
|
|
|
|
|
|
|
|
TQMessageBox::message(i18n("KDocker"),
|
|
|
|
i18n("This window is already docked.\n"
|
|
|
|
"Click on system tray icon to toggle docking."));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TrayLabelMgr::isWindowDocked(Window w)
|
|
|
|
{
|
|
|
|
TQPtrListIterator<TQTrayLabel> it(mTrayLabels);
|
|
|
|
for(TQTrayLabel *t; (t = it.current()); ++it)
|
|
|
|
if (t->dockedWindow() == w) return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Forks application specified by argv. Requests root window SubstructreNotify
|
|
|
|
* notifications (for MapEvent on children). We will monitor these new windows
|
|
|
|
* to make a pid to wid mapping (see HACKING for more details)
|
|
|
|
*/
|
|
|
|
TQTrayLabel *TrayLabelMgr::dockApplication(char *argv[])
|
|
|
|
{
|
|
|
|
pid_t pid = -1;
|
|
|
|
int filedes[2];
|
|
|
|
char buf[4] = { 't', 'e', 'e', 'e' }; // teeeeeee :x :-*
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The pipe created here serves as a synchronization mechanism between the
|
|
|
|
* parent and the child. TQTrayLabel ctor keeps looking out for newly created
|
|
|
|
* windows. Need to make sure that the application is actually exec'ed only
|
|
|
|
* after we TQTrayLabel is created (it requires pid of child)
|
|
|
|
*/
|
|
|
|
pipe(filedes);
|
|
|
|
|
|
|
|
if ((pid = fork()) == 0)
|
|
|
|
{
|
|
|
|
close(filedes[1]);
|
|
|
|
read(filedes[0], buf, sizeof(buf));
|
|
|
|
close(filedes[0]);
|
|
|
|
|
|
|
|
if (execvp(argv[0], argv) == -1)
|
|
|
|
{
|
|
|
|
tqDebug("%s", i18n("Failed to exec [%1]: %2").arg(argv[0]).arg(strerror(errno)).local8Bit().data());
|
|
|
|
::exit(0); // will become a zombie in some systems :(
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pid == -1)
|
|
|
|
{
|
|
|
|
TQMessageBox::critical(NULL, "KDocker",
|
|
|
|
i18n("Failed to fork: %1").arg(strerror(errno)));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList cmd_line;
|
|
|
|
for(int i=0;;i++)
|
|
|
|
if (argv[i]) cmd_line << argv[i]; else break;
|
|
|
|
|
|
|
|
TQTrayLabel *label = new CustomTrayLabel(cmd_line, pid);
|
|
|
|
tqApp->syncX();
|
|
|
|
write(filedes[1], buf, sizeof(buf));
|
|
|
|
close(filedes[0]);
|
|
|
|
close(filedes[1]);
|
|
|
|
return label;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns the number of TQTrayLabels actually created but not show in the
|
|
|
|
* System Tray
|
|
|
|
*/
|
|
|
|
int TrayLabelMgr::hiddenLabelsCount(void) const
|
|
|
|
{
|
|
|
|
TQPtrListIterator<TQTrayLabel> it(mTrayLabels);
|
|
|
|
int count = 0;
|
|
|
|
for(TQTrayLabel *t; (t=it.current()); ++it)
|
|
|
|
if (t->dockedWindow() == None) ++count;
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The number of labes that are docked in the system tray
|
|
|
|
int TrayLabelMgr::dockedLabelsCount(void) const
|
|
|
|
{
|
|
|
|
return mTrayLabels.count() - hiddenLabelsCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrayLabelMgr::trayLabelDestroyed(TQObject *t)
|
|
|
|
{
|
|
|
|
bool reconnect = ((TQObject *)mTrayLabels.getLast() == t);
|
|
|
|
mTrayLabels.removeRef((TQTrayLabel*)t);
|
|
|
|
if (mTrayLabels.isEmpty()) tqApp->quit();
|
|
|
|
else if (reconnect)
|
|
|
|
{
|
|
|
|
TRACE("Reconnecting");
|
|
|
|
connect(mTrayLabels.getFirst(), SIGNAL(sysTrayDestroyed()),
|
|
|
|
this, SLOT(sysTrayDestroyed()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrayLabelMgr::sysTrayDestroyed(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* The system tray got destroyed. This could happen when it was
|
|
|
|
* hidden/removed or killed/crashed/exited. Now we must be genteel enough
|
|
|
|
* to not pop up a box when the user is logging out. So, we set ourselves
|
|
|
|
* up to notify user after 3 seconds.
|
|
|
|
*/
|
|
|
|
TQTimer::singleShot(3000, this, SLOT(notifySysTrayAbsence()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrayLabelMgr::notifySysTrayAbsence()
|
|
|
|
{
|
|
|
|
SysTrayState state = sysTrayStatus(TQPaintDevice::x11AppDisplay());
|
|
|
|
|
|
|
|
if (state == SysTrayPresent)
|
|
|
|
return; // So sweet of the systray to come back so soon
|
|
|
|
|
|
|
|
if (TQMessageBox::warning(NULL, i18n("KDocker"),
|
|
|
|
i18n("The System tray was hidden or removed"),
|
|
|
|
i18n("Undock All"), i18n("Ignore")) == 0)
|
|
|
|
undockAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Session Management. Always return "true". Atleast, for now
|
|
|
|
*/
|
|
|
|
bool TrayLabelMgr::restoreSession(const TQString& sessionId)
|
|
|
|
{
|
|
|
|
TQString session_file = "kdocker_" + sessionId;
|
|
|
|
|
|
|
|
TQSettings settings;
|
|
|
|
settings.beginGroup(TQString("/" + session_file));
|
|
|
|
|
|
|
|
for(int i = 1;; i++)
|
|
|
|
{
|
|
|
|
settings.beginGroup(TQString("/Instance") + TQString("").setNum(i));
|
|
|
|
TQString pname = settings.readEntry("/Application");
|
|
|
|
TRACE("Restoring Application[%s]", pname.latin1());
|
|
|
|
if (pname.isEmpty()) break;
|
|
|
|
if (settings.readBoolEntry("/LaunchOnStartup"))
|
|
|
|
{
|
|
|
|
TQStringList args("kdocker");
|
|
|
|
args += TQStringList::split(" ", pname);
|
|
|
|
TRACE("Triggering AutoLaunch");
|
|
|
|
if (!processCommand(args)) continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
manageTrayLabel(new CustomTrayLabel(TQStringList::split(" ", pname), 0));
|
|
|
|
|
|
|
|
TQTrayLabel *tl = mTrayLabels.getFirst(); // the one that was created above
|
|
|
|
tl->restoreState(settings);
|
|
|
|
settings.endGroup();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString TrayLabelMgr::saveSession(void)
|
|
|
|
{
|
|
|
|
TQString session_file = "kdocker_" + tqApp->sessionId();
|
|
|
|
|
|
|
|
TQSettings settings;
|
|
|
|
settings.beginGroup(TQString("/" + session_file));
|
|
|
|
|
|
|
|
TRACE("Saving session");
|
|
|
|
|
|
|
|
TQPtrListIterator <TQTrayLabel> it(mTrayLabels);
|
|
|
|
TQTrayLabel *t;
|
|
|
|
int i = 1;
|
|
|
|
while ((t = it.current()) != 0)
|
|
|
|
{
|
|
|
|
++it;
|
|
|
|
TRACE("Saving instance %i", i);
|
|
|
|
settings.beginGroup(TQString("/Instance") + TQString("").setNum(i));
|
|
|
|
bool ok = t->saveState(settings);
|
|
|
|
settings.endGroup();
|
|
|
|
if (ok) ++i; else TRACE("Saving of instance %i was skipped", i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Aaaaaaaaaaaaaa.........
|
|
|
|
settings.removeEntry(TQString("/Instance") + TQString("").setNum(i));
|
|
|
|
|
|
|
|
return TQDir::homeDirPath() + "/.qt/" + session_file + "rc";
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The X11 Event Filter. Pass on events to the TQTrayLabels that we created.
|
|
|
|
* The logic and the code below is a bit fuzzy.
|
|
|
|
* a) Events about windows that are being docked need to be processed only by
|
|
|
|
* the TQTrayLabel object that is docking that window.
|
|
|
|
* b) Events about windows that are not docked but of interest (like
|
|
|
|
* SystemTray) need to be passed on to all TQTrayLabel objects.
|
|
|
|
* c) When a TQTrayLabel manages to find the window that is was looking for, we
|
|
|
|
* need not process the event further
|
|
|
|
*/
|
|
|
|
bool TrayLabelMgr::x11EventFilter(XEvent *ev)
|
|
|
|
{
|
|
|
|
TQPtrListIterator<TQTrayLabel> it(mTrayLabels);
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
// We pass on the event to all tray labels
|
|
|
|
for(TQTrayLabel *t; (t = it.current()); ++it)
|
|
|
|
{
|
|
|
|
Window w = t->dockedWindow();
|
|
|
|
bool res = t->x11EventFilter(ev);
|
|
|
|
if (w == (((XAnyEvent *)ev)->window)) return res;
|
|
|
|
if (w != None) ret |= res;
|
|
|
|
else if (res) return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "traylabelmgr.moc"
|