diff --git a/Telegram/SourceFiles/auth_session.h b/Telegram/SourceFiles/auth_session.h index bd45b01e8..1599a66f3 100644 --- a/Telegram/SourceFiles/auth_session.h +++ b/Telegram/SourceFiles/auth_session.h @@ -57,6 +57,12 @@ public: base::Observable &savedGifsUpdated() { return _savedGifsUpdated; } + base::Observable> &historyCleared() { + return _historyCleared; + } + base::Observable> &repaintLogEntry() { + return _repaintLogEntry; + } void copyFrom(const AuthSessionData &other) { _variables = other._variables; @@ -131,6 +137,8 @@ private: base::Variable _allChatsLoaded = { false }; base::Observable _moreChatsLoaded; base::Observable _savedGifsUpdated; + base::Observable> _historyCleared; + base::Observable> _repaintLogEntry; Variables _variables; TimeMs _lastTimeVideoPlayedAt = 0; diff --git a/Telegram/SourceFiles/boxes/confirm_box.cpp b/Telegram/SourceFiles/boxes/confirm_box.cpp index 47ab08844..897b0c80e 100644 --- a/Telegram/SourceFiles/boxes/confirm_box.cpp +++ b/Telegram/SourceFiles/boxes/confirm_box.cpp @@ -186,9 +186,8 @@ void ConfirmBox::updateLink() { } void ConfirmBox::updateHover() { - QPoint m(mapFromGlobal(_lastMousePos)); - - auto state = _text.getStateLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width()); + auto m = mapFromGlobal(_lastMousePos); + auto state = _text.getStateLeft(m - QPoint(st::boxPadding.left(), st::boxPadding.top()), _textWidth, width()); ClickHandler::setActive(state.link, this); } diff --git a/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp b/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp index ecc813e34..a64c20042 100644 --- a/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp +++ b/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp @@ -52,7 +52,7 @@ const style::TextStyle &BotKeyboard::Style::textStyle() const { return st::botKbStyle; } -void BotKeyboard::Style::repaint(const HistoryItem *item) const { +void BotKeyboard::Style::repaint(gsl::not_null item) const { _parent->update(); } @@ -237,10 +237,10 @@ void BotKeyboard::updateSelected() { if (!_impl) return; - QPoint p(mapFromGlobal(_lastMousePos)); - int x = rtl() ? st::botKbScroll.width : _st->margin; + auto p = mapFromGlobal(_lastMousePos); + auto x = rtl() ? st::botKbScroll.width : _st->margin; - auto link = _impl->getState(p.x() - x, p.y() - _st->margin); + auto link = _impl->getState(p - QPoint(x, _st->margin)); if (ClickHandler::setActive(link, this)) { Ui::Tooltip::Hide(); setCursor(link ? style::cur_pointer : style::cur_default); diff --git a/Telegram/SourceFiles/chat_helpers/bot_keyboard.h b/Telegram/SourceFiles/chat_helpers/bot_keyboard.h index 9fefc56ae..519dd2323 100644 --- a/Telegram/SourceFiles/chat_helpers/bot_keyboard.h +++ b/Telegram/SourceFiles/chat_helpers/bot_keyboard.h @@ -92,7 +92,7 @@ private: void startPaint(Painter &p) const override; const style::TextStyle &textStyle() const override; - void repaint(const HistoryItem *item) const override; + void repaint(gsl::not_null item) const override; protected: void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const override; diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 8d180bf48..f36d52d61 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -900,7 +900,7 @@ void GifsListWidget::updateSelected() { } if (col < inlineItems.size()) { sel = row * MatrixRowShift + col; - inlineItems.at(col)->getState(lnk, cursor, sx, sy); + inlineItems.at(col)->getState(lnk, cursor, QPoint(sx, sy)); lnkhost = inlineItems.at(col); } else { row = col = -1; diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index fb6364e31..ca17f1085 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -253,7 +253,7 @@ bool isMediaViewShown() { return false; } -void repaintHistoryItem(const HistoryItem *item) { +void repaintHistoryItem(gsl::not_null item) { if (auto main = App::main()) { main->ui_repaintHistoryItem(item); } @@ -379,7 +379,7 @@ void handlePendingHistoryUpdate() { if (auto media = item->getMedia()) { if (auto reader = media->getClipReader()) { if (!reader->started() && reader->mode() == Media::Clip::Reader::Mode::Video) { - item->history()->resizeGetHeight(item->history()->width); + item->resizeGetHeight(item->width()); } } } diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index c6796a7f0..60d9be41e 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -107,7 +107,7 @@ void hideSettingsAndLayer(bool fast = false); bool isLayerShown(); bool isMediaViewShown(); -void repaintHistoryItem(const HistoryItem *item); +void repaintHistoryItem(gsl::not_null item); void autoplayMediaInlineAsync(const FullMsgId &msgId); void showPeerProfile(const PeerId &peer); diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 4091204c7..0e408e160 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -2060,7 +2060,9 @@ void History::clear(bool leaveItems) { peer->asChannel()->mgInfo->markupSenders.clear(); } } - if (leaveItems && App::main()) App::main()->historyCleared(this); + if (leaveItems) { + AuthSession::Current().data().historyCleared().notify(this, true); + } } void History::clearBlocks(bool leaveItems) { diff --git a/Telegram/SourceFiles/history/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/history_admin_log_inner.cpp index 427f15649..2fa9c13f6 100644 --- a/Telegram/SourceFiles/history/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/history_admin_log_inner.cpp @@ -20,21 +20,37 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #include "history/history_admin_log_inner.h" +#include "styles/style_history.h" +#include "history/history_media_types.h" #include "history/history_admin_log_item.h" #include "history/history_admin_log_section.h" +#include "mainwindow.h" +#include "window/window_controller.h" +#include "auth_session.h" +#include "lang/lang_keys.h" namespace AdminLog { namespace { -constexpr int kEventsPerPage = 3; +constexpr auto kScrollDateHideTimeout = 1000; +constexpr auto kEventsPerPage = 10; } // namespace -InnerWidget::InnerWidget(QWidget *parent, gsl::not_null channel, base::lambda scrollTo) : TWidget(parent) +InnerWidget::InnerWidget(QWidget *parent, gsl::not_null controller, gsl::not_null channel, base::lambda scrollTo) : TWidget(parent) +, _controller(controller) , _channel(channel) , _history(App::history(channel)) -, _scrollTo(std::move(scrollTo)) { +, _scrollTo(std::move(scrollTo)) +, _scrollDateCheck([this] { scrollDateCheck(); }) { setMouseTracking(true); + _scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); }); + subscribe(AuthSession::Current().data().repaintLogEntry(), [this](gsl::not_null historyItem) { + auto it = _itemsByHistoryItems.find(historyItem); + if (it != _itemsByHistoryItems.cend()) { + repaintItem(it->second); + } + }); } void InnerWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) { @@ -59,6 +75,59 @@ void InnerWidget::updateVisibleTopItem() { } } +bool InnerWidget::displayScrollDate() const { + return (_visibleTop <= height() - 2 * (_visibleBottom - _visibleTop)); +} + +void InnerWidget::scrollDateCheck() { + if (!_visibleTopItem) { + _scrollDateLastItem = nullptr; + _scrollDateLastItemTop = 0; + scrollDateHide(); + } else if (_visibleTopItem != _scrollDateLastItem || _visibleTopFromItem != _scrollDateLastItemTop) { + // Show scroll date only if it is not the initial onScroll() event (with empty _scrollDateLastItem). + if (_scrollDateLastItem && !_scrollDateShown) { + toggleScrollDateShown(); + } + _scrollDateLastItem = _visibleTopItem; + _scrollDateLastItemTop = _visibleTopFromItem; + _scrollDateHideTimer.callOnce(kScrollDateHideTimeout); + } +} + +void InnerWidget::scrollDateHideByTimer() { + _scrollDateHideTimer.cancel(); + if (!_scrollDateLink || ClickHandler::getPressed() != _scrollDateLink) { + scrollDateHide(); + } +} + +void InnerWidget::scrollDateHide() { + if (_scrollDateShown) { + toggleScrollDateShown(); + } +} + +void InnerWidget::keepScrollDateForNow() { + if (!_scrollDateShown && _scrollDateLastItem && _scrollDateOpacity.animating()) { + toggleScrollDateShown(); + } + _scrollDateHideTimer.callOnce(kScrollDateHideTimeout); +} + +void InnerWidget::toggleScrollDateShown() { + _scrollDateShown = !_scrollDateShown; + auto from = _scrollDateShown ? 0. : 1.; + auto to = _scrollDateShown ? 1. : 0.; + _scrollDateOpacity.start([this] { repaintScrollDateCallback(); }, from, to, st::historyDateFadeDuration); +} + +void InnerWidget::repaintScrollDateCallback() { + auto updateTop = _visibleTop; + auto updateHeight = st::msgServiceMargin.top() + st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom(); + update(0, updateTop, width(), updateHeight); +} + void InnerWidget::checkPreloadMore() { if (_visibleTop + PreloadHeightsCount * (_visibleBottom - _visibleTop) > height()) { preloadMore(Direction::Down); @@ -73,6 +142,26 @@ void InnerWidget::applyFilter(MTPDchannelAdminLogEventsFilter::Flags flags, cons _filterAdmins = admins; } +QString InnerWidget::tooltipText() const { + if (_mouseCursorState == HistoryInDateCursorState && _mouseAction == MouseAction::None) { + if (_itemOver) { + auto dateText = _itemOver->date().toString(QLocale::system().dateTimeFormat(QLocale::LongFormat)); + return dateText; + } + } else if (_mouseCursorState == HistoryInForwardedCursorState && _mouseAction == MouseAction::None) { + if (_itemOver) { + auto forwarded = _itemOver->getForwardedInfoText(); + } + } else if (auto lnk = ClickHandler::getActive()) { + return lnk->tooltip(); + } + return QString(); +} + +QPoint InnerWidget::tooltipPos() const { + return _mousePosition; +} + void InnerWidget::saveState(gsl::not_null memento) const { //if (auto count = _items.size()) { // QList> groups; @@ -162,7 +251,7 @@ void InnerWidget::itemsAdded(Direction direction) { void InnerWidget::updateSize() { TWidget::resizeToWidth(width()); - auto newVisibleTop = (_visibleTopItem ? _visibleTopItem->top() : 0) + _visibleTopFromItem; + auto newVisibleTop = _visibleTopItem ? (itemTop(_visibleTopItem) + _visibleTopFromItem) : ScrollMax; _scrollTo(newVisibleTop); updateVisibleTopItem(); checkPreloadMore(); @@ -176,10 +265,16 @@ int InnerWidget::resizeGetHeight(int newWidth) { item->setTop(newHeight); newHeight += item->resizeGetHeight(newWidth); } - return qMax(newHeight, _minHeight); + _itemsHeight = newHeight; + _itemsTop = (_minHeight > _itemsHeight + st::historyPaddingBottom) ? (_minHeight - _itemsHeight - st::historyPaddingBottom) : 0; + return _itemsTop + _itemsHeight + st::historyPaddingBottom; } void InnerWidget::paintEvent(QPaintEvent *e) { + if (Ui::skipPaintEvent(this, e)) { + return; + } + Painter p(this); auto ms = getms(); @@ -189,14 +284,14 @@ void InnerWidget::paintEvent(QPaintEvent *e) { paintEmpty(p); } else { auto start = std::rbegin(_items), end = std::rend(_items); - auto from = std::upper_bound(start, end, clip.top(), [](int top, auto &elem) { - return top <= elem->top() + elem->height(); + auto from = std::upper_bound(start, end, clip.top(), [this](int top, auto &elem) { + return top <= itemTop(elem.get()) + elem->height(); }); - auto to = std::lower_bound(start, end, clip.top() + clip.height(), [](auto &elem, int bottom) { - return elem->top() < bottom; + auto to = std::lower_bound(start, end, clip.top() + clip.height(), [this](auto &elem, int bottom) { + return itemTop(elem.get()) < bottom; }); if (from != end) { - auto top = (*from)->top(); + auto top = itemTop(from->get()); p.translate(0, top); for (auto i = from; i != to; ++i) { (*i)->draw(p, clip.translated(0, -top), TextSelection(), ms); @@ -226,12 +321,464 @@ void InnerWidget::keyPressEvent(QKeyEvent *e) { } void InnerWidget::mousePressEvent(QMouseEvent *e) { + if (_menu) { + e->accept(); + return; // ignore mouse press, that was hiding context menu + } + mouseActionStart(e->globalPos(), e->button()); } void InnerWidget::mouseMoveEvent(QMouseEvent *e) { + static auto lastGlobalPosition = e->globalPos(); + auto reallyMoved = (lastGlobalPosition != e->globalPos()); + auto buttonsPressed = (e->buttons() & (Qt::LeftButton | Qt::MiddleButton)); + if (!buttonsPressed && _mouseAction != MouseAction::None) { + mouseReleaseEvent(e); + } + if (reallyMoved) { + lastGlobalPosition = e->globalPos(); + if (!buttonsPressed || (_scrollDateLink && ClickHandler::getPressed() == _scrollDateLink)) { + keepScrollDateForNow(); + } + } + mouseActionUpdate(e->globalPos()); } void InnerWidget::mouseReleaseEvent(QMouseEvent *e) { + mouseActionFinish(e->globalPos(), e->button()); + if (!rect().contains(e->pos())) { + leaveEvent(e); + } +} + +void InnerWidget::enterEventHook(QEvent *e) { + mouseActionUpdate(QCursor::pos()); + return TWidget::enterEventHook(e); +} + +void InnerWidget::leaveEventHook(QEvent *e) { + repaintItem(base::take(_itemOver)); + ClickHandler::clearActive(); + Ui::Tooltip::Hide(); + if (!ClickHandler::getPressed() && _cursor != style::cur_default) { + _cursor = style::cur_default; + setCursor(_cursor); + } + return TWidget::leaveEventHook(e); +} + +void InnerWidget::mouseActionStart(const QPoint &screenPos, Qt::MouseButton button) { + mouseActionUpdate(screenPos); + if (button != Qt::LeftButton) return; + + ClickHandler::pressed(); + if (_itemPressed != _itemOver) { + repaintItem(_itemPressed); + _itemPressed = _itemOver; + repaintItem(_itemPressed); + } + + _mouseAction = MouseAction::None; + _mouseActionItem = _itemNearest; + _dragStartPosition = mapPointToItem(mapFromGlobal(screenPos), _mouseActionItem); + _pressWasInactive = _controller->window()->wasInactivePress(); + if (_pressWasInactive) _controller->window()->setInactivePress(false); + + if (ClickHandler::getPressed()) { + _mouseAction = MouseAction::PrepareDrag; + } + if (_mouseAction == MouseAction::None && _mouseActionItem) { + HistoryTextState dragState; + if (_trippleClickTimer.isActive() && (screenPos - _trippleClickPoint).manhattanLength() < QApplication::startDragDistance()) { + HistoryStateRequest request; + request.flags = Text::StateRequest::Flag::LookupSymbol; + dragState = _mouseActionItem->getState(_dragStartPosition, request).data; + if (dragState.cursor == HistoryInTextCursorState) { + auto selection = TextSelection { dragState.symbol, dragState.symbol }; + repaintItem(std::exchange(_selectedItem, _mouseActionItem)); + _selectedText = selection; + _mouseTextSymbol = dragState.symbol; + _mouseAction = MouseAction::Selecting; + _mouseSelectType = TextSelectType::Paragraphs; + mouseActionUpdate(_mousePosition); + _trippleClickTimer.callOnce(QApplication::doubleClickInterval()); + } + } else if (_itemPressed) { + HistoryStateRequest request; + request.flags = Text::StateRequest::Flag::LookupSymbol; + dragState = _mouseActionItem->getState(_dragStartPosition, request).data; + } + if (_mouseSelectType != TextSelectType::Paragraphs) { + if (_itemPressed) { + _mouseTextSymbol = dragState.symbol; + auto uponSelected = (dragState.cursor == HistoryInTextCursorState); + if (uponSelected) { + if (!_selectedItem || _selectedItem != _mouseActionItem) { + uponSelected = false; + } else if (_mouseTextSymbol < _selectedText.from || _mouseTextSymbol >= _selectedText.to) { + uponSelected = false; + } + } + if (uponSelected) { + _mouseAction = MouseAction::PrepareDrag; // start text drag + } else if (!_pressWasInactive) { + //if (dynamic_cast(_itemPressed->getMedia())) { + // _mouseAction = MouseAction::PrepareDrag; // start sticker drag or by-date drag + //} else { // TODO + if (dragState.afterSymbol) ++_mouseTextSymbol; + auto selection = TextSelection { _mouseTextSymbol, _mouseTextSymbol }; + repaintItem(std::exchange(_selectedItem, _mouseActionItem)); + _selectedText = selection; + _mouseAction = MouseAction::Selecting; + repaintItem(_mouseActionItem); + //} // TODO + } + } + } + } + + if (!_mouseActionItem) { + _mouseAction = MouseAction::None; + } else if (_mouseAction == MouseAction::None) { + _mouseActionItem = nullptr; + } +} + +void InnerWidget::mouseActionUpdate(const QPoint &screenPos) { + _mousePosition = screenPos; + updateSelected(); +} + +void InnerWidget::mouseActionCancel() { + _mouseActionItem = nullptr; + _mouseAction = MouseAction::None; + _dragStartPosition = QPoint(0, 0); + _wasSelectedText = false; + //_widget->noSelectingScroll(); // TODO +} + +void InnerWidget::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton button) { + mouseActionUpdate(screenPos); + + ClickHandlerPtr activated = ClickHandler::unpressed(); + if (_mouseAction == MouseAction::Dragging) { + activated.clear(); + } + repaintItem(base::take(_itemPressed)); + + _wasSelectedText = false; + + if (activated) { + mouseActionCancel(); + App::activateClickHandler(activated, button); + return; + } + if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && button != Qt::RightButton) { + repaintItem(base::take(_selectedItem)); + } else if (_mouseAction == MouseAction::Selecting) { + if (_selectedItem && !_pressWasInactive) { + if (_selectedText.from == _selectedText.to) { + _selectedItem = nullptr; + App::wnd()->setInnerFocus(); + } + } + } + _mouseAction = MouseAction::None; + _mouseActionItem = nullptr; + _mouseSelectType = TextSelectType::Letters; + //_widget->noSelectingScroll(); // TODO + +#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64 + if (_selectedItem && _selectedText.from != _selectedText.to) { + setToClipboard(_selectedItem->selectedText(_selectedText), QClipboard::Selection); + } +#endif // Q_OS_LINUX32 || Q_OS_LINUX64 +} + +void InnerWidget::updateSelected() { + auto mousePosition = mapFromGlobal(_mousePosition); + auto point = QPoint(snap(mousePosition.x(), 0, width()), snap(mousePosition.y(), _visibleTop, _visibleBottom)); + + auto itemPoint = QPoint(); + auto start = std::rbegin(_items), end = std::rend(_items); + auto from = (point.y() >= _itemsTop && point.y() < _itemsTop + _itemsHeight) ? std::upper_bound(start, end, point.y(), [this](int top, auto &elem) { + return top <= itemTop(elem.get()) + elem->height(); + }) : end; + if (from != end) { + _itemNearest = from->get(); + itemPoint = mapPointToItem(point, _itemNearest); + if (_itemNearest->hasPoint(itemPoint)) { + if (_itemOver != _itemNearest) { + repaintItem(std::exchange(_itemOver, _itemNearest)); + repaintItem(_itemNearest); + } + } else { + repaintItem(base::take(_itemOver)); + } + } else { + _itemNearest = nullptr; + } + + Item::TextState dragState; + ClickHandlerHost *lnkhost = nullptr; + auto selectingText = (_itemNearest == _mouseActionItem && _itemNearest == _itemOver && _selectedItem); + if (_itemNearest) { + if (_itemNearest != _mouseActionItem || (itemPoint - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) { + if (_mouseAction == MouseAction::PrepareDrag) { + _mouseAction = MouseAction::Dragging; + InvokeQueued(this, [this] { performDrag(); }); + } + } + + auto dateHeight = st::msgServicePadding.bottom() + st::msgServiceFont->height + st::msgServicePadding.top(); + auto scrollDateOpacity = _scrollDateOpacity.current(_scrollDateShown ? 1. : 0.); + //enumerateDates([this, &dragState, &lnkhost, &point, scrollDateOpacity, dateHeight/*, lastDate, showFloatingBefore*/](HistoryItem *item, int itemtop, int dateTop) { + // // stop enumeration if the date is above our point + // if (dateTop + dateHeight <= point.y()) { + // return false; + // } + + // bool displayDate = item->displayDate(); + // bool dateInPlace = displayDate; + // if (dateInPlace) { + // int correctDateTop = itemtop + st::msgServiceMargin.top(); + // dateInPlace = (dateTop < correctDateTop + dateHeight); + // } + + // // stop enumeration if we've found a date under the cursor + // if (dateTop <= point.y()) { + // auto opacity = (dateInPlace/* || noFloatingDate*/) ? 1. : scrollDateOpacity; + // if (opacity > 0.) { + // auto dateWidth = 0; + // if (auto date = item->Get()) { + // dateWidth = date->_width; + // } else { + // dateWidth = st::msgServiceFont->width(langDayOfMonthFull(item->date.date())); + // } + // dateWidth += st::msgServicePadding.left() + st::msgServicePadding.right(); + // auto dateLeft = st::msgServiceMargin.left(); + // auto maxwidth = item->history()->width; + // if (Adaptive::ChatWide()) { + // maxwidth = qMin(maxwidth, int32(st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left())); + // } + // auto widthForDate = maxwidth - st::msgServiceMargin.left() - st::msgServiceMargin.left(); + + // dateLeft += (widthForDate - dateWidth) / 2; + + // if (point.x() >= dateLeft && point.x() < dateLeft + dateWidth) { + // if (!_scrollDateLink) { + // _scrollDateLink = MakeShared(item->history()->peer, item->date.date()); + // } else { + // static_cast(_scrollDateLink.data())->setDate(item->date.date()); + // } + // dragState.link = _scrollDateLink; + // lnkhost = item; + // } + // } + // return false; + // } + // return true; + //}); // TODO + if (!dragState.data.link) { + HistoryStateRequest request; + if (_mouseAction == MouseAction::Selecting) { + request.flags |= Text::StateRequest::Flag::LookupSymbol; + } else { + selectingText = false; + } + dragState = _itemNearest->getState(itemPoint, request); + lnkhost = dragState.handler; + if (!dragState.data.link && itemPoint.x() >= st::historyPhotoLeft && itemPoint.x() < st::historyPhotoLeft + st::msgPhotoSize) { + //if (auto msg = item->toHistoryMessage()) { + // if (msg->hasFromPhoto()) { + // enumerateUserpics([&dragState, &lnkhost, &point](HistoryMessage *message, int userpicTop) -> bool { + // // stop enumeration if the userpic is below our point + // if (userpicTop > point.y()) { + // return false; + // } + + // // stop enumeration if we've found a userpic under the cursor + // if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) { + // dragState.link = message->from()->openLink(); + // lnkhost = message; + // return false; + // } + // return true; + // }); + // } + //} // TODO + } + } + } + auto lnkChanged = ClickHandler::setActive(dragState.data.link, lnkhost); + if (lnkChanged || dragState.data.cursor != _mouseCursorState) { + Ui::Tooltip::Hide(); + } + if (dragState.data.link || dragState.data.cursor == HistoryInDateCursorState || dragState.data.cursor == HistoryInForwardedCursorState) { + Ui::Tooltip::Show(1000, this); + } + + auto cursor = style::cur_default; + if (_mouseAction == MouseAction::None) { + _mouseCursorState = dragState.data.cursor; + if (dragState.data.link) { + cursor = style::cur_pointer; + } else if (_mouseCursorState == HistoryInTextCursorState) { + cursor = style::cur_text; + } else if (_mouseCursorState == HistoryInDateCursorState) { +// cursor = style::cur_cross; + } + } else if (_itemNearest) { + if (_mouseAction == MouseAction::Selecting) { + if (selectingText) { + auto second = dragState.data.symbol; + if (dragState.data.afterSymbol && _mouseSelectType == TextSelectType::Letters) { + ++second; + } + auto selection = _mouseActionItem->adjustSelection({ qMin(second, _mouseTextSymbol), qMax(second, _mouseTextSymbol) }, _mouseSelectType); + if (_selectedText != selection) { + _selectedText = selection; + repaintItem(_mouseActionItem); + } + if (!_wasSelectedText && (selection.from != selection.to)) { + _wasSelectedText = true; + setFocus(); + } + } + } else if (_mouseAction == MouseAction::Dragging) { + } + + if (ClickHandler::getPressed()) { + cursor = style::cur_pointer; + } else if (_mouseAction == MouseAction::Selecting && _selectedItem) { + cursor = style::cur_text; + } + } + + // Voice message seek support. + if (_itemPressed) { + auto adjustedPoint = mapPointToItem(point, _itemPressed); + _itemPressed->updatePressed(adjustedPoint); + } + + //if (_mouseAction == MouseAction::Selecting) { + // _widget->checkSelectingScroll(mousePos); + //} else { + // _widget->noSelectingScroll(); + //} // TODO + + if (_mouseAction == MouseAction::None && (lnkChanged || cursor != _cursor)) { + setCursor(_cursor = cursor); + } +} + +void InnerWidget::performDrag() { + if (_mouseAction != MouseAction::Dragging) return; + + auto uponSelected = false; + //if (_mouseActionItem) { + // if (!_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { + // uponSelected = _selected.contains(_mouseActionItem); + // } else { + // HistoryStateRequest request; + // request.flags |= Text::StateRequest::Flag::LookupSymbol; + // auto dragState = _mouseActionItem->getState(_dragStartPosition.x(), _dragStartPosition.y(), request); + // uponSelected = (dragState.cursor == HistoryInTextCursorState); + // if (uponSelected) { + // if (_selected.isEmpty() || + // _selected.cbegin().value() == FullSelection || + // _selected.cbegin().key() != _mouseActionItem + // ) { + // uponSelected = false; + // } else { + // uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to; + // if (dragState.symbol < selFrom || dragState.symbol >= selTo) { + // uponSelected = false; + // } + // } + // } + // } + //} + //auto pressedHandler = ClickHandler::getPressed(); + + //if (dynamic_cast(pressedHandler.data())) { + // return; + //} + + //TextWithEntities sel; + //QList urls; + //if (uponSelected) { + // sel = getSelectedText(); + //} else if (pressedHandler) { + // sel = { pressedHandler->dragText(), EntitiesInText() }; + // //if (!sel.isEmpty() && sel.at(0) != '/' && sel.at(0) != '@' && sel.at(0) != '#') { + // // urls.push_back(QUrl::fromEncoded(sel.toUtf8())); // Google Chrome crashes in Mac OS X O_o + // //} + //} + //if (auto mimeData = mimeDataFromTextWithEntities(sel)) { + // updateDragSelection(0, 0, false); + // _widget->noSelectingScroll(); + + // if (!urls.isEmpty()) mimeData->setUrls(urls); + // if (uponSelected && !Adaptive::OneColumn()) { + // auto selectedState = getSelectionState(); + // if (selectedState.count > 0 && selectedState.count == selectedState.canForwardCount) { + // mimeData->setData(qsl("application/x-td-forward-selected"), "1"); + // } + // } + // _controller->window()->launchDrag(std::move(mimeData)); + // return; + //} else { + // auto forwardMimeType = QString(); + // auto pressedMedia = static_cast(nullptr); + // if (auto pressedItem = App::pressedItem()) { + // pressedMedia = pressedItem->getMedia(); + // if (_mouseCursorState == HistoryInDateCursorState || (pressedMedia && pressedMedia->dragItem())) { + // forwardMimeType = qsl("application/x-td-forward-pressed"); + // } + // } + // if (auto pressedLnkItem = App::pressedLinkItem()) { + // if ((pressedMedia = pressedLnkItem->getMedia())) { + // if (forwardMimeType.isEmpty() && pressedMedia->dragItemByHandler(pressedHandler)) { + // forwardMimeType = qsl("application/x-td-forward-pressed-link"); + // } + // } + // } + // if (!forwardMimeType.isEmpty()) { + // auto mimeData = std::make_unique(); + // mimeData->setData(forwardMimeType, "1"); + // if (auto document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) { + // auto filepath = document->filepath(DocumentData::FilePathResolveChecked); + // if (!filepath.isEmpty()) { + // QList urls; + // urls.push_back(QUrl::fromLocalFile(filepath)); + // mimeData->setUrls(urls); + // } + // } + + // // This call enters event loop and can destroy any QObject. + // _controller->window()->launchDrag(std::move(mimeData)); + // return; + // } + //} // TODO +} + +int InnerWidget::itemTop(gsl::not_null item) const { + return _itemsTop + item->top(); +} + +void InnerWidget::repaintItem(Item *item) { + if (!item) { + return; + } + update(0, itemTop(item), width(), item->height()); +} + +QPoint InnerWidget::mapPointToItem(QPoint point, Item *item) const { + if (!item) { + return QPoint(); + } + return point - QPoint(0, itemTop(item)); } InnerWidget::~InnerWidget() = default; diff --git a/Telegram/SourceFiles/history/history_admin_log_inner.h b/Telegram/SourceFiles/history/history_admin_log_inner.h index 8e7df385d..d93b76d1d 100644 --- a/Telegram/SourceFiles/history/history_admin_log_inner.h +++ b/Telegram/SourceFiles/history/history_admin_log_inner.h @@ -20,7 +20,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once +#include "ui/widgets/tooltip.h" #include "mtproto/sender.h" +#include "base/timer.h" + +namespace Ui { +class PopupMenu; +} // namespace Ui + +namespace Window { +class Controller; +} // namespace Window namespace AdminLog { @@ -47,9 +57,9 @@ private: }; -class InnerWidget final : public TWidget, private MTP::Sender { +class InnerWidget final : public TWidget, public Ui::AbstractTooltipShower, private MTP::Sender, private base::Subscriber { public: - InnerWidget(QWidget *parent, gsl::not_null channel, base::lambda scrollTo); + InnerWidget(QWidget *parent, gsl::not_null controller, gsl::not_null channel, base::lambda scrollTo); gsl::not_null channel() const { return _channel; @@ -72,6 +82,10 @@ public: // Empty "flags" means all events. Empty "admins" means all admins. void applyFilter(MTPDchannelAdminLogEventsFilter::Flags flags, const std::vector> &admins); + // AbstractTooltipShower interface + QString tooltipText() const override; + QPoint tooltipPos() const override; + ~InnerWidget(); protected: @@ -80,6 +94,8 @@ protected: void mousePressEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; + void enterEventHook(QEvent *e) override; + void leaveEventHook(QEvent *e) override; // Resizes content and counts natural widget height for the desired width. int resizeGetHeight(int newWidth) override; @@ -89,6 +105,23 @@ private: Up, Down, }; + enum class MouseAction { + None, + PrepareDrag, + Dragging, + Selecting, + }; + + void mouseActionStart(const QPoint &screenPos, Qt::MouseButton button); + void mouseActionUpdate(const QPoint &screenPos); + void mouseActionFinish(const QPoint &screenPos, Qt::MouseButton button); + void mouseActionCancel(); + void updateSelected(); + void performDrag(); + int itemTop(gsl::not_null item) const; + void repaintItem(Item *item); + QPoint mapPointToItem(QPoint point, Item *item) const; + void checkPreloadMore(); void updateVisibleTopItem(); void preloadMore(Direction direction); @@ -96,11 +129,23 @@ private: void updateSize(); void paintEmpty(Painter &p); + void toggleScrollDateShown(); + void repaintScrollDateCallback(); + bool displayScrollDate() const; + void scrollDateHide(); + void keepScrollDateForNow(); + void scrollDateCheck(); + void scrollDateHideByTimer(); + + gsl::not_null _controller; gsl::not_null _channel; gsl::not_null _history; base::lambda _cancelledCallback; base::lambda _scrollTo; std::vector> _items; + std::map, gsl::not_null, std::less<>> _itemsByHistoryItems; + int _itemsTop = 0; + int _itemsHeight = 0; LocalIdManager _idManager; int _minHeight = 0; @@ -109,6 +154,14 @@ private: Item *_visibleTopItem = nullptr; int _visibleTopFromItem = 0; + bool _scrollDateShown = false; + Animation _scrollDateOpacity; + SingleQueuedInvokation _scrollDateCheck; + base::Timer _scrollDateHideTimer; + Item *_scrollDateLastItem = nullptr; + int _scrollDateLastItemTop = 0; + ClickHandlerPtr _scrollDateLink; + // Up - max, Down - min. uint64 _maxId = 0; uint64 _minId = 0; @@ -117,6 +170,29 @@ private: bool _upLoaded = false; bool _downLoaded = true; + MouseAction _mouseAction = MouseAction::None; + TextSelectType _mouseSelectType = TextSelectType::Letters; + QPoint _dragStartPosition; + QPoint _mousePosition; + Item *_mouseActionItem = nullptr; + HistoryCursorState _mouseCursorState = HistoryDefaultCursorState; + uint16 _mouseTextSymbol = 0; + bool _pressWasInactive = false; + + Item *_itemNearest = nullptr; + Item *_itemOver = nullptr; + Item *_itemPressed = nullptr; + Item *_selectedItem = nullptr; + TextSelection _selectedText; + bool _wasSelectedText = false; // was some text selected in current drag action + Qt::CursorShape _cursor = style::cur_default; + + // context menu + Ui::PopupMenu *_menu = nullptr; + + QPoint _trippleClickPoint; + base::Timer _trippleClickTimer; + MTPDchannelAdminLogEventsFilter::Flags _filterFlags = 0; std::vector> _filterAdmins; diff --git a/Telegram/SourceFiles/history/history_admin_log_item.cpp b/Telegram/SourceFiles/history/history_admin_log_item.cpp index 209940ab5..01a7fec65 100644 --- a/Telegram/SourceFiles/history/history_admin_log_item.cpp +++ b/Telegram/SourceFiles/history/history_admin_log_item.cpp @@ -235,6 +235,7 @@ TextWithEntities GenerateParticipantChangeText(gsl::not_null chann Item::Item(gsl::not_null history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event) : _id(event.vid.v) +, _date(::date(event.vdate)) , _history(history) , _from(App::user(event.vuser_id.v)) { auto &action = event.vaction; @@ -439,23 +440,42 @@ bool Item::hasPoint(QPoint point) const { for (auto part : _parts) { auto height = part->height(); if (point.y() >= top && point.y() < top + height) { - return part->hasPoint(point.x(), point.y() - top); + return part->hasPoint(point - QPoint(0, top)); } top += height; } return false; } -HistoryTextState Item::getState(QPoint point, HistoryStateRequest request) const { +Item::TextState Item::getState(QPoint point, HistoryStateRequest request) const { auto top = 0; for (auto part : _parts) { auto height = part->height(); if (point.y() >= top && point.y() < top + height) { - return part->getState(point.x(), point.y() - top, request); + auto result = TextState(); + result.data = part->getState(point - QPoint(0, top), request); + result.handler = part; + return result; } top += height; } - return HistoryTextState(); + return Item::TextState(); +} + +TextSelection Item::adjustSelection(TextSelection selection, TextSelectType type) const { + return selection; +} + +void Item::updatePressed(QPoint point) { +} + +QString Item::getForwardedInfoText() const { + for (auto part : _parts) { + if (auto forwarded = part->Get()) { + return forwarded->_text.originalText(AllTextSelection, ExpandLinksNone); + } + } + return QString(); } Item::~Item() { diff --git a/Telegram/SourceFiles/history/history_admin_log_item.h b/Telegram/SourceFiles/history/history_admin_log_item.h index d2a1de4c4..58a069bfc 100644 --- a/Telegram/SourceFiles/history/history_admin_log_item.h +++ b/Telegram/SourceFiles/history/history_admin_log_item.h @@ -26,11 +26,19 @@ namespace AdminLog { class Item { public: + struct TextState { + HistoryTextState data; + ClickHandlerHost *handler = nullptr; + }; + Item(gsl::not_null history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event); uint64 id() const { return _id; } + QDateTime date() const { + return _date; + } int top() const { return _top; } @@ -44,7 +52,11 @@ public: int resizeGetHeight(int newWidth); void draw(Painter &p, QRect clip, TextSelection selection, TimeMs ms); bool hasPoint(QPoint point) const; - HistoryTextState getState(QPoint point, HistoryStateRequest request) const; + TextState getState(QPoint point, HistoryStateRequest request) const; + TextSelection adjustSelection(TextSelection selection, TextSelectType type) const; + void updatePressed(QPoint point); + + QString getForwardedInfoText() const; ~Item(); @@ -55,6 +67,7 @@ private: void addPart(HistoryItem *item); uint64 _id = 0; + QDateTime _date; gsl::not_null _history; gsl::not_null _from; std::vector _parts; diff --git a/Telegram/SourceFiles/history/history_admin_log_section.cpp b/Telegram/SourceFiles/history/history_admin_log_section.cpp index 0de33c386..fed64fd84 100644 --- a/Telegram/SourceFiles/history/history_admin_log_section.cpp +++ b/Telegram/SourceFiles/history/history_admin_log_section.cpp @@ -139,7 +139,7 @@ Widget::Widget(QWidget *parent, gsl::not_null controller, g updateAdaptiveLayout(); subscribe(Adaptive::Changed(), [this]() { updateAdaptiveLayout(); }); - _inner = _scroll->setOwnedWidget(object_ptr(this, channel, [this](int top) { _scroll->scrollToY(top); })); + _inner = _scroll->setOwnedWidget(object_ptr(this, controller, channel, [this](int top) { _scroll->scrollToY(top); })); _scroll->move(0, _fixedBar->height()); _scroll->show(); diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 9b66fa7d1..311e7249f 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -57,12 +57,12 @@ private: }; -QMimeData *mimeDataFromTextWithEntities(const TextWithEntities &forClipboard) { +std::unique_ptr mimeDataFromTextWithEntities(const TextWithEntities &forClipboard) { if (forClipboard.text.isEmpty()) { return nullptr; } - auto result = new QMimeData(); + auto result = std::make_unique(); result->setText(forClipboard.text); auto tags = ConvertEntitiesToTextTags(forClipboard.entities); if (!tags.isEmpty()) { @@ -107,6 +107,14 @@ HistoryInner::HistoryInner(HistoryWidget *historyWidget, gsl::not_nullwindow()->dragFinished(), [this] { + mouseActionUpdate(QCursor::pos()); + }); + subscribe(AuthSession::Current().data().historyCleared(), [this](gsl::not_null history) { + if (_history == history) { + mouseActionCancel(); + } + }); } void HistoryInner::messagesReceived(PeerData *peer, const QVector &messages) { @@ -363,7 +371,7 @@ void HistoryInner::enumerateDates(Method method) { } void HistoryInner::paintEvent(QPaintEvent *e) { - if (!App::main() || (App::wnd() && App::wnd()->contentOverlapped(this, e))) { + if (Ui::skipPaintEvent(this, e)) { return; } if (hasPendingResizedItems()) { @@ -371,17 +379,13 @@ void HistoryInner::paintEvent(QPaintEvent *e) { } Painter p(this); - QRect r(e->rect()); - bool trivial = (rect() == r); - if (!trivial) { - p.setClipRect(r); - } + auto clip = e->rect(); auto ms = getms(); bool historyDisplayedEmpty = (_history->isDisplayedEmpty() && (!_migrated || _migrated->isDisplayedEmpty())); bool noHistoryDisplayed = _firstLoading || historyDisplayedEmpty; if (!_firstLoading && _botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) { - if (r.y() < _botAbout->rect.y() + _botAbout->rect.height() && r.y() + r.height() > _botAbout->rect.y()) { + if (clip.y() < _botAbout->rect.y() + _botAbout->rect.height() && clip.y() + clip.height() > _botAbout->rect.y()) { p.setTextPalette(st::inTextPalette); App::roundRect(p, _botAbout->rect, st::msgInBg, MessageInCorners, &st::msgInShadow); @@ -398,14 +402,15 @@ void HistoryInner::paintEvent(QPaintEvent *e) { HistoryLayout::paintEmpty(p, width(), height()); } if (!noHistoryDisplayed) { - adjustCurrent(r.top()); + adjustCurrent(clip.top()); - SelectedItems::const_iterator selEnd = _selected.cend(); - bool hasSel = !_selected.isEmpty(); + auto selEnd = _selected.cend(); + auto hasSel = !_selected.isEmpty(); - int32 drawToY = r.y() + r.height(); + auto drawToY = clip.y() + clip.height(); - int32 selfromy = itemTop(_dragSelFrom), seltoy = itemTop(_dragSelTo); + auto selfromy = itemTop(_dragSelFrom); + auto seltoy = itemTop(_dragSelTo); if (selfromy < 0 || seltoy < 0) { selfromy = seltoy = -1; } else { @@ -424,7 +429,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) { auto y = mtop + block->y() + item->y(); p.save(); p.translate(0, y); - if (r.y() < y + item->height()) while (y < drawToY) { + if (clip.y() < y + item->height()) while (y < drawToY) { TextSelection sel; if (y >= selfromy && y < seltoy) { if (_dragSelecting && !item->serviceMsg() && item->id > 0) { @@ -436,7 +441,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) { sel = i.value(); } } - item->draw(p, r.translated(0, -y), sel, ms); + item->draw(p, clip.translated(0, -y), sel, ms); if (item->hasViews()) { App::main()->scheduleViewIncrement(item); @@ -465,7 +470,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) { auto iItem = (_curHistory == _history ? _curItem : 0); auto item = block->items[iItem]; - auto historyRect = r.intersected(QRect(0, hdrawtop, width(), r.top() + r.height())); + auto historyRect = clip.intersected(QRect(0, hdrawtop, width(), clip.top() + clip.height())); auto y = htop + block->y() + item->y(); p.save(); p.translate(0, y); @@ -507,14 +512,14 @@ void HistoryInner::paintEvent(QPaintEvent *e) { } if (mtop >= 0 || htop >= 0) { - enumerateUserpics([&p, &r](HistoryMessage *message, int userpicTop) { + enumerateUserpics([&p, &clip](HistoryMessage *message, int userpicTop) { // stop the enumeration if the userpic is below the painted rect - if (userpicTop >= r.top() + r.height()) { + if (userpicTop >= clip.top() + clip.height()) { return false; } // paint the userpic if it intersects the painted rect - if (userpicTop + st::msgPhotoSize > r.top()) { + if (userpicTop + st::msgPhotoSize > clip.top()) { message->from()->paintUserpicLeft(p, st::historyPhotoLeft, userpicTop, message->history()->width, st::msgPhotoSize); } return true; @@ -530,9 +535,9 @@ void HistoryInner::paintEvent(QPaintEvent *e) { //int showFloatingBefore = height() - 2 * (_visibleAreaBottom - _visibleAreaTop) - dateHeight; auto scrollDateOpacity = _scrollDateOpacity.current(ms, _scrollDateShown ? 1. : 0.); - enumerateDates([&p, &r, scrollDateOpacity, dateHeight/*, lastDate, showFloatingBefore*/](HistoryItem *item, int itemtop, int dateTop) { + enumerateDates([&p, &clip, scrollDateOpacity, dateHeight/*, lastDate, showFloatingBefore*/](HistoryItem *item, int itemtop, int dateTop) { // stop the enumeration if the date is above the painted rect - if (dateTop + dateHeight <= r.top()) { + if (dateTop + dateHeight <= clip.top()) { return false; } @@ -550,7 +555,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) { //} // paint the date if it intersects the painted rect - if (dateTop < r.top() + r.height()) { + if (dateTop < clip.top() + clip.height()) { auto opacity = (dateInPlace/* || noFloatingDate*/) ? 1. : scrollDateOpacity; if (opacity > 0.) { p.setOpacity(opacity); @@ -660,7 +665,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) { _touchSelectTimer.stop(); _touchScroll = _touchSelect = false; _touchScrollState = Ui::TouchScrollState::Manual; - dragActionCancel(); + mouseActionCancel(); return; } @@ -696,7 +701,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) { case QEvent::TouchUpdate: if (!_touchInProgress) return; if (_touchSelect) { - dragActionUpdate(_touchPos); + mouseActionUpdate(_touchPos); } else if (!_touchScroll && (_touchPos - _touchStart).manhattanLength() >= QApplication::startDragDistance()) { _touchSelectTimer.stop(); _touchScroll = true; @@ -719,7 +724,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) { if (!_touchInProgress) return; _touchInProgress = false; if (_touchSelect) { - dragActionFinish(_touchPos, Qt::RightButton); + mouseActionFinish(_touchPos, Qt::RightButton); QContextMenuEvent contextMenu(QContextMenuEvent::Mouse, mapFromGlobal(_touchPos), _touchPos); showContextMenu(&contextMenu, true); _touchScroll = false; @@ -738,9 +743,9 @@ void HistoryInner::touchEvent(QTouchEvent *e) { _touchWaitingAcceleration = false; _touchPrevPosValid = false; } - } else { // one short tap -- like mouse click - dragActionStart(_touchPos); - dragActionFinish(_touchPos); + } else { // One short tap is like left mouse click. + mouseActionStart(_touchPos, Qt::LeftButton); + mouseActionFinish(_touchPos, Qt::LeftButton); } _touchSelectTimer.stop(); _touchSelect = false; @@ -752,7 +757,7 @@ void HistoryInner::mouseMoveEvent(QMouseEvent *e) { static auto lastGlobalPosition = e->globalPos(); auto reallyMoved = (lastGlobalPosition != e->globalPos()); auto buttonsPressed = (e->buttons() & (Qt::LeftButton | Qt::MiddleButton)); - if (!buttonsPressed && _dragAction != NoDrag) { + if (!buttonsPressed && _mouseAction != MouseAction::None) { mouseReleaseEvent(e); } if (reallyMoved) { @@ -761,11 +766,11 @@ void HistoryInner::mouseMoveEvent(QMouseEvent *e) { keepScrollDateForNow(); } } - dragActionUpdate(e->globalPos()); + mouseActionUpdate(e->globalPos()); } -void HistoryInner::dragActionUpdate(const QPoint &screenPos) { - _dragPos = screenPos; +void HistoryInner::mouseActionUpdate(const QPoint &screenPos) { + _mousePosition = screenPos; onUpdateSelected(); } @@ -788,11 +793,11 @@ void HistoryInner::mousePressEvent(QMouseEvent *e) { e->accept(); return; // ignore mouse press, that was hiding context menu } - dragActionStart(e->globalPos(), e->button()); + mouseActionStart(e->globalPos(), e->button()); } -void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton button) { - dragActionUpdate(screenPos); +void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton button) { + mouseActionUpdate(screenPos); if (button != Qt::LeftButton) return; ClickHandler::pressed(); @@ -802,29 +807,29 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt repaintItem(App::pressedItem()); } - _dragAction = NoDrag; - _dragItem = App::mousedItem(); - _dragStartPos = mapMouseToItem(mapFromGlobal(screenPos), _dragItem); - _dragWasInactive = App::wnd()->inactivePress(); - if (_dragWasInactive) App::wnd()->inactivePress(false); + _mouseAction = MouseAction::None; + _mouseActionItem = App::mousedItem(); + _dragStartPosition = mapMouseToItem(mapFromGlobal(screenPos), _mouseActionItem); + _pressWasInactive = _controller->window()->wasInactivePress(); + if (_pressWasInactive) _controller->window()->setInactivePress(false); if (ClickHandler::getPressed()) { - _dragAction = PrepareDrag; + _mouseAction = MouseAction::PrepareDrag; } else if (!_selected.isEmpty()) { if (_selected.cbegin().value() == FullSelection) { - if (_selected.constFind(_dragItem) != _selected.cend() && App::hoveredItem()) { - _dragAction = PrepareDrag; // start items drag - } else if (!_dragWasInactive) { - _dragAction = PrepareSelect; // start items select + if (_selected.constFind(_mouseActionItem) != _selected.cend() && App::hoveredItem()) { + _mouseAction = MouseAction::PrepareDrag; // start items drag + } else if (!_pressWasInactive) { + _mouseAction = MouseAction::PrepareSelect; // start items select } } } - if (_dragAction == NoDrag && _dragItem) { + if (_mouseAction == MouseAction::None && _mouseActionItem) { HistoryTextState dragState; if (_trippleClickTimer.isActive() && (screenPos - _trippleClickPoint).manhattanLength() < QApplication::startDragDistance()) { HistoryStateRequest request; request.flags = Text::StateRequest::Flag::LookupSymbol; - dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request); + dragState = _mouseActionItem->getState(_dragStartPosition, request); if (dragState.cursor == HistoryInTextCursorState) { TextSelection selStatus = { dragState.symbol, dragState.symbol }; if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) { @@ -832,95 +837,95 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt repaintItem(_selected.cbegin().key()); _selected.clear(); } - _selected.insert(_dragItem, selStatus); - _dragSymbol = dragState.symbol; - _dragAction = Selecting; - _dragSelType = TextSelectType::Paragraphs; - dragActionUpdate(_dragPos); + _selected.insert(_mouseActionItem, selStatus); + _mouseTextSymbol = dragState.symbol; + _mouseAction = MouseAction::Selecting; + _mouseSelectType = TextSelectType::Paragraphs; + mouseActionUpdate(_mousePosition); _trippleClickTimer.start(QApplication::doubleClickInterval()); } } } else if (App::pressedItem()) { HistoryStateRequest request; request.flags = Text::StateRequest::Flag::LookupSymbol; - dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request); + dragState = _mouseActionItem->getState(_dragStartPosition, request); } - if (_dragSelType != TextSelectType::Paragraphs) { + if (_mouseSelectType != TextSelectType::Paragraphs) { if (App::pressedItem()) { - _dragSymbol = dragState.symbol; + _mouseTextSymbol = dragState.symbol; bool uponSelected = (dragState.cursor == HistoryInTextCursorState); if (uponSelected) { if (_selected.isEmpty() || _selected.cbegin().value() == FullSelection || - _selected.cbegin().key() != _dragItem + _selected.cbegin().key() != _mouseActionItem ) { uponSelected = false; } else { uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to; - if (_dragSymbol < selFrom || _dragSymbol >= selTo) { + if (_mouseTextSymbol < selFrom || _mouseTextSymbol >= selTo) { uponSelected = false; } } } if (uponSelected) { - _dragAction = PrepareDrag; // start text drag - } else if (!_dragWasInactive) { - if (dynamic_cast(App::pressedItem()->getMedia()) || _dragCursorState == HistoryInDateCursorState) { - _dragAction = PrepareDrag; // start sticker drag or by-date drag + _mouseAction = MouseAction::PrepareDrag; // start text drag + } else if (!_pressWasInactive) { + if (dynamic_cast(App::pressedItem()->getMedia()) || _mouseCursorState == HistoryInDateCursorState) { + _mouseAction = MouseAction::PrepareDrag; // start sticker drag or by-date drag } else { - if (dragState.afterSymbol) ++_dragSymbol; - TextSelection selStatus = { _dragSymbol, _dragSymbol }; + if (dragState.afterSymbol) ++_mouseTextSymbol; + TextSelection selStatus = { _mouseTextSymbol, _mouseTextSymbol }; if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) { if (!_selected.isEmpty()) { repaintItem(_selected.cbegin().key()); _selected.clear(); } - _selected.insert(_dragItem, selStatus); - _dragAction = Selecting; - repaintItem(_dragItem); + _selected.insert(_mouseActionItem, selStatus); + _mouseAction = MouseAction::Selecting; + repaintItem(_mouseActionItem); } else { - _dragAction = PrepareSelect; + _mouseAction = MouseAction::PrepareSelect; } } } - } else if (!_dragWasInactive) { - _dragAction = PrepareSelect; // start items select + } else if (!_pressWasInactive) { + _mouseAction = MouseAction::PrepareSelect; // start items select } } } - if (!_dragItem) { - _dragAction = NoDrag; - } else if (_dragAction == NoDrag) { - _dragItem = nullptr; + if (!_mouseActionItem) { + _mouseAction = MouseAction::None; + } else if (_mouseAction == MouseAction::None) { + _mouseActionItem = nullptr; } } -void HistoryInner::dragActionCancel() { - _dragItem = 0; - _dragAction = NoDrag; - _dragStartPos = QPoint(0, 0); - _dragSelFrom = _dragSelTo = 0; +void HistoryInner::mouseActionCancel() { + _mouseActionItem = nullptr; + _mouseAction = MouseAction::None; + _dragStartPosition = QPoint(0, 0); + _dragSelFrom = _dragSelTo = nullptr; _wasSelectedText = false; _widget->noSelectingScroll(); } -void HistoryInner::onDragExec() { - if (_dragAction != Dragging) return; +void HistoryInner::performDrag() { + if (_mouseAction != MouseAction::Dragging) return; bool uponSelected = false; - if (_dragItem) { + if (_mouseActionItem) { if (!_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { - uponSelected = _selected.contains(_dragItem); + uponSelected = _selected.contains(_mouseActionItem); } else { HistoryStateRequest request; request.flags |= Text::StateRequest::Flag::LookupSymbol; - auto dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request); + auto dragState = _mouseActionItem->getState(_dragStartPosition, request); uponSelected = (dragState.cursor == HistoryInTextCursorState); if (uponSelected) { if (_selected.isEmpty() || _selected.cbegin().value() == FullSelection || - _selected.cbegin().key() != _dragItem + _selected.cbegin().key() != _mouseActionItem ) { uponSelected = false; } else { @@ -952,7 +957,6 @@ void HistoryInner::onDragExec() { updateDragSelection(0, 0, false); _widget->noSelectingScroll(); - auto drag = std::make_unique(App::wnd()); if (!urls.isEmpty()) mimeData->setUrls(urls); if (uponSelected && !Adaptive::OneColumn()) { auto selectedState = getSelectionState(); @@ -960,19 +964,14 @@ void HistoryInner::onDragExec() { mimeData->setData(qsl("application/x-td-forward-selected"), "1"); } } - drag->setMimeData(mimeData); - drag->exec(Qt::CopyAction); - - // We don't receive mouseReleaseEvent when drag is finished. - ClickHandler::unpressed(); - if (App::main()) App::main()->updateAfterDrag(); + _controller->window()->launchDrag(std::move(mimeData)); return; } else { auto forwardMimeType = QString(); auto pressedMedia = static_cast(nullptr); if (auto pressedItem = App::pressedItem()) { pressedMedia = pressedItem->getMedia(); - if (_dragCursorState == HistoryInDateCursorState || (pressedMedia && pressedMedia->dragItem())) { + if (_mouseCursorState == HistoryInDateCursorState || (pressedMedia && pressedMedia->dragItem())) { forwardMimeType = qsl("application/x-td-forward-pressed"); } } @@ -984,9 +983,7 @@ void HistoryInner::onDragExec() { } } if (!forwardMimeType.isEmpty()) { - auto drag = std::make_unique(App::wnd()); auto mimeData = std::make_unique(); - mimeData->setData(forwardMimeType, "1"); if (auto document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) { auto filepath = document->filepath(DocumentData::FilePathResolveChecked); @@ -997,12 +994,8 @@ void HistoryInner::onDragExec() { } } - drag->setMimeData(mimeData.release()); - drag->exec(Qt::CopyAction); - - // We don't receive mouseReleaseEvent when drag is finished. - ClickHandler::unpressed(); - if (App::main()) App::main()->updateAfterDrag(); + // This call enters event loop and can destroy any QObject. + _controller->window()->launchDrag(std::move(mimeData)); return; } } @@ -1022,8 +1015,8 @@ void HistoryInner::itemRemoved(HistoryItem *item) { _widget->updateTopBarSelection(); } - if (_dragItem == item) { - dragActionCancel(); + if (_mouseActionItem == item) { + mouseActionCancel(); } if (_dragSelFrom == item || _dragSelTo == item) { @@ -1034,16 +1027,16 @@ void HistoryInner::itemRemoved(HistoryItem *item) { onUpdateSelected(); } -void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton button) { - dragActionUpdate(screenPos); +void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton button) { + mouseActionUpdate(screenPos); ClickHandlerPtr activated = ClickHandler::unpressed(); - if (_dragAction == Dragging) { + if (_mouseAction == MouseAction::Dragging) { activated.clear(); - } else if (HistoryItem *pressed = App::pressedLinkItem()) { + } else if (auto pressed = App::pressedLinkItem()) { // if we are in selecting items mode perhaps we want to // toggle selection instead of activating the pressed link - if (_dragAction == PrepareDrag && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection && button != Qt::RightButton) { + if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection && button != Qt::RightButton) { if (HistoryMedia *media = pressed->getMedia()) { if (media->toggleSelectionByHandlerClick(activated)) { activated.clear(); @@ -1059,52 +1052,52 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but _wasSelectedText = false; if (activated) { - dragActionCancel(); + mouseActionCancel(); App::activateClickHandler(activated, button); return; } - if (_dragAction == PrepareSelect && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { - SelectedItems::iterator i = _selected.find(_dragItem); - if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0) { + if (_mouseAction == MouseAction::PrepareSelect && !_pressWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { + SelectedItems::iterator i = _selected.find(_mouseActionItem); + if (i == _selected.cend() && !_mouseActionItem->serviceMsg() && _mouseActionItem->id > 0) { if (_selected.size() < MaxSelectedItems) { if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { _selected.clear(); } - _selected.insert(_dragItem, FullSelection); + _selected.insert(_mouseActionItem, FullSelection); } } else { _selected.erase(i); } - repaintItem(_dragItem); - } else if (_dragAction == PrepareDrag && !_dragWasInactive && button != Qt::RightButton) { - SelectedItems::iterator i = _selected.find(_dragItem); + repaintItem(_mouseActionItem); + } else if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && button != Qt::RightButton) { + SelectedItems::iterator i = _selected.find(_mouseActionItem); if (i != _selected.cend() && i.value() == FullSelection) { _selected.erase(i); - repaintItem(_dragItem); - } else if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { + repaintItem(_mouseActionItem); + } else if (i == _selected.cend() && !_mouseActionItem->serviceMsg() && _mouseActionItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { if (_selected.size() < MaxSelectedItems) { - _selected.insert(_dragItem, FullSelection); - repaintItem(_dragItem); + _selected.insert(_mouseActionItem, FullSelection); + repaintItem(_mouseActionItem); } } else { _selected.clear(); update(); } - } else if (_dragAction == Selecting) { + } else if (_mouseAction == MouseAction::Selecting) { if (_dragSelFrom && _dragSelTo) { applyDragSelection(); _dragSelFrom = _dragSelTo = 0; - } else if (!_selected.isEmpty() && !_dragWasInactive) { + } else if (!_selected.isEmpty() && !_pressWasInactive) { auto sel = _selected.cbegin().value(); if (sel != FullSelection && sel.from == sel.to) { _selected.clear(); - if (App::wnd()) App::wnd()->setInnerFocus(); + App::wnd()->setInnerFocus(); } } } - _dragAction = NoDrag; - _dragItem = 0; - _dragSelType = TextSelectType::Letters; + _mouseAction = MouseAction::None; + _mouseActionItem = nullptr; + _mouseSelectType = TextSelectType::Letters; _widget->noSelectingScroll(); _widget->updateTopBarSelection(); @@ -1116,7 +1109,7 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but } void HistoryInner::mouseReleaseEvent(QMouseEvent *e) { - dragActionFinish(e->globalPos(), e->button()); + mouseActionFinish(e->globalPos(), e->button()); if (!rect().contains(e->pos())) { leaveEvent(e); } @@ -1125,22 +1118,22 @@ void HistoryInner::mouseReleaseEvent(QMouseEvent *e) { void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) { if (!_history) return; - dragActionStart(e->globalPos(), e->button()); - if (((_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) || (_dragAction == NoDrag && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection))) && _dragSelType == TextSelectType::Letters && _dragItem) { + mouseActionStart(e->globalPos(), e->button()); + if (((_mouseAction == MouseAction::Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) || (_mouseAction == MouseAction::None && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection))) && _mouseSelectType == TextSelectType::Letters && _mouseActionItem) { HistoryStateRequest request; request.flags |= Text::StateRequest::Flag::LookupSymbol; - auto dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request); + auto dragState = _mouseActionItem->getState(_dragStartPosition, request); if (dragState.cursor == HistoryInTextCursorState) { - _dragSymbol = dragState.symbol; - _dragSelType = TextSelectType::Words; - if (_dragAction == NoDrag) { - _dragAction = Selecting; + _mouseTextSymbol = dragState.symbol; + _mouseSelectType = TextSelectType::Words; + if (_mouseAction == MouseAction::None) { + _mouseAction = MouseAction::Selecting; TextSelection selStatus = { dragState.symbol, dragState.symbol }; if (!_selected.isEmpty()) { repaintItem(_selected.cbegin().key()); _selected.clear(); } - _selected.insert(_dragItem, selStatus); + _selected.insert(_mouseActionItem, selStatus); } mouseMoveEvent(e); @@ -1160,7 +1153,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { _menu = 0; } if (e->reason() == QContextMenuEvent::Mouse) { - dragActionUpdate(e->globalPos()); + mouseActionUpdate(e->globalPos()); } auto selectedState = getSelectionState(); @@ -1181,10 +1174,10 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to; hasSelected = (selTo > selFrom) ? 1 : 0; if (App::mousedItem() && App::mousedItem() == App::hoveredItem()) { - QPoint mousePos(mapMouseToItem(mapFromGlobal(_dragPos), App::mousedItem())); + QPoint mousePos(mapMouseToItem(mapFromGlobal(_mousePosition), App::mousedItem())); HistoryStateRequest request; request.flags |= Text::StateRequest::Flag::LookupSymbol; - auto dragState = App::mousedItem()->getState(mousePos.x(), mousePos.y(), request); + auto dragState = App::mousedItem()->getState(mousePos, request); if (dragState.cursor == HistoryInTextCursorState && dragState.symbol >= selFrom && dragState.symbol < selTo) { isUponSelected = 1; } @@ -1472,7 +1465,7 @@ void HistoryInner::openContextGif() { if (auto item = App::contextItem()) { if (auto media = item->getMedia()) { if (auto document = media->getDocument()) { - App::wnd()->showDocument(document, item); + _controller->window()->showDocument(document, item); } } } @@ -1499,7 +1492,7 @@ void HistoryInner::copyContextText() { void HistoryInner::setToClipboard(const TextWithEntities &forClipboard, QClipboard::Mode mode) { if (auto data = mimeDataFromTextWithEntities(forClipboard)) { - QApplication::clipboard()->setMimeData(data, mode); + QApplication::clipboard()->setMimeData(data.release(), mode); } } @@ -1510,7 +1503,7 @@ void HistoryInner::resizeEvent(QResizeEvent *e) { TextWithEntities HistoryInner::getSelectedText() const { SelectedItems sel = _selected; - if (_dragAction == Selecting && _dragSelFrom && _dragSelTo) { + if (_mouseAction == MouseAction::Selecting && _dragSelFrom && _dragSelTo) { applyDragSelection(&sel); } @@ -1813,14 +1806,14 @@ void HistoryInner::updateSize() { if (width() != _scroll->width() || height() != newHeight) { resize(_scroll->width(), newHeight); - dragActionUpdate(QCursor::pos()); + mouseActionUpdate(QCursor::pos()); } else { update(); } } void HistoryInner::enterEventHook(QEvent *e) { - dragActionUpdate(QCursor::pos()); + mouseActionUpdate(QCursor::pos()); return TWidget::enterEventHook(e); } @@ -1840,7 +1833,7 @@ void HistoryInner::leaveEventHook(QEvent *e) { HistoryInner::~HistoryInner() { delete _menu; - _dragAction = NoDrag; + _mouseAction = MouseAction::None; } bool HistoryInner::focusNextPrevChild(bool next) { @@ -1992,7 +1985,7 @@ void HistoryInner::selectItem(HistoryItem *item) { void HistoryInner::onTouchSelect() { _touchSelect = true; - dragActionStart(_touchPos); + mouseActionStart(_touchPos, Qt::LeftButton); } void HistoryInner::onUpdateSelected() { @@ -2000,7 +1993,7 @@ void HistoryInner::onUpdateSelected() { return; } - auto mousePos = mapFromGlobal(_dragPos); + auto mousePos = mapFromGlobal(_mousePosition); auto point = _widget->clampMousePosition(mousePos); HistoryBlock *block = 0; @@ -2014,7 +2007,7 @@ void HistoryInner::onUpdateSelected() { App::mousedItem(item); m = mapMouseToItem(point, item); - if (item->hasPoint(m.x(), m.y())) { + if (item->hasPoint(m)) { if (App::hoveredItem() != item) { repaintItem(App::hoveredItem()); App::hoveredItem(item); @@ -2025,25 +2018,25 @@ void HistoryInner::onUpdateSelected() { App::hoveredItem(0); } } - if (_dragItem && _dragItem->detached()) { - dragActionCancel(); + if (_mouseActionItem && _mouseActionItem->detached()) { + mouseActionCancel(); } HistoryTextState dragState; ClickHandlerHost *lnkhost = nullptr; - bool selectingText = (item == _dragItem && item == App::hoveredItem() && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection); + bool selectingText = (item == _mouseActionItem && item == App::hoveredItem() && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection); if (point.y() < _historyPaddingTop) { if (_botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) { - dragState = _botAbout->info->text.getState(point.x() - _botAbout->rect.left() - st::msgPadding.left(), point.y() - _botAbout->rect.top() - st::msgPadding.top() - st::botDescSkip - st::msgNameFont->height, _botAbout->width); + dragState = _botAbout->info->text.getState(point - _botAbout->rect.topLeft() - QPoint(st::msgPadding.left(), st::msgPadding.top() + st::botDescSkip + st::msgNameFont->height), _botAbout->width); lnkhost = _botAbout.get(); } } else if (item) { - if (item != _dragItem || (m - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()) { - if (_dragAction == PrepareDrag) { - _dragAction = Dragging; - QTimer::singleShot(1, this, SLOT(onDragExec())); - } else if (_dragAction == PrepareSelect) { - _dragAction = Selecting; + if (item != _mouseActionItem || (m - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) { + if (_mouseAction == MouseAction::PrepareDrag) { + _mouseAction = MouseAction::Dragging; + InvokeQueued(this, [this] { performDrag(); }); + } else if (_mouseAction == MouseAction::PrepareSelect) { + _mouseAction = MouseAction::Selecting; } } @@ -2098,12 +2091,12 @@ void HistoryInner::onUpdateSelected() { }); if (!dragState.link) { HistoryStateRequest request; - if (_dragAction == Selecting) { + if (_mouseAction == MouseAction::Selecting) { request.flags |= Text::StateRequest::Flag::LookupSymbol; } else { selectingText = false; } - dragState = item->getState(m.x(), m.y(), request); + dragState = item->getState(m, request); lnkhost = item; if (!dragState.link && m.x() >= st::historyPhotoLeft && m.x() < st::historyPhotoLeft + st::msgPhotoSize) { if (auto msg = item->toHistoryMessage()) { @@ -2128,7 +2121,7 @@ void HistoryInner::onUpdateSelected() { } } auto lnkChanged = ClickHandler::setActive(dragState.link, lnkhost); - if (lnkChanged || dragState.cursor != _dragCursorState) { + if (lnkChanged || dragState.cursor != _mouseCursorState) { Ui::Tooltip::Hide(); } if (dragState.link || dragState.cursor == HistoryInDateCursorState || dragState.cursor == HistoryInForwardedCursorState) { @@ -2136,27 +2129,27 @@ void HistoryInner::onUpdateSelected() { } Qt::CursorShape cur = style::cur_default; - if (_dragAction == NoDrag) { - _dragCursorState = dragState.cursor; + if (_mouseAction == MouseAction::None) { + _mouseCursorState = dragState.cursor; if (dragState.link) { cur = style::cur_pointer; - } else if (_dragCursorState == HistoryInTextCursorState && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) { + } else if (_mouseCursorState == HistoryInTextCursorState && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) { cur = style::cur_text; - } else if (_dragCursorState == HistoryInDateCursorState) { + } else if (_mouseCursorState == HistoryInDateCursorState) { // cur = style::cur_cross; } } else if (item) { - if (_dragAction == Selecting) { + if (_mouseAction == MouseAction::Selecting) { auto canSelectMany = (_history != nullptr); if (selectingText) { uint16 second = dragState.symbol; - if (dragState.afterSymbol && _dragSelType == TextSelectType::Letters) { + if (dragState.afterSymbol && _mouseSelectType == TextSelectType::Letters) { ++second; } - auto selState = _dragItem->adjustSelection({ qMin(second, _dragSymbol), qMax(second, _dragSymbol) }, _dragSelType); - if (_selected[_dragItem] != selState) { - _selected[_dragItem] = selState; - repaintItem(_dragItem); + auto selState = _mouseActionItem->adjustSelection({ qMin(second, _mouseTextSymbol), qMax(second, _mouseTextSymbol) }, _mouseSelectType); + if (_selected[_mouseActionItem] != selState) { + _selected[_mouseActionItem] = selState; + repaintItem(_mouseActionItem); } if (!_wasSelectedText && (selState == FullSelection || selState.from != selState.to)) { _wasSelectedText = true; @@ -2164,20 +2157,20 @@ void HistoryInner::onUpdateSelected() { } updateDragSelection(0, 0, false); } else if (canSelectMany) { - auto selectingDown = (itemTop(_dragItem) < itemTop(item)) || (_dragItem == item && _dragStartPos.y() < m.y()); - auto dragSelFrom = _dragItem, dragSelTo = item; - if (!dragSelFrom->hasPoint(_dragStartPos.x(), _dragStartPos.y())) { // maybe exclude dragSelFrom + auto selectingDown = (itemTop(_mouseActionItem) < itemTop(item)) || (_mouseActionItem == item && _dragStartPosition.y() < m.y()); + auto dragSelFrom = _mouseActionItem, dragSelTo = item; + if (!dragSelFrom->hasPoint(_dragStartPosition)) { // maybe exclude dragSelFrom if (selectingDown) { - if (_dragStartPos.y() >= dragSelFrom->height() - dragSelFrom->marginBottom() || ((item == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance() || m.y() < dragSelFrom->marginTop()))) { + if (_dragStartPosition.y() >= dragSelFrom->height() - dragSelFrom->marginBottom() || ((item == dragSelFrom) && (m.y() < _dragStartPosition.y() + QApplication::startDragDistance() || m.y() < dragSelFrom->marginTop()))) { dragSelFrom = (dragSelFrom == dragSelTo) ? 0 : nextItem(dragSelFrom); } } else { - if (_dragStartPos.y() < dragSelFrom->marginTop() || ((item == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance() || m.y() >= dragSelFrom->height() - dragSelFrom->marginBottom()))) { + if (_dragStartPosition.y() < dragSelFrom->marginTop() || ((item == dragSelFrom) && (m.y() >= _dragStartPosition.y() - QApplication::startDragDistance() || m.y() >= dragSelFrom->height() - dragSelFrom->marginBottom()))) { dragSelFrom = (dragSelFrom == dragSelTo) ? 0 : prevItem(dragSelFrom); } } } - if (_dragItem != item) { // maybe exclude dragSelTo + if (_mouseActionItem != item) { // maybe exclude dragSelTo if (selectingDown) { if (m.y() < dragSelTo->marginTop()) { dragSelTo = (dragSelFrom == dragSelTo) ? 0 : prevItem(dragSelTo); @@ -2199,12 +2192,12 @@ void HistoryInner::onUpdateSelected() { } updateDragSelection(dragSelFrom, dragSelTo, dragSelecting); } - } else if (_dragAction == Dragging) { + } else if (_mouseAction == MouseAction::Dragging) { } if (ClickHandler::getPressed()) { cur = style::cur_pointer; - } else if (_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { + } else if (_mouseAction == MouseAction::Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { if (!_dragSelFrom || !_dragSelTo) { cur = style::cur_text; } @@ -2216,19 +2209,19 @@ void HistoryInner::onUpdateSelected() { if (!pressedItem->detached()) { if (pressedItem->history() == _history || pressedItem->history() == _migrated) { auto adjustedPoint = mapMouseToItem(point, pressedItem); - pressedItem->updatePressed(adjustedPoint.x(), adjustedPoint.y()); + pressedItem->updatePressed(adjustedPoint); } } } - if (_dragAction == Selecting) { + if (_mouseAction == MouseAction::Selecting) { _widget->checkSelectingScroll(mousePos); } else { updateDragSelection(0, 0, false); _widget->noSelectingScroll(); } - if (_dragAction == NoDrag && (lnkChanged || cur != _cursor)) { + if (_mouseAction == MouseAction::None && (lnkChanged || cur != _cursor)) { setCursor(_cursor = cur); } } @@ -2414,7 +2407,7 @@ void HistoryInner::applyDragSelection(SelectedItems *toItems) const { } QString HistoryInner::tooltipText() const { - if (_dragCursorState == HistoryInDateCursorState && _dragAction == NoDrag) { + if (_mouseCursorState == HistoryInDateCursorState && _mouseAction == MouseAction::None) { if (App::hoveredItem()) { auto dateText = App::hoveredItem()->date.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat)); if (auto edited = App::hoveredItem()->Get()) { @@ -2425,7 +2418,7 @@ QString HistoryInner::tooltipText() const { } return dateText; } - } else if (_dragCursorState == HistoryInForwardedCursorState && _dragAction == NoDrag) { + } else if (_mouseCursorState == HistoryInForwardedCursorState && _mouseAction == MouseAction::None) { if (App::hoveredItem()) { if (auto forwarded = App::hoveredItem()->Get()) { return forwarded->_text.originalText(AllTextSelection, ExpandLinksNone); @@ -2438,14 +2431,14 @@ QString HistoryInner::tooltipText() const { } QPoint HistoryInner::tooltipPos() const { - return _dragPos; + return _mousePosition; } void HistoryInner::onParentGeometryChanged() { auto mousePos = QCursor::pos(); auto mouseOver = _widget->rect().contains(_widget->mapFromGlobal(mousePos)); - auto needToUpdate = (_dragAction != NoDrag || _touchScroll || mouseOver); + auto needToUpdate = (_mouseAction != MouseAction::None || _touchScroll || mouseOver); if (needToUpdate) { - dragActionUpdate(mousePos); + mouseActionUpdate(mousePos); } } diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index 6d329e8d8..1374d0ffb 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -44,11 +44,6 @@ public: TextWithEntities getSelectedText() const; - void dragActionStart(const QPoint &screenPos, Qt::MouseButton button = Qt::LeftButton); - void dragActionUpdate(const QPoint &screenPos); - void dragActionFinish(const QPoint &screenPos, Qt::MouseButton button = Qt::LeftButton); - void dragActionCancel(); - void touchScrollUpdated(const QPoint &screenPos); QPoint mapMouseToItem(QPoint p, HistoryItem *item); @@ -125,13 +120,26 @@ public slots: void onMenuDestroy(QObject *obj); void onTouchSelect(); void onTouchScrollTimer(); - void onDragExec(); private slots: void onScrollDateCheck(); void onScrollDateHideByTimer(); private: + enum class MouseAction { + None, + PrepareDrag, + Dragging, + PrepareSelect, + Selecting, + }; + + void mouseActionStart(const QPoint &screenPos, Qt::MouseButton button); + void mouseActionUpdate(const QPoint &screenPos); + void mouseActionFinish(const QPoint &screenPos, Qt::MouseButton button); + void mouseActionCancel(); + void performDrag(); + void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false); void itemRemoved(HistoryItem *item); @@ -207,20 +215,14 @@ private: return (_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems()); } - enum DragAction { - NoDrag = 0x00, - PrepareDrag = 0x01, - Dragging = 0x02, - PrepareSelect = 0x03, - Selecting = 0x04, - }; - DragAction _dragAction = NoDrag; - TextSelectType _dragSelType = TextSelectType::Letters; - QPoint _dragStartPos, _dragPos; - HistoryItem *_dragItem = nullptr; - HistoryCursorState _dragCursorState = HistoryDefaultCursorState; - uint16 _dragSymbol = 0; - bool _dragWasInactive = false; + MouseAction _mouseAction = MouseAction::None; + TextSelectType _mouseSelectType = TextSelectType::Letters; + QPoint _dragStartPosition; + QPoint _mousePosition; + HistoryItem *_mouseActionItem = nullptr; + HistoryCursorState _mouseCursorState = HistoryDefaultCursorState; + uint16 _mouseTextSymbol = 0; + bool _pressWasInactive = false; QPoint _trippleClickPoint; QTimer _trippleClickTimer; @@ -232,7 +234,7 @@ private: bool _dragSelecting = false; bool _wasSelectedText = false; // was some text selected in current drag action - // scroll by touch support (at least Windows Surface tablets) + // scroll by touch support (at least Windows Surface tablets) bool _touchScroll = false; bool _touchSelect = false; bool _touchInProgress = false; diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index a8408f37c..f1292a114 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -244,7 +244,7 @@ void ReplyKeyboard::paint(Painter &p, int outerWidth, const QRect &clip, TimeMs } } -ClickHandlerPtr ReplyKeyboard::getState(int x, int y) const { +ClickHandlerPtr ReplyKeyboard::getState(QPoint point) const { t_assert(_width > 0); for_const (auto &row, _rows) { @@ -254,8 +254,8 @@ ClickHandlerPtr ReplyKeyboard::getState(int x, int y) const { // just ignore the buttons that didn't layout well if (rect.x() + rect.width() > _width) break; - if (rect.contains(x, y)) { - _savedCoords = QPoint(x, y); + if (rect.contains(point)) { + _savedCoords = point; return button.link; } } diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index fa548c9a5..21c9947e7 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -298,7 +298,7 @@ public: int buttonHeight() const; virtual int buttonRadius() const = 0; - virtual void repaint(const HistoryItem *item) const = 0; + virtual void repaint(gsl::not_null item) const = 0; virtual ~Style() { } @@ -330,7 +330,7 @@ public: int naturalHeight() const; void paint(Painter &p, int outerWidth, const QRect &clip, TimeMs ms) const; - ClickHandlerPtr getState(int x, int y) const; + ClickHandlerPtr getState(QPoint point) const; void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active); void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed); @@ -629,12 +629,12 @@ public: virtual bool needCheck() const { return out() || (id < 0 && history()->peer->isSelf()); } - virtual bool hasPoint(int x, int y) const { + virtual bool hasPoint(QPoint point) const { return false; } - virtual HistoryTextState getState(int x, int y, HistoryStateRequest request) const = 0; - virtual void updatePressed(int x, int y) { + virtual HistoryTextState getState(QPoint point, HistoryStateRequest request) const = 0; + virtual void updatePressed(QPoint point) { } virtual TextSelection adjustSelection(TextSelection selection, TextSelectType type) const { @@ -745,14 +745,14 @@ public: virtual int timeWidth() const { return 0; } - virtual bool pointInTime(int32 right, int32 bottom, int x, int y, InfoDisplayType type) const { + virtual bool pointInTime(int right, int bottom, QPoint point, InfoDisplayType type) const { return false; } - int32 skipBlockWidth() const { + int skipBlockWidth() const { return st::msgDateSpace + infoWidth() - st::msgDateDelta.x(); } - int32 skipBlockHeight() const { + int skipBlockHeight() const { return st::msgDateFont->height - st::msgDateDelta.y(); } QString skipBlock() const { diff --git a/Telegram/SourceFiles/history/history_media.h b/Telegram/SourceFiles/history/history_media.h index 0875371d8..1a7bb8e99 100644 --- a/Telegram/SourceFiles/history/history_media.h +++ b/Telegram/SourceFiles/history/history_media.h @@ -46,8 +46,8 @@ public: } virtual TextWithEntities selectedText(TextSelection selection) const = 0; - bool hasPoint(int x, int y) const { - return (x >= 0 && y >= 0 && x < _width && y < _height); + bool hasPoint(QPoint point) const { + return QRect(0, 0, _width, _height).contains(point); } virtual bool isDisplayed() const { @@ -65,8 +65,8 @@ public: return _height; } virtual void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const = 0; - virtual HistoryTextState getState(int x, int y, HistoryStateRequest request) const = 0; - virtual void updatePressed(int x, int y) { + virtual HistoryTextState getState(QPoint point, HistoryStateRequest request) const = 0; + virtual void updatePressed(QPoint point) { } virtual int32 addToOverview(AddToOverviewMethod method) { diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index 0db124ef3..eeb13d241 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -462,7 +462,7 @@ void HistoryPhoto::draw(Painter &p, const QRect &r, TextSelection selection, Tim } } -HistoryTextState HistoryPhoto::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryPhoto::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return result; @@ -478,8 +478,8 @@ HistoryTextState HistoryPhoto::getState(int x, int y, HistoryStateRequest reques if (isBubbleBottom()) { height -= st::msgPadding.bottom(); } - if (x >= st::msgPadding.left() && y >= height && x < st::msgPadding.left() + captionw && y < _height) { - result = _caption.getState(x - st::msgPadding.left(), y - height, captionw, request.forText()); + if (QRect(st::msgPadding.left(), height, captionw, _height - height).contains(point)) { + result = _caption.getState(point - QPoint(st::msgPadding.left(), height), captionw, request.forText()); return result; } height -= st::mediaCaptionSkip; @@ -487,13 +487,13 @@ HistoryTextState HistoryPhoto::getState(int x, int y, HistoryStateRequest reques width -= st::mediaPadding.left() + st::mediaPadding.right(); height -= skipy + st::mediaPadding.bottom(); } - if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { + if (QRect(skipx, skipy, width, height).contains(point)) { if (_data->uploading()) { result.link = _cancell; } else if (_data->loaded()) { result.link = _openl; } else if (_data->loading()) { - DelayedStorageImage *delayed = _data->full->toDelayedStorageImage(); + auto delayed = _data->full->toDelayedStorageImage(); if (!delayed || !delayed->location().isNull()) { result.link = _cancell; } @@ -501,9 +501,9 @@ HistoryTextState HistoryPhoto::getState(int x, int y, HistoryStateRequest reques result.link = _savel; } if (_caption.isEmpty() && _parent->getMedia() == this) { - int32 fullRight = skipx + width, fullBottom = skipy + height; - bool inDate = _parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); - if (inDate) { + auto fullRight = skipx + width; + auto fullBottom = skipy + height; + if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayOverImage)) { result.cursor = HistoryInDateCursorState; } } @@ -826,7 +826,7 @@ void HistoryVideo::draw(Painter &p, const QRect &r, TextSelection selection, Tim } } -HistoryTextState HistoryVideo::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryVideo::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return result; @@ -845,24 +845,24 @@ HistoryTextState HistoryVideo::getState(int x, int y, HistoryStateRequest reques if (isBubbleBottom()) { height -= st::msgPadding.bottom(); } - if (x >= st::msgPadding.left() && y >= height && x < st::msgPadding.left() + captionw && y < _height) { - result = _caption.getState(x - st::msgPadding.left(), y - height, captionw, request.forText()); + if (QRect(st::msgPadding.left(), height, captionw, _height - height).contains(point)) { + result = _caption.getState(point - QPoint(st::msgPadding.left(), height), captionw, request.forText()); } height -= st::mediaCaptionSkip; } width -= st::mediaPadding.left() + st::mediaPadding.right(); height -= skipy + st::mediaPadding.bottom(); } - if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { + if (QRect(skipx, skipy, width, height).contains(point)) { if (_data->uploading()) { result.link = _cancell; } else { result.link = loaded ? _openl : (_data->loading() ? _cancell : _savel); } if (_caption.isEmpty() && _parent->getMedia() == this) { - int32 fullRight = skipx + width, fullBottom = skipy + height; - bool inDate = _parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); - if (inDate) { + auto fullRight = skipx + width; + auto fullBottom = skipy + height; + if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayOverImage)) { result.cursor = HistoryInDateCursorState; } } @@ -1380,7 +1380,7 @@ void HistoryDocument::draw(Painter &p, const QRect &r, TextSelection selection, } } -HistoryTextState HistoryDocument::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryDocument::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return result; @@ -1401,13 +1401,13 @@ HistoryTextState HistoryDocument::getState(int x, int y, HistoryStateRequest req QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top() - topMinus, st::msgFileThumbSize, st::msgFileThumbSize, _width)); - if ((_data->loading() || _data->uploading() || !loaded) && rthumb.contains(x, y)) { + if ((_data->loading() || _data->uploading() || !loaded) && rthumb.contains(point)) { result.link = (_data->loading() || _data->uploading()) ? _cancell : _savel; return result; } if (_data->status != FileUploadFailed) { - if (rtlrect(nameleft, linktop, thumbed->_linkw, st::semiboldFont->height, _width).contains(x, y)) { + if (rtlrect(nameleft, linktop, thumbed->_linkw, st::semiboldFont->height, _width).contains(point)) { result.link = (_data->loading() || _data->uploading()) ? thumbed->_linkcancell : thumbed->_linksavel; return result; } @@ -1419,7 +1419,7 @@ HistoryTextState HistoryDocument::getState(int x, int y, HistoryStateRequest req bottom = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom() - topMinus; QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top() - topMinus, st::msgFileSize, st::msgFileSize, _width)); - if ((_data->loading() || _data->uploading() || !loaded) && inner.contains(x, y)) { + if ((_data->loading() || _data->uploading() || !loaded) && inner.contains(point)) { result.link = (_data->loading() || _data->uploading()) ? _cancell : _savel; return result; } @@ -1428,11 +1428,11 @@ HistoryTextState HistoryDocument::getState(int x, int y, HistoryStateRequest req if (auto voice = Get()) { auto namewidth = _width - nameleft - nameright; auto waveformbottom = st::msgFilePadding.top() - topMinus + st::msgWaveformMax + st::msgWaveformMin; - if (x >= nameleft && x < nameleft + namewidth && y >= nametop && y < waveformbottom) { + if (QRect(nameleft, nametop, namewidth, waveformbottom - nametop).contains(point)) { auto state = Media::Player::mixer()->currentState(AudioMsgId::Type::Voice); if (state.id == AudioMsgId(_data, _parent->fullId()) && !Media::Player::IsStoppedOrStopping(state.state)) { if (!voice->seeking()) { - voice->setSeekingStart((x - nameleft) / float64(namewidth)); + voice->setSeekingStart((point.x() - nameleft) / float64(namewidth)); } result.link = voice->_seekl; return result; @@ -1440,10 +1440,10 @@ HistoryTextState HistoryDocument::getState(int x, int y, HistoryStateRequest req } } - int32 height = _height; + auto height = _height; if (auto captioned = Get()) { - if (y >= bottom) { - result = captioned->_caption.getState(x - st::msgPadding.left(), y - bottom, _width - st::msgPadding.left() - st::msgPadding.right(), request.forText()); + if (point.y() >= bottom) { + result = captioned->_caption.getState(point - QPoint(st::msgPadding.left(), bottom), _width - st::msgPadding.left() - st::msgPadding.right(), request.forText()); return result; } auto captionw = _width - st::msgPadding.left() - st::msgPadding.right(); @@ -1452,14 +1452,14 @@ HistoryTextState HistoryDocument::getState(int x, int y, HistoryStateRequest req height -= st::msgPadding.bottom(); } } - if (x >= 0 && y >= 0 && x < _width && y < height && !_data->loading() && !_data->uploading() && _data->isValid()) { + if (QRect(0, 0, _width, height).contains(point) && !_data->loading() && !_data->uploading() && _data->isValid()) { result.link = _openl; return result; } return result; } -void HistoryDocument::updatePressed(int x, int y) { +void HistoryDocument::updatePressed(QPoint point) { if (auto voice = Get()) { if (voice->seeking()) { auto nameleft = 0, nameright = 0; @@ -1470,7 +1470,7 @@ void HistoryDocument::updatePressed(int x, int y) { nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right(); nameright = st::msgFilePadding.left(); } - voice->setSeekingCurrent(snap((x - nameleft) / float64(_width - nameleft - nameright), 0., 1.)); + voice->setSeekingCurrent(snap((point.x() - nameleft) / float64(_width - nameleft - nameright), 0., 1.)); Ui::repaintHistoryItem(_parent); } } @@ -2157,7 +2157,7 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM } } -HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryGif::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return result; @@ -2173,8 +2173,8 @@ HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request) if (isBubbleBottom()) { height -= st::msgPadding.bottom(); } - if (x >= st::msgPadding.left() && y >= height && x < st::msgPadding.left() + captionw && y < _height) { - result = _caption.getState(x - st::msgPadding.left(), y - height, captionw, request.forText()); + if (QRect(st::msgPadding.left(), height, captionw, _height - height).contains(point)) { + result = _caption.getState(point - QPoint(st::msgPadding.left(), height), captionw, request.forText()); return result; } height -= st::mediaCaptionSkip; @@ -2217,13 +2217,13 @@ HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request) if (rtl()) rectx = _width - rectx - rectw; if (forwarded) { - if (x >= rectx && y >= recty && x < rectx + rectw && y < recty + st::msgReplyPadding.top() + forwardedHeight) { + if (QRect(rectx, recty, rectw, st::msgReplyPadding.top() + forwardedHeight).contains(point)) { auto breakEverywhere = (forwardedHeightReal > forwardedHeight); auto textRequest = request.forText(); if (breakEverywhere) { textRequest.flags |= Text::StateRequest::Flag::BreakEverywhere; } - result = forwarded->_text.getState(x - rectx - st::msgReplyPadding.left(), y - recty - st::msgReplyPadding.top(), innerw, textRequest); + result = forwarded->_text.getState(point - QPoint(rectx + st::msgReplyPadding.left(), recty + st::msgReplyPadding.top()), innerw, textRequest); result.symbol = 0; result.afterSymbol = false; if (breakEverywhere) { @@ -2236,23 +2236,23 @@ HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request) recty += forwardedHeight; recth -= forwardedHeight; } else if (via) { - int viah = st::msgReplyPadding.top() + st::msgServiceNameFont->height + (reply ? 0 : st::msgReplyPadding.bottom()); - if (x >= rectx && y >= recty && x < rectx + rectw && y < recty + viah) { + auto viah = st::msgReplyPadding.top() + st::msgServiceNameFont->height + (reply ? 0 : st::msgReplyPadding.bottom()); + if (QRect(rectx, recty, rectw, viah).contains(point)) { result.link = via->_lnk; return result; } - int skip = st::msgServiceNameFont->height + (reply ? 2 * st::msgReplyPadding.top() : 0); + auto skip = st::msgServiceNameFont->height + (reply ? 2 * st::msgReplyPadding.top() : 0); recty += skip; recth -= skip; } if (reply) { - if (x >= rectx && y >= recty && x < rectx + rectw && y < recty + recth) { + if (QRect(rectx, recty, rectw, recth).contains(point)) { result.link = reply->replyToLink(); return result; } } } - if (x >= usex + skipx && y >= skipy && x < usex + skipx + usew && y < skipy + height) { + if (QRect(usex + skipx, skipy, usew, height).contains(point)) { if (_data->uploading()) { result.link = _cancell; } else if (!_gif || !cAutoPlayGif() || _data->isRoundVideo()) { @@ -2261,9 +2261,9 @@ HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request) result.link = _openInMediaviewLink; } if (!isChildMedia) { - int32 fullRight = usex + skipx + usew, fullBottom = skipy + height; - bool inDate = _parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); - if (inDate) { + auto fullRight = usex + skipx + usew; + auto fullBottom = skipy + height; + if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayOverImage)) { result.cursor = HistoryInDateCursorState; } } @@ -2630,7 +2630,7 @@ void HistorySticker::draw(Painter &p, const QRect &r, TextSelection selection, T } } -HistoryTextState HistorySticker::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistorySticker::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return result; @@ -2666,7 +2666,7 @@ HistoryTextState HistorySticker::getState(int x, int y, HistoryStateRequest requ if (via) { int viah = st::msgReplyPadding.top() + st::msgServiceNameFont->height + (reply ? 0 : st::msgReplyPadding.bottom()); - if (x >= rectx && y >= recty && x < rectx + rectw && y < recty + viah) { + if (QRect(rectx, recty, rectw, viah).contains(point)) { result.link = via->_lnk; return result; } @@ -2675,21 +2675,21 @@ HistoryTextState HistorySticker::getState(int x, int y, HistoryStateRequest requ recth -= skip; } if (reply) { - if (x >= rectx && y >= recty && x < rectx + rectw && y < recty + recth) { + if (QRect(rectx, recty, rectw, recth).contains(point)) { result.link = reply->replyToLink(); return result; } } } if (_parent->getMedia() == this) { - bool inDate = _parent->pointInTime(usex + usew, _height, x, y, InfoDisplayOverImage); - if (inDate) { + if (_parent->pointInTime(usex + usew, _height, point, InfoDisplayOverImage)) { result.cursor = HistoryInDateCursorState; } } - int pixLeft = usex + (usew - _pixw) / 2, pixTop = (_minh - _pixh) / 2; - if (x >= pixLeft && x < pixLeft + _pixw && y >= pixTop && y < pixTop + _pixh) { + auto pixLeft = usex + (usew - _pixw) / 2; + auto pixTop = (_minh - _pixh) / 2; + if (QRect(pixLeft, pixTop, _pixw, _pixh).contains(point)) { result.link = _packLink; return result; } @@ -2885,7 +2885,7 @@ void HistoryContact::draw(Painter &p, const QRect &r, TextSelection selection, T p.drawTextLeft(nameleft, statustop, width, _phone); } -HistoryTextState HistoryContact::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryContact::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; bool out = _parent->out(), isPost = _parent->isPost(), outbg = out && !isPost; @@ -2894,12 +2894,12 @@ HistoryTextState HistoryContact::getState(int x, int y, HistoryStateRequest requ if (_userId) { nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right(); linktop = st::msgFileThumbLinkTop - topMinus; - if (rtlrect(nameleft, linktop, _linkw, st::semiboldFont->height, _width).contains(x, y)) { + if (rtlrect(nameleft, linktop, _linkw, st::semiboldFont->height, _width).contains(point)) { result.link = _linkl; return result; } } - if (x >= 0 && y >= 0 && x < _width && y < _height && _contact) { + if (QRect(0, 0, _width, _height).contains(point) && _contact) { result.link = _contact->openLink(); return result; } @@ -3034,9 +3034,9 @@ void HistoryCall::draw(Painter &p, const QRect &r, TextSelection selection, Time icon.paint(p, width - st::historyCallIconPosition.x() - icon.width(), st::historyCallIconPosition.y() - topMinus, width); } -HistoryTextState HistoryCall::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryCall::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; - if (x >= 0 && y >= 0 && x < _width && y < _height) { + if (QRect(0, 0, _width, _height).contains(point)) { result.link = _link; return result; } @@ -3459,7 +3459,7 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, T } } -HistoryTextState HistoryWebPage::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryWebPage::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return result; @@ -3478,7 +3478,7 @@ HistoryTextState HistoryWebPage::getState(int x, int y, HistoryStateRequest requ auto inThumb = false; if (_asArticle) { int32 pw = qMax(_pixw, int16(lineHeight)); - if (rtlrect(padding.left() + width - pw, 0, pw, _pixh, _width).contains(x, y)) { + if (rtlrect(padding.left() + width - pw, 0, pw, _pixh, _width).contains(point)) { inThumb = true; } width -= pw + st::webPagePhotoDelta; @@ -3488,21 +3488,21 @@ HistoryTextState HistoryWebPage::getState(int x, int y, HistoryStateRequest requ tshift += lineHeight; } if (_titleLines) { - if (y >= tshift && y < tshift + _titleLines * lineHeight) { + if (point.y() >= tshift && point.y() < tshift + _titleLines * lineHeight) { Text::StateRequestElided titleRequest = request.forText(); titleRequest.lines = _titleLines; - result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest); - } else if (y >= tshift + _titleLines * lineHeight) { + result = _title.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, titleRequest); + } else if (point.y() >= tshift + _titleLines * lineHeight) { symbolAdd += _title.length(); } tshift += _titleLines * lineHeight; } if (_descriptionLines) { - if (y >= tshift && y < tshift + _descriptionLines * lineHeight) { + if (point.y() >= tshift && point.y() < tshift + _descriptionLines * lineHeight) { Text::StateRequestElided descriptionRequest = request.forText(); descriptionRequest.lines = _descriptionLines; - result = _description.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, descriptionRequest); - } else if (y >= tshift + _descriptionLines * lineHeight) { + result = _description.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, descriptionRequest); + } else if (point.y() >= tshift + _descriptionLines * lineHeight) { symbolAdd += _description.length(); } tshift += _descriptionLines * lineHeight; @@ -3513,11 +3513,11 @@ HistoryTextState HistoryWebPage::getState(int x, int y, HistoryStateRequest requ auto attachAtTop = !_siteNameWidth && !_titleLines && !_descriptionLines; if (!attachAtTop) tshift += st::mediaInBubbleSkip; - if (x >= padding.left() && x < padding.left() + width && y >= tshift && y < _height - bshift) { + if (QRect(padding.left(), tshift, width, _height - tshift - bshift).contains(point)) { auto attachLeft = padding.left() - bubble.left(); auto attachTop = tshift - bubble.top(); if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth(); - result = _attach->getState(x - attachLeft, y - attachTop, request); + result = _attach->getState(point - QPoint(attachLeft, attachTop), request); if (result.link && !_data->document && _data->photo && _attach->isReadyForOpen()) { if (_data->type == WebPageProfile || _data->type == WebPageVideo) { @@ -3831,7 +3831,7 @@ void HistoryGame::draw(Painter &p, const QRect &r, TextSelection selection, Time } } -HistoryTextState HistoryGame::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryGame::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return result; @@ -3850,21 +3850,21 @@ HistoryTextState HistoryGame::getState(int x, int y, HistoryStateRequest request auto symbolAdd = 0; auto lineHeight = unitedLineHeight(); if (_titleLines) { - if (y >= tshift && y < tshift + _titleLines * lineHeight) { + if (point.y() >= tshift && point.y() < tshift + _titleLines * lineHeight) { Text::StateRequestElided titleRequest = request.forText(); titleRequest.lines = _titleLines; - result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest); - } else if (y >= tshift + _titleLines * lineHeight) { + result = _title.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, titleRequest); + } else if (point.y() >= tshift + _titleLines * lineHeight) { symbolAdd += _title.length(); } tshift += _titleLines * lineHeight; } if (_descriptionLines) { - if (y >= tshift && y < tshift + _descriptionLines * lineHeight) { + if (point.y() >= tshift && point.y() < tshift + _descriptionLines * lineHeight) { Text::StateRequestElided descriptionRequest = request.forText(); descriptionRequest.lines = _descriptionLines; - result = _description.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, descriptionRequest); - } else if (y >= tshift + _descriptionLines * lineHeight) { + result = _description.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, descriptionRequest); + } else if (point.y() >= tshift + _descriptionLines * lineHeight) { symbolAdd += _description.length(); } tshift += _descriptionLines * lineHeight; @@ -3879,11 +3879,11 @@ HistoryTextState HistoryGame::getState(int x, int y, HistoryStateRequest request auto attachTop = tshift - bubble.top(); if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth(); - if (x >= attachLeft && x < attachLeft + _attach->currentWidth() && y >= tshift && y < _height - bshift) { + if (QRect(attachLeft, tshift, _attach->currentWidth(), _height - tshift - bshift).contains(point)) { if (_attach->isReadyForOpen()) { result.link = _openl; } else { - result = _attach->getState(x - attachLeft, y - attachTop, request); + result = _attach->getState(point - QPoint(attachLeft, attachTop), request); } } } @@ -4254,7 +4254,7 @@ void HistoryInvoice::draw(Painter &p, const QRect &r, TextSelection selection, T } } -HistoryTextState HistoryInvoice::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryInvoice::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return result; @@ -4272,19 +4272,19 @@ HistoryTextState HistoryInvoice::getState(int x, int y, HistoryStateRequest requ auto lineHeight = unitedLineHeight(); auto symbolAdd = 0; if (_titleHeight) { - if (y >= tshift && y < tshift + _titleHeight) { + if (point.y() >= tshift && point.y() < tshift + _titleHeight) { Text::StateRequestElided titleRequest = request.forText(); titleRequest.lines = _titleHeight / lineHeight; - result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest); - } else if (y >= tshift + _titleHeight) { + result = _title.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, titleRequest); + } else if (point.y() >= tshift + _titleHeight) { symbolAdd += _title.length(); } tshift += _titleHeight; } if (_descriptionHeight) { - if (y >= tshift && y < tshift + _descriptionHeight) { - result = _description.getStateLeft(x - padding.left(), y - tshift, width, _width, request.forText()); - } else if (y >= tshift + _descriptionHeight) { + if (point.y() >= tshift && point.y() < tshift + _descriptionHeight) { + result = _description.getStateLeft(point - QPoint(padding.left(), tshift), width, _width, request.forText()); + } else if (point.y() >= tshift + _descriptionHeight) { symbolAdd += _description.length(); } tshift += _descriptionHeight; @@ -4297,8 +4297,8 @@ HistoryTextState HistoryInvoice::getState(int x, int y, HistoryStateRequest requ auto attachTop = tshift - bubble.top(); if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth(); - if (x >= attachLeft && x < attachLeft + _attach->currentWidth() && y >= tshift && y < _height - bshift) { - result = _attach->getState(x - attachLeft, y - attachTop, request); + if (QRect(attachLeft, tshift, _attach->currentWidth(), _height - tshift - bshift).contains(point)) { + result = _attach->getState(point - QPoint(attachLeft, attachTop), request); } } @@ -4534,7 +4534,7 @@ void HistoryLocation::draw(Painter &p, const QRect &r, TextSelection selection, } } -HistoryTextState HistoryLocation::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryLocation::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; auto symbolAdd = 0; @@ -4553,23 +4553,23 @@ HistoryTextState HistoryLocation::getState(int x, int y, HistoryStateRequest req } width -= st::mediaPadding.left() + st::mediaPadding.right(); - int32 textw = _width - st::msgPadding.left() - st::msgPadding.right(); + auto textw = _width - st::msgPadding.left() - st::msgPadding.right(); if (!_title.isEmpty()) { auto titleh = qMin(_title.countHeight(textw), 2 * st::webPageTitleFont->height); - if (y >= skipy && y < skipy + titleh) { - result = _title.getStateLeft(x - skipx - st::msgPadding.left(), y - skipy, textw, _width, request.forText()); + if (point.y() >= skipy && point.y() < skipy + titleh) { + result = _title.getStateLeft(point - QPoint(skipx + st::msgPadding.left(), skipy), textw, _width, request.forText()); return result; - } else if (y >= skipy + titleh) { + } else if (point.y() >= skipy + titleh) { symbolAdd += _title.length(); } skipy += titleh; } if (!_description.isEmpty()) { auto descriptionh = qMin(_description.countHeight(textw), 3 * st::webPageDescriptionFont->height); - if (y >= skipy && y < skipy + descriptionh) { - result = _description.getStateLeft(x - skipx - st::msgPadding.left(), y - skipy, textw, _width, request.forText()); - } else if (y >= skipy + descriptionh) { + if (point.y() >= skipy && point.y() < skipy + descriptionh) { + result = _description.getStateLeft(point - QPoint(skipx + st::msgPadding.left(), skipy), textw, _width, request.forText()); + } else if (point.y() >= skipy + descriptionh) { symbolAdd += _description.length(); } skipy += descriptionh; @@ -4579,12 +4579,12 @@ HistoryTextState HistoryLocation::getState(int x, int y, HistoryStateRequest req } height -= skipy + st::mediaPadding.bottom(); } - if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height && _data) { + if (QRect(skipx, skipy, width, height).contains(point) && _data) { result.link = _link; - int32 fullRight = skipx + width, fullBottom = _height - (skipx ? st::mediaPadding.bottom() : 0); - bool inDate = _parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); - if (inDate) { + auto fullRight = skipx + width; + auto fullBottom = _height - (skipx ? st::mediaPadding.bottom() : 0); + if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayOverImage)) { result.cursor = HistoryInDateCursorState; } } diff --git a/Telegram/SourceFiles/history/history_media_types.h b/Telegram/SourceFiles/history/history_media_types.h index dea68a9b4..b2626e7f8 100644 --- a/Telegram/SourceFiles/history/history_media_types.h +++ b/Telegram/SourceFiles/history/history_media_types.h @@ -133,7 +133,7 @@ public: int resizeGetHeight(int width) override; void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override { return _caption.adjustSelection(selection, type); @@ -226,7 +226,7 @@ public: int resizeGetHeight(int width) override; void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override { return _caption.adjustSelection(selection, type); @@ -384,8 +384,8 @@ public: int resizeGetHeight(int width) override; void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; - void updatePressed(int x, int y) override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; + void updatePressed(QPoint point) override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override { if (auto captioned = Get()) { @@ -491,7 +491,7 @@ public: int resizeGetHeight(int width) override; void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override { return _caption.adjustSelection(selection, type); @@ -614,7 +614,7 @@ public: int resizeGetHeight(int width) override; void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override { return true; @@ -682,7 +682,7 @@ public: void initDimensions() override; void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override { return true; @@ -744,7 +744,7 @@ public: void initDimensions() override; void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override { return true; @@ -801,7 +801,7 @@ public: int resizeGetHeight(int width) override; void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override; bool hasTextForCopy() const override { @@ -900,7 +900,7 @@ public: int resizeGetHeight(int width) override; void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override; bool isAboveMessage() const override { @@ -1008,7 +1008,7 @@ public: static QString fillAmountAndCurrency(int amount, const QString ¤cy); void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override; bool hasTextForCopy() const override { @@ -1091,7 +1091,7 @@ public: int resizeGetHeight(int32 width) override; void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override; bool hasTextForCopy() const override { diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 628bb1f71..2c279b365 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -350,7 +350,7 @@ const style::TextStyle &HistoryMessage::KeyboardStyle::textStyle() const { return st::serviceTextStyle; } -void HistoryMessage::KeyboardStyle::repaint(const HistoryItem *item) const { +void HistoryMessage::KeyboardStyle::repaint(gsl::not_null item) const { Ui::repaintHistoryItem(item); } @@ -1640,23 +1640,24 @@ int HistoryMessage::performResizeGetHeight() { return _height; } -bool HistoryMessage::hasPoint(int x, int y) const { +bool HistoryMessage::hasPoint(QPoint point) const { auto g = countGeometry(); if (g.width() < 1) { return false; } if (drawBubble()) { - return g.contains(x, y); + return g.contains(point); } else if (_media) { - return _media->hasPoint(x - g.left(), y - g.top()); + return _media->hasPoint(point - g.topLeft()); } else { return false; } } -bool HistoryMessage::pointInTime(int32 right, int32 bottom, int x, int y, InfoDisplayType type) const { - int32 infoRight = right, infoBottom = bottom; +bool HistoryMessage::pointInTime(int right, int bottom, QPoint point, InfoDisplayType type) const { + auto infoRight = right; + auto infoBottom = bottom; switch (type) { case InfoDisplayDefault: infoRight -= st::msgPadding.right() - st::msgDateDelta.x(); @@ -1667,12 +1668,12 @@ bool HistoryMessage::pointInTime(int32 right, int32 bottom, int x, int y, InfoDi infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y(); break; } - int32 dateX = infoRight - HistoryMessage::infoWidth() + HistoryMessage::timeLeft(); - int32 dateY = infoBottom - st::msgDateFont->height; - return QRect(dateX, dateY, HistoryMessage::timeWidth(), st::msgDateFont->height).contains(x, y); + auto dateX = infoRight - HistoryMessage::infoWidth() + HistoryMessage::timeLeft(); + auto dateY = infoBottom - st::msgDateFont->height; + return QRect(dateX, dateY, HistoryMessage::timeWidth(), st::msgDateFont->height).contains(point); } -HistoryTextState HistoryMessage::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryMessage::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; auto g = countGeometry(); @@ -1693,10 +1694,10 @@ HistoryTextState HistoryMessage::getState(int x, int y, HistoryStateRequest requ if (mediaDisplayed && _media->isBubbleTop()) { trect.setY(trect.y() - st::msgPadding.top()); } else { - if (getStateFromName(x, y, trect, &result)) return result; - if (getStateForwardedInfo(x, y, trect, &result, request)) return result; - if (getStateReplyInfo(x, y, trect, &result)) return result; - if (getStateViaBotIdInfo(x, y, trect, &result)) return result; + if (getStateFromName(point, trect, &result)) return result; + if (getStateForwardedInfo(point, trect, &result, request)) return result; + if (getStateReplyInfo(point, trect, &result)) return result; + if (getStateViaBotIdInfo(point, trect, &result)) return result; } if (mediaDisplayed && _media->isBubbleBottom()) { trect.setHeight(trect.height() + st::msgPadding.bottom()); @@ -1709,34 +1710,34 @@ HistoryTextState HistoryMessage::getState(int x, int y, HistoryStateRequest requ auto mediaLeft = trect.x() - st::msgPadding.left(); auto mediaTop = mediaAboveText ? trect.y() : (trect.y() + trect.height() - mediaHeight); - if (y >= mediaTop && y < mediaTop + mediaHeight) { - result = _media->getState(x - mediaLeft, y - mediaTop, request); + if (point.y() >= mediaTop && point.y() < mediaTop + mediaHeight) { + result = _media->getState(point - QPoint(mediaLeft, mediaTop), request); result.symbol += _text.length(); } else { if (mediaAboveText) { trect.setY(trect.y() + mediaHeight); } - getStateText(x, y, trect, &result, request); + getStateText(point, trect, &result, request); } needDateCheck = !_media->customInfoLayout(); } else { - getStateText(x, y, trect, &result, request); + getStateText(point, trect, &result, request); } if (needDateCheck) { - if (HistoryMessage::pointInTime(g.left() + g.width(), g.top() + g.height(), x, y, InfoDisplayDefault)) { + if (HistoryMessage::pointInTime(g.left() + g.width(), g.top() + g.height(), point, InfoDisplayDefault)) { result.cursor = HistoryInDateCursorState; } } } else if (_media) { - result = _media->getState(x - g.left(), y - g.top(), request); + result = _media->getState(point - g.topLeft(), request); result.symbol += _text.length(); } if (keyboard) { auto keyboardTop = g.top() + g.height() + st::msgBotKbButton.margin; - if (QRect(g.left(), keyboardTop, g.width(), keyboardHeight).contains(x, y)) { - result.link = keyboard->getState(x - g.left(), y - keyboardTop); + if (QRect(g.left(), keyboardTop, g.width(), keyboardHeight).contains(point)) { + result.link = keyboard->getState(point - g.topLeft()); return result; } } @@ -1745,7 +1746,7 @@ HistoryTextState HistoryMessage::getState(int x, int y, HistoryStateRequest requ } // Forward to _media. -void HistoryMessage::updatePressed(int x, int y) { +void HistoryMessage::updatePressed(QPoint point) { if (!_media) return; auto g = countGeometry(); @@ -1788,23 +1789,23 @@ void HistoryMessage::updatePressed(int x, int y) { auto mediaHeight = _media->height(); auto mediaLeft = trect.x() - st::msgPadding.left(); auto mediaTop = mediaAboveText ? trect.y() : (trect.y() + trect.height() - mediaHeight); - _media->updatePressed(x - mediaLeft, y - mediaTop); + _media->updatePressed(point - QPoint(mediaLeft, mediaTop)); } } else { - _media->updatePressed(x - g.left(), y - g.top()); + _media->updatePressed(point - g.topLeft()); } } -bool HistoryMessage::getStateFromName(int x, int y, QRect &trect, HistoryTextState *outResult) const { +bool HistoryMessage::getStateFromName(QPoint point, QRect &trect, HistoryTextState *outResult) const { if (displayFromName()) { - if (y >= trect.top() && y < trect.top() + st::msgNameFont->height) { - if (x >= trect.left() && x < trect.left() + trect.width() && x < trect.left() + author()->nameText.maxWidth()) { + if (point.y() >= trect.top() && point.y() < trect.top() + st::msgNameFont->height) { + if (point.x() >= trect.left() && point.x() < trect.left() + trect.width() && point.x() < trect.left() + author()->nameText.maxWidth()) { outResult->link = author()->openLink(); return true; } auto forwarded = Get(); auto via = Get(); - if (via && !forwarded && x >= trect.left() + author()->nameText.maxWidth() + st::msgServiceFont->spacew && x < trect.left() + author()->nameText.maxWidth() + st::msgServiceFont->spacew + via->_width) { + if (via && !forwarded && point.x() >= trect.left() + author()->nameText.maxWidth() + st::msgServiceFont->spacew && point.x() < trect.left() + author()->nameText.maxWidth() + st::msgServiceFont->spacew + via->_width) { outResult->link = via->_lnk; return true; } @@ -1814,17 +1815,17 @@ bool HistoryMessage::getStateFromName(int x, int y, QRect &trect, HistoryTextSta return false; } -bool HistoryMessage::getStateForwardedInfo(int x, int y, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const { +bool HistoryMessage::getStateForwardedInfo(QPoint point, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const { if (displayForwardedFrom()) { auto forwarded = Get(); auto fwdheight = ((forwarded->_text.maxWidth() > trect.width()) ? 2 : 1) * st::semiboldFont->height; - if (y >= trect.top() && y < trect.top() + fwdheight) { + if (point.y() >= trect.top() && point.y() < trect.top() + fwdheight) { auto breakEverywhere = (forwarded->_text.countHeight(trect.width()) > 2 * st::semiboldFont->height); auto textRequest = request.forText(); if (breakEverywhere) { textRequest.flags |= Text::StateRequest::Flag::BreakEverywhere; } - *outResult = forwarded->_text.getState(x - trect.left(), y - trect.top(), trect.width(), textRequest); + *outResult = forwarded->_text.getState(point - trect.topLeft(), trect.width(), textRequest); outResult->symbol = 0; outResult->afterSymbol = false; if (breakEverywhere) { @@ -1839,11 +1840,11 @@ bool HistoryMessage::getStateForwardedInfo(int x, int y, QRect &trect, HistoryTe return false; } -bool HistoryMessage::getStateReplyInfo(int x, int y, QRect &trect, HistoryTextState *outResult) const { +bool HistoryMessage::getStateReplyInfo(QPoint point, QRect &trect, HistoryTextState *outResult) const { if (auto reply = Get()) { int32 h = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - if (y >= trect.top() && y < trect.top() + h) { - if (reply->replyToMsg && y >= trect.top() + st::msgReplyPadding.top() && y < trect.top() + st::msgReplyPadding.top() + st::msgReplyBarSize.height() && x >= trect.left() && x < trect.left() + trect.width()) { + if (point.y() >= trect.top() && point.y() < trect.top() + h) { + if (reply->replyToMsg && QRect(trect.x(), trect.y() + st::msgReplyPadding.top(), trect.width(), st::msgReplyBarSize.height()).contains(point)) { outResult->link = reply->replyToLink(); } return true; @@ -1853,10 +1854,10 @@ bool HistoryMessage::getStateReplyInfo(int x, int y, QRect &trect, HistoryTextSt return false; } -bool HistoryMessage::getStateViaBotIdInfo(int x, int y, QRect &trect, HistoryTextState *outResult) const { +bool HistoryMessage::getStateViaBotIdInfo(QPoint point, QRect &trect, HistoryTextState *outResult) const { if (!displayFromName() && !Has()) { if (auto via = Get()) { - if (x >= trect.left() && y >= trect.top() && y < trect.top() + st::msgNameFont->height && x < trect.left() + via->_width) { + if (QRect(trect.x(), trect.y(), via->_width, st::msgNameFont->height).contains(point)) { outResult->link = via->_lnk; return true; } @@ -1866,9 +1867,9 @@ bool HistoryMessage::getStateViaBotIdInfo(int x, int y, QRect &trect, HistoryTex return false; } -bool HistoryMessage::getStateText(int x, int y, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const { - if (trect.contains(x, y)) { - *outResult = _text.getState(x - trect.x(), y - trect.y(), trect.width(), request.forText()); +bool HistoryMessage::getStateText(QPoint point, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const { + if (trect.contains(point)) { + *outResult = _text.getState(point - trect.topLeft(), trect.width(), request.forText()); return true; } return false; @@ -2370,7 +2371,7 @@ int HistoryService::resizeContentGetHeight() { return _height; } -bool HistoryService::hasPoint(int x, int y) const { +bool HistoryService::hasPoint(QPoint point) const { auto g = countGeometry(); if (g.width() < 1) { return false; @@ -2385,10 +2386,10 @@ bool HistoryService::hasPoint(int x, int y) const { if (_media) { g.setHeight(g.height() - (st::msgServiceMargin.top() + _media->height())); } - return g.contains(x, y); + return g.contains(point); } -HistoryTextState HistoryService::getState(int x, int y, HistoryStateRequest request) const { +HistoryTextState HistoryService::getState(QPoint point, HistoryStateRequest request) const { HistoryTextState result; auto g = countGeometry(); @@ -2397,12 +2398,12 @@ HistoryTextState HistoryService::getState(int x, int y, HistoryStateRequest requ } if (auto dateh = displayedDateHeight()) { - y -= dateh; + point.setY(point.y() - dateh); g.setHeight(g.height() - dateh); } if (auto unreadbar = Get()) { auto unreadbarh = unreadbar->height(); - y -= unreadbarh; + point.setY(point.y() - unreadbarh); g.setHeight(g.height() - unreadbarh); } @@ -2410,21 +2411,21 @@ HistoryTextState HistoryService::getState(int x, int y, HistoryStateRequest requ g.setHeight(g.height() - (st::msgServiceMargin.top() + _media->height())); } auto trect = g.marginsAdded(-st::msgServicePadding); - if (trect.contains(x, y)) { + if (trect.contains(point)) { auto textRequest = request.forText(); textRequest.align = style::al_center; - result = _text.getState(x - trect.x(), y - trect.y(), trect.width(), textRequest); + result = _text.getState(point - trect.topLeft(), trect.width(), textRequest); if (auto gamescore = Get()) { - if (!result.link && result.cursor == HistoryInTextCursorState && g.contains(x, y)) { + if (!result.link && result.cursor == HistoryInTextCursorState && g.contains(point)) { result.link = gamescore->lnk; } } else if (auto payment = Get()) { - if (!result.link && result.cursor == HistoryInTextCursorState && g.contains(x, y)) { + if (!result.link && result.cursor == HistoryInTextCursorState && g.contains(point)) { result.link = payment->lnk; } } } else if (_media) { - result = _media->getState(x - st::msgServiceMargin.left() - (g.width() - _media->maxWidth()) / 2, y - st::msgServiceMargin.top() - g.height() - st::msgServiceMargin.top(), request); + result = _media->getState(point - QPoint(st::msgServiceMargin.left() + (g.width() - _media->maxWidth()) / 2, st::msgServiceMargin.top() + g.height() + st::msgServiceMargin.top()), request); } return result; } diff --git a/Telegram/SourceFiles/history/history_message.h b/Telegram/SourceFiles/history/history_message.h index ce76692cc..27fa5c233 100644 --- a/Telegram/SourceFiles/history/history_message.h +++ b/Telegram/SourceFiles/history/history_message.h @@ -75,11 +75,11 @@ public: void dependencyItemRemoved(HistoryItem *dependency) override; - bool hasPoint(int x, int y) const override; - bool pointInTime(int32 right, int32 bottom, int x, int y, InfoDisplayType type) const override; + bool hasPoint(QPoint point) const override; + bool pointInTime(int right, int bottom, QPoint point, InfoDisplayType type) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; - void updatePressed(int x, int y) override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; + void updatePressed(QPoint point) override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override; @@ -184,11 +184,11 @@ private: void paintViaBotIdInfo(Painter &p, QRect &trect, bool selected) const; void paintText(Painter &p, QRect &trect, TextSelection selection) const; - bool getStateFromName(int x, int y, QRect &trect, HistoryTextState *outResult) const; - bool getStateForwardedInfo(int x, int y, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const; - bool getStateReplyInfo(int x, int y, QRect &trect, HistoryTextState *outResult) const; - bool getStateViaBotIdInfo(int x, int y, QRect &trect, HistoryTextState *outResult) const; - bool getStateText(int x, int y, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const; + bool getStateFromName(QPoint point, QRect &trect, HistoryTextState *outResult) const; + bool getStateForwardedInfo(QPoint point, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const; + bool getStateReplyInfo(QPoint point, QRect &trect, HistoryTextState *outResult) const; + bool getStateViaBotIdInfo(QPoint point, QRect &trect, HistoryTextState *outResult) const; + bool getStateText(QPoint point, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const; void setMedia(const MTPMessageMedia *media); void setReplyMarkup(const MTPReplyMarkup *markup); @@ -223,7 +223,7 @@ private: void startPaint(Painter &p) const override; const style::TextStyle &textStyle() const override; - void repaint(const HistoryItem *item) const override; + void repaint(gsl::not_null item) const override; protected: void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const override; @@ -300,8 +300,8 @@ public: QRect countGeometry() const; void draw(Painter &p, QRect clip, TextSelection selection, TimeMs ms) const override; - bool hasPoint(int x, int y) const override; - HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; + bool hasPoint(QPoint point) const override; + HistoryTextState getState(QPoint point, HistoryStateRequest request) const override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override { return _text.adjustSelection(selection, type); diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index ef8f79891..cd98a5e66 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -665,7 +665,7 @@ HistoryWidget::HistoryWidget(QWidget *parent, gsl::not_null onPreviewCheck(); } })); - subscribe(controller->widgetGrabbed(), [this] { + subscribe(controller->window()->widgetGrabbed(), [this] { // Qt bug workaround: QWidget::render() for an arbitrary widget calls // sendPendingMoveAndResizeEvents(true, true) for the whole window, // which does something like: @@ -2047,10 +2047,6 @@ void HistoryWidget::clearAllLoadRequests() { _preloadRequest = _preloadDownRequest = _firstLoadRequest = 0; } -void HistoryWidget::updateAfterDrag() { - if (_list) _list->dragActionUpdate(QCursor::pos()); -} - void HistoryWidget::updateFieldSubmitSettings() { auto settings = Ui::FlatTextarea::SubmitSettings::Enter; if (_isInlineBot) { @@ -2434,12 +2430,6 @@ void HistoryWidget::unreadCountChanged(History *history) { } } -void HistoryWidget::historyCleared(History *history) { - if (history == _history) { - _list->dragActionCancel(); - } -} - bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId) { if (MTP::isDefaultHandledError(error)) return false; @@ -3452,7 +3442,7 @@ void HistoryWidget::hideSingleUseKeyboard(PeerData *peer, MsgId replyTo) { } } -void HistoryWidget::app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col) { +void HistoryWidget::app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, gsl::not_null msg, int row, int col) { if (msg->id < 0 || _peer != msg->history()->peer) { return; } @@ -3520,7 +3510,7 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC bool HistoryWidget::botCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req) { // show error? - if (HistoryItem *item = App::histItemById(info.msgId)) { + if (auto item = App::histItemById(info.msgId)) { if (auto markup = item->Get()) { if (info.row < markup->rows.size() && info.col < markup->rows.at(info.row).size()) { if (markup->rows.at(info.row).at(info.col).requestId == req) { @@ -4803,7 +4793,7 @@ bool HistoryWidget::isItemVisible(HistoryItem *item) { return true; } -void HistoryWidget::ui_repaintHistoryItem(const HistoryItem *item) { +void HistoryWidget::ui_repaintHistoryItem(gsl::not_null item) { if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) { auto ms = getms(); if (_lastScrolled + kSkipRepaintWhileScrollMs <= ms) { diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index f293db3e5..d5bdc8851 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -199,7 +199,6 @@ public: void newUnreadMsg(History *history, HistoryItem *item); void historyToDown(History *history); void historyWasRead(ReadServerHistoryChecks checks); - void historyCleared(History *history); void unreadCountChanged(History *history); QRect historyRect() const; @@ -315,7 +314,6 @@ public: void updateHistoryDownPosition(); void updateHistoryDownVisibility(); - void updateAfterDrag(); void updateFieldSubmitSettings(); void setInnerFocus(); @@ -345,9 +343,9 @@ public: bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override; QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) override; - void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col); + void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, gsl::not_null msg, int row, int col); - void ui_repaintHistoryItem(const HistoryItem *item); + void ui_repaintHistoryItem(gsl::not_null item); PeerData *ui_getPeerForMouseAction(); void notify_historyItemLayoutChanged(const HistoryItem *item); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index 33c258ff8..68da37939 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -209,9 +209,9 @@ void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) cons } } -void Gif::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { - if (x >= 0 && x < _width && y >= 0 && y < st::inlineMediaHeight) { - if (_delete && (rtl() ? _width - x : x) >= _width - st::stickerPanDelete.width() && y < st::stickerPanDelete.height()) { +void Gif::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { + if (QRect(0, 0, _width, st::inlineMediaHeight).contains(point)) { + if (_delete && rtlpoint(point, _width).x() >= _width - st::stickerPanDelete.width() && point.y() < st::stickerPanDelete.height()) { link = _delete; } else { link = _send; @@ -400,8 +400,8 @@ void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) } } -void Sticker::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { - if (x >= 0 && x < _width && y >= 0 && y < st::inlineMediaHeight) { +void Sticker::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { + if (QRect(0, 0, _width, st::inlineMediaHeight).contains(point)) { link = _send; } } @@ -487,8 +487,8 @@ void Photo::paint(Painter &p, const QRect &clip, const PaintContext *context) co } } -void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { - if (x >= 0 && x < _width && y >= 0 && y < st::inlineMediaHeight) { +void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { + if (QRect(0, 0, _width, st::inlineMediaHeight).contains(point)) { link = _send; } } @@ -629,12 +629,12 @@ void Video::paint(Painter &p, const QRect &clip, const PaintContext *context) co } } -void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { - if (x >= 0 && x < st::inlineThumbSize && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::inlineThumbSize) { +void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { + if (QRect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize).contains(point)) { link = _link; return; } - if (x >= st::inlineThumbSize + st::inlineThumbSkip && x < _width && y >= 0 && y < _height) { + if (QRect(st::inlineThumbSize + st::inlineThumbSkip, 0, _width - st::inlineThumbSize - st::inlineThumbSkip, _height).contains(point)) { link = _send; return; } @@ -769,12 +769,13 @@ void File::paint(Painter &p, const QRect &clip, const PaintContext *context) con } } -void File::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { - if (x >= 0 && x < st::msgFileSize && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::msgFileSize) { +void File::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { + if (QRect(0, st::inlineRowMargin, st::msgFileSize, st::msgFileSize).contains(point)) { link = getShownDocument()->loading() ? _cancel : _open; return; } - if (x >= st::msgFileSize + st::inlineThumbSkip && x < _width && y >= 0 && y < _height) { + auto left = st::msgFileSize + st::inlineThumbSkip; + if (QRect(left, 0, _width - left, _height).contains(point)) { link = _send; return; } @@ -928,12 +929,12 @@ void Contact::paint(Painter &p, const QRect &clip, const PaintContext *context) } } -void Contact::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { - int left = (st::msgFileSize + st::inlineThumbSkip); - if (x >= 0 && x < left - st::inlineThumbSkip && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::inlineThumbSize) { +void Contact::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { + if (QRect(0, st::inlineRowMargin, st::msgFileSize, st::inlineThumbSize).contains(point)) { return; } - if (x >= left && x < _width && y >= 0 && y < _height) { + auto left = (st::msgFileSize + st::inlineThumbSkip); + if (QRect(left, 0, _width - left, _height).contains(point)) { link = _send; return; } @@ -1064,19 +1065,19 @@ void Article::paint(Painter &p, const QRect &clip, const PaintContext *context) } } -void Article::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { - int left = _withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : 0; - if (x >= 0 && x < left - st::inlineThumbSkip && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::inlineThumbSize) { +void Article::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { + if (_withThumb && QRect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize).contains(point)) { link = _link; return; } - if (x >= left && x < _width && y >= 0 && y < _height) { + auto left = _withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : 0; + if (QRect(left, 0, _width - left, _height).contains(point)) { if (_url) { - int32 left = st::inlineThumbSize + st::inlineThumbSkip; - int32 titleHeight = qMin(_title.countHeight(_width - left), st::semiboldFont->height * 2); - int32 descriptionLines = 2; - int32 descriptionHeight = qMin(_description.countHeight(_width - left), st::normalFont->height * descriptionLines); - if (rtlrect(left, st::inlineRowMargin + titleHeight + descriptionHeight, _urlWidth, st::normalFont->height, _width).contains(x, y)) { + auto left = st::inlineThumbSize + st::inlineThumbSkip; + auto titleHeight = qMin(_title.countHeight(_width - left), st::semiboldFont->height * 2); + auto descriptionLines = 2; + auto descriptionHeight = qMin(_description.countHeight(_width - left), st::normalFont->height * descriptionLines); + if (rtlrect(left, st::inlineRowMargin + titleHeight + descriptionHeight, _urlWidth, st::normalFont->height, _width).contains(point)) { link = _url; return; } @@ -1248,13 +1249,13 @@ void Game::paint(Painter &p, const QRect &clip, const PaintContext *context) con } } -void Game::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { +void Game::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { int left = st::inlineThumbSize + st::inlineThumbSkip; - if (x >= 0 && x < left - st::inlineThumbSkip && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::inlineThumbSize) { + if (QRect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize).contains(point)) { link = _send; return; } - if (x >= left && x < _width && y >= 0 && y < _height) { + if (QRect(left, 0, _width - left, _height).contains(point)) { link = _send; return; } diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h index 7685fdb2e..6c10c67b9 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h @@ -72,7 +72,7 @@ public: } void paint(Painter &p, const QRect &clip, const PaintContext *context) const override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; // ClickHandlerHost interface void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override; @@ -131,7 +131,7 @@ public: } void paint(Painter &p, const QRect &clip, const PaintContext *context) const override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; private: PhotoData *getShownPhoto() const; @@ -161,7 +161,7 @@ public: void preload() const override; void paint(Painter &p, const QRect &clip, const PaintContext *context) const override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; // ClickHandlerHost interface void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override; @@ -185,7 +185,7 @@ public: void initDimensions() override; void paint(Painter &p, const QRect &clip, const PaintContext *context) const override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; private: ClickHandlerPtr _link; @@ -232,7 +232,7 @@ public: void initDimensions() override; void paint(Painter &p, const QRect &clip, const PaintContext *context) const override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; // ClickHandlerHost interface void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override; @@ -295,7 +295,7 @@ public: int resizeGetHeight(int width) override; void paint(Painter &p, const QRect &clip, const PaintContext *context) const override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; private: mutable QPixmap _thumb; @@ -313,7 +313,7 @@ public: int resizeGetHeight(int width) override; void paint(Painter &p, const QRect &clip, const PaintContext *context) const override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; private: ClickHandlerPtr _url, _link; @@ -336,7 +336,7 @@ public: void initDimensions() override; void paint(Painter &p, const QRect &clip, const PaintContext *context) const override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; private: void countFrameSize(); diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp index b3d182d0c..1e9fcd842 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp @@ -640,7 +640,7 @@ void Inner::updateSelected() { } if (col < inlineItems.size()) { sel = row * MatrixRowShift + col; - inlineItems.at(col)->getState(lnk, cursor, sx, sy); + inlineItems.at(col)->getState(lnk, cursor, QPoint(sx, sy)); lnkhost = inlineItems.at(col); } else { row = col = -1; diff --git a/Telegram/SourceFiles/layout.h b/Telegram/SourceFiles/layout.h index 9633a42b6..8cd340ac2 100644 --- a/Telegram/SourceFiles/layout.h +++ b/Telegram/SourceFiles/layout.h @@ -108,38 +108,38 @@ public: LayoutItemBase(const LayoutItemBase &other) = delete; LayoutItemBase &operator=(const LayoutItemBase &other) = delete; - int32 maxWidth() const { + int maxWidth() const { return _maxw; } - int32 minHeight() const { + int minHeight() const { return _minh; } virtual void initDimensions() = 0; - virtual int32 resizeGetHeight(int32 width) { + virtual int resizeGetHeight(int width) { _width = qMin(width, _maxw); _height = _minh; return _height; } - virtual void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { + virtual void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { link.clear(); cursor = HistoryDefaultCursorState; } - virtual void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const { // from text - upon = hasPoint(x, y); + virtual void getSymbol(uint16 &symbol, bool &after, bool &upon, QPoint point) const { // from text + upon = hasPoint(point); symbol = upon ? 0xFFFF : 0; after = false; } - int32 width() const { + int width() const { return _width; } - int32 height() const { + int height() const { return _height; } - bool hasPoint(int x, int y) const { - return (x >= 0 && y >= 0 && x < width() && y < height()); + bool hasPoint(QPoint point) const { + return QRect(0, 0, width(), height()).contains(point); } virtual ~LayoutItemBase() { diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index c1acd5c78..693adcfe6 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -872,13 +872,17 @@ void MainWidget::notify_migrateUpdated(PeerData *peer) { _history->notify_migrateUpdated(peer); } -void MainWidget::ui_repaintHistoryItem(const HistoryItem *item) { - _history->ui_repaintHistoryItem(item); - if (item->history()->lastMsg == item) { - item->history()->updateChatListEntry(); +void MainWidget::ui_repaintHistoryItem(gsl::not_null item) { + if (item->isLogEntry()) { + AuthSession::Current().data().repaintLogEntry().notify(item, true); + } else { + _history->ui_repaintHistoryItem(item); + if (item->history()->lastMsg == item) { + item->history()->updateChatListEntry(); + } + _playerPlaylist->ui_repaintHistoryItem(item); + _playerPanel->ui_repaintHistoryItem(item); } - _playerPlaylist->ui_repaintHistoryItem(item); - _playerPanel->ui_repaintHistoryItem(item); if (_overview) _overview->ui_repaintHistoryItem(item); if (auto last = currentFloatPlayer()) { last->widget->ui_repaintHistoryItem(item); @@ -2471,14 +2475,6 @@ void MainWidget::clearBotStartToken(PeerData *peer) { } } -void MainWidget::updateAfterDrag() { - if (_overview) { - _overview->updateAfterDrag(); - } else { - _history->updateAfterDrag(); - } -} - void MainWidget::ctrlEnterSubmitUpdated() { _history->updateFieldSubmitSettings(); } @@ -3197,10 +3193,6 @@ void MainWidget::markActiveHistoryAsRead() { _history->historyWasRead(ReadServerHistoryChecks::OnlyIfUnread); } -void MainWidget::historyCleared(History *history) { - _history->historyCleared(history); -} - void MainWidget::showAnimated(const QPixmap &bgAnimCache, bool back) { _showBack = back; (_showBack ? _cacheOver : _cacheUnder) = bgAnimCache; diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 39b260c27..a2364f9af 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -203,7 +203,6 @@ public: void dialogsToUp(); void newUnreadMsg(History *history, HistoryItem *item); void markActiveHistoryAsRead(); - void historyCleared(History *history); void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg); void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg); @@ -366,7 +365,6 @@ public: void ptsWaiterStartTimerFor(ChannelData *channel, int32 ms); // ms <= 0 - stop timer void feedUpdates(const MTPUpdates &updates, uint64 randomId = 0); void feedUpdate(const MTPUpdate &update); - void updateAfterDrag(); void ctrlEnterSubmitUpdated(); void setInnerFocus(); @@ -386,7 +384,7 @@ public: void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col); - void ui_repaintHistoryItem(const HistoryItem *item); + void ui_repaintHistoryItem(gsl::not_null item); void ui_showPeerHistory(quint64 peer, qint32 msgId, Ui::ShowWay way); PeerData *ui_getPeerForMouseAction(); diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 719369f8b..4d78769ba 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -131,46 +131,16 @@ MainWindow::MainWindow() { setLocale(QLocale(QLocale::English, QLocale::UnitedStates)); - _inactiveTimer.setSingleShot(true); - connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer())); - subscribe(Global::RefSelfChanged(), [this] { updateGlobalMenu(); }); subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &data) { themeUpdated(data); }); - subscribe(Messenger::Instance().authSessionChanged(), [this] { checkAuthSession(); }); subscribe(Messenger::Instance().passcodedChanged(), [this] { updateGlobalMenu(); }); - checkAuthSession(); setAttribute(Qt::WA_NoSystemBackground); setAttribute(Qt::WA_OpaquePaintEvent); } -void MainWindow::checkAuthSession() { - if (AuthSession::Exists()) { - _controller = std::make_unique(this); - } else { - _controller = nullptr; - } -} - -void MainWindow::inactivePress(bool inactive) { - _inactivePress = inactive; - if (_inactivePress) { - _inactiveTimer.start(200); - } else { - _inactiveTimer.stop(); - } -} - -bool MainWindow::inactivePress() const { - return _inactivePress; -} - -void MainWindow::onInactiveTimer() { - inactivePress(false); -} - void MainWindow::initHook() { Platform::MainWindow::initHook(); @@ -368,9 +338,9 @@ void MainWindow::showMainMenu() { void MainWindow::ensureLayerCreated() { if (!_layerBg) { - _layerBg.create(bodyWidget(), _controller.get()); - if (_controller) { - _controller->enableGifPauseReason(Window::GifPauseReason::Layer); + _layerBg.create(bodyWidget(), controller()); + if (controller()) { + controller()->enableGifPauseReason(Window::GifPauseReason::Layer); } } } @@ -378,8 +348,8 @@ void MainWindow::ensureLayerCreated() { void MainWindow::destroyLayerDelayed() { if (_layerBg) { _layerBg.destroyDelayed(); - if (_controller) { - _controller->disableGifPauseReason(Window::GifPauseReason::Layer); + if (controller()) { + controller()->disableGifPauseReason(Window::GifPauseReason::Layer); } } } @@ -756,8 +726,8 @@ void MainWindow::noIntro(Intro::Widget *was) { void MainWindow::noLayerStack(LayerStackWidget *was) { if (was == _layerBg) { _layerBg = nullptr; - if (_controller) { - _controller->disableGifPauseReason(Window::GifPauseReason::Layer); + if (controller()) { + controller()->disableGifPauseReason(Window::GifPauseReason::Layer); } } } diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h index bce2168fc..af2634288 100644 --- a/Telegram/SourceFiles/mainwindow.h +++ b/Telegram/SourceFiles/mainwindow.h @@ -42,7 +42,6 @@ namespace Theme { struct BackgroundUpdate; class WarningWidget; } // namespace Theme -class Controller; } // namespace Window namespace Ui { @@ -78,15 +77,8 @@ public: MainWindow(); ~MainWindow(); - Window::Controller *controller() const { - return _controller.get(); - } - void firstShow(); - void inactivePress(bool inactive); - bool inactivePress() const; - void setupPasscode(); void clearPasscode(); void setupIntro(); @@ -169,8 +161,6 @@ public slots: void toggleTray(QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Unknown); void toggleDisplayNotifyFromTray(); - void onInactiveTimer(); - void onClearFinished(int task, void *manager); void onClearFailed(int task, void *manager); @@ -187,7 +177,6 @@ signals: void checkNewAuthorization(); private: - void checkAuthSession(); void showConnecting(const QString &text, const QString &reconnect = QString()); void hideConnecting(); @@ -211,7 +200,6 @@ private: QList _delayedServiceMsgs; mtpRequestId _serviceHistoryRequest = 0; - std::unique_ptr _controller; object_ptr _passcode = { nullptr }; object_ptr _intro = { nullptr }; object_ptr _main = { nullptr }; @@ -223,9 +211,6 @@ private: Local::ClearManager *_clearManager = nullptr; - bool _inactivePress = false; - QTimer _inactiveTimer; - }; class PreLaunchWindow : public TWidget { diff --git a/Telegram/SourceFiles/media/player/media_player_float.h b/Telegram/SourceFiles/media/player/media_player_float.h index c69a5e6f8..98f5ddcbe 100644 --- a/Telegram/SourceFiles/media/player/media_player_float.h +++ b/Telegram/SourceFiles/media/player/media_player_float.h @@ -56,7 +56,7 @@ public: finishDrag(false); } } - void ui_repaintHistoryItem(const HistoryItem *item) { + void ui_repaintHistoryItem(gsl::not_null item) { if (item == _item) { repaintItem(); } diff --git a/Telegram/SourceFiles/media/player/media_player_list.cpp b/Telegram/SourceFiles/media/player/media_player_list.cpp index 106a1525a..2d87d3190 100644 --- a/Telegram/SourceFiles/media/player/media_player_list.cpp +++ b/Telegram/SourceFiles/media/player/media_player_list.cpp @@ -95,7 +95,7 @@ void ListWidget::mouseMoveEvent(QMouseEvent *e) { if (y <= m.y()) { if (auto media = layout->toMediaItem()) { item = media->getItem(); - media->getState(lnk, cursorState, m.x(), m.y() - y); + media->getState(lnk, cursorState, m - QPoint(0, y)); lnkhost = media; } } @@ -117,7 +117,7 @@ void ListWidget::mouseMoveEvent(QMouseEvent *e) { } } -void ListWidget::ui_repaintHistoryItem(const HistoryItem *item) { +void ListWidget::ui_repaintHistoryItem(gsl::not_null item) { repaintItem(item); } diff --git a/Telegram/SourceFiles/media/player/media_player_list.h b/Telegram/SourceFiles/media/player/media_player_list.h index e8d0a5d15..1f7193b8d 100644 --- a/Telegram/SourceFiles/media/player/media_player_list.h +++ b/Telegram/SourceFiles/media/player/media_player_list.h @@ -33,7 +33,7 @@ class ListWidget : public TWidget, private base::Subscriber { public: ListWidget(QWidget *parent); - void ui_repaintHistoryItem(const HistoryItem *item); + void ui_repaintHistoryItem(gsl::not_null item); QRect getCurrentTrackGeometry() const; diff --git a/Telegram/SourceFiles/media/player/media_player_panel.cpp b/Telegram/SourceFiles/media/player/media_player_panel.cpp index eedb05453..a166294fb 100644 --- a/Telegram/SourceFiles/media/player/media_player_panel.cpp +++ b/Telegram/SourceFiles/media/player/media_player_panel.cpp @@ -96,7 +96,7 @@ void Panel::updateControlsGeometry() { } } -void Panel::ui_repaintHistoryItem(const HistoryItem *item) { +void Panel::ui_repaintHistoryItem(gsl::not_null item) { if (auto list = static_cast(_scroll->widget())) { list->ui_repaintHistoryItem(item); } diff --git a/Telegram/SourceFiles/media/player/media_player_panel.h b/Telegram/SourceFiles/media/player/media_player_panel.h index a7c42927c..902aa9f75 100644 --- a/Telegram/SourceFiles/media/player/media_player_panel.h +++ b/Telegram/SourceFiles/media/player/media_player_panel.h @@ -52,7 +52,7 @@ public: void setPinCallback(ButtonCallback &&callback); void setCloseCallback(ButtonCallback &&callback); - void ui_repaintHistoryItem(const HistoryItem *item); + void ui_repaintHistoryItem(gsl::not_null item); int bestPositionFor(int left) const; diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index 5c15a087f..25c45e8ed 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -2458,13 +2458,12 @@ bool MediaView::updateOverState(OverState newState) { void MediaView::updateOver(QPoint pos) { ClickHandlerPtr lnk; ClickHandlerHost *lnkhost = nullptr; - if (_saveMsgStarted && _saveMsg.contains(pos)) { - auto textState = _saveMsgText.getState(pos.x() - _saveMsg.x() - st::mediaviewSaveMsgPadding.left(), pos.y() - _saveMsg.y() - st::mediaviewSaveMsgPadding.top(), _saveMsg.width() - st::mediaviewSaveMsgPadding.left() - st::mediaviewSaveMsgPadding.right()); + auto textState = _saveMsgText.getState(pos - _saveMsg.topLeft() - QPoint(st::mediaviewSaveMsgPadding.left(), st::mediaviewSaveMsgPadding.top()), _saveMsg.width() - st::mediaviewSaveMsgPadding.left() - st::mediaviewSaveMsgPadding.right()); lnk = textState.link; lnkhost = this; } else if (_captionRect.contains(pos)) { - auto textState = _caption.getState(pos.x() - _captionRect.x(), pos.y() - _captionRect.y(), _captionRect.width()); + auto textState = _caption.getState(pos - _captionRect.topLeft(), _captionRect.width()); lnk = textState.link; lnkhost = this; } diff --git a/Telegram/SourceFiles/overview/overview_layout.cpp b/Telegram/SourceFiles/overview/overview_layout.cpp index f4b4cfc7b..04bfb019d 100644 --- a/Telegram/SourceFiles/overview/overview_layout.cpp +++ b/Telegram/SourceFiles/overview/overview_layout.cpp @@ -282,8 +282,8 @@ void Photo::ensureCheckboxCreated() { }); } -void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { - if (hasPoint(x, y)) { +void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { + if (hasPoint(point)) { link = _link; } } @@ -462,10 +462,10 @@ void Video::invalidateCache() { } } -void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { +void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { bool loaded = _data->loaded(); - if (hasPoint(x, y)) { + if (hasPoint(point)) { link = loaded ? _openl : (_data->loading() ? _cancell : _savel); } } @@ -614,7 +614,7 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const } } -void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { +void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { bool loaded = _data->loaded(); int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0; @@ -625,18 +625,18 @@ void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i statustop = _st.songStatusTop; auto inner = rtlrect(_st.songPadding.left(), _st.songPadding.top(), _st.songThumbSize, _st.songThumbSize, _width); - if (inner.contains(x, y)) { + if (inner.contains(point)) { link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl); return; } - if (rtlrect(nameleft, statustop, _width - nameleft - nameright, st::normalFont->height, _width).contains(x, y)) { + if (rtlrect(nameleft, statustop, _width - nameleft - nameright, st::normalFont->height, _width).contains(point)) { if (_status.size() == FileStatusSizeLoaded || _status.size() == FileStatusSizeReady) { - auto textState = _details.getStateLeft(x - nameleft, y - statustop, _width, _width); + auto textState = _details.getStateLeft(point - QPoint(nameleft, statustop), _width, _width); link = textState.link; cursor = textState.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState; } } - if (hasPoint(x, y) && !link && !_data->loading()) { + if (hasPoint(point) && !link && !_data->loading()) { link = _namel; return; } @@ -883,7 +883,7 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con } } -void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { +void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { bool loaded = _data->loaded() || Local::willStickerImageLoad(_data->mediaKey()); int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0; @@ -896,11 +896,11 @@ void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x statustop = _st.songStatusTop; auto inner = rtlrect(_st.songPadding.left(), _st.songPadding.top(), _st.songThumbSize, _st.songThumbSize, _width); - if (inner.contains(x, y)) { + if (inner.contains(point)) { link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl); return; } - if (hasPoint(x, y) && !_data->loading()) { + if (hasPoint(point) && !_data->loading()) { link = _namel; return; } @@ -912,23 +912,23 @@ void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x auto rthumb = rtlrect(0, st::linksBorder + _st.filePadding.top(), _st.fileThumbSize, _st.fileThumbSize, _width); - if (rthumb.contains(x, y)) { + if (rthumb.contains(point)) { link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _savel); return; } if (_data->status != FileUploadFailed) { - if (rtlrect(nameleft, datetop, _datew, st::normalFont->height, _width).contains(x, y)) { + if (rtlrect(nameleft, datetop, _datew, st::normalFont->height, _width).contains(point)) { link = _msgl; return; } } if (!_data->loading() && _data->isValid()) { - if (loaded && rtlrect(0, st::linksBorder, nameleft, _height - st::linksBorder, _width).contains(x, y)) { + if (loaded && rtlrect(0, st::linksBorder, nameleft, _height - st::linksBorder, _width).contains(point)) { link = _namel; return; } - if (rtlrect(nameleft, nametop, qMin(_width - nameleft - nameright, _name.maxWidth()), st::semiboldFont->height, _width).contains(x, y)) { + if (rtlrect(nameleft, nametop, qMin(_width - nameleft - nameright, _name.maxWidth()), st::semiboldFont->height, _width).contains(point)) { link = _namel; return; } @@ -1203,9 +1203,9 @@ void Link::paint(Painter &p, const QRect &clip, TextSelection selection, const P } } -void Link::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { +void Link::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const { int32 left = st::linksPhotoSize + st::linksPhotoPadding, top = st::linksMargin.top() + st::linksBorder, w = _width - left; - if (rtlrect(0, top, st::linksPhotoSize, st::linksPhotoSize, _width).contains(x, y)) { + if (rtlrect(0, top, st::linksPhotoSize, st::linksPhotoSize, _width).contains(point)) { link = _photol; return; } @@ -1214,7 +1214,7 @@ void Link::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, in top += (st::linksPhotoSize - st::semiboldFont->height - st::normalFont->height) / 2; } if (!_title.isEmpty()) { - if (rtlrect(left, top, qMin(w, _titlew), st::semiboldFont->height, _width).contains(x, y)) { + if (rtlrect(left, top, qMin(w, _titlew), st::semiboldFont->height, _width).contains(point)) { link = _photol; return; } @@ -1224,7 +1224,7 @@ void Link::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, in top += qMin(st::normalFont->height * 3, _text.countHeight(w)); } for (int32 i = 0, l = _links.size(); i < l; ++i) { - if (rtlrect(left, top, qMin(w, _links.at(i).width), st::normalFont->height, _width).contains(x, y)) { + if (rtlrect(left, top, qMin(w, _links.at(i).width), st::normalFont->height, _width).contains(point)) { link = _links.at(i).lnk; return; } diff --git a/Telegram/SourceFiles/overview/overview_layout.h b/Telegram/SourceFiles/overview/overview_layout.h index e6a7750fe..c3b28f4ad 100644 --- a/Telegram/SourceFiles/overview/overview_layout.h +++ b/Telegram/SourceFiles/overview/overview_layout.h @@ -55,7 +55,7 @@ public: return nullptr; } MsgId msgId() const { - const HistoryItem *item = getItem(); + auto item = getItem(); return item ? item->id : 0; } @@ -184,7 +184,7 @@ public: void initDimensions() override; int32 resizeGetHeight(int32 width) override; void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override; void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override; @@ -211,7 +211,7 @@ public: void initDimensions() override; int32 resizeGetHeight(int32 width) override; void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override; void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override; @@ -254,7 +254,7 @@ public: void initDimensions() override; void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; protected: float64 dataProgress() const override { @@ -291,7 +291,7 @@ public: void initDimensions() override; void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; virtual DocumentData *getDocument() const override { return _data; @@ -340,7 +340,7 @@ public: void initDimensions() override; int32 resizeGetHeight(int32 width) override; void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; - void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override; + void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override; private: ClickHandlerPtr _photol; diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index f28371865..f716d32d8 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -92,6 +92,9 @@ OverviewInner::OverviewInner(OverviewWidget *overview, Ui::ScrollArea *scroll, P invalidateCache(); } }); + subscribe(App::wnd()->dragFinished(), [this] { + dragActionUpdate(QCursor::pos()); + }); if (_type == OverviewLinks || _type == OverviewFiles) { _search->show(); @@ -469,8 +472,8 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but _dragItem = _mousedItem; _dragItemIndex = _mousedItemIndex; _dragStartPos = mapMouseToItem(mapFromGlobal(screenPos), _dragItem, _dragItemIndex); - _dragWasInactive = App::wnd()->inactivePress(); - if (_dragWasInactive) App::wnd()->inactivePress(false); + _dragWasInactive = App::wnd()->wasInactivePress(); + if (_dragWasInactive) App::wnd()->setInactivePress(false); if (ClickHandler::getPressed() && _selected.isEmpty()) { _dragAction = PrepareDrag; } else if (!_selected.isEmpty()) { @@ -564,7 +567,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu _overview->updateTopBarSelection(); } -void OverviewInner::onDragExec() { +void OverviewInner::performDrag() { if (_dragAction != Dragging) return; bool uponSelected = false; @@ -596,25 +599,20 @@ void OverviewInner::onDragExec() { updateDragSelection(0, -1, 0, -1, false); _overview->noSelectingScroll(); - QDrag *drag = new QDrag(App::wnd()); - QMimeData *mimeData = new QMimeData; - + auto mimeData = std::make_unique(); if (!sel.isEmpty()) mimeData->setText(sel); if (!urls.isEmpty()) mimeData->setUrls(urls); if (forwardSelected) { mimeData->setData(qsl("application/x-td-forward-selected"), "1"); } - drag->setMimeData(mimeData); - drag->exec(Qt::CopyAction); - // We don't receive mouseReleaseEvent when drag is finished. - ClickHandler::unpressed(); - if (App::main()) App::main()->updateAfterDrag(); + // This call enters event loop and can destroy any QObject. + App::wnd()->launchDrag(std::move(mimeData)); return; } else { QString forwardMimeType; HistoryMedia *pressedMedia = nullptr; - if (HistoryItem *pressedLnkItem = App::pressedLinkItem()) { + if (auto pressedLnkItem = App::pressedLinkItem()) { if ((pressedMedia = pressedLnkItem->getMedia())) { if (forwardMimeType.isEmpty() && pressedMedia->dragItemByHandler(pressedHandler)) { forwardMimeType = qsl("application/x-td-forward-pressed-link"); @@ -622,12 +620,10 @@ void OverviewInner::onDragExec() { } } if (!forwardMimeType.isEmpty()) { - QDrag *drag = new QDrag(App::wnd()); - QMimeData *mimeData = new QMimeData; - + auto mimeData = std::make_unique(); mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1"); - if (DocumentData *document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) { - QString filepath = document->filepath(DocumentData::FilePathResolveChecked); + if (auto document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) { + auto filepath = document->filepath(DocumentData::FilePathResolveChecked); if (!filepath.isEmpty()) { QList urls; urls.push_back(QUrl::fromLocalFile(filepath)); @@ -635,12 +631,8 @@ void OverviewInner::onDragExec() { } } - drag->setMimeData(mimeData); - drag->exec(Qt::CopyAction); - - // We don't receive mouseReleaseEvent when drag is finished. - ClickHandler::unpressed(); - if (App::main()) App::main()->updateAfterDrag(); + // This call enters event loop and can destroy any QObject. + App::wnd()->launchDrag(std::move(mimeData)); return; } } @@ -904,7 +896,7 @@ void OverviewInner::onUpdateSelected() { item = media->getItem(); index = i; if (upon) { - media->getState(lnk, cursorState, m.x() - col * w - st::overviewPhotoSkip, m.y() - _marginTop - row * vsize - st::overviewPhotoSkip); + media->getState(lnk, cursorState, m - QPoint(col * w + st::overviewPhotoSkip, _marginTop + row * vsize + st::overviewPhotoSkip)); lnkhost = media; } } @@ -940,7 +932,7 @@ void OverviewInner::onUpdateSelected() { if (auto media = _items.at(i)->toMediaItem()) { item = media->getItem(); index = i; - media->getState(lnk, cursorState, m.x() - _rowsLeft, m.y() - _marginTop - top); + media->getState(lnk, cursorState, m - QPoint(_rowsLeft, _marginTop + top)); lnkhost = media; } break; @@ -989,7 +981,7 @@ void OverviewInner::onUpdateSelected() { if (_mousedItem != _dragItem || (m - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()) { if (_dragAction == PrepareDrag) { _dragAction = Dragging; - QTimer::singleShot(1, this, SLOT(onDragExec())); + InvokeQueued(this, [this] { performDrag(); }); } else if (_dragAction == PrepareSelect) { _dragAction = Selecting; } @@ -2267,7 +2259,7 @@ void OverviewWidget::grabFinish() { _topShadow->show(); } -void OverviewWidget::ui_repaintHistoryItem(const HistoryItem *item) { +void OverviewWidget::ui_repaintHistoryItem(gsl::not_null item) { if (peer() == item->history()->peer || migratePeer() == item->history()->peer) { _inner->repaintItem(item); } @@ -2283,10 +2275,6 @@ SelectedItemSet OverviewWidget::getSelectedItems() const { return _inner->getSelectedItems(); } -void OverviewWidget::updateAfterDrag() { - _inner->dragActionUpdate(QCursor::pos()); -} - OverviewWidget::~OverviewWidget() { onClearSelected(); updateTopBarSelection(); diff --git a/Telegram/SourceFiles/overviewwidget.h b/Telegram/SourceFiles/overviewwidget.h index f28671ce0..2f8091f1f 100644 --- a/Telegram/SourceFiles/overviewwidget.h +++ b/Telegram/SourceFiles/overviewwidget.h @@ -132,8 +132,6 @@ public slots: void onTouchSelect(); void onTouchScrollTimer(); - void onDragExec(); - bool onSearchMessages(bool searchCache = false); void onNeedSearchMessages(); @@ -142,6 +140,7 @@ private: void invalidateCache(); void resizeItems(); void resizeAndRepositionItems(); + void performDrag(); void itemRemoved(HistoryItem *item); MsgId complexMsgId(const HistoryItem *item) const; @@ -333,8 +332,6 @@ public: SelectedItemSet getSelectedItems() const; - void updateAfterDrag(); - void grabStart() override { _inGrab = true; resizeEvent(0); @@ -355,7 +352,7 @@ public: bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override; QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) override; - void ui_repaintHistoryItem(const HistoryItem *item); + void ui_repaintHistoryItem(gsl::not_null item); void notify_historyItemLayoutChanged(const HistoryItem *item); diff --git a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp index 400f67e18..3d2566240 100644 --- a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp +++ b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp @@ -93,7 +93,7 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa case WM_ACTIVATE: { if (LOWORD(wParam) == WA_CLICKACTIVE) { - App::wnd()->inactivePress(true); + App::wnd()->setInactivePress(true); } if (LOWORD(wParam) != WA_INACTIVE) { App::wnd()->shadowsActivate(); diff --git a/Telegram/SourceFiles/ui/text/text.cpp b/Telegram/SourceFiles/ui/text/text.cpp index 22b75f1cd..044f87161 100644 --- a/Telegram/SourceFiles/ui/text/text.cpp +++ b/Telegram/SourceFiles/ui/text/text.cpp @@ -1020,11 +1020,11 @@ public: draw(left, top, w, align, yFrom, yTo, selection); } - Text::StateResult getState(int x, int y, int w, Text::StateRequest request) { - if (!_t->isNull() && y >= 0) { + Text::StateResult getState(QPoint point, int w, Text::StateRequest request) { + if (!_t->isNull() && point.y() >= 0) { _lookupRequest = request; - _lookupX = x; - _lookupY = y; + _lookupX = point.x(); + _lookupY = point.y(); _breakEverywhere = (_lookupRequest.flags & Text::StateRequest::Flag::BreakEverywhere); _lookupSymbol = (_lookupRequest.flags & Text::StateRequest::Flag::LookupSymbol); @@ -1036,11 +1036,11 @@ public: return _lookupResult; } - Text::StateResult getStateElided(int x, int y, int w, Text::StateRequestElided request) { - if (!_t->isNull() && y >= 0 && request.lines > 0) { + Text::StateResult getStateElided(QPoint point, int w, Text::StateRequestElided request) { + if (!_t->isNull() && point.y() >= 0 && request.lines > 0) { _lookupRequest = request; - _lookupX = x; - _lookupY = y; + _lookupX = point.x(); + _lookupY = point.y(); _breakEverywhere = (_lookupRequest.flags & Text::StateRequest::Flag::BreakEverywhere); _lookupSymbol = (_lookupRequest.flags & Text::StateRequest::Flag::LookupSymbol); @@ -2838,14 +2838,14 @@ void Text::drawElided(Painter &painter, int32 left, int32 top, int32 w, int32 li p.drawElided(left, top, w, align, lines, yFrom, yTo, removeFromEnd, breakEverywhere, selection); } -Text::StateResult Text::getState(int x, int y, int width, StateRequest request) const { +Text::StateResult Text::getState(QPoint point, int width, StateRequest request) const { TextPainter p(0, this); - return p.getState(x, y, width, request); + return p.getState(point, width, request); } -Text::StateResult Text::getStateElided(int x, int y, int width, StateRequestElided request) const { +Text::StateResult Text::getStateElided(QPoint point, int width, StateRequestElided request) const { TextPainter p(0, this); - return p.getStateElided(x, y, width, request); + return p.getStateElided(point, width, request); } TextSelection Text::adjustSelection(TextSelection selection, TextSelectType selectType) const { diff --git a/Telegram/SourceFiles/ui/text/text.h b/Telegram/SourceFiles/ui/text/text.h index 17e21d2ea..bbaa9d894 100644 --- a/Telegram/SourceFiles/ui/text/text.h +++ b/Telegram/SourceFiles/ui/text/text.h @@ -146,9 +146,9 @@ public: bool afterSymbol = false; uint16 symbol = 0; }; - StateResult getState(int x, int y, int width, StateRequest request = StateRequest()) const; - StateResult getStateLeft(int x, int y, int width, int outerw, StateRequest request = StateRequest()) const { - return getState(rtl() ? (outerw - x - width) : x, y, width, request); + StateResult getState(QPoint point, int width, StateRequest request = StateRequest()) const; + StateResult getStateLeft(QPoint point, int width, int outerw, StateRequest request = StateRequest()) const { + return getState(rtlpoint(point, outerw), width, request); } struct StateRequestElided : public StateRequest { StateRequestElided() { @@ -158,9 +158,9 @@ public: int lines = 1; int removeFromEnd = 0; }; - StateResult getStateElided(int x, int y, int width, StateRequestElided request = StateRequestElided()) const; - StateResult getStateElidedLeft(int x, int y, int width, int outerw, StateRequestElided request = StateRequestElided()) const { - return getStateElided(rtl() ? (outerw - x - width) : x, y, width, request); + StateResult getStateElided(QPoint point, int width, StateRequestElided request = StateRequestElided()) const; + StateResult getStateElidedLeft(QPoint point, int width, int outerw, StateRequestElided request = StateRequestElided()) const { + return getStateElided(rtlpoint(point, outerw), width, request); } TextSelection adjustSelection(TextSelection selection, TextSelectType selectType) const; diff --git a/Telegram/SourceFiles/ui/twidget.cpp b/Telegram/SourceFiles/ui/twidget.cpp index 6d22f1d2f..e9848ef25 100644 --- a/Telegram/SourceFiles/ui/twidget.cpp +++ b/Telegram/SourceFiles/ui/twidget.cpp @@ -22,7 +22,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "application.h" #include "mainwindow.h" -#include "window/window_controller.h" namespace Fonts { namespace { @@ -156,7 +155,7 @@ QPixmap myGrab(TWidget *target, QRect rect, QColor bg) { result.fill(bg); } - App::wnd()->controller()->widgetGrabbed().notify(true); + App::wnd()->widgetGrabbed().notify(true); target->grabStart(); target->render(&result, QPoint(0, 0), rect, QWidget::DrawChildren | QWidget::IgnoreMask); diff --git a/Telegram/SourceFiles/ui/widgets/labels.cpp b/Telegram/SourceFiles/ui/widgets/labels.cpp index 28287ecdc..d97acdb7c 100644 --- a/Telegram/SourceFiles/ui/widgets/labels.cpp +++ b/Telegram/SourceFiles/ui/widgets/labels.cpp @@ -262,8 +262,8 @@ Text::StateResult FlatLabel::dragActionStart(const QPoint &p, Qt::MouseButton bu ClickHandler::pressed(); _dragAction = NoDrag; - _dragWasInactive = App::wnd()->inactivePress(); - if (_dragWasInactive) App::wnd()->inactivePress(false); + _dragWasInactive = App::wnd()->wasInactivePress(); + if (_dragWasInactive) App::wnd()->setInactivePress(false); if (ClickHandler::getPressed()) { _dragStartPosition = mapFromGlobal(_lastMousePos); @@ -750,9 +750,9 @@ Text::StateResult FlatLabel::getTextState(const QPoint &m) const { if (_breakEverywhere) { request.flags |= Text::StateRequest::Flag::BreakEverywhere; } - state = _text.getStateElided(m.x() - _st.margin.left(), m.y() - _st.margin.top(), textWidth, request); + state = _text.getStateElided(m - QPoint(_st.margin.left(), _st.margin.top()), textWidth, request); } else { - state = _text.getState(m.x() - _st.margin.left(), m.y() - _st.margin.top(), textWidth, request); + state = _text.getState(m - QPoint(_st.margin.left(), _st.margin.top()), textWidth, request); } return state; diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 598794812..0756ef6cd 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -24,12 +24,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "styles/style_window.h" #include "platform/platform_window_title.h" #include "window/themes/window_theme.h" +#include "window/window_controller.h" #include "mediaview.h" #include "messenger.h" #include "mainwindow.h" namespace Window { +constexpr auto kInactivePressTimeout = 200; + QImage LoadLogo() { return QImage(qsl(":/gui/art/logo_256.png")); } @@ -58,8 +61,7 @@ MainWindow::MainWindow() : QWidget() , _positionUpdatedTimer(this) , _body(this) , _icon(CreateIcon()) -, _titleText(qsl("Telegram")) -, _isActiveTimer(this) { +, _titleText(qsl("Telegram")) { subscribe(Theme::Background(), [this](const Theme::BackgroundUpdate &data) { if (data.paletteChanged()) { if (_title) { @@ -70,9 +72,11 @@ MainWindow::MainWindow() : QWidget() }); subscribe(Global::RefUnreadCounterUpdate(), [this] { updateUnreadCounter(); }); subscribe(Global::RefWorkMode(), [this](DBIWorkMode mode) { workmodeUpdated(mode); }); + subscribe(Messenger::Instance().authSessionChanged(), [this] { checkAuthSession(); }); + checkAuthSession(); - _isActiveTimer->setSingleShot(true); - connect(_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActiveByTimer())); + _isActiveTimer.setCallback([this] { updateIsActive(0); }); + _inactivePressTimer.setCallback([this] { setInactivePress(false); }); } bool MainWindow::hideNoQuit() { @@ -140,8 +144,8 @@ bool MainWindow::ui_isMediaViewShown() { } void MainWindow::updateIsActive(int timeout) { - if (timeout) { - return _isActiveTimer->start(timeout); + if (timeout > 0) { + return _isActiveTimer.callOnce(timeout); } _isActive = computeIsActive(); updateIsActiveHook(); @@ -433,6 +437,36 @@ PeerData *MainWindow::ui_getPeerForMouseAction() { return nullptr; } +void MainWindow::launchDrag(std::unique_ptr data) { + auto weak = QPointer(this); + auto drag = std::make_unique(App::wnd()); + drag->setMimeData(data.release()); + drag->exec(Qt::CopyAction); + + // We don't receive mouseReleaseEvent when drag is finished. + ClickHandler::unpressed(); + if (weak) { + weak->dragFinished().notify(); + } +} + +void MainWindow::checkAuthSession() { + if (AuthSession::Exists()) { + _controller = std::make_unique(this); + } else { + _controller = nullptr; + } +} + +void MainWindow::setInactivePress(bool inactive) { + _wasInactivePress = inactive; + if (_wasInactivePress) { + _inactivePressTimer.callOnce(kInactivePressTimeout); + } else { + _inactivePressTimer.cancel(); + } +} + MainWindow::~MainWindow() = default; } // namespace Window diff --git a/Telegram/SourceFiles/window/main_window.h b/Telegram/SourceFiles/window/main_window.h index 5f539d57f..d8625ea04 100644 --- a/Telegram/SourceFiles/window/main_window.h +++ b/Telegram/SourceFiles/window/main_window.h @@ -21,11 +21,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #pragma once #include "window/window_title.h" +#include "base/timer.h" class MediaView; namespace Window { +class Controller; class TitleWidget; QImage LoadLogo(); @@ -38,6 +40,14 @@ class MainWindow : public QWidget, protected base::Subscriber { public: MainWindow(); + Window::Controller *controller() const { + return _controller.get(); + } + void setInactivePress(bool inactive); + bool wasInactivePress() const { + return _wasInactivePress; + } + bool hideNoQuit(); void hideMediaview(); @@ -90,6 +100,14 @@ public: } virtual PeerData *ui_getPeerForMouseAction(); + void launchDrag(std::unique_ptr data); + base::Observable &dragFinished() { + return _dragFinished; + } + base::Observable &widgetGrabbed() { + return _widgetGrabbed; + } + public slots: bool minimizeToTray(); void updateGlobalMenu() { @@ -154,11 +172,9 @@ private slots: savePosition(); } void onReActivate(); - void updateIsActiveByTimer() { - updateIsActive(0); - } private: + void checkAuthSession(); void updatePalette(); void updateUnreadCounter(); void initSize(); @@ -168,6 +184,7 @@ private: object_ptr _positionUpdatedTimer; bool _positionInited = false; + std::unique_ptr _controller; object_ptr _title = { nullptr }; object_ptr _body; object_ptr _rightColumn = { nullptr }; @@ -175,11 +192,16 @@ private: QIcon _icon; QString _titleText; - object_ptr _isActiveTimer; bool _isActive = false; + base::Timer _isActiveTimer; + bool _wasInactivePress = false; + base::Timer _inactivePressTimer; object_ptr _mediaView = { nullptr }; + base::Observable _dragFinished; + base::Observable _widgetGrabbed; + }; } // namespace Window diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h index b4ff1460f..4fb289e44 100644 --- a/Telegram/SourceFiles/window/window_controller.h +++ b/Telegram/SourceFiles/window/window_controller.h @@ -68,9 +68,6 @@ public: base::Observable &floatPlayerAreaUpdated() { return _floatPlayerAreaUpdated; } - base::Observable &widgetGrabbed() { - return _widgetGrabbed; - } struct ColumnLayout { int bodyWidth; @@ -111,7 +108,6 @@ private: GifPauseReasons _gifPauseReasons = { 0 }; base::Observable _gifPauseLevelChanged; base::Observable _floatPlayerAreaUpdated; - base::Observable _widgetGrabbed; base::Variable _dialogsWidthRatio = { kDefaultDialogsWidthRatio }; base::Variable _dialogsListFocused = { false };