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(); }
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(); } }
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; }
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(); }
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; } }
// ======================== // 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; }
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; }
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(); }
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; }