Ejemplo n.º 1
0
int  main(int argc, char *argv[]) {
   LTHEME::LoadCustomEnvSettings();
   LSingleApplication a(argc, argv, "lumina-terminal");
    if( !a.isPrimaryProcess() ){ return 0; } //poked the current process instead
	
   //First make sure a system tray is available
  /*qDebug() << "Checking for system tray";
   bool ready = false;
   for(int i=0; i<60 && !ready; i++){
      ready = QSystemTrayIcon::isSystemTrayAvailable();
      if(!ready){
	//Pause for 5 seconds
        sleep(5); //don't worry about stopping event handling - nothing running yet
      }
   }
   if(!ready){
     qDebug() << "Could not find any available system tray after 5 minutes: exiting....";
     return 1;
   }*/
   
   //Now go ahead and setup the app
   LuminaThemeEngine theme(&a);
     QApplication::setQuitOnLastWindowClosed(false);   
     
   //Now start the tray icon
   TrayIcon tray;
    QObject::connect(&a, SIGNAL(InputsAvailable(QStringList)), &tray, SLOT(slotSingleInstance(QStringList)) );
    QObject::connect(&theme, SIGNAL(updateIcons()), &tray, SLOT(updateIcons()) );
    tray.parseInputs(a.inputlist);
   tray.show();
   return  a.exec();
}
Ejemplo n.º 2
0
void LxQtTray::x11EventFilter(XEventType* event)
{
    TrayIcon* icon;
    int event_type;
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) // use XCB for Qt5
    event_type = event->response_type & ~0x80;
#else // use XLib for Qt4
    event_type = event->type;
#endif

    switch (event_type)
    {
        case ClientMessage:
            clientMessageEvent(event);
            break;

//        case ConfigureNotify:
//            icon = findIcon(event->xconfigure.window);
//            if (icon)
//                icon->configureEvent(&(event->xconfigure));
//            break;

        case DestroyNotify: {
            unsigned long event_window;
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) // use XCB for Qt5
            event_window = reinterpret_cast<xcb_destroy_notify_event_t*>(event)->window;
#else // use XLib for Qt4
            event_window = event->xany.window;
#endif
            icon = findIcon(event_window);
            if (icon)
            {
                mIcons.removeAll(icon);
                delete icon;
            }
            break;
        }
        default:
            if (event_type == mDamageEvent + XDamageNotify)
            {
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) // use XCB for Qt5
                //FIXME: implement for XCB
                xcb_damage_notify_event_t* dmg = reinterpret_cast<xcb_damage_notify_event_t*>(event);
#else // use XLib for Qt4
                XDamageNotifyEvent* dmg = reinterpret_cast<XDamageNotifyEvent*>(event);
#endif
                icon = findIcon(dmg->drawable);
                if (icon)
                    icon->update();
            }
            break;
    }
}
void WindowsPlatformIntegration::showNotification(Notification *notification)
{
	TrayIcon *trayIcon = Application::getInstance()->getTrayIcon();

	if (trayIcon && QSystemTrayIcon::supportsMessages())
	{
		trayIcon->showMessage(notification);
	}
	else
	{
		NotificationDialog *dialog = new NotificationDialog(notification);
		dialog->show();
	}
}
Ejemplo n.º 4
0
bool LXQtTray::nativeEventFilter(const QByteArray &eventType, void *message, long *)
{
    if (eventType != "xcb_generic_event_t")
        return false;

    xcb_generic_event_t* event = static_cast<xcb_generic_event_t *>(message);

    TrayIcon* icon;
    int event_type = event->response_type & ~0x80;

    switch (event_type)
    {
        case ClientMessage:
            clientMessageEvent(event);
            break;

//        case ConfigureNotify:
//            icon = findIcon(event->xconfigure.window);
//            if (icon)
//                icon->configureEvent(&(event->xconfigure));
//            break;

        case DestroyNotify: {
            unsigned long event_window;
            event_window = reinterpret_cast<xcb_destroy_notify_event_t*>(event)->window;
            icon = findIcon(event_window);
            if (icon)
            {
                icon->windowDestroyed(event_window);
                mIcons.removeAll(icon);
                delete icon;
            }
            break;
        }
        default:
            if (event_type == mDamageEvent + XDamageNotify)
            {
                xcb_damage_notify_event_t* dmg = reinterpret_cast<xcb_damage_notify_event_t*>(event);
                icon = findIcon(dmg->drawable);
                if (icon)
                    icon->update();
            }
            break;
    }

    return false;
}
Ejemplo n.º 5
0
int main(int argc, char **argv)
{
	int err;

	QApplication app(argc, argv);
	err = setup_signal_handlers();
	if (err) {
		cerr << "Failed to initilize signal handlers" << endl;
		return 1;
	}
	if (!waitForSystray())
		return 1;
	TrayIcon icon;
	icon.show();
	if (!icon.init())
		return 1;
	return app.exec();
}
Ejemplo n.º 6
0
void RazorTray::x11EventFilter(XEvent* event) {
  TrayIcon* icon;

  switch(event->type) {
  case ClientMessage:
    if(event->xany.window == mTrayId)
      clientMessageEvent(&(event->xclient));
    break;

//        case ConfigureNotify:
//            icon = findIcon(event->xconfigure.window);
//            if (icon)
//                icon->configureEvent(&(event->xconfigure));
//            break;

  case SelectionClear:
    stopTray();
    break;

  case DestroyNotify:
    icon = findIcon(event->xany.window);

    if(icon) {
      mIcons.removeAll(icon);
      delete icon;
    }

    break;

  default:

    if(event->type == mDamageEvent + XDamageNotify) {
      XDamageNotifyEvent* dmg = reinterpret_cast<XDamageNotifyEvent*>(event);
      icon = findIcon(dmg->drawable);

      if(icon)
        icon->update();
    }

    break;
  }
}
Ejemplo n.º 7
0
// ========================
//    PRIVATE FUNCTIONS
// ========================
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());
  for(int i=0; i<trayIcons.length(); i++){
    int index = wins.indexOf(trayIcons[i]->appID());
    if(index < 0){
      //Tray Icon no longer exists: remove it
      qDebug() << " - Visual System Tray: Remove Icon";
      TrayIcon *cont = trayIcons.takeAt(i);
      LI->removeWidget(cont);
      delete cont;
      i--; //List size changed
      listChanged = true;
      //Re-adjust the maximum widget size to account for what is left
      if(this->layout()->direction()==QBoxLayout::LeftToRight){
        this->setMaximumSize( trayIcons.length()*this->height(), 10000);
      }else{
        this->setMaximumSize(10000, trayIcons.length()*this->width());
      }
    }else{
      //Tray Icon already exists
      //qDebug() << " - SysTray: Update Icon";
      //trayIcons[i]->update();
      wins.removeAt(index); //Already found - remove from the list
    }
  }
  //Now go through any remaining windows and add them
  for(int i=0; i<wins.length() && TrayRunning; i++){
    qDebug() << " - Visual System Tray: Add Icon";
    TrayIcon *cont = new TrayIcon(this);
      LSession::processEvents();
      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(wins[i]);
      if(cont->appID()==0){ 
	//could not attach window - remove the widget
	qDebug() << "Invalid Tray Container:"; 
	trayIcons.takeAt(trayIcons.length()-1); //Always at the end
	LI->removeWidget(cont);
	delete cont;
	continue;
      }else{
	listChanged = true;
      }
    LI->update(); //make sure there is no blank space in the layout
  }
  /*if(listChanged){
    //Icons got moved around: be sure to re-draw all of them to fix visuals
    for(int i=0; i<trayIcons.length(); i++){
      trayIcons[i]->update();
    }
  }*/
  //qDebug() << " - System Tray: check done";
  checking = false;
}
Ejemplo n.º 8
0
LRESULT TrayIcon::OnTryIcon(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
	#ifdef _DEBUG
	wchar_t szMsg[128];
	#endif

	switch (lParam)
	{
		case WM_LBUTTONUP:
		case NIN_BALLOONUSERCLICK:
			#ifdef _DEBUG
			_wsprintf(szMsg, SKIPLEN(countof(szMsg)) (lParam==WM_LBUTTONUP) ? L"TSA: WM_LBUTTONUP(%i,0x%08X)\n" : L"TSA: NIN_BALLOONUSERCLICK(%i,0x%08X)\n", (int)wParam, (DWORD)lParam);
			DEBUGSTRICON(szMsg);
			#endif
			if (gpSet->isQuakeStyle)
			{
				SingleInstanceShowHideType sih = sih_ShowHideTSA;
				if (IsWindowVisible(ghWnd))
				{
					if (gpSet->isAlwaysOnTop || (gpSet->isQuakeStyle == 2))
					{
						sih = sih_HideTSA;
					}
					else
					{
						// Хм. Тут проблема. Если поверх ConEmu есть какое-то окно, то ConEmu нужно поднять?
					}
				}
				gpConEmu->OnMinimizeRestore(sih);
			}
			else if (gpSet->isAlwaysShowTrayIcon && IsWindowVisible(ghWnd))
			{
				if (gpSet->isMinToTray())
					Icon.HideWindowToTray();
				else
					SendMessage(ghWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
			}
			else
			{
				Icon.RestoreWindowFromTray();
			}

			if (m_MsgSource == tsa_Source_Updater)
			{
				m_MsgSource = tsa_Source_None;
				gpConEmu->CheckUpdates(2);
			}
			break;
		case NIN_BALLOONSHOW:
			#ifdef _DEBUG
			_wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: NIN_BALLOONSHOW(%i,0x%08X)\n", (int)wParam, (DWORD)lParam);
			DEBUGSTRICON(szMsg);
			#endif
			mn_BalloonShowTick = GetTickCount();
			break;
		case NIN_BALLOONTIMEOUT:
			{
				#ifdef _DEBUG
				_wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: NIN_BALLOONTIMEOUT(%i,0x%08X)\n", (int)wParam, (DWORD)lParam);
				DEBUGSTRICON(szMsg);
				#endif

				if (mb_SecondTimeoutMsg
					|| (mn_BalloonShowTick && ((GetTickCount() - mn_BalloonShowTick) > MY_BALLOON_TICK)))
				{
					m_MsgSource = tsa_Source_None;
					Icon.RestoreWindowFromTray(TRUE);
				}
				else if (!mb_SecondTimeoutMsg && (mn_BalloonShowTick && ((GetTickCount() - mn_BalloonShowTick) > MY_BALLOON_TICK)))
				{
					mb_SecondTimeoutMsg = true;
				}
			}
			break;
		case WM_RBUTTONUP:
		{
			#ifdef _DEBUG
			_wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: WM_RBUTTONUP(%i,0x%08X)\n", (int)wParam, (DWORD)lParam);
			DEBUGSTRICON(szMsg);
			#endif
			POINT mPos;
			GetCursorPos(&mPos);
			apiSetForegroundWindow(ghWnd);
			gpConEmu->mp_Menu->ShowSysmenu(mPos.x, mPos.y);
			PostMessage(hWnd, WM_NULL, 0, 0);
		}
		break;

	#ifdef _DEBUG
	default:
		_wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: OnTryIcon(uMsg, wParam=%i, lParam=0x%04X)\n", messg, (int)wParam, (DWORD)lParam);
		DEBUGSTRICON(szMsg);
	#endif
	}

	return 0;
}
Ejemplo n.º 9
0
int main(int argc, char * argv[])
{
    /*
     * Before starting main application, need to set 'QT_X11_NO_MITSHM=1'
     * to make the runtime work with IBM PPC machine.
     */
#if defined (Q_OS_LINUX)
    QByteArray val("1");
    qputenv("QT_X11_NO_MITSHM", val);
#endif

    // Create the QT application
    QApplication app(argc, argv);
    app.setQuitOnLastWindowClosed(false);

    // Setup the settings management
    QCoreApplication::setOrganizationName("pgadmin");
    QCoreApplication::setOrganizationDomain("pgadmin.org");
    QCoreApplication::setApplicationName(PGA_APP_NAME.toLower().replace(" ", ""));

#if QT_VERSION >= 0x050000
    // Set high DPI pixmap to display icons clear on Qt widget.
    QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif

    // Create a hash of the executable path so we can run copies side-by-side
    QString homeDir = QDir::homePath();
    unsigned long exeHash = sdbm((unsigned char *)argv[0]);

    // Create the address file, that will be used to store the appserver URL for this instance
    addrFileName = homeDir + (QString("/.%1.%2.addr").arg(PGA_APP_NAME).arg(exeHash)).remove(" ");
    QFile addrFile(addrFileName);

    // Create a system-wide semaphore keyed by app name, exe hash and the username
    // to ensure instances are unique to the user and path
    QString userName = qgetenv("USER"); // *nix
    if (userName.isEmpty())
        userName = qgetenv("USERNAME"); // Windows

    QString semaName = QString("%1-%2-%3-sema").arg(PGA_APP_NAME).arg(userName).arg(exeHash);
    QString shmemName = QString("%1-%2-%3-shmem").arg(PGA_APP_NAME).arg(userName).arg(exeHash);

    QSystemSemaphore sema(semaName, 1);
    sema.acquire();

#ifndef Q_OS_WIN32
    // We may need to clean up stale shmem segments on *nix. Attaching and detaching
    // should remove the segment if it is orphaned.
    QSharedMemory stale_shmem(shmemName);
    if (stale_shmem.attach())
        stale_shmem.detach();
#endif

    QSharedMemory shmem(shmemName);
    bool is_running;
    if (shmem.attach())
    {
        is_running = true;
    }
    else
    {
        shmem.create(1);
        is_running = false;
    }
    sema.release();

    QSettings settings;

    if (is_running){
        addrFile.open(QIODevice::ReadOnly | QIODevice::Text);
        QTextStream in(&addrFile);
        QString addr = in.readLine();

        QString cmd = settings.value("BrowserCommand").toString();

        if (!cmd.isEmpty())
        {
            cmd.replace("%URL%", addr);
            QProcess::startDetached(cmd);
        }
        else
        {
            if (!QDesktopServices::openUrl(addr))
            {
                QString error(QWidget::tr("Failed to open the system default web browser. Is one installed?."));
                QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

                exit(1);
            }
        }

        return 0;
    }

    atexit(cleanup);

    // In windows and linux, it is required to set application level proxy
    // because socket bind logic to find free port gives socket creation error
    // when system proxy is configured. We are also setting
    // "setUseSystemConfiguration"=true to use the system proxy which will
    // override this application level proxy. As this bug is fixed in Qt 5.9 so
    // need to set application proxy for Qt version < 5.9.
    //
#if defined (Q_OS_WIN) && QT_VERSION <= 0x050800
    // Give dummy URL required to find proxy server configured in windows.
    QNetworkProxyQuery proxyQuery(QUrl("https://www.pgadmin.org"));
    QNetworkProxy l_proxy;
    QList<QNetworkProxy> listOfProxies = QNetworkProxyFactory::systemProxyForQuery(proxyQuery);

    if (listOfProxies.size())
    {
        l_proxy = listOfProxies[0];

        // If host name is not empty means proxy server is configured.
        if (!l_proxy.hostName().isEmpty()) {
            QNetworkProxy::setApplicationProxy(QNetworkProxy());
        }
    }
#endif

#if defined (Q_OS_LINUX) && QT_VERSION <= 0x050800
    QByteArray proxy_env;
    proxy_env = qgetenv("http_proxy");
    // If http_proxy environment is defined in linux then proxy server is configured.
    if (!proxy_env.isEmpty()) {
        QNetworkProxy::setApplicationProxy(QNetworkProxy());
    }
#endif

    // Display the spash screen
    QSplashScreen *splash = new QSplashScreen();
    splash->setPixmap(QPixmap(":/splash.png"));
    splash->show();
    app.processEvents(QEventLoop::AllEvents);

    quint16 port = 0L;

    // Find an unused port number. Essentially, we're just reserving one
    // here that Flask will use when we start up the server.
    // In order to use the socket, we need to free this socket ASAP.
    // Hence - putting this code in a code block so the scope of the socket
    // variable vanishes to make that socket available.
    {
#if QT_VERSION >= 0x050000
        QTcpSocket socket;

        #if QT_VERSION >= 0x050900
        socket.setProxy(QNetworkProxy::NoProxy);
        #endif

        socket.bind(0, QTcpSocket::ShareAddress);
#else
        QUdpSocket socket;
        socket.bind(0, QUdpSocket::ShareAddress);
#endif
        port = socket.localPort();
    }

    // Generate a random key to authenticate the client to the server
    QString key = QUuid::createUuid().toString();
    key = key.mid(1, key.length() - 2);

    // Generate the filename for the log
    logFileName = homeDir + (QString("/.%1.%2.log").arg(PGA_APP_NAME).arg(exeHash)).remove(" ");

    // Start the tray service
    TrayIcon *trayicon = new TrayIcon(logFileName);

    if (!trayicon->Init())
    {
        QString error = QString(QWidget::tr("An error occurred initialising the tray icon"));
        QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

        exit(1);
    }

    // Fire up the webserver
    Server *server;

    bool done = false;

    while (done != true)
    {
        server = new Server(port, key, logFileName);

        if (!server->Init())
        {
            splash->finish(NULL);

            qDebug() << server->getError();

            QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
            QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

            exit(1);
        }

        server->start();

        // This is a hack to give the server a chance to start and potentially fail. As
        // the Python interpreter is a synchronous call, we can't check for proper startup
        // easily in a more robust way - we have to rely on a clean startup not returning.
        // It should always fail pretty quickly, and take longer to start if it succeeds, so
        // we don't really get a visible delay here.
        delay(1000);

        // Any errors?
        if (server->isFinished() || server->getError().length() > 0)
        {
            splash->finish(NULL);

            qDebug() << server->getError();

            QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
            QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

            // Allow the user to tweak the Python Path if needed
            bool ok;

            ConfigWindow *dlg = new ConfigWindow();
            dlg->setWindowTitle(QWidget::tr("Configuration"));
            dlg->setBrowserCommand(settings.value("BrowserCommand").toString());
            dlg->setPythonPath(settings.value("PythonPath").toString());
            dlg->setApplicationPath(settings.value("ApplicationPath").toString());
            dlg->setModal(true);
            ok = dlg->exec();

            QString browsercommand = dlg->getBrowserCommand();
            QString pythonpath = dlg->getPythonPath();
            QString applicationpath = dlg->getApplicationPath();

            if (ok)
            {
                settings.setValue("BrowserCommand", browsercommand);
                settings.setValue("PythonPath", pythonpath);
                settings.setValue("ApplicationPath", applicationpath);
                settings.sync();
            }
            else
            {
                exit(1);
            }

            delete server;
        }
        else
            done = true;
    }

    // Ensure the server gets cleaned up later
    QObject::connect(server, SIGNAL(finished()), server, SLOT(deleteLater()));

    // Generate the app server URL
    QString appServerUrl = QString("http://127.0.0.1:%1/?key=%2").arg(port).arg(key);

    // Read the server connection timeout from the registry or set the default timeout.
    int timeout = settings.value("ConnectionTimeout", 30).toInt();

    // Now the server should be up, we'll attempt to connect and get a response.
    // We'll retry in a loop a few time before aborting if necessary.

    QTime endTime = QTime::currentTime().addSecs(timeout);
    bool alive = false;

    while(QTime::currentTime() <= endTime)
    {
        alive = PingServer(QUrl(appServerUrl));

        if (alive)
        {
            break;
        }

        delay(200);
    }

    // Attempt to connect one more time in case of a long network timeout while looping
    if (!alive && !PingServer(QUrl(appServerUrl)))
    {
        splash->finish(NULL);
        QString error(QWidget::tr("The application server could not be contacted."));
        QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

        exit(1);
    }

    // Stash the URL for any duplicate processes to open
    if (addrFile.open(QIODevice::WriteOnly))
    {
        addrFile.setPermissions(QFile::ReadOwner|QFile::WriteOwner);
        QTextStream out(&addrFile);
        out << appServerUrl << endl;
    }

    // Go!
    trayicon->setAppServerUrl(appServerUrl);
    // Enable the shutdown server menu as server started successfully.
    trayicon->enableShutdownMenu();

    QString cmd = settings.value("BrowserCommand").toString();

    if (!cmd.isEmpty())
    {
        cmd.replace("%URL%", appServerUrl);
        QProcess::startDetached(cmd);
    }
    else
    {
        if (!QDesktopServices::openUrl(appServerUrl))
        {
            QString error(QWidget::tr("Failed to open the system default web browser. Is one installed?."));
            QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

            exit(1);
        }
    }

    QObject::connect(trayicon, SIGNAL(shutdownSignal(QUrl)), server, SLOT(shutdown(QUrl)));

    splash->finish(NULL);

    return app.exec();
}
Ejemplo n.º 10
0
LRESULT TrayIcon::OnTryIcon(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
	#ifdef _DEBUG
	wchar_t szMsg[128];
	#endif

	switch (lParam)
	{
		case WM_LBUTTONUP:
		case NIN_BALLOONUSERCLICK:
			#ifdef _DEBUG
			_wsprintf(szMsg, SKIPLEN(countof(szMsg)) (lParam==WM_LBUTTONUP) ? L"TSA: WM_LBUTTONUP(%i,0x%08X)\n" : L"TSA: NIN_BALLOONUSERCLICK(%i,0x%08X)\n", (int)wParam, (DWORD)lParam);
			DEBUGSTRICON(szMsg);
			#endif
			if (gpSet->isQuakeStyle)
			{
				bool bJustActivate = false;
				SingleInstanceShowHideType sih = sih_QuakeShowHide;
				SingleInstanceShowHideType sihHide = gpSet->isMinToTray() ? sih_HideTSA : sih_Minimize;

				if (IsWindowVisible(ghWnd) && !gpConEmu->isIconic())
				{
					if (gpSet->isAlwaysOnTop || (gpSet->isQuakeStyle == 2))
					{
						sih = sihHide;
					}
					else
					{
						UINT nVisiblePart = gpConEmu->IsQuakeVisible();
						if (nVisiblePart >= QUAKEVISIBLELIMIT)
						{
							sih = sihHide;
						}
						else
						{
							// Если поверх ConEmu есть какое-то окно, то ConEmu нужно поднять?
							// Не "выезжать" а просто "вынести наверх", если видимая область достаточно большая
							bJustActivate = (nVisiblePart >= QUAKEVISIBLETRASH) && !gpConEmu->isIconic();
						}
					}
				}

				if (bJustActivate)
				{
					SetForegroundWindow(ghWnd);
				}
				else
				{
					gpConEmu->DoMinimizeRestore(sih);
				}
			}
			else if (gpSet->isAlwaysShowTrayIcon() && IsWindowVisible(ghWnd))
			{
				if (gpSet->isMinToTray())
					Icon.HideWindowToTray();
				else
					SendMessage(ghWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
			}
			else
			{
				Icon.RestoreWindowFromTray();
			}

			switch (m_MsgSource)
			{
			case tsa_Source_Updater:
				m_MsgSource = tsa_Source_None;
				gpConEmu->CheckUpdates(2);
				break;
			case tsa_Push_Notify:
				gpConEmu->mp_PushInfo->OnNotificationClick();
				m_MsgSource = tsa_Source_None;
				break;
			}
			break;
		case NIN_BALLOONSHOW:
			#ifdef _DEBUG
			_wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: NIN_BALLOONSHOW(%i,0x%08X)\n", (int)wParam, (DWORD)lParam);
			DEBUGSTRICON(szMsg);
			#endif
			mn_BalloonShowTick = GetTickCount();
			break;
		case NIN_BALLOONTIMEOUT:
			{
				#ifdef _DEBUG
				_wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: NIN_BALLOONTIMEOUT(%i,0x%08X)\n", (int)wParam, (DWORD)lParam);
				DEBUGSTRICON(szMsg);
				#endif

				if (mb_SecondTimeoutMsg
					|| (mn_BalloonShowTick && ((GetTickCount() - mn_BalloonShowTick) > MY_BALLOON_TICK)))
				{
					m_MsgSource = tsa_Source_None;
					Icon.RestoreWindowFromTray(TRUE);
				}
				else if (!mb_SecondTimeoutMsg && (mn_BalloonShowTick && ((GetTickCount() - mn_BalloonShowTick) > MY_BALLOON_TICK)))
				{
					mb_SecondTimeoutMsg = true;
				}
			}
			break;
		case WM_RBUTTONUP:
		{
			#ifdef _DEBUG
			_wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: WM_RBUTTONUP(%i,0x%08X)\n", (int)wParam, (DWORD)lParam);
			DEBUGSTRICON(szMsg);
			#endif
			POINT mPos;
			GetCursorPos(&mPos);
			gpConEmu->SetIgnoreQuakeActivation(true);
			apiSetForegroundWindow(ghWnd);
			LogString(L"ShowSysmenu called from (TSA)");
			gpConEmu->mp_Menu->ShowSysmenu(mPos.x, mPos.y);
			gpConEmu->SetIgnoreQuakeActivation(false);
			PostMessage(hWnd, WM_NULL, 0, 0);
		}
		break;

	#ifdef _DEBUG
	default:
		_wsprintf(szMsg, SKIPLEN(countof(szMsg)) L"TSA: OnTryIcon(uMsg, wParam=%i, lParam=0x%04X)\n", messg, (int)wParam, (DWORD)lParam);
		DEBUGSTRICON(szMsg);
	#endif
	}

	return 0;
}