From dde1a5a6eb20cbae51b09eb1da0de39a91a99f06 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 26 Jan 2015 16:04:41 +0300 Subject: [PATCH] new online / offline status update, notify delayed if other clients are active --- Telegram/Resources/lang.strings | 4 +- Telegram/SourceFiles/app.cpp | 1 + Telegram/SourceFiles/application.cpp | 5 +- Telegram/SourceFiles/application.h | 2 + Telegram/SourceFiles/config.h | 1 - Telegram/SourceFiles/history.cpp | 8 +- Telegram/SourceFiles/mainwidget.cpp | 129 +++++++++++++++-------- Telegram/SourceFiles/mainwidget.h | 16 ++- Telegram/SourceFiles/pspecific_linux.cpp | 72 ++----------- Telegram/SourceFiles/pspecific_linux.h | 12 +-- Telegram/SourceFiles/pspecific_mac.cpp | 77 +++----------- Telegram/SourceFiles/pspecific_mac.h | 7 +- Telegram/SourceFiles/pspecific_mac_p.h | 2 +- Telegram/SourceFiles/pspecific_mac_p.mm | 11 +- Telegram/SourceFiles/pspecific_wnd.cpp | 83 +++------------ Telegram/SourceFiles/pspecific_wnd.h | 12 +-- Telegram/SourceFiles/settings.cpp | 10 ++ Telegram/SourceFiles/settings.h | 10 ++ Telegram/SourceFiles/window.cpp | 123 ++++++++++++++------- Telegram/SourceFiles/window.h | 12 ++- 20 files changed, 281 insertions(+), 316 deletions(-) diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings index 436cae515..a9042c860 100644 --- a/Telegram/Resources/lang.strings +++ b/Telegram/Resources/lang.strings @@ -173,7 +173,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_check_now" = "Check for updates"; "lng_settings_update_checking" = "Checking for updates.."; "lng_settings_latest_installed" = "Latest version is installed"; -"lng_settings_downloading" = "Downloading update {ready} / {total} Mb.."; +"lng_settings_downloading" = "Downloading update {ready} / {total} MB.."; "lng_settings_update_ready" = "New version is ready"; "lng_settings_update_now" = "Restart Now"; "lng_settings_update_fail" = "Update check failed :("; @@ -457,7 +457,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org // Wnd specific -"lng_wnd_choose_program_menu" = "Choose default program..."; +"lng_wnd_choose_program_menu" = "Choose Default Program..."; // Mac specific diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index a11ce0e14..2ac976ba3 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -123,6 +123,7 @@ namespace App { MainWidget *m(main()); if (m) m->destroyData(); MTP::authed(0); + cSetOtherOnline(0); histories().clear(); globalNotifyAllPtr = UnknownNotifySettings; globalNotifyUsersPtr = UnknownNotifySettings; diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index a8d05b7a1..95554e1b3 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -382,6 +382,7 @@ void Application::onWriteUserConfig() { void Application::onAppStateChanged(Qt::ApplicationState state) { checkLocalTime(); + if (window) window->updateIsActive((state == Qt::ApplicationActive) ? cOnlineFocusTimeout() : cOfflineBlurTimeout()); } void Application::killDownloadSessions() { @@ -707,9 +708,7 @@ void Application::startApp() { } } -// if (!cLangErrors().isEmpty()) { -// window->showLayer(new ConfirmBox("Custom lang failed :(\n\nError: " + cLangErrors(), true, lang(lng_close))); -// } + window->updateIsActive(cOnlineFocusTimeout()); } void Application::socketDisconnected() { diff --git a/Telegram/SourceFiles/application.h b/Telegram/SourceFiles/application.h index 2f0d4d16c..21495a02c 100644 --- a/Telegram/SourceFiles/application.h +++ b/Telegram/SourceFiles/application.h @@ -131,6 +131,8 @@ private: ClientSockets clients; bool closing; + uint64 lastActionTime; + void execExternal(const QString &cmd); Window *window; diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index d5d255ef2..8ef12e59b 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -260,7 +260,6 @@ enum { MemoryForImageCache = 64 * 1024 * 1024, // after 64mb of unpacked images we try to clear some memory NotifyWindowsCount = 3, // 3 desktop notifies at the same time - NotifyWaitTimeout = 1200, // 1.2 seconds timeout before notification NotifySettingSaveTimeout = 1000, // wait 1 second before saving notify setting to server UpdateChunk = 100 * 1024, // 100kb parts when downloading the update IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 7499512e9..aeda5064f 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -2341,10 +2341,10 @@ void HistoryPhoto::draw(QPainter &p, const HistoryItem *parent, bool selected, i QString formatSizeText(qint64 size) { if (size >= 1024 * 1024) { // more than 1 mb qint64 sizeTenthMb = (size * 10 / (1024 * 1024)); - return QString::number(sizeTenthMb / 10) + '.' + QString::number(sizeTenthMb % 10) + qsl("Mb"); + return QString::number(sizeTenthMb / 10) + '.' + QString::number(sizeTenthMb % 10) + qsl("MB"); } qint64 sizeTenthKb = (size * 10 / 1024); - return QString::number(sizeTenthKb / 10) + '.' + QString::number(sizeTenthKb % 10) + qsl("Kb"); + return QString::number(sizeTenthKb / 10) + '.' + QString::number(sizeTenthKb % 10) + qsl("KB"); } QString formatDownloadText(qint64 ready, qint64 total) { @@ -2353,12 +2353,12 @@ QString formatDownloadText(qint64 ready, qint64 total) { qint64 readyTenthMb = (ready * 10 / (1024 * 1024)), totalTenthMb = (total * 10 / (1024 * 1024)); readyStr = QString::number(readyTenthMb / 10) + '.' + QString::number(readyTenthMb % 10); totalStr = QString::number(totalTenthMb / 10) + '.' + QString::number(totalTenthMb % 10); - mb = qsl("Mb"); + mb = qsl("MB"); } else { qint64 readyKb = (ready / 1024), totalKb = (total / 1024); readyStr = QString::number(readyKb); totalStr = QString::number(totalKb); - mb = qsl("Kb"); + mb = qsl("KB"); } return lng_save_downloaded(lt_ready, readyStr, lt_total, totalStr, lt_mb, mb); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index bc3b6ef56..ed6169f27 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -350,16 +350,18 @@ MainWidget *TopBarWidget::main() { MainWidget::MainWidget(Window *window) : QWidget(window), _started(0), failedObjId(0), _dialogsWidth(st::dlgMinWidth), dialogs(this), history(this), profile(0), overview(0), _topBar(this), _forwardConfirm(0), hider(0), _mediaType(this), _mediaTypeMask(0), -updPts(0), updDate(0), updQts(-1), updSeq(0), updInited(false), onlineRequest(0), _failDifferenceTimeout(1), _lastUpdateTime(0) { +updPts(0), updDate(0), updQts(-1), updSeq(0), updInited(false), _onlineRequest(0), _lastWasOnline(false), _lastSetOnline(0), _isIdle(false), +_failDifferenceTimeout(1), _lastUpdateTime(0) { setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight)); connect(window, SIGNAL(resized(const QSize &)), this, SLOT(onParentResize(const QSize &))); connect(&dialogs, SIGNAL(cancelled()), this, SLOT(dialogsCancelled())); connect(&history, SIGNAL(cancelled()), &dialogs, SLOT(activate())); - connect(this, SIGNAL(peerPhotoChanged(PeerData *)), this, SIGNAL(dialogsUpdated())); + connect(this, SIGNAL(peerPhotoChanged(PeerData*)), this, SIGNAL(dialogsUpdated())); connect(&noUpdatesTimer, SIGNAL(timeout()), this, SLOT(getDifference())); - connect(&onlineTimer, SIGNAL(timeout()), this, SLOT(setOnline())); - connect(&onlineUpdater, SIGNAL(timeout()), this, SLOT(updateOnlineDisplay())); + connect(&_onlineTimer, SIGNAL(timeout()), this, SLOT(updateOnline())); + connect(&_onlineUpdater, SIGNAL(timeout()), this, SLOT(updateOnlineDisplay())); + connect(&_idleFinishTimer, SIGNAL(timeout()), this, SLOT(checkIdleFinish())); connect(&_bySeqTimer, SIGNAL(timeout()), this, SLOT(getDifference())); connect(&_failDifferenceTimer, SIGNAL(timeout()), this, SLOT(getDifferenceForce())); connect(this, SIGNAL(peerUpdated(PeerData*)), &history, SLOT(peerUpdated(PeerData*))); @@ -1272,6 +1274,10 @@ bool MainWidget::serviceHistoryFail(const RPCError &error) { return false; } +bool MainWidget::isIdle() const { + return _isIdle; +} + void MainWidget::setInnerFocus() { if (hider || !history.peer()) { if (hider && hider->wasOffered()) { @@ -2082,7 +2088,7 @@ void MainWidget::gotState(const MTPupdates_State &state) { updInited = true; dialogs.loadDialogs(); - setOnline(); + updateOnline(); } void MainWidget::gotDifference(const MTPupdates_Difference &diff) { @@ -2173,6 +2179,7 @@ void MainWidget::getDifference() { void MainWidget::start(const MTPUser &user) { MTP::authed(user.c_userSelf().vid.v); + cSetOtherOnline(0); App::initMedia(); App::feedUsers(MTP_vector(1, user)); App::app()->startUpdateCheck(); @@ -2398,7 +2405,7 @@ void MainWidget::destroyData() { } void MainWidget::updateOnlineDisplayIn(int32 msecs) { - onlineUpdater.start(msecs); + _onlineUpdater.start(msecs); } void MainWidget::addNewContact(int32 uid, bool show) { @@ -2408,13 +2415,21 @@ void MainWidget::addNewContact(int32 uid, bool show) { } bool MainWidget::isActive() const { - return isVisible() && !animating(); + return !_isIdle && isVisible() && !animating(); } bool MainWidget::historyIsActive() const { return isActive() && !profile && !overview && history.isActive(); } +bool MainWidget::lastWasOnline() const { + return _lastWasOnline; +} + +uint64 MainWidget::lastSetOnline() const { + return _lastSetOnline; +} + int32 MainWidget::dlgsWidth() const { return dialogs.width(); } @@ -2428,28 +2443,52 @@ MainWidget::~MainWidget() { if (App::wnd()) App::wnd()->noMain(this); } -void MainWidget::setOnline(int windowState) { - if (onlineRequest) { - MTP::cancel(onlineRequest); - onlineRequest = 0; +void MainWidget::updateOnline(bool gotOtherOffline) { + bool isOnline = App::wnd()->isActive(); + int updateIn = cOnlineUpdatePeriod(); + if (isOnline) { + uint64 idle = psIdleTime(); + if (idle >= cOfflineIdleTimeout()) { + isOnline = false; + if (!_isIdle) { + _isIdle = true; + _idleFinishTimer.start(900); + } + } else { + updateIn = qMin(updateIn, int(cOfflineIdleTimeout() - idle)); + } } - onlineTimer.stop(); - bool isOnline = App::wnd()->psIsOnline(windowState); - if (isOnline || windowState >= 0) { - onlineRequest = MTP::send(MTPaccount_UpdateStatus(MTP_bool(!isOnline))); - LOG(("App Info: Updating Online!")); + uint64 ms = getms(true); + if (isOnline != _lastWasOnline || (isOnline && _lastSetOnline + cOnlineUpdatePeriod() <= ms) || (isOnline && gotOtherOffline)) { + if (_onlineRequest) { + MTP::cancel(_onlineRequest); + _onlineRequest = 0; + } + + _lastWasOnline = isOnline; + _lastSetOnline = ms; + _onlineRequest = MTP::send(MTPaccount_UpdateStatus(MTP_bool(!isOnline))); + + if (App::self()) App::self()->onlineTill = unixtime() + (isOnline ? (cOnlineUpdatePeriod() / 1000) : -1); + + _lastSetOnline = getms(true); + + updateOnlineDisplay(); + } else if (isOnline) { + updateIn = _lastSetOnline + cOnlineUpdatePeriod() - ms; } - if (App::self()) App::self()->onlineTill = unixtime() + (isOnline ? 60 : -1); - if (profile) { - profile->updateOnlineDisplayTimer(); - } else { - history.updateOnlineDisplayTimer(); - } - onlineTimer.start(55000); + _onlineTimer.start(updateIn); } -void MainWidget::mainStateChanged(Qt::WindowState state) { - setOnline(state); +void MainWidget::checkIdleFinish() { + if (psIdleTime() < cOfflineIdleTimeout()) { + _idleFinishTimer.stop(); + _isIdle = false; + updateOnline(); + if (App::wnd()) App::wnd()->checkHistoryActivation(); + } else { + _idleFinishTimer.start(900); + } } void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) { @@ -2669,24 +2708,30 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { case mtpc_updateUserStatus: { const MTPDupdateUserStatus &d(update.c_updateUserStatus()); - if (d.vuser_id.v == MTP::authedId() && (d.vstatus.type() == mtpc_userStatusOffline || d.vstatus.type() == mtpc_userStatusEmpty)) { - setOnline(); - } else { - UserData *user = App::userLoaded(d.vuser_id.v); - if (user) { - switch (d.vstatus.type()) { - case mtpc_userStatusEmpty: user->onlineTill = 0; break; - case mtpc_userStatusRecently: - if (user->onlineTill > -10) { // don't modify pseudo-online - user->onlineTill = -2; - } - break; - case mtpc_userStatusLastWeek: user->onlineTill = -3; break; - case mtpc_userStatusLastMonth: user->onlineTill = -4; break; - case mtpc_userStatusOffline: user->onlineTill = d.vstatus.c_userStatusOffline().vwas_online.v; break; - case mtpc_userStatusOnline: user->onlineTill = d.vstatus.c_userStatusOnline().vexpires.v; break; + UserData *user = App::userLoaded(d.vuser_id.v); + if (user) { + switch (d.vstatus.type()) { + case mtpc_userStatusEmpty: user->onlineTill = 0; break; + case mtpc_userStatusRecently: + if (user->onlineTill > -10) { // don't modify pseudo-online + user->onlineTill = -2; } - if (App::main()) App::main()->peerUpdated(user); + break; + case mtpc_userStatusLastWeek: user->onlineTill = -3; break; + case mtpc_userStatusLastMonth: user->onlineTill = -4; break; + case mtpc_userStatusOffline: user->onlineTill = d.vstatus.c_userStatusOffline().vwas_online.v; break; + case mtpc_userStatusOnline: user->onlineTill = d.vstatus.c_userStatusOnline().vexpires.v; break; + } + if (App::main()) App::main()->peerUpdated(user); + } + if (d.vuser_id.v == MTP::authedId()) { + if (d.vstatus.type() == mtpc_userStatusOffline || d.vstatus.type() == mtpc_userStatusEmpty) { + updateOnline(true); + if (d.vstatus.type() == mtpc_userStatusOffline) { + cSetOtherOnline(d.vstatus.c_userStatusOffline().vwas_online.v); + } + } else if (d.vstatus.type() == mtpc_userStatusOnline) { + cSetOtherOnline(d.vstatus.c_userStatusOnline().vexpires.v); } } } break; diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 24738f0c7..aa241d6a8 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -242,6 +242,8 @@ public: bool isActive() const; bool historyIsActive() const; + bool lastWasOnline() const; + uint64 lastSetOnline() const; int32 dlgsWidth() const; @@ -312,6 +314,8 @@ public: void serviceHistoryDone(const MTPmessages_Messages &msgs); bool serviceHistoryFail(const RPCError &error); + bool isIdle() const; + ~MainWidget(); signals: @@ -344,8 +348,8 @@ public slots: void getDifference(); void getDifferenceForce(); - void setOnline(int windowState = -1); - void mainStateChanged(Qt::WindowState state); + void updateOnline(bool gotOtherOffline = false); + void checkIdleFinish(); void updateOnlineDisplay(); void showPeer(quint64 peer, qint32 msgId = 0, bool back = false, bool force = false); // PeerId, MsgId @@ -423,9 +427,11 @@ private: bool updInited; SingleTimer noUpdatesTimer; - mtpRequestId onlineRequest; - SingleTimer onlineTimer; - SingleTimer onlineUpdater; + mtpRequestId _onlineRequest; + SingleTimer _onlineTimer, _onlineUpdater, _idleFinishTimer; + bool _lastWasOnline; + uint64 _lastSetOnline; + bool _isIdle; QSet updateNotifySettingPeers; SingleTimer updateNotifySettingTimer; diff --git a/Telegram/SourceFiles/pspecific_linux.cpp b/Telegram/SourceFiles/pspecific_linux.cpp index a5234e7c0..ba0da1698 100644 --- a/Telegram/SourceFiles/pspecific_linux.cpp +++ b/Telegram/SourceFiles/pspecific_linux.cpp @@ -445,9 +445,6 @@ namespace { PsMainWindow::PsMainWindow(QWidget *parent) : QMainWindow(parent), posInited(false), trayIcon(0), trayIconMenu(0), icon256(qsl(":/gui/art/icon256.png")), iconbig256(icon256), wndIcon(QPixmap::fromImage(icon256, Qt::ColorOnly)), _psCheckStatusIconLeft(100), _psLastIndicatorUpdate(0) { - connect(&psIdleTimer, SIGNAL(timeout()), this, SLOT(psIdleTimeout())); - psIdleTimer.setSingleShot(false); - connect(&_psCheckStatusIconTimer, SIGNAL(timeout()), this, SLOT(psStatusIconCheck())); _psCheckStatusIconTimer.setSingleShot(false); @@ -455,15 +452,6 @@ posInited(false), trayIcon(0), trayIconMenu(0), icon256(qsl(":/gui/art/icon256.p _psUpdateIndicatorTimer.setSingleShot(true); } -void PsMainWindow::psNotIdle() const { - psIdleTimer.stop(); - if (psIdle) { - psIdle = false; - if (App::main()) App::main()->setOnline(); - if (App::wnd()) App::wnd()->checkHistoryActivation(); - } -} - bool PsMainWindow::psHasTrayIcon() const { return trayIcon || ((useAppIndicator || (useStatusIcon && trayIconChecked)) && (cWorkMode() != dbiwmWindowOnly)); } @@ -476,50 +464,9 @@ void PsMainWindow::psStatusIconCheck() { } } -void PsMainWindow::psIdleTimeout() { - int64 idleTime = 0;//objc_idleTime(); - if (idleTime >= 0) { - if (idleTime <= IdleMsecs) { - psNotIdle(); - } - } else { // error - psNotIdle(); - } -} - void PsMainWindow::psShowTrayMenu() { } -bool PsMainWindow::psIsOnline(int state) const { - if (state < 0) state = this->windowState(); - if (state & Qt::WindowMinimized) { - return false; - } else if (!isVisible()) { - return false; - } - int64 idleTime = 0;//objc_idleTime(); - LOG(("App Info: idle time %1").arg(idleTime)); - if (idleTime >= 0) { - if (idleTime > IdleMsecs) { - if (!psIdle) { - psIdle = true; - psIdleTimer.start(900); - } - return false; - } else { - psNotIdle(); - } - } else { // error - psNotIdle(); - } - return true; -} - -bool PsMainWindow::psIsActive(int state) const { - if (state < 0) state = this->windowState(); - return isActiveWindow() && isVisible() && !(state & Qt::WindowMinimized) && !psIdle; -} - void PsMainWindow::psRefreshTaskbarIcon() { } @@ -657,8 +604,6 @@ void PsMainWindow::psInitFrameless() { if (frameless) { //setWindowFlags(Qt::FramelessWindowHint); } - - connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(psStateChanged(Qt::WindowState))); } void PsMainWindow::psSavePosition(Qt::WindowState state) { @@ -708,12 +653,6 @@ void PsMainWindow::psUpdatedPosition() { psUpdatedPositionTimer.start(SaveWindowPositionTimeout); } -void PsMainWindow::psStateChanged(Qt::WindowState state) { - psUpdateSysMenu(state); - psUpdateMargins(); - psSavePosition(state); -} - void PsMainWindow::psCreateTrayIcon() { if (useAppIndicator) { DEBUG_LOG(("Trying to create AppIndicator")); @@ -1361,6 +1300,17 @@ PsUpdateDownloader::~PsUpdateDownloader() { reply = 0; } +namespace { + uint64 _lastUserAction = 0; +} + +void psUserActionDone() { + _lastUserAction = getms(true); +} + +uint64 psIdleTime() { + return getms(true) - _lastUserAction; +} QStringList psInitLogs() { return _initLogs; diff --git a/Telegram/SourceFiles/pspecific_linux.h b/Telegram/SourceFiles/pspecific_linux.h index 5db14f15a..c06f71133 100644 --- a/Telegram/SourceFiles/pspecific_linux.h +++ b/Telegram/SourceFiles/pspecific_linux.h @@ -53,9 +53,6 @@ public: void psFlash(); void psNotifySettingGot(); - bool psIsActive(int state = -1) const; - bool psIsOnline(int state) const; - void psUpdateWorkmode(); void psRefreshTaskbarIcon(); @@ -77,10 +74,8 @@ public: public slots: - void psStateChanged(Qt::WindowState state); void psUpdateDelegate(); void psSavePosition(Qt::WindowState state = Qt::WindowActive); - void psIdleTimeout(); void psShowTrayMenu(); void psStatusIconCheck(); @@ -88,7 +83,6 @@ public slots: protected: - void psNotIdle() const; bool psHasTrayIcon() const; bool posInited; @@ -105,9 +99,6 @@ protected: private: void psCreateTrayIcon(); - mutable bool psIdle; - mutable QTimer psIdleTimer; - QTimer _psCheckStatusIconTimer; int _psCheckStatusIconLeft; @@ -175,6 +166,9 @@ private: }; +void psUserActionDone(); +uint64 psIdleTime(); + QStringList psInitLogs(); void psClearInitLogs(); diff --git a/Telegram/SourceFiles/pspecific_mac.cpp b/Telegram/SourceFiles/pspecific_mac.cpp index efa747fa3..3b82b8a80 100644 --- a/Telegram/SourceFiles/pspecific_mac.cpp +++ b/Telegram/SourceFiles/pspecific_mac.cpp @@ -78,67 +78,15 @@ psLogout(0), psUndo(0), psRedo(0), psCut(0), psCopy(0), psPaste(0), psDelete(0), QImage tray(qsl(":/gui/art/osxtray.png")); trayImg = tray.copy(0, cRetina() ? 0 : tray.width() / 2, tray.width() / (cRetina() ? 2 : 4), tray.width() / (cRetina() ? 2 : 4)); trayImgSel = tray.copy(tray.width() / (cRetina() ? 2 : 4), cRetina() ? 0 : tray.width() / 2, tray.width() / (cRetina() ? 2 : 4), tray.width() / (cRetina() ? 2 : 4)); - connect(&psIdleTimer, SIGNAL(timeout()), this, SLOT(psIdleTimeout())); - psIdleTimer.setSingleShot(false); -} - -void PsMainWindow::psNotIdle() const { - psIdleTimer.stop(); - if (psIdle) { - psIdle = false; - if (App::main()) App::main()->setOnline(); - if (App::wnd()) App::wnd()->checkHistoryActivation(); - } } QImage PsMainWindow::psTrayIcon(bool selected) const { return selected ? trayImgSel : trayImg; } -void PsMainWindow::psIdleTimeout() { - int64 idleTime = objc_idleTime(); - if (idleTime >= 0) { - if (idleTime <= IdleMsecs) { - psNotIdle(); - } - } else { // error - psNotIdle(); - } -} - void PsMainWindow::psShowTrayMenu() { } -bool PsMainWindow::psIsOnline(int state) const { - if (state < 0) state = this->windowState(); - if (state & Qt::WindowMinimized) { - return false; - } else if (!isVisible()) { - return false; - } - int64 idleTime = objc_idleTime(); - LOG(("App Info: idle time %1").arg(idleTime)); - if (idleTime >= 0) { - if (idleTime > IdleMsecs) { - if (!psIdle) { - psIdle = true; - psIdleTimer.start(900); - } - return false; - } else { - psNotIdle(); - } - } else { // error - psNotIdle(); - } - return true; -} - -bool PsMainWindow::psIsActive(int state) const { - if (state < 0) state = this->windowState(); - return isActiveWindow() && isVisible() && !(state & Qt::WindowMinimized) && !psIdle; -} - void PsMainWindow::psRefreshTaskbarIcon() { } @@ -280,8 +228,6 @@ void PsMainWindow::psInitFrameless() { if (frameless) { //setWindowFlags(Qt::FramelessWindowHint); } - - connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(psStateChanged(Qt::WindowState))); } void PsMainWindow::psSavePosition(Qt::WindowState state) { @@ -331,15 +277,6 @@ void PsMainWindow::psUpdatedPosition() { psUpdatedPositionTimer.start(SaveWindowPositionTimeout); } -void PsMainWindow::psStateChanged(Qt::WindowState state) { - psUpdateSysMenu(state); - psUpdateMargins(); -// if (state == Qt::WindowMinimized && GetWindowLong(ps_hWnd, GWL_HWNDPARENT)) { -// App::wnd()->minimizeToTray(); -// } - psSavePosition(state); -} - void PsMainWindow::psFirstShow() { finished = false; @@ -492,7 +429,7 @@ void PsMainWindow::psMacUpdateMenu() { _forceDisabled(psContacts, !isLogged); _forceDisabled(psAddContact, !isLogged); _forceDisabled(psNewGroup, !isLogged); - _forceDisabled(psShowTelegram, psIsActive()); + _forceDisabled(psShowTelegram, App::wnd()->isActive(false)); } void PsMainWindow::psFlash() { @@ -980,6 +917,18 @@ PsUpdateDownloader::~PsUpdateDownloader() { reply = 0; } +namespace { + uint64 _lastUserAction = 0; +} + +void psUserActionDone() { + _lastUserAction = getms(true); +} + +uint64 psIdleTime() { + int64 idleTime = 0; + return objc_idleTime(idleTime) ? idleTime : (getms(true) - _lastUserAction); +} QStringList psInitLogs() { return _initLogs; diff --git a/Telegram/SourceFiles/pspecific_mac.h b/Telegram/SourceFiles/pspecific_mac.h index 2d17569ff..7d7da05a7 100644 --- a/Telegram/SourceFiles/pspecific_mac.h +++ b/Telegram/SourceFiles/pspecific_mac.h @@ -64,9 +64,6 @@ public: void psFlash(); - bool psIsActive(int state = -1) const; - bool psIsOnline(int state) const; - void psUpdateWorkmode(); void psRefreshTaskbarIcon(); @@ -90,7 +87,6 @@ public: public slots: - void psStateChanged(Qt::WindowState state); void psUpdateDelegate(); void psSavePosition(Qt::WindowState state = Qt::WindowActive); void psIdleTimeout(); @@ -199,6 +195,9 @@ private: }; +void psUserActionDone(); +uint64 psIdleTime(); + QStringList psInitLogs(); void psClearInitLogs(); diff --git a/Telegram/SourceFiles/pspecific_mac_p.h b/Telegram/SourceFiles/pspecific_mac_p.h index cb95f02a6..a3a4e184d 100644 --- a/Telegram/SourceFiles/pspecific_mac_p.h +++ b/Telegram/SourceFiles/pspecific_mac_p.h @@ -57,7 +57,7 @@ void objc_activateWnd(WId winId); void objc_debugShowAlert(const QString &str); void objc_outputDebugString(const QString &str); -int64 objc_idleTime(); +bool objc_idleTime(int64 &idleTime); bool objc_showOpenWithMenu(int x, int y, const QString &file); diff --git a/Telegram/SourceFiles/pspecific_mac_p.mm b/Telegram/SourceFiles/pspecific_mac_p.mm index c60fdd819..25dee8e57 100644 --- a/Telegram/SourceFiles/pspecific_mac_p.mm +++ b/Telegram/SourceFiles/pspecific_mac_p.mm @@ -319,7 +319,7 @@ PsMacWindowPrivate::~PsMacWindowPrivate() { delete data; } -int64 objc_idleTime() { // taken from https://github.com/trueinteractions/tint/issues/53 +bool objc_idleTime(int64 &idleTime) { // taken from https://github.com/trueinteractions/tint/issues/53 CFMutableDictionaryRef properties = 0; CFTypeRef obj; mach_port_t masterPort; @@ -331,7 +331,7 @@ int64 objc_idleTime() { // taken from https://github.com/trueinteractions/tint/i /* Get IOHIDSystem */ IOServiceGetMatchingServices(masterPort, IOServiceMatching("IOHIDSystem"), &iter); if (iter == 0) { - return -1; + return false; } else { curObj = IOIteratorNext(iter); } @@ -339,7 +339,7 @@ int64 objc_idleTime() { // taken from https://github.com/trueinteractions/tint/i obj = CFDictionaryGetValue(properties, CFSTR("HIDIdleTime")); CFRetain(obj); } else { - return -1; + return false; } uint64 err = ~0L, result = err; @@ -366,7 +366,10 @@ int64 objc_idleTime() { // taken from https://github.com/trueinteractions/tint/i CFRelease((CFTypeRef)properties); IOObjectRelease(curObj); IOObjectRelease(iter); - return (result == err) ? -1 : int64(result); + if (result == err) return false; + + idleTime = int64(result); + return true; } @interface OpenWithApp : NSObject { diff --git a/Telegram/SourceFiles/pspecific_wnd.cpp b/Telegram/SourceFiles/pspecific_wnd.cpp index 122e1b337..ecd9f767a 100644 --- a/Telegram/SourceFiles/pspecific_wnd.cpp +++ b/Telegram/SourceFiles/pspecific_wnd.cpp @@ -885,71 +885,14 @@ namespace { }; PsMainWindow::PsMainWindow(QWidget *parent) : QMainWindow(parent), ps_hWnd(0), ps_menu(0), icon256(qsl(":/gui/art/icon256.png")), iconbig256(qsl(":/gui/art/iconbig256.png")), wndIcon(QPixmap::fromImage(icon256, Qt::ColorOnly)), - ps_iconBig(0), ps_iconSmall(0), ps_iconOverlay(0), trayIcon(0), trayIconMenu(0), posInited(false), ps_tbHider_hWnd(createTaskbarHider()), psIdle(false) { + ps_iconBig(0), ps_iconSmall(0), ps_iconOverlay(0), trayIcon(0), trayIconMenu(0), posInited(false), ps_tbHider_hWnd(createTaskbarHider()) { tbCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated"); - connect(&psIdleTimer, SIGNAL(timeout()), this, SLOT(psIdleTimeout())); - psIdleTimer.setSingleShot(false); -} - -void PsMainWindow::psNotIdle() const { - psIdleTimer.stop(); - if (psIdle) { - psIdle = false; - if (App::main()) App::main()->setOnline(); - if (App::wnd()) App::wnd()->checkHistoryActivation(); - } -} - -void PsMainWindow::psIdleTimeout() { - LASTINPUTINFO lii; - lii.cbSize = sizeof(LASTINPUTINFO); - BOOL res = GetLastInputInfo(&lii); - if (res) { - uint64 ticks = GetTickCount(); - if (lii.dwTime >= ticks - IdleMsecs) { - psNotIdle(); - } - } else { // error { - psNotIdle(); - } } void PsMainWindow::psShowTrayMenu() { trayIconMenu->popup(QCursor::pos()); } -bool PsMainWindow::psIsActive(int state) const { - if (state < 0) state = this->windowState(); - return isActiveWindow() && isVisible() && !(state & Qt::WindowMinimized) && !psIdle; -} - -bool PsMainWindow::psIsOnline(int windowState) const { - if (windowState < 0) windowState = this->windowState(); - if (windowState & Qt::WindowMinimized) { - return false; - } else if (!isVisible()) { - return false; - } - LASTINPUTINFO lii; - lii.cbSize = sizeof(LASTINPUTINFO); - BOOL res = GetLastInputInfo(&lii); - if (res) { - uint64 ticks = GetTickCount(); - if (lii.dwTime < ticks - IdleMsecs) { - if (!psIdle) { - psIdle = true; - psIdleTimer.start(900); - } - return false; - } else { - psNotIdle(); - } - } else { // error - psNotIdle(); - } - return true; -} - void PsMainWindow::psRefreshTaskbarIcon() { QWidget *w = new QWidget(this); w->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); @@ -1136,7 +1079,6 @@ void PsMainWindow::psInitFrameless() { // RegisterApplicationRestart(NULL, 0); psInitSysMenu(); - connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(psStateChanged(Qt::WindowState))); } void PsMainWindow::psSavePosition(Qt::WindowState state) { @@ -1181,15 +1123,6 @@ void PsMainWindow::psUpdatedPosition() { psUpdatedPositionTimer.start(SaveWindowPositionTimeout); } -void PsMainWindow::psStateChanged(Qt::WindowState state) { - psUpdateSysMenu(state); - psUpdateMargins(); - if (state == Qt::WindowMinimized && GetWindowLong(ps_hWnd, GWL_HWNDPARENT)) { - App::wnd()->minimizeToTray(); - } - psSavePosition(state); -} - Q_DECLARE_METATYPE(QMargins); void PsMainWindow::psFirstShow() { _psShadowWindows.init(_shActive); @@ -1803,6 +1736,20 @@ namespace { } } +namespace { + uint64 _lastUserAction = 0; +} + +void psUserActionDone() { + _lastUserAction = getms(true); +} + +uint64 psIdleTime() { + LASTINPUTINFO lii; + lii.cbSize = sizeof(LASTINPUTINFO); + return GetLastInputInfo(&lii) ? (GetTickCount() - lii.dwTime) : (getms(true) - _lastUserAction); +} + QStringList psInitLogs() { return _initLogs; } diff --git a/Telegram/SourceFiles/pspecific_wnd.h b/Telegram/SourceFiles/pspecific_wnd.h index 3eee4d0cc..357bc44cc 100644 --- a/Telegram/SourceFiles/pspecific_wnd.h +++ b/Telegram/SourceFiles/pspecific_wnd.h @@ -52,9 +52,6 @@ public: void psFlash(); void psNotifySettingGot(); - bool psIsActive(int state = -1) const; - bool psIsOnline(int windowState) const; - void psUpdateWorkmode(); void psRefreshTaskbarIcon(); @@ -76,15 +73,12 @@ public: public slots: - void psStateChanged(Qt::WindowState state); void psUpdateDelegate(); void psSavePosition(Qt::WindowState state = Qt::WindowActive); - void psIdleTimeout(); void psShowTrayMenu(); protected: - void psNotIdle() const; bool psHasTrayIcon() const { return trayIcon; } @@ -106,9 +100,6 @@ private: HMENU ps_menu; HICON ps_iconBig, ps_iconSmall, ps_iconOverlay; - mutable bool psIdle; - mutable QTimer psIdleTimer; - void psDestroyIcons(); }; @@ -176,6 +167,9 @@ private: }; +void psUserActionDone(); +uint64 psIdleTime(); + QStringList psInitLogs(); void psClearInitLogs(); diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index 2624048c7..71fbcb879 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -117,6 +117,16 @@ bool gContactsReceived = false; bool gWideMode = true; +int gOnlineUpdatePeriod = 120000; +int gOfflineBlurTimeout = 5000; +int gOfflineIdleTimeout = 30000; +int gOnlineFocusTimeout = 1000; +int gOnlineCloudTimeout = 300000; +int gNotifyCloudDelay = 30000; +int gNotifyDefaultDelay = 1500; + +int gOtherOnline = 0; + void settingsParseArgs(int argc, char *argv[]) { if (cPlatform() == dbipMac) { gCustomNotifies = false; diff --git a/Telegram/SourceFiles/settings.h b/Telegram/SourceFiles/settings.h index ee171e7aa..fca343af2 100644 --- a/Telegram/SourceFiles/settings.h +++ b/Telegram/SourceFiles/settings.h @@ -172,4 +172,14 @@ DeclareSetting(bool, ContactsReceived); DeclareSetting(bool, WideMode); +DeclareSetting(int, OnlineUpdatePeriod); +DeclareSetting(int, OfflineBlurTimeout); +DeclareSetting(int, OfflineIdleTimeout); +DeclareSetting(int, OnlineFocusTimeout); +DeclareSetting(int, OnlineCloudTimeout); +DeclareSetting(int, NotifyCloudDelay); +DeclareSetting(int, NotifyDefaultDelay); + +DeclareSetting(int, OtherOnline); + void settingsParseArgs(int argc, char *argv[]); diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index 649138a9c..2b02ab76d 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -330,7 +330,7 @@ NotifyWindow::~NotifyWindow() { } Window::Window(QWidget *parent) : PsMainWindow(parent), _serviceHistoryRequest(0), -intro(0), main(0), settings(0), layerBG(0), _topWidget(0), +intro(0), main(0), settings(0), layerBG(0), _isActive(false), _topWidget(0), _connecting(0), _clearManager(0), dragging(false), _inactivePress(false), _mediaView(0) { icon16 = icon256.scaledToWidth(16, Qt::SmoothTransformation); @@ -356,6 +356,9 @@ _connecting(0), _clearManager(0), dragging(false), _inactivePress(false), _media connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer())); connect(¬ifyWaitTimer, SIGNAL(timeout()), this, SLOT(notifyFire())); + + _isActiveTimer.setSingleShot(true); + connect(&_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActive())); } void Window::inactivePress(bool inactive) { @@ -375,12 +378,26 @@ void Window::onInactiveTimer() { inactivePress(false); } +void Window::stateChanged(Qt::WindowState state) { + psUserActionDone(); + + updateIsActive((state == Qt::WindowMinimized) ? cOfflineBlurTimeout() : cOnlineFocusTimeout()); + + psUpdateSysMenu(state); + psUpdateMargins(); + if (state == Qt::WindowMinimized && cWorkMode() == dbiwmTrayOnly) { + App::wnd()->minimizeToTray(); + } + psSavePosition(state); +} + void Window::init() { psInitFrameless(); setWindowIcon(wndIcon); App::app()->installEventFilter(this); - connect(windowHandle(), SIGNAL(activeChanged()), this, SLOT(checkHistoryActivation())); + connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(stateChanged(Qt::WindowState))); + connect(windowHandle(), SIGNAL(activeChanged()), this, SLOT(checkHistoryActivation())); QPalette p(palette()); p.setColor(QPalette::Window, st::wndBG->c); @@ -706,12 +723,12 @@ bool Window::layerShown() { return !!layerBG || !!_topWidget; } -bool Window::historyIsActive(int state) const { - return psIsActive(state) && main && main->historyIsActive() && (!settings || !settings->isVisible()); +bool Window::historyIsActive() const { + return isActive(false) && main && main->historyIsActive() && (!settings || !settings->isVisible()); } -void Window::checkHistoryActivation(int state) { - if (main && MTP::authedId() && historyIsActive(state)) { +void Window::checkHistoryActivation() { + if (main && MTP::authedId() && historyIsActive()) { main->historyWasRead(); } QTimer::singleShot(1, this, SLOT(updateTrayMenu())); @@ -790,26 +807,37 @@ QRect Window::iconRect() const { } bool Window::eventFilter(QObject *obj, QEvent *evt) { - if (obj == App::app() && (evt->type() == QEvent::ApplicationActivate)) { - QTimer::singleShot(1, this, SLOT(checkHistoryActivation())); - } else if (obj == App::app() && (evt->type() == QEvent::FileOpen)) { - QString url = static_cast(evt)->url().toEncoded(); - if (!url.trimmed().midRef(0, 5).compare(qsl("tg://"), Qt::CaseInsensitive)) { - cSetStartUrl(url); - if (!cStartUrl().isEmpty() && App::main() && App::self()) { - App::main()->openLocalUrl(cStartUrl()); - cSetStartUrl(QString()); + QEvent::Type t = evt->type(); + if (t == QEvent::MouseButtonPress || t == QEvent::KeyPress || t == QEvent::TouchBegin) { + psUserActionDone(); + } else if (t == QEvent::MouseMove) { + if (main && main->isIdle()) { + psUserActionDone(); + main->checkIdleFinish(); + } + } + if (obj == App::app()) { + if (t == QEvent::ApplicationActivate) { + psUserActionDone(); + QTimer::singleShot(1, this, SLOT(checkHistoryActivation())); + } else if (t == QEvent::FileOpen) { + QString url = static_cast(evt)->url().toEncoded(); + if (!url.trimmed().midRef(0, 5).compare(qsl("tg://"), Qt::CaseInsensitive)) { + cSetStartUrl(url); + if (!cStartUrl().isEmpty() && App::main() && App::self()) { + App::main()->openLocalUrl(cStartUrl()); + cSetStartUrl(QString()); + } } + activate(); } - activate(); - } else if (obj == this && evt->type() == QEvent::WindowStateChange) { - Qt::WindowState state = (windowState() & Qt::WindowMinimized) ? Qt::WindowMinimized : ((windowState() & Qt::WindowMaximized) ? Qt::WindowMaximized : ((windowState() & Qt::WindowFullScreen) ? Qt::WindowFullScreen : Qt::WindowNoState)); - psStateChanged(state); - if (App::main()) { - App::main()->mainStateChanged(state); + } else if (obj == this) { + if (t == QEvent::WindowStateChange) { + Qt::WindowState state = (windowState() & Qt::WindowMinimized) ? Qt::WindowMinimized : ((windowState() & Qt::WindowMaximized) ? Qt::WindowMaximized : ((windowState() & Qt::WindowFullScreen) ? Qt::WindowFullScreen : Qt::WindowNoState)); + stateChanged(state); + } else if (t == QEvent::Move || t == QEvent::Resize) { + psUpdatedPosition(); } - } else if (obj == this && (evt->type() == QEvent::Move || evt->type() == QEvent::Resize)) { - psUpdatedPosition(); } return PsMainWindow::eventFilter(obj, evt); } @@ -843,7 +871,7 @@ bool Window::minimizeToTray() { cSetSeenTrayTooltip(true); App::writeConfig(); } - if (App::main()) App::main()->setOnline(windowState()); + updateIsActive(cOfflineBlurTimeout()); updateTrayMenu(); updateGlobalMenu(); return true; @@ -852,7 +880,7 @@ bool Window::minimizeToTray() { void Window::updateTrayMenu(bool force) { if (!trayIconMenu || (cPlatform() == dbipWindows && !force)) return; - bool active = psIsActive(); + bool active = isActive(false); if (cPlatform() == dbipWindows || cPlatform() == dbipMac) { QAction *first = trayIconMenu->actions().at(0); first->setText(lang(active ? lng_minimize_to_tray : lng_open_from_tray)); @@ -911,6 +939,7 @@ void Window::activate() { setVisible(true); psActivateProcess(); activateWindow(); + updateIsActive(cOnlineFocusTimeout()); if (wasHidden) { if (main) { main->windowShown(); @@ -972,17 +1001,16 @@ void Window::showFromTray(QSystemTrayIcon::ActivationReason reason) { QTimer::singleShot(1, this, SLOT(updateGlobalMenu())); activate(); updateCounter(); - if (App::main()) App::main()->setOnline(windowState()); } } void Window::toggleTray(QSystemTrayIcon::ActivationReason reason) { - if (cPlatform() == dbipMac && psIsActive()) return; + if (cPlatform() == dbipMac && isActive(false)) return; if (reason == QSystemTrayIcon::Context) { updateTrayMenu(true); QTimer::singleShot(1, this, SLOT(psShowTrayMenu())); } else { - if (psIsActive()) { + if (isActive(false)) { minimizeToTray(); } else { showFromTray(reason); @@ -1081,7 +1109,7 @@ void Window::quit() { } void Window::notifySchedule(History *history, MsgId msgId) { - if (App::quiting() || !history->currentNotification()) return; + if (App::quiting() || !history->currentNotification() || !main) return; bool haveSetting = (history->peer->notify != UnknownNotifySettings); if (haveSetting) { @@ -1093,24 +1121,35 @@ void Window::notifySchedule(History *history, MsgId msgId) { App::wnd()->getNotifySetting(MTP_inputNotifyPeer(history->peer->input)); } - uint64 ms = getms(true) + NotifyWaitTimeout; - notifyWhenAlerts[history].insert(ms, NullType()); + int delay = 100, t = unixtime(); + uint64 ms = getms(true); + bool isOnline = main->lastWasOnline(), otherNotOld = ((cOtherOnline() * uint64(1000)) + cOnlineCloudTimeout() > t * uint64(1000)); + bool otherLaterThanMe = (cOtherOnline() * uint64(1000) + (ms - main->lastSetOnline()) > t * uint64(1000)); + if (!isOnline && otherNotOld && otherLaterThanMe) { + delay = cNotifyCloudDelay(); + } else if (cOtherOnline() >= t) { + delay = cNotifyDefaultDelay(); + } + + uint64 when = getms(true) + delay; + notifyWhenAlerts[history].insert(when, NullType()); if (cDesktopNotify()) { NotifyWhenMaps::iterator i = notifyWhenMaps.find(history); if (i == notifyWhenMaps.end()) { i = notifyWhenMaps.insert(history, NotifyWhenMap()); } if (i.value().constFind(msgId) == i.value().cend()) { - i.value().insert(msgId, ms); + i.value().insert(msgId, when); } NotifyWaiters *addTo = haveSetting ? ¬ifyWaiters : ¬ifySettingWaiters; - if (addTo->constFind(history) == addTo->cend()) { - addTo->insert(history, NotifyWaiter(msgId, ms)); + NotifyWaiters::const_iterator it = addTo->constFind(history); + if (it == addTo->cend() || it->when > when) { + addTo->insert(history, NotifyWaiter(msgId, when)); } } if (haveSetting) { - if (!notifyWaitTimer.isActive()) { - notifyWaitTimer.start(NotifyWaitTimeout); + if (!notifyWaitTimer.isActive() || notifyWaitTimer.remainingTime() > delay) { + notifyWaitTimer.start(delay); } } } @@ -1279,7 +1318,6 @@ void Window::notifyShowNext(NotifyWindow *remove) { psPlatformNotify(notifyItem); } - uint64 ms = getms(true); History *history = notifyItem->history(); history->skipNotification(); @@ -1508,6 +1546,17 @@ void Window::changingMsgId(HistoryItem *row, MsgId newId) { _mediaView->changingMsgId(row, newId); } +bool Window::isActive(bool cached) const { + if (cached) return _isActive; + return isActiveWindow() && isVisible() && !(windowState() & Qt::WindowMinimized); +} + +void Window::updateIsActive(int timeout) { + if (timeout) return _isActiveTimer.start(timeout); + _isActive = isActive(false); + if (main) main->updateOnline(); +} + Window::~Window() { notifyClearFast(); delete _clearManager; diff --git a/Telegram/SourceFiles/window.h b/Telegram/SourceFiles/window.h index e08e669ff..374d7a473 100644 --- a/Telegram/SourceFiles/window.h +++ b/Telegram/SourceFiles/window.h @@ -180,7 +180,7 @@ public: bool layerShown(); - bool historyIsActive(int state = -1) const; + bool historyIsActive() const; void activate(); @@ -225,9 +225,14 @@ public: void mediaOverviewUpdated(PeerData *peer); void changingMsgId(HistoryItem *row, MsgId newId); + bool isActive(bool cached = true) const; + public slots: + + void updateIsActive(int timeout = 0); + void stateChanged(Qt::WindowState state); - void checkHistoryActivation(int state = -1); + void checkHistoryActivation(); void updateCounter(); void showSettings(); @@ -279,6 +284,9 @@ private: SettingsWidget *settings; BackgroundWidget *layerBG; + QTimer _isActiveTimer; + bool _isActive; + QWidget *_topWidget; // temp hack for CountrySelect ConnectingWidget *_connecting;