From bb70a76b9c376c3981aecd4f1f302d84aa62ee95 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 14 Apr 2016 22:24:42 +0300 Subject: [PATCH] Several crashes fixed. --- Telegram/SourceFiles/app.cpp | 12 +-- Telegram/SourceFiles/application.cpp | 15 ++-- Telegram/SourceFiles/application.h | 9 +- .../SourceFiles/core/click_handler_types.cpp | 8 +- .../SourceFiles/dialogs/dialogs_layout.cpp | 4 +- Telegram/SourceFiles/dialogswidget.cpp | 7 +- Telegram/SourceFiles/facades.cpp | 18 +++- Telegram/SourceFiles/facades.h | 4 +- Telegram/SourceFiles/history.cpp | 70 +++++++++------ Telegram/SourceFiles/history.h | 6 +- Telegram/SourceFiles/historywidget.cpp | 88 ++++++++++--------- Telegram/SourceFiles/historywidget.h | 2 +- Telegram/SourceFiles/intro/introwidget.cpp | 49 ++++------- Telegram/SourceFiles/intro/introwidget.h | 23 +++-- Telegram/SourceFiles/mainwidget.cpp | 13 +-- Telegram/SourceFiles/mainwidget.h | 2 +- Telegram/SourceFiles/mainwindow.cpp | 12 +-- Telegram/SourceFiles/mainwindow.h | 3 +- Telegram/SourceFiles/profilewidget.cpp | 4 +- Telegram/SourceFiles/pspecific_mac.cpp | 4 +- Telegram/SourceFiles/settingswidget.cpp | 2 +- Telegram/SourceFiles/ui/text/text.h | 6 +- 22 files changed, 195 insertions(+), 166 deletions(-) diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index c227c243b..ec8db9052 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -1768,22 +1768,22 @@ namespace { void historyItemDetached(HistoryItem *item) { if (::hoveredItem == item) { - hoveredItem(0); + hoveredItem(nullptr); } if (::pressedItem == item) { - pressedItem(0); + pressedItem(nullptr); } if (::hoveredLinkItem == item) { - hoveredLinkItem(0); + hoveredLinkItem(nullptr); } if (::pressedLinkItem == item) { - pressedLinkItem(0); + pressedLinkItem(nullptr); } if (::contextItem == item) { - contextItem(0); + contextItem(nullptr); } if (::mousedItem == item) { - mousedItem(0); + mousedItem(nullptr); } if (App::wnd()) { App::wnd()->notifyItemRemoved(item); diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index a5d4a7334..906c8c7e7 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -90,14 +90,7 @@ namespace { AppClass *AppObject = 0; -Application::Application(int &argc, char **argv) : QApplication(argc, argv) -, _secondInstance(false) -#ifndef TDESKTOP_DISABLE_AUTOUPDATE -, _updateReply(0) -, _updateThread(0) -, _updateChecker(0) -#endif -{ +Application::Application(int &argc, char **argv) : QApplication(argc, argv) { QByteArray d(QFile::encodeName(QDir(cWorkingDir()).absolutePath())); char h[33] = { 0 }; hashMd5Hex(d.constData(), d.size(), h); @@ -905,6 +898,12 @@ void AppClass::call_handleHistoryUpdate() { Notify::handlePendingHistoryUpdate(); } +void AppClass::call_handleUnreadCounterUpdate() { + if (auto w = App::wnd()) { + w->updateUnreadCounter(); + } +} + void AppClass::killDownloadSessions() { uint64 ms = getms(), left = MTPAckSendWaiting + MTPKillFileSessionTimeout; for (QMap::iterator i = killDownloadSessionTimes.begin(); i != killDownloadSessionTimes.end(); ) { diff --git a/Telegram/SourceFiles/application.h b/Telegram/SourceFiles/application.h index 774ebc85b..f894102fe 100644 --- a/Telegram/SourceFiles/application.h +++ b/Telegram/SourceFiles/application.h @@ -56,7 +56,7 @@ private: QLocalServer _localServer; QLocalSocket _localSocket; LocalClients _localClients; - bool _secondInstance; + bool _secondInstance = false; void singleInstanceChecked(); @@ -98,10 +98,10 @@ public slots: private: SingleTimer _updateCheckTimer; - QNetworkReply *_updateReply; + QNetworkReply *_updateReply = nullptr; QNetworkAccessManager _updateManager; - QThread *_updateThread; - UpdateChecker *_updateChecker; + QThread *_updateThread = nullptr; + UpdateChecker *_updateChecker = nullptr; #endif }; @@ -202,6 +202,7 @@ public slots: void onAppStateChanged(Qt::ApplicationState state); void call_handleHistoryUpdate(); + void call_handleUnreadCounterUpdate(); private: diff --git a/Telegram/SourceFiles/core/click_handler_types.cpp b/Telegram/SourceFiles/core/click_handler_types.cpp index 3c317c3dd..5bbf2df64 100644 --- a/Telegram/SourceFiles/core/click_handler_types.cpp +++ b/Telegram/SourceFiles/core/click_handler_types.cpp @@ -124,8 +124,14 @@ void HashtagClickHandler::onClick(Qt::MouseButton button) const { void BotCommandClickHandler::onClick(Qt::MouseButton button) const { if (button == Qt::LeftButton || button == Qt::MiddleButton) { if (PeerData *peer = Ui::getPeerForMouseAction()) { + UserData *bot = peer->isUser() ? peer->asUser() : nullptr; + if (auto item = App::hoveredLinkItem()) { + if (!bot) { + bot = item->fromOriginal()->asUser(); // may return nullptr + } + } Ui::showPeerHistory(peer, ShowAtTheEndMsgId); - App::sendBotCommand(peer, _cmd); + App::sendBotCommand(peer, bot, _cmd); } else { App::insertBotCommand(_cmd); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index 64671379c..081463267 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -132,10 +132,10 @@ QImage colorizeCircleHalf(int size, int half, int xoffset, style::color color) { int a = color->c.alpha() + 1; int fg_r = color->c.red() * a, fg_g = color->c.green() * a, fg_b = color->c.blue() * a, fg_a = 255 * a; - QImage result(size, size, QImage::Format_ARGB32_Premultiplied); + QImage result(half, size, QImage::Format_ARGB32_Premultiplied); uchar *bits = result.bits(), *maskbits = unreadBadgeStyle->circle.bits(); int bpl = result.bytesPerLine(), maskbpl = unreadBadgeStyle->circle.bytesPerLine(); - for (int x = 0; x < size; ++x) { + for (int x = 0; x < half; ++x) { for (int y = 0; y < size; ++y) { int s = y * bpl + (x * 4); int o = maskbits[y * maskbpl + x + xoffset] + 1; diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 1f0aa382f..f6447d0a4 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -1028,7 +1028,7 @@ void DialogsInner::dialogsReceived(const QVector &added) { } } - if (App::wnd()) App::wnd()->updateCounter(); + Notify::unreadCounterUpdated(); if (!_sel && !shownDialogs()->isEmpty()) { _sel = *shownDialogs()->cbegin(); _importantSwitchSel = false; @@ -1936,7 +1936,7 @@ void DialogsWidget::unreadCountsReceived(const QVector &dialogs) { if (History *h = App::historyLoaded(peerFromMTP(d.vpeer))) { App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, h); if (d.vunread_count.v >= h->unreadCount()) { - h->setUnreadCount(d.vunread_count.v, false); + h->setUnreadCount(d.vunread_count.v); h->inboxReadBefore = d.vread_inbox_max_id.v + 1; } } @@ -1954,14 +1954,13 @@ void DialogsWidget::unreadCountsReceived(const QVector &dialogs) { App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, h); int32 unreadCount = h->isMegagroup() ? d.vunread_count.v : d.vunread_important_count.v; if (unreadCount >= h->unreadCount()) { - h->setUnreadCount(unreadCount, false); + h->setUnreadCount(unreadCount); h->inboxReadBefore = d.vread_inbox_max_id.v + 1; } } } break; } } - if (App::wnd()) App::wnd()->updateCounter(); } void DialogsWidget::dialogsReceived(const MTPmessages_Dialogs &dialogs, mtpRequestId req) { diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 60aa53e2e..4932f1887 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -33,12 +33,16 @@ Q_DECLARE_METATYPE(Qt::MouseButton); namespace App { -void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo) { - if (MainWidget *m = main()) m->sendBotCommand(peer, cmd, replyTo); +void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo) { + if (auto m = main()) { + m->sendBotCommand(peer, bot, cmd, replyTo); + } } bool insertBotCommand(const QString &cmd, bool specialGif) { - if (MainWidget *m = main()) return m->insertBotCommand(cmd, specialGif); + if (auto m = main()) { + return m->insertBotCommand(cmd, specialGif); + } return false; } @@ -59,7 +63,7 @@ void activateBotCommand(const HistoryItem *msg, int row, int col) { // Copy string before passing it to the sending method // because the original button can be destroyed inside. MsgId replyTo = (msg->id > 0) ? msg->id : 0; - sendBotCommand(msg->history()->peer, QString(button->text), replyTo); + sendBotCommand(msg->history()->peer, msg->fromOriginal()->asUser(), QString(button->text), replyTo); } break; case HistoryMessageReplyMarkup::Button::Callback: { @@ -326,6 +330,10 @@ void handlePendingHistoryUpdate() { Global::RefPendingRepaintItems().clear(); } +void unreadCounterUpdated() { + Global::RefHandleUnreadCounterUpdate().call(); +} + } // namespace Notify #define DefineReadOnlyVar(Namespace, Type, Name) const Type &Name() { \ @@ -479,6 +487,7 @@ namespace internal { struct Data { uint64 LaunchId = 0; SingleDelayedCall HandleHistoryUpdate = { App::app(), "call_handleHistoryUpdate" }; + SingleDelayedCall HandleUnreadCounterUpdate = { App::app(), "call_handleUnreadCounterUpdate" }; Adaptive::Layout AdaptiveLayout = Adaptive::NormalLayout; bool AdaptiveForWide = true; @@ -541,6 +550,7 @@ void finish() { DefineReadOnlyVar(Global, uint64, LaunchId); DefineRefVar(Global, SingleDelayedCall, HandleHistoryUpdate); +DefineRefVar(Global, SingleDelayedCall, HandleUnreadCounterUpdate); DefineVar(Global, Adaptive::Layout, AdaptiveLayout); DefineVar(Global, bool, AdaptiveForWide); diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index a8bf6fbb1..412c0d65a 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -24,7 +24,7 @@ class LayeredWidget; namespace App { -void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo = 0); +void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo = 0); bool insertBotCommand(const QString &cmd, bool specialGif = false); void activateBotCommand(const HistoryItem *msg, int row, int col); void searchByHashtag(const QString &tag, PeerData *inPeer); @@ -116,6 +116,7 @@ void historyMuteUpdated(History *history); // handle pending resize() / paint() on history items void handlePendingHistoryUpdate(); +void unreadCounterUpdated(); } // namespace Notify @@ -184,6 +185,7 @@ void finish(); DeclareReadOnlyVar(uint64, LaunchId); DeclareRefVar(SingleDelayedCall, HandleHistoryUpdate); +DeclareRefVar(SingleDelayedCall, HandleUnreadCounterUpdate); DeclareVar(Adaptive::Layout, AdaptiveLayout); DeclareVar(bool, AdaptiveForWide); diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index ec27218e1..7970cfbe2 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -325,9 +325,7 @@ void ChannelHistory::insertCollapseItem(MsgId wasMinId) { HistoryItem *item = block->items.at(itemIndex); if (insertAfter || item->id > wasMinId || (item->id == wasMinId && !item->isImportant())) { _collapseMessage = HistoryCollapse::create((History*)this, wasMinId, item->date); - if (!addNewInTheMiddle(_collapseMessage, blockIndex, itemIndex)) { - _collapseMessage = 0; - } + addNewInTheMiddle(_collapseMessage, blockIndex, itemIndex); return; } else if (item->id == wasMinId && item->isImportant()) { insertAfter = true; @@ -663,16 +661,19 @@ void ChannelHistory::switchMode() { checkJoinedMessage(); } -void ChannelHistory::cleared() { - _collapseMessage = 0; - _joinedMessage = 0; +void ChannelHistory::cleared(bool leaveItems) { + _collapseMessage = nullptr; + _joinedMessage = nullptr; + if (!leaveItems) { + _otherList.clear(); + } } HistoryGroup *ChannelHistory::findGroup(MsgId msgId) const { // find message group using binary search if (!_onlyImportant) return findGroupInOther(msgId); HistoryBlock *block = findGroupBlock(msgId); - if (!block) return 0; + if (!block) return nullptr; int32 itemIndex = 0; if (block->items.size() > 1) for (int32 minItem = 0, maxItem = block->items.size();;) { @@ -698,10 +699,14 @@ HistoryGroup *ChannelHistory::findGroup(MsgId msgId) const { // find message gro } } - HistoryItem *item = block->items.at(itemIndex); - if (item->type() != HistoryItemGroup) return 0; - HistoryGroup *result = static_cast(item); - return (result->minId() < msgId && result->maxId() > msgId) ? result : 0; + auto item = block->items.at(itemIndex); + if (item->type() == HistoryItemGroup) { + auto result = static_cast(item); + if (result->minId() < msgId && result->maxId() > msgId) { + return result; + } + } + return nullptr; } HistoryBlock *ChannelHistory::findGroupBlock(MsgId msgId) const { // find block with message group using binary search @@ -838,7 +843,7 @@ History *Histories::findOrInsert(const PeerId &peerId, int32 unreadCount, int32 Map::const_iterator i = map.constFind(peerId); if (i == map.cend()) { i = map.insert(peerId, peerIsChannel(peerId) ? static_cast(new ChannelHistory(peerId)) : (new History(peerId))); - i.value()->setUnreadCount(unreadCount, false); + i.value()->setUnreadCount(unreadCount); i.value()->inboxReadBefore = maxInboxRead + 1; } return i.value(); @@ -846,18 +851,17 @@ History *Histories::findOrInsert(const PeerId &peerId, int32 unreadCount, int32 void Histories::clear() { App::historyClearMsgs(); - for (Map::const_iterator i = map.cbegin(), e = map.cend(); i != e; ++i) { - delete i.value(); + + Map temp; + std::swap(temp, map); + for_const (auto history, temp) { + delete history; } - Global::RefPendingRepaintItems().clear(); _unreadFull = _unreadMuted = 0; - if (App::wnd()) { - App::wnd()->updateCounter(); - } + Notify::unreadCounterUpdated(); App::historyClearItems(); typing.clear(); - map.clear(); } void Histories::regSendAction(History *history, UserData *user, const MTPSendMessageAction &action) { @@ -1742,7 +1746,7 @@ HistoryItem *History::lastImportantMessage() const { return nullptr; } -void History::setUnreadCount(int newUnreadCount, bool psUpdate) { +void History::setUnreadCount(int newUnreadCount) { if (_unreadCount != newUnreadCount) { if (newUnreadCount == 1) { if (loadedAtBottom()) showFrom = lastImportantMessage(); @@ -1753,8 +1757,8 @@ void History::setUnreadCount(int newUnreadCount, bool psUpdate) { } if (inChatList(Dialogs::Mode::All)) { App::histories().unreadIncrement(newUnreadCount - _unreadCount, mute()); - if (psUpdate && (!mute() || cIncludeMuted()) && App::wnd()) { - App::wnd()->updateCounter(); + if (!mute() || cIncludeMuted()) { + Notify::unreadCounterUpdated(); } } _unreadCount = newUnreadCount; @@ -1780,7 +1784,7 @@ void History::setUnreadCount(int newUnreadCount, bool psUpdate) { if (inChatList(Dialogs::Mode::All)) { if (_unreadCount) { App::histories().unreadMuteChanged(_unreadCount, newMute); - if (App::wnd()) App::wnd()->updateCounter(); + Notify::unreadCounterUpdated(); } Notify::historyMuteUpdated(this); } @@ -2179,6 +2183,15 @@ void History::clear(bool leaveItems) { } if (!leaveItems) { setLastMessage(nullptr); + notifies.clear(); + auto &pending = Global::RefPendingRepaintItems(); + for (auto i = pending.begin(); i != pending.end();) { + if ((*i)->history() == this) { + i = pending.erase(i); + } else { + ++i; + } + } } for (int32 i = 0; i < OverviewCount; ++i) { if (!overview[i].isEmpty() || !overviewIds[i].isEmpty()) { @@ -2199,6 +2212,10 @@ void History::clear(bool leaveItems) { lastKeyboardInited = false; } else { setUnreadCount(0); + if (peer->isMegagroup()) { + peer->asChannel()->mgInfo->pinnedMsgId = 0; + } + clearLastKeyboard(); } setPendingResize(); @@ -2209,7 +2226,7 @@ void History::clear(bool leaveItems) { peer->asChat()->lastAuthors.clear(); peer->asChat()->markupSenders.clear(); } else if (isChannel()) { - asChannelHistory()->cleared(); + asChannelHistory()->cleared(leaveItems); if (isMegagroup()) { peer->asChannel()->mgInfo->markupSenders.clear(); } @@ -2251,7 +2268,7 @@ Dialogs::Row *History::addToChatList(Dialogs::Mode list, Dialogs::IndexedList *i chatListLinks(list) = indexed->addToEnd(this); if (list == Dialogs::Mode::All && unreadCount()) { App::histories().unreadIncrement(unreadCount(), mute()); - if (App::wnd()) App::wnd()->updateCounter(); + Notify::unreadCounterUpdated(); } } return mainChatListLink(list); @@ -2264,7 +2281,7 @@ void History::removeFromChatList(Dialogs::Mode list, Dialogs::IndexedList *index chatListLinks(list).clear(); if (list == Dialogs::Mode::All && unreadCount()) { App::histories().unreadIncrement(-unreadCount(), mute()); - if (App::wnd()) App::wnd()->updateCounter(); + Notify::unreadCounterUpdated(); } } } @@ -2994,6 +3011,7 @@ void HistoryItem::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pres } void HistoryItem::destroy() { + // All this must be done for all items manually in History::clear(false)! bool wasAtBottom = history()->loadedAtBottom(); _history->removeNotification(this); detach(); diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index de909ffd0..81314ee64 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -255,7 +255,7 @@ public: int unreadCount() const { return _unreadCount; } - void setUnreadCount(int newUnreadCount, bool psUpdate = true); + void setUnreadCount(int newUnreadCount); bool mute() const { return _mute; } @@ -642,7 +642,7 @@ private: HistoryItem *findPrevItem(HistoryItem *item) const; void switchMode(); - void cleared(); + void cleared(bool leaveItems); bool _onlyImportant; @@ -2637,7 +2637,7 @@ public: HistoryItem::clickHandlerActiveChanged(p, active); } void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override { - if (_media) _media->clickHandlerActiveChanged(p, pressed); + if (_media) _media->clickHandlerPressedChanged(p, pressed); HistoryItem::clickHandlerPressedChanged(p, pressed); } diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index c5556bb25..59c6ae8ec 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -2260,8 +2260,7 @@ void BotKeyboard::enterEvent(QEvent *e) { } void BotKeyboard::leaveEvent(QEvent *e) { - _lastMousePos = QPoint(-1, -1); - updateSelected(); + clearSelection(); } void BotKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) { @@ -2275,44 +2274,43 @@ void BotKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pres } bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) { - if (to && to->definesReplyKeyboard()) { - if (_wasForMsgId == FullMsgId(to->channelId(), to->id) && !force) { - return false; + if (!to || !to->definesReplyKeyboard()) { + if (_wasForMsgId.msg) { + _maximizeSize = _singleUse = _forceReply = false; + _wasForMsgId = FullMsgId(); + _impl = nullptr; + return true; } - - _wasForMsgId = FullMsgId(to->channelId(), to->id); - clearSelection(); - - auto markupFlags = to->replyKeyboardFlags(); - _forceReply = markupFlags & MTPDreplyKeyboardMarkup_ClientFlag::f_force_reply; - _maximizeSize = !(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_resize); - _singleUse = _forceReply || (markupFlags & MTPDreplyKeyboardMarkup::Flag::f_single_use); - - _impl = nullptr; - if (auto markup = to->Get()) { - if (!markup->rows.isEmpty()) { - _impl.reset(new ReplyKeyboard(to, std_::make_unique