Handle channel event log mouse events.

This commit is contained in:
John Preston 2017-06-22 00:38:31 +03:00
parent 1791b251ad
commit e39b95175b
50 changed files with 1298 additions and 668 deletions

View File

@ -57,6 +57,12 @@ public:
base::Observable<void> &savedGifsUpdated() { base::Observable<void> &savedGifsUpdated() {
return _savedGifsUpdated; return _savedGifsUpdated;
} }
base::Observable<gsl::not_null<History*>> &historyCleared() {
return _historyCleared;
}
base::Observable<gsl::not_null<const HistoryItem*>> &repaintLogEntry() {
return _repaintLogEntry;
}
void copyFrom(const AuthSessionData &other) { void copyFrom(const AuthSessionData &other) {
_variables = other._variables; _variables = other._variables;
@ -131,6 +137,8 @@ private:
base::Variable<bool> _allChatsLoaded = { false }; base::Variable<bool> _allChatsLoaded = { false };
base::Observable<void> _moreChatsLoaded; base::Observable<void> _moreChatsLoaded;
base::Observable<void> _savedGifsUpdated; base::Observable<void> _savedGifsUpdated;
base::Observable<gsl::not_null<History*>> _historyCleared;
base::Observable<gsl::not_null<const HistoryItem*>> _repaintLogEntry;
Variables _variables; Variables _variables;
TimeMs _lastTimeVideoPlayedAt = 0; TimeMs _lastTimeVideoPlayedAt = 0;

View File

@ -186,9 +186,8 @@ void ConfirmBox::updateLink() {
} }
void ConfirmBox::updateHover() { void ConfirmBox::updateHover() {
QPoint m(mapFromGlobal(_lastMousePos)); auto m = mapFromGlobal(_lastMousePos);
auto state = _text.getStateLeft(m - QPoint(st::boxPadding.left(), st::boxPadding.top()), _textWidth, width());
auto state = _text.getStateLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width());
ClickHandler::setActive(state.link, this); ClickHandler::setActive(state.link, this);
} }

View File

@ -52,7 +52,7 @@ const style::TextStyle &BotKeyboard::Style::textStyle() const {
return st::botKbStyle; return st::botKbStyle;
} }
void BotKeyboard::Style::repaint(const HistoryItem *item) const { void BotKeyboard::Style::repaint(gsl::not_null<const HistoryItem*> item) const {
_parent->update(); _parent->update();
} }
@ -237,10 +237,10 @@ void BotKeyboard::updateSelected() {
if (!_impl) return; if (!_impl) return;
QPoint p(mapFromGlobal(_lastMousePos)); auto p = mapFromGlobal(_lastMousePos);
int x = rtl() ? st::botKbScroll.width : _st->margin; 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)) { if (ClickHandler::setActive(link, this)) {
Ui::Tooltip::Hide(); Ui::Tooltip::Hide();
setCursor(link ? style::cur_pointer : style::cur_default); setCursor(link ? style::cur_pointer : style::cur_default);

View File

@ -92,7 +92,7 @@ private:
void startPaint(Painter &p) const override; void startPaint(Painter &p) const override;
const style::TextStyle &textStyle() const override; const style::TextStyle &textStyle() const override;
void repaint(const HistoryItem *item) const override; void repaint(gsl::not_null<const HistoryItem*> item) const override;
protected: protected:
void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const override; void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const override;

View File

@ -900,7 +900,7 @@ void GifsListWidget::updateSelected() {
} }
if (col < inlineItems.size()) { if (col < inlineItems.size()) {
sel = row * MatrixRowShift + col; 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); lnkhost = inlineItems.at(col);
} else { } else {
row = col = -1; row = col = -1;

View File

@ -253,7 +253,7 @@ bool isMediaViewShown() {
return false; return false;
} }
void repaintHistoryItem(const HistoryItem *item) { void repaintHistoryItem(gsl::not_null<const HistoryItem*> item) {
if (auto main = App::main()) { if (auto main = App::main()) {
main->ui_repaintHistoryItem(item); main->ui_repaintHistoryItem(item);
} }
@ -379,7 +379,7 @@ void handlePendingHistoryUpdate() {
if (auto media = item->getMedia()) { if (auto media = item->getMedia()) {
if (auto reader = media->getClipReader()) { if (auto reader = media->getClipReader()) {
if (!reader->started() && reader->mode() == Media::Clip::Reader::Mode::Video) { if (!reader->started() && reader->mode() == Media::Clip::Reader::Mode::Video) {
item->history()->resizeGetHeight(item->history()->width); item->resizeGetHeight(item->width());
} }
} }
} }

View File

@ -107,7 +107,7 @@ void hideSettingsAndLayer(bool fast = false);
bool isLayerShown(); bool isLayerShown();
bool isMediaViewShown(); bool isMediaViewShown();
void repaintHistoryItem(const HistoryItem *item); void repaintHistoryItem(gsl::not_null<const HistoryItem*> item);
void autoplayMediaInlineAsync(const FullMsgId &msgId); void autoplayMediaInlineAsync(const FullMsgId &msgId);
void showPeerProfile(const PeerId &peer); void showPeerProfile(const PeerId &peer);

View File

@ -2060,7 +2060,9 @@ void History::clear(bool leaveItems) {
peer->asChannel()->mgInfo->markupSenders.clear(); 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) { void History::clearBlocks(bool leaveItems) {

View File

@ -20,21 +20,37 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/ */
#include "history/history_admin_log_inner.h" #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_item.h"
#include "history/history_admin_log_section.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 AdminLog {
namespace { namespace {
constexpr int kEventsPerPage = 3; constexpr auto kScrollDateHideTimeout = 1000;
constexpr auto kEventsPerPage = 10;
} // namespace } // namespace
InnerWidget::InnerWidget(QWidget *parent, gsl::not_null<ChannelData*> channel, base::lambda<void(int top)> scrollTo) : TWidget(parent) InnerWidget::InnerWidget(QWidget *parent, gsl::not_null<Window::Controller*> controller, gsl::not_null<ChannelData*> channel, base::lambda<void(int top)> scrollTo) : TWidget(parent)
, _controller(controller)
, _channel(channel) , _channel(channel)
, _history(App::history(channel)) , _history(App::history(channel))
, _scrollTo(std::move(scrollTo)) { , _scrollTo(std::move(scrollTo))
, _scrollDateCheck([this] { scrollDateCheck(); }) {
setMouseTracking(true); setMouseTracking(true);
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
subscribe(AuthSession::Current().data().repaintLogEntry(), [this](gsl::not_null<const HistoryItem*> historyItem) {
auto it = _itemsByHistoryItems.find(historyItem);
if (it != _itemsByHistoryItems.cend()) {
repaintItem(it->second);
}
});
} }
void InnerWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) { 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() { void InnerWidget::checkPreloadMore() {
if (_visibleTop + PreloadHeightsCount * (_visibleBottom - _visibleTop) > height()) { if (_visibleTop + PreloadHeightsCount * (_visibleBottom - _visibleTop) > height()) {
preloadMore(Direction::Down); preloadMore(Direction::Down);
@ -73,6 +142,26 @@ void InnerWidget::applyFilter(MTPDchannelAdminLogEventsFilter::Flags flags, cons
_filterAdmins = admins; _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<SectionMemento*> memento) const { void InnerWidget::saveState(gsl::not_null<SectionMemento*> memento) const {
//if (auto count = _items.size()) { //if (auto count = _items.size()) {
// QList<gsl::not_null<PeerData*>> groups; // QList<gsl::not_null<PeerData*>> groups;
@ -162,7 +251,7 @@ void InnerWidget::itemsAdded(Direction direction) {
void InnerWidget::updateSize() { void InnerWidget::updateSize() {
TWidget::resizeToWidth(width()); TWidget::resizeToWidth(width());
auto newVisibleTop = (_visibleTopItem ? _visibleTopItem->top() : 0) + _visibleTopFromItem; auto newVisibleTop = _visibleTopItem ? (itemTop(_visibleTopItem) + _visibleTopFromItem) : ScrollMax;
_scrollTo(newVisibleTop); _scrollTo(newVisibleTop);
updateVisibleTopItem(); updateVisibleTopItem();
checkPreloadMore(); checkPreloadMore();
@ -176,10 +265,16 @@ int InnerWidget::resizeGetHeight(int newWidth) {
item->setTop(newHeight); item->setTop(newHeight);
newHeight += item->resizeGetHeight(newWidth); 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) { void InnerWidget::paintEvent(QPaintEvent *e) {
if (Ui::skipPaintEvent(this, e)) {
return;
}
Painter p(this); Painter p(this);
auto ms = getms(); auto ms = getms();
@ -189,14 +284,14 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
paintEmpty(p); paintEmpty(p);
} else { } else {
auto start = std::rbegin(_items), end = std::rend(_items); auto start = std::rbegin(_items), end = std::rend(_items);
auto from = std::upper_bound(start, end, clip.top(), [](int top, auto &elem) { auto from = std::upper_bound(start, end, clip.top(), [this](int top, auto &elem) {
return top <= elem->top() + elem->height(); return top <= itemTop(elem.get()) + elem->height();
}); });
auto to = std::lower_bound(start, end, clip.top() + clip.height(), [](auto &elem, int bottom) { auto to = std::lower_bound(start, end, clip.top() + clip.height(), [this](auto &elem, int bottom) {
return elem->top() < bottom; return itemTop(elem.get()) < bottom;
}); });
if (from != end) { if (from != end) {
auto top = (*from)->top(); auto top = itemTop(from->get());
p.translate(0, top); p.translate(0, top);
for (auto i = from; i != to; ++i) { for (auto i = from; i != to; ++i) {
(*i)->draw(p, clip.translated(0, -top), TextSelection(), ms); (*i)->draw(p, clip.translated(0, -top), TextSelection(), ms);
@ -226,12 +321,464 @@ void InnerWidget::keyPressEvent(QKeyEvent *e) {
} }
void InnerWidget::mousePressEvent(QMouseEvent *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) { 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) { 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<HistorySticker*>(_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<HistoryMessageDate>()) {
// 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<DateClickHandler>(item->history()->peer, item->date.date());
// } else {
// static_cast<DateClickHandler*>(_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<VoiceSeekClickHandler*>(pressedHandler.data())) {
// return;
//}
//TextWithEntities sel;
//QList<QUrl> 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<HistoryMedia*>(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<QMimeData>();
// mimeData->setData(forwardMimeType, "1");
// if (auto document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) {
// auto filepath = document->filepath(DocumentData::FilePathResolveChecked);
// if (!filepath.isEmpty()) {
// QList<QUrl> 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*> 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; InnerWidget::~InnerWidget() = default;

View File

@ -20,7 +20,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include "ui/widgets/tooltip.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "base/timer.h"
namespace Ui {
class PopupMenu;
} // namespace Ui
namespace Window {
class Controller;
} // namespace Window
namespace AdminLog { 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: public:
InnerWidget(QWidget *parent, gsl::not_null<ChannelData*> channel, base::lambda<void(int top)> scrollTo); InnerWidget(QWidget *parent, gsl::not_null<Window::Controller*> controller, gsl::not_null<ChannelData*> channel, base::lambda<void(int top)> scrollTo);
gsl::not_null<ChannelData*> channel() const { gsl::not_null<ChannelData*> channel() const {
return _channel; return _channel;
@ -72,6 +82,10 @@ public:
// Empty "flags" means all events. Empty "admins" means all admins. // Empty "flags" means all events. Empty "admins" means all admins.
void applyFilter(MTPDchannelAdminLogEventsFilter::Flags flags, const std::vector<gsl::not_null<UserData*>> &admins); void applyFilter(MTPDchannelAdminLogEventsFilter::Flags flags, const std::vector<gsl::not_null<UserData*>> &admins);
// AbstractTooltipShower interface
QString tooltipText() const override;
QPoint tooltipPos() const override;
~InnerWidget(); ~InnerWidget();
protected: protected:
@ -80,6 +94,8 @@ protected:
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override;
void mouseReleaseEvent(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. // Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override; int resizeGetHeight(int newWidth) override;
@ -89,6 +105,23 @@ private:
Up, Up,
Down, 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*> item) const;
void repaintItem(Item *item);
QPoint mapPointToItem(QPoint point, Item *item) const;
void checkPreloadMore(); void checkPreloadMore();
void updateVisibleTopItem(); void updateVisibleTopItem();
void preloadMore(Direction direction); void preloadMore(Direction direction);
@ -96,11 +129,23 @@ private:
void updateSize(); void updateSize();
void paintEmpty(Painter &p); void paintEmpty(Painter &p);
void toggleScrollDateShown();
void repaintScrollDateCallback();
bool displayScrollDate() const;
void scrollDateHide();
void keepScrollDateForNow();
void scrollDateCheck();
void scrollDateHideByTimer();
gsl::not_null<Window::Controller*> _controller;
gsl::not_null<ChannelData*> _channel; gsl::not_null<ChannelData*> _channel;
gsl::not_null<History*> _history; gsl::not_null<History*> _history;
base::lambda<void()> _cancelledCallback; base::lambda<void()> _cancelledCallback;
base::lambda<void(int top)> _scrollTo; base::lambda<void(int top)> _scrollTo;
std::vector<std::unique_ptr<Item>> _items; std::vector<std::unique_ptr<Item>> _items;
std::map<gsl::not_null<HistoryItem*>, gsl::not_null<Item*>, std::less<>> _itemsByHistoryItems;
int _itemsTop = 0;
int _itemsHeight = 0;
LocalIdManager _idManager; LocalIdManager _idManager;
int _minHeight = 0; int _minHeight = 0;
@ -109,6 +154,14 @@ private:
Item *_visibleTopItem = nullptr; Item *_visibleTopItem = nullptr;
int _visibleTopFromItem = 0; 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. // Up - max, Down - min.
uint64 _maxId = 0; uint64 _maxId = 0;
uint64 _minId = 0; uint64 _minId = 0;
@ -117,6 +170,29 @@ private:
bool _upLoaded = false; bool _upLoaded = false;
bool _downLoaded = true; 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; MTPDchannelAdminLogEventsFilter::Flags _filterFlags = 0;
std::vector<gsl::not_null<UserData*>> _filterAdmins; std::vector<gsl::not_null<UserData*>> _filterAdmins;

View File

@ -235,6 +235,7 @@ TextWithEntities GenerateParticipantChangeText(gsl::not_null<ChannelData*> chann
Item::Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event) Item::Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event)
: _id(event.vid.v) : _id(event.vid.v)
, _date(::date(event.vdate))
, _history(history) , _history(history)
, _from(App::user(event.vuser_id.v)) { , _from(App::user(event.vuser_id.v)) {
auto &action = event.vaction; auto &action = event.vaction;
@ -439,23 +440,42 @@ bool Item::hasPoint(QPoint point) const {
for (auto part : _parts) { for (auto part : _parts) {
auto height = part->height(); auto height = part->height();
if (point.y() >= top && point.y() < top + 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; top += height;
} }
return false; return false;
} }
HistoryTextState Item::getState(QPoint point, HistoryStateRequest request) const { Item::TextState Item::getState(QPoint point, HistoryStateRequest request) const {
auto top = 0; auto top = 0;
for (auto part : _parts) { for (auto part : _parts) {
auto height = part->height(); auto height = part->height();
if (point.y() >= top && point.y() < top + 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; 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<HistoryMessageForwarded>()) {
return forwarded->_text.originalText(AllTextSelection, ExpandLinksNone);
}
}
return QString();
} }
Item::~Item() { Item::~Item() {

View File

@ -26,11 +26,19 @@ namespace AdminLog {
class Item { class Item {
public: public:
struct TextState {
HistoryTextState data;
ClickHandlerHost *handler = nullptr;
};
Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event); Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event);
uint64 id() const { uint64 id() const {
return _id; return _id;
} }
QDateTime date() const {
return _date;
}
int top() const { int top() const {
return _top; return _top;
} }
@ -44,7 +52,11 @@ public:
int resizeGetHeight(int newWidth); int resizeGetHeight(int newWidth);
void draw(Painter &p, QRect clip, TextSelection selection, TimeMs ms); void draw(Painter &p, QRect clip, TextSelection selection, TimeMs ms);
bool hasPoint(QPoint point) const; 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(); ~Item();
@ -55,6 +67,7 @@ private:
void addPart(HistoryItem *item); void addPart(HistoryItem *item);
uint64 _id = 0; uint64 _id = 0;
QDateTime _date;
gsl::not_null<History*> _history; gsl::not_null<History*> _history;
gsl::not_null<UserData*> _from; gsl::not_null<UserData*> _from;
std::vector<HistoryItem*> _parts; std::vector<HistoryItem*> _parts;

View File

@ -139,7 +139,7 @@ Widget::Widget(QWidget *parent, gsl::not_null<Window::Controller*> controller, g
updateAdaptiveLayout(); updateAdaptiveLayout();
subscribe(Adaptive::Changed(), [this]() { updateAdaptiveLayout(); }); subscribe(Adaptive::Changed(), [this]() { updateAdaptiveLayout(); });
_inner = _scroll->setOwnedWidget(object_ptr<InnerWidget>(this, channel, [this](int top) { _scroll->scrollToY(top); })); _inner = _scroll->setOwnedWidget(object_ptr<InnerWidget>(this, controller, channel, [this](int top) { _scroll->scrollToY(top); }));
_scroll->move(0, _fixedBar->height()); _scroll->move(0, _fixedBar->height());
_scroll->show(); _scroll->show();

View File

@ -57,12 +57,12 @@ private:
}; };
QMimeData *mimeDataFromTextWithEntities(const TextWithEntities &forClipboard) { std::unique_ptr<QMimeData> mimeDataFromTextWithEntities(const TextWithEntities &forClipboard) {
if (forClipboard.text.isEmpty()) { if (forClipboard.text.isEmpty()) {
return nullptr; return nullptr;
} }
auto result = new QMimeData(); auto result = std::make_unique<QMimeData>();
result->setText(forClipboard.text); result->setText(forClipboard.text);
auto tags = ConvertEntitiesToTextTags(forClipboard.entities); auto tags = ConvertEntitiesToTextTags(forClipboard.entities);
if (!tags.isEmpty()) { if (!tags.isEmpty()) {
@ -107,6 +107,14 @@ HistoryInner::HistoryInner(HistoryWidget *historyWidget, gsl::not_null<Window::C
update(); update();
} }
}); });
subscribe(_controller->window()->dragFinished(), [this] {
mouseActionUpdate(QCursor::pos());
});
subscribe(AuthSession::Current().data().historyCleared(), [this](gsl::not_null<History*> history) {
if (_history == history) {
mouseActionCancel();
}
});
} }
void HistoryInner::messagesReceived(PeerData *peer, const QVector<MTPMessage> &messages) { void HistoryInner::messagesReceived(PeerData *peer, const QVector<MTPMessage> &messages) {
@ -363,7 +371,7 @@ void HistoryInner::enumerateDates(Method method) {
} }
void HistoryInner::paintEvent(QPaintEvent *e) { void HistoryInner::paintEvent(QPaintEvent *e) {
if (!App::main() || (App::wnd() && App::wnd()->contentOverlapped(this, e))) { if (Ui::skipPaintEvent(this, e)) {
return; return;
} }
if (hasPendingResizedItems()) { if (hasPendingResizedItems()) {
@ -371,17 +379,13 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
} }
Painter p(this); Painter p(this);
QRect r(e->rect()); auto clip = e->rect();
bool trivial = (rect() == r);
if (!trivial) {
p.setClipRect(r);
}
auto ms = getms(); auto ms = getms();
bool historyDisplayedEmpty = (_history->isDisplayedEmpty() && (!_migrated || _migrated->isDisplayedEmpty())); bool historyDisplayedEmpty = (_history->isDisplayedEmpty() && (!_migrated || _migrated->isDisplayedEmpty()));
bool noHistoryDisplayed = _firstLoading || historyDisplayedEmpty; bool noHistoryDisplayed = _firstLoading || historyDisplayedEmpty;
if (!_firstLoading && _botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) { 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); p.setTextPalette(st::inTextPalette);
App::roundRect(p, _botAbout->rect, st::msgInBg, MessageInCorners, &st::msgInShadow); App::roundRect(p, _botAbout->rect, st::msgInBg, MessageInCorners, &st::msgInShadow);
@ -398,14 +402,15 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
HistoryLayout::paintEmpty(p, width(), height()); HistoryLayout::paintEmpty(p, width(), height());
} }
if (!noHistoryDisplayed) { if (!noHistoryDisplayed) {
adjustCurrent(r.top()); adjustCurrent(clip.top());
SelectedItems::const_iterator selEnd = _selected.cend(); auto selEnd = _selected.cend();
bool hasSel = !_selected.isEmpty(); 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) { if (selfromy < 0 || seltoy < 0) {
selfromy = seltoy = -1; selfromy = seltoy = -1;
} else { } else {
@ -424,7 +429,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
auto y = mtop + block->y() + item->y(); auto y = mtop + block->y() + item->y();
p.save(); p.save();
p.translate(0, y); p.translate(0, y);
if (r.y() < y + item->height()) while (y < drawToY) { if (clip.y() < y + item->height()) while (y < drawToY) {
TextSelection sel; TextSelection sel;
if (y >= selfromy && y < seltoy) { if (y >= selfromy && y < seltoy) {
if (_dragSelecting && !item->serviceMsg() && item->id > 0) { if (_dragSelecting && !item->serviceMsg() && item->id > 0) {
@ -436,7 +441,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
sel = i.value(); sel = i.value();
} }
} }
item->draw(p, r.translated(0, -y), sel, ms); item->draw(p, clip.translated(0, -y), sel, ms);
if (item->hasViews()) { if (item->hasViews()) {
App::main()->scheduleViewIncrement(item); App::main()->scheduleViewIncrement(item);
@ -465,7 +470,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
auto iItem = (_curHistory == _history ? _curItem : 0); auto iItem = (_curHistory == _history ? _curItem : 0);
auto item = block->items[iItem]; 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(); auto y = htop + block->y() + item->y();
p.save(); p.save();
p.translate(0, y); p.translate(0, y);
@ -507,14 +512,14 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
} }
if (mtop >= 0 || htop >= 0) { 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 // 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; return false;
} }
// paint the userpic if it intersects the painted rect // 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); message->from()->paintUserpicLeft(p, st::historyPhotoLeft, userpicTop, message->history()->width, st::msgPhotoSize);
} }
return true; return true;
@ -530,9 +535,9 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
//int showFloatingBefore = height() - 2 * (_visibleAreaBottom - _visibleAreaTop) - dateHeight; //int showFloatingBefore = height() - 2 * (_visibleAreaBottom - _visibleAreaTop) - dateHeight;
auto scrollDateOpacity = _scrollDateOpacity.current(ms, _scrollDateShown ? 1. : 0.); 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 // stop the enumeration if the date is above the painted rect
if (dateTop + dateHeight <= r.top()) { if (dateTop + dateHeight <= clip.top()) {
return false; return false;
} }
@ -550,7 +555,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
//} //}
// paint the date if it intersects the painted rect // 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; auto opacity = (dateInPlace/* || noFloatingDate*/) ? 1. : scrollDateOpacity;
if (opacity > 0.) { if (opacity > 0.) {
p.setOpacity(opacity); p.setOpacity(opacity);
@ -660,7 +665,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
_touchSelectTimer.stop(); _touchSelectTimer.stop();
_touchScroll = _touchSelect = false; _touchScroll = _touchSelect = false;
_touchScrollState = Ui::TouchScrollState::Manual; _touchScrollState = Ui::TouchScrollState::Manual;
dragActionCancel(); mouseActionCancel();
return; return;
} }
@ -696,7 +701,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
case QEvent::TouchUpdate: case QEvent::TouchUpdate:
if (!_touchInProgress) return; if (!_touchInProgress) return;
if (_touchSelect) { if (_touchSelect) {
dragActionUpdate(_touchPos); mouseActionUpdate(_touchPos);
} else if (!_touchScroll && (_touchPos - _touchStart).manhattanLength() >= QApplication::startDragDistance()) { } else if (!_touchScroll && (_touchPos - _touchStart).manhattanLength() >= QApplication::startDragDistance()) {
_touchSelectTimer.stop(); _touchSelectTimer.stop();
_touchScroll = true; _touchScroll = true;
@ -719,7 +724,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
if (!_touchInProgress) return; if (!_touchInProgress) return;
_touchInProgress = false; _touchInProgress = false;
if (_touchSelect) { if (_touchSelect) {
dragActionFinish(_touchPos, Qt::RightButton); mouseActionFinish(_touchPos, Qt::RightButton);
QContextMenuEvent contextMenu(QContextMenuEvent::Mouse, mapFromGlobal(_touchPos), _touchPos); QContextMenuEvent contextMenu(QContextMenuEvent::Mouse, mapFromGlobal(_touchPos), _touchPos);
showContextMenu(&contextMenu, true); showContextMenu(&contextMenu, true);
_touchScroll = false; _touchScroll = false;
@ -738,9 +743,9 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
_touchWaitingAcceleration = false; _touchWaitingAcceleration = false;
_touchPrevPosValid = false; _touchPrevPosValid = false;
} }
} else { // one short tap -- like mouse click } else { // One short tap is like left mouse click.
dragActionStart(_touchPos); mouseActionStart(_touchPos, Qt::LeftButton);
dragActionFinish(_touchPos); mouseActionFinish(_touchPos, Qt::LeftButton);
} }
_touchSelectTimer.stop(); _touchSelectTimer.stop();
_touchSelect = false; _touchSelect = false;
@ -752,7 +757,7 @@ void HistoryInner::mouseMoveEvent(QMouseEvent *e) {
static auto lastGlobalPosition = e->globalPos(); static auto lastGlobalPosition = e->globalPos();
auto reallyMoved = (lastGlobalPosition != e->globalPos()); auto reallyMoved = (lastGlobalPosition != e->globalPos());
auto buttonsPressed = (e->buttons() & (Qt::LeftButton | Qt::MiddleButton)); auto buttonsPressed = (e->buttons() & (Qt::LeftButton | Qt::MiddleButton));
if (!buttonsPressed && _dragAction != NoDrag) { if (!buttonsPressed && _mouseAction != MouseAction::None) {
mouseReleaseEvent(e); mouseReleaseEvent(e);
} }
if (reallyMoved) { if (reallyMoved) {
@ -761,11 +766,11 @@ void HistoryInner::mouseMoveEvent(QMouseEvent *e) {
keepScrollDateForNow(); keepScrollDateForNow();
} }
} }
dragActionUpdate(e->globalPos()); mouseActionUpdate(e->globalPos());
} }
void HistoryInner::dragActionUpdate(const QPoint &screenPos) { void HistoryInner::mouseActionUpdate(const QPoint &screenPos) {
_dragPos = screenPos; _mousePosition = screenPos;
onUpdateSelected(); onUpdateSelected();
} }
@ -788,11 +793,11 @@ void HistoryInner::mousePressEvent(QMouseEvent *e) {
e->accept(); e->accept();
return; // ignore mouse press, that was hiding context menu 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) { void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton button) {
dragActionUpdate(screenPos); mouseActionUpdate(screenPos);
if (button != Qt::LeftButton) return; if (button != Qt::LeftButton) return;
ClickHandler::pressed(); ClickHandler::pressed();
@ -802,29 +807,29 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
repaintItem(App::pressedItem()); repaintItem(App::pressedItem());
} }
_dragAction = NoDrag; _mouseAction = MouseAction::None;
_dragItem = App::mousedItem(); _mouseActionItem = App::mousedItem();
_dragStartPos = mapMouseToItem(mapFromGlobal(screenPos), _dragItem); _dragStartPosition = mapMouseToItem(mapFromGlobal(screenPos), _mouseActionItem);
_dragWasInactive = App::wnd()->inactivePress(); _pressWasInactive = _controller->window()->wasInactivePress();
if (_dragWasInactive) App::wnd()->inactivePress(false); if (_pressWasInactive) _controller->window()->setInactivePress(false);
if (ClickHandler::getPressed()) { if (ClickHandler::getPressed()) {
_dragAction = PrepareDrag; _mouseAction = MouseAction::PrepareDrag;
} else if (!_selected.isEmpty()) { } else if (!_selected.isEmpty()) {
if (_selected.cbegin().value() == FullSelection) { if (_selected.cbegin().value() == FullSelection) {
if (_selected.constFind(_dragItem) != _selected.cend() && App::hoveredItem()) { if (_selected.constFind(_mouseActionItem) != _selected.cend() && App::hoveredItem()) {
_dragAction = PrepareDrag; // start items drag _mouseAction = MouseAction::PrepareDrag; // start items drag
} else if (!_dragWasInactive) { } else if (!_pressWasInactive) {
_dragAction = PrepareSelect; // start items select _mouseAction = MouseAction::PrepareSelect; // start items select
} }
} }
} }
if (_dragAction == NoDrag && _dragItem) { if (_mouseAction == MouseAction::None && _mouseActionItem) {
HistoryTextState dragState; HistoryTextState dragState;
if (_trippleClickTimer.isActive() && (screenPos - _trippleClickPoint).manhattanLength() < QApplication::startDragDistance()) { if (_trippleClickTimer.isActive() && (screenPos - _trippleClickPoint).manhattanLength() < QApplication::startDragDistance()) {
HistoryStateRequest request; HistoryStateRequest request;
request.flags = Text::StateRequest::Flag::LookupSymbol; request.flags = Text::StateRequest::Flag::LookupSymbol;
dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request); dragState = _mouseActionItem->getState(_dragStartPosition, request);
if (dragState.cursor == HistoryInTextCursorState) { if (dragState.cursor == HistoryInTextCursorState) {
TextSelection selStatus = { dragState.symbol, dragState.symbol }; TextSelection selStatus = { dragState.symbol, dragState.symbol };
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) { 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()); repaintItem(_selected.cbegin().key());
_selected.clear(); _selected.clear();
} }
_selected.insert(_dragItem, selStatus); _selected.insert(_mouseActionItem, selStatus);
_dragSymbol = dragState.symbol; _mouseTextSymbol = dragState.symbol;
_dragAction = Selecting; _mouseAction = MouseAction::Selecting;
_dragSelType = TextSelectType::Paragraphs; _mouseSelectType = TextSelectType::Paragraphs;
dragActionUpdate(_dragPos); mouseActionUpdate(_mousePosition);
_trippleClickTimer.start(QApplication::doubleClickInterval()); _trippleClickTimer.start(QApplication::doubleClickInterval());
} }
} }
} else if (App::pressedItem()) { } else if (App::pressedItem()) {
HistoryStateRequest request; HistoryStateRequest request;
request.flags = Text::StateRequest::Flag::LookupSymbol; 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()) { if (App::pressedItem()) {
_dragSymbol = dragState.symbol; _mouseTextSymbol = dragState.symbol;
bool uponSelected = (dragState.cursor == HistoryInTextCursorState); bool uponSelected = (dragState.cursor == HistoryInTextCursorState);
if (uponSelected) { if (uponSelected) {
if (_selected.isEmpty() || if (_selected.isEmpty() ||
_selected.cbegin().value() == FullSelection || _selected.cbegin().value() == FullSelection ||
_selected.cbegin().key() != _dragItem _selected.cbegin().key() != _mouseActionItem
) { ) {
uponSelected = false; uponSelected = false;
} else { } else {
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to; uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
if (_dragSymbol < selFrom || _dragSymbol >= selTo) { if (_mouseTextSymbol < selFrom || _mouseTextSymbol >= selTo) {
uponSelected = false; uponSelected = false;
} }
} }
} }
if (uponSelected) { if (uponSelected) {
_dragAction = PrepareDrag; // start text drag _mouseAction = MouseAction::PrepareDrag; // start text drag
} else if (!_dragWasInactive) { } else if (!_pressWasInactive) {
if (dynamic_cast<HistorySticker*>(App::pressedItem()->getMedia()) || _dragCursorState == HistoryInDateCursorState) { if (dynamic_cast<HistorySticker*>(App::pressedItem()->getMedia()) || _mouseCursorState == HistoryInDateCursorState) {
_dragAction = PrepareDrag; // start sticker drag or by-date drag _mouseAction = MouseAction::PrepareDrag; // start sticker drag or by-date drag
} else { } else {
if (dragState.afterSymbol) ++_dragSymbol; if (dragState.afterSymbol) ++_mouseTextSymbol;
TextSelection selStatus = { _dragSymbol, _dragSymbol }; TextSelection selStatus = { _mouseTextSymbol, _mouseTextSymbol };
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) { if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
if (!_selected.isEmpty()) { if (!_selected.isEmpty()) {
repaintItem(_selected.cbegin().key()); repaintItem(_selected.cbegin().key());
_selected.clear(); _selected.clear();
} }
_selected.insert(_dragItem, selStatus); _selected.insert(_mouseActionItem, selStatus);
_dragAction = Selecting; _mouseAction = MouseAction::Selecting;
repaintItem(_dragItem); repaintItem(_mouseActionItem);
} else { } else {
_dragAction = PrepareSelect; _mouseAction = MouseAction::PrepareSelect;
} }
} }
} }
} else if (!_dragWasInactive) { } else if (!_pressWasInactive) {
_dragAction = PrepareSelect; // start items select _mouseAction = MouseAction::PrepareSelect; // start items select
} }
} }
} }
if (!_dragItem) { if (!_mouseActionItem) {
_dragAction = NoDrag; _mouseAction = MouseAction::None;
} else if (_dragAction == NoDrag) { } else if (_mouseAction == MouseAction::None) {
_dragItem = nullptr; _mouseActionItem = nullptr;
} }
} }
void HistoryInner::dragActionCancel() { void HistoryInner::mouseActionCancel() {
_dragItem = 0; _mouseActionItem = nullptr;
_dragAction = NoDrag; _mouseAction = MouseAction::None;
_dragStartPos = QPoint(0, 0); _dragStartPosition = QPoint(0, 0);
_dragSelFrom = _dragSelTo = 0; _dragSelFrom = _dragSelTo = nullptr;
_wasSelectedText = false; _wasSelectedText = false;
_widget->noSelectingScroll(); _widget->noSelectingScroll();
} }
void HistoryInner::onDragExec() { void HistoryInner::performDrag() {
if (_dragAction != Dragging) return; if (_mouseAction != MouseAction::Dragging) return;
bool uponSelected = false; bool uponSelected = false;
if (_dragItem) { if (_mouseActionItem) {
if (!_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { if (!_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
uponSelected = _selected.contains(_dragItem); uponSelected = _selected.contains(_mouseActionItem);
} else { } else {
HistoryStateRequest request; HistoryStateRequest request;
request.flags |= Text::StateRequest::Flag::LookupSymbol; 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); uponSelected = (dragState.cursor == HistoryInTextCursorState);
if (uponSelected) { if (uponSelected) {
if (_selected.isEmpty() || if (_selected.isEmpty() ||
_selected.cbegin().value() == FullSelection || _selected.cbegin().value() == FullSelection ||
_selected.cbegin().key() != _dragItem _selected.cbegin().key() != _mouseActionItem
) { ) {
uponSelected = false; uponSelected = false;
} else { } else {
@ -952,7 +957,6 @@ void HistoryInner::onDragExec() {
updateDragSelection(0, 0, false); updateDragSelection(0, 0, false);
_widget->noSelectingScroll(); _widget->noSelectingScroll();
auto drag = std::make_unique<QDrag>(App::wnd());
if (!urls.isEmpty()) mimeData->setUrls(urls); if (!urls.isEmpty()) mimeData->setUrls(urls);
if (uponSelected && !Adaptive::OneColumn()) { if (uponSelected && !Adaptive::OneColumn()) {
auto selectedState = getSelectionState(); auto selectedState = getSelectionState();
@ -960,19 +964,14 @@ void HistoryInner::onDragExec() {
mimeData->setData(qsl("application/x-td-forward-selected"), "1"); mimeData->setData(qsl("application/x-td-forward-selected"), "1");
} }
} }
drag->setMimeData(mimeData); _controller->window()->launchDrag(std::move(mimeData));
drag->exec(Qt::CopyAction);
// We don't receive mouseReleaseEvent when drag is finished.
ClickHandler::unpressed();
if (App::main()) App::main()->updateAfterDrag();
return; return;
} else { } else {
auto forwardMimeType = QString(); auto forwardMimeType = QString();
auto pressedMedia = static_cast<HistoryMedia*>(nullptr); auto pressedMedia = static_cast<HistoryMedia*>(nullptr);
if (auto pressedItem = App::pressedItem()) { if (auto pressedItem = App::pressedItem()) {
pressedMedia = pressedItem->getMedia(); pressedMedia = pressedItem->getMedia();
if (_dragCursorState == HistoryInDateCursorState || (pressedMedia && pressedMedia->dragItem())) { if (_mouseCursorState == HistoryInDateCursorState || (pressedMedia && pressedMedia->dragItem())) {
forwardMimeType = qsl("application/x-td-forward-pressed"); forwardMimeType = qsl("application/x-td-forward-pressed");
} }
} }
@ -984,9 +983,7 @@ void HistoryInner::onDragExec() {
} }
} }
if (!forwardMimeType.isEmpty()) { if (!forwardMimeType.isEmpty()) {
auto drag = std::make_unique<QDrag>(App::wnd());
auto mimeData = std::make_unique<QMimeData>(); auto mimeData = std::make_unique<QMimeData>();
mimeData->setData(forwardMimeType, "1"); mimeData->setData(forwardMimeType, "1");
if (auto document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) { if (auto document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) {
auto filepath = document->filepath(DocumentData::FilePathResolveChecked); auto filepath = document->filepath(DocumentData::FilePathResolveChecked);
@ -997,12 +994,8 @@ void HistoryInner::onDragExec() {
} }
} }
drag->setMimeData(mimeData.release()); // This call enters event loop and can destroy any QObject.
drag->exec(Qt::CopyAction); _controller->window()->launchDrag(std::move(mimeData));
// We don't receive mouseReleaseEvent when drag is finished.
ClickHandler::unpressed();
if (App::main()) App::main()->updateAfterDrag();
return; return;
} }
} }
@ -1022,8 +1015,8 @@ void HistoryInner::itemRemoved(HistoryItem *item) {
_widget->updateTopBarSelection(); _widget->updateTopBarSelection();
} }
if (_dragItem == item) { if (_mouseActionItem == item) {
dragActionCancel(); mouseActionCancel();
} }
if (_dragSelFrom == item || _dragSelTo == item) { if (_dragSelFrom == item || _dragSelTo == item) {
@ -1034,16 +1027,16 @@ void HistoryInner::itemRemoved(HistoryItem *item) {
onUpdateSelected(); onUpdateSelected();
} }
void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton button) { void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton button) {
dragActionUpdate(screenPos); mouseActionUpdate(screenPos);
ClickHandlerPtr activated = ClickHandler::unpressed(); ClickHandlerPtr activated = ClickHandler::unpressed();
if (_dragAction == Dragging) { if (_mouseAction == MouseAction::Dragging) {
activated.clear(); 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 // if we are in selecting items mode perhaps we want to
// toggle selection instead of activating the pressed link // 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 (HistoryMedia *media = pressed->getMedia()) {
if (media->toggleSelectionByHandlerClick(activated)) { if (media->toggleSelectionByHandlerClick(activated)) {
activated.clear(); activated.clear();
@ -1059,52 +1052,52 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
_wasSelectedText = false; _wasSelectedText = false;
if (activated) { if (activated) {
dragActionCancel(); mouseActionCancel();
App::activateClickHandler(activated, button); App::activateClickHandler(activated, button);
return; return;
} }
if (_dragAction == PrepareSelect && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { if (_mouseAction == MouseAction::PrepareSelect && !_pressWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
SelectedItems::iterator i = _selected.find(_dragItem); SelectedItems::iterator i = _selected.find(_mouseActionItem);
if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0) { if (i == _selected.cend() && !_mouseActionItem->serviceMsg() && _mouseActionItem->id > 0) {
if (_selected.size() < MaxSelectedItems) { if (_selected.size() < MaxSelectedItems) {
if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
_selected.clear(); _selected.clear();
} }
_selected.insert(_dragItem, FullSelection); _selected.insert(_mouseActionItem, FullSelection);
} }
} else { } else {
_selected.erase(i); _selected.erase(i);
} }
repaintItem(_dragItem); repaintItem(_mouseActionItem);
} else if (_dragAction == PrepareDrag && !_dragWasInactive && button != Qt::RightButton) { } else if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && button != Qt::RightButton) {
SelectedItems::iterator i = _selected.find(_dragItem); SelectedItems::iterator i = _selected.find(_mouseActionItem);
if (i != _selected.cend() && i.value() == FullSelection) { if (i != _selected.cend() && i.value() == FullSelection) {
_selected.erase(i); _selected.erase(i);
repaintItem(_dragItem); repaintItem(_mouseActionItem);
} else if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { } else if (i == _selected.cend() && !_mouseActionItem->serviceMsg() && _mouseActionItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
if (_selected.size() < MaxSelectedItems) { if (_selected.size() < MaxSelectedItems) {
_selected.insert(_dragItem, FullSelection); _selected.insert(_mouseActionItem, FullSelection);
repaintItem(_dragItem); repaintItem(_mouseActionItem);
} }
} else { } else {
_selected.clear(); _selected.clear();
update(); update();
} }
} else if (_dragAction == Selecting) { } else if (_mouseAction == MouseAction::Selecting) {
if (_dragSelFrom && _dragSelTo) { if (_dragSelFrom && _dragSelTo) {
applyDragSelection(); applyDragSelection();
_dragSelFrom = _dragSelTo = 0; _dragSelFrom = _dragSelTo = 0;
} else if (!_selected.isEmpty() && !_dragWasInactive) { } else if (!_selected.isEmpty() && !_pressWasInactive) {
auto sel = _selected.cbegin().value(); auto sel = _selected.cbegin().value();
if (sel != FullSelection && sel.from == sel.to) { if (sel != FullSelection && sel.from == sel.to) {
_selected.clear(); _selected.clear();
if (App::wnd()) App::wnd()->setInnerFocus(); App::wnd()->setInnerFocus();
} }
} }
} }
_dragAction = NoDrag; _mouseAction = MouseAction::None;
_dragItem = 0; _mouseActionItem = nullptr;
_dragSelType = TextSelectType::Letters; _mouseSelectType = TextSelectType::Letters;
_widget->noSelectingScroll(); _widget->noSelectingScroll();
_widget->updateTopBarSelection(); _widget->updateTopBarSelection();
@ -1116,7 +1109,7 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
} }
void HistoryInner::mouseReleaseEvent(QMouseEvent *e) { void HistoryInner::mouseReleaseEvent(QMouseEvent *e) {
dragActionFinish(e->globalPos(), e->button()); mouseActionFinish(e->globalPos(), e->button());
if (!rect().contains(e->pos())) { if (!rect().contains(e->pos())) {
leaveEvent(e); leaveEvent(e);
} }
@ -1125,22 +1118,22 @@ void HistoryInner::mouseReleaseEvent(QMouseEvent *e) {
void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) { void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) {
if (!_history) return; if (!_history) return;
dragActionStart(e->globalPos(), e->button()); mouseActionStart(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) { 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; HistoryStateRequest request;
request.flags |= Text::StateRequest::Flag::LookupSymbol; 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) { if (dragState.cursor == HistoryInTextCursorState) {
_dragSymbol = dragState.symbol; _mouseTextSymbol = dragState.symbol;
_dragSelType = TextSelectType::Words; _mouseSelectType = TextSelectType::Words;
if (_dragAction == NoDrag) { if (_mouseAction == MouseAction::None) {
_dragAction = Selecting; _mouseAction = MouseAction::Selecting;
TextSelection selStatus = { dragState.symbol, dragState.symbol }; TextSelection selStatus = { dragState.symbol, dragState.symbol };
if (!_selected.isEmpty()) { if (!_selected.isEmpty()) {
repaintItem(_selected.cbegin().key()); repaintItem(_selected.cbegin().key());
_selected.clear(); _selected.clear();
} }
_selected.insert(_dragItem, selStatus); _selected.insert(_mouseActionItem, selStatus);
} }
mouseMoveEvent(e); mouseMoveEvent(e);
@ -1160,7 +1153,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu = 0; _menu = 0;
} }
if (e->reason() == QContextMenuEvent::Mouse) { if (e->reason() == QContextMenuEvent::Mouse) {
dragActionUpdate(e->globalPos()); mouseActionUpdate(e->globalPos());
} }
auto selectedState = getSelectionState(); 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; uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
hasSelected = (selTo > selFrom) ? 1 : 0; hasSelected = (selTo > selFrom) ? 1 : 0;
if (App::mousedItem() && App::mousedItem() == App::hoveredItem()) { if (App::mousedItem() && App::mousedItem() == App::hoveredItem()) {
QPoint mousePos(mapMouseToItem(mapFromGlobal(_dragPos), App::mousedItem())); QPoint mousePos(mapMouseToItem(mapFromGlobal(_mousePosition), App::mousedItem()));
HistoryStateRequest request; HistoryStateRequest request;
request.flags |= Text::StateRequest::Flag::LookupSymbol; 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) { if (dragState.cursor == HistoryInTextCursorState && dragState.symbol >= selFrom && dragState.symbol < selTo) {
isUponSelected = 1; isUponSelected = 1;
} }
@ -1472,7 +1465,7 @@ void HistoryInner::openContextGif() {
if (auto item = App::contextItem()) { if (auto item = App::contextItem()) {
if (auto media = item->getMedia()) { if (auto media = item->getMedia()) {
if (auto document = media->getDocument()) { 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) { void HistoryInner::setToClipboard(const TextWithEntities &forClipboard, QClipboard::Mode mode) {
if (auto data = mimeDataFromTextWithEntities(forClipboard)) { 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 { TextWithEntities HistoryInner::getSelectedText() const {
SelectedItems sel = _selected; SelectedItems sel = _selected;
if (_dragAction == Selecting && _dragSelFrom && _dragSelTo) { if (_mouseAction == MouseAction::Selecting && _dragSelFrom && _dragSelTo) {
applyDragSelection(&sel); applyDragSelection(&sel);
} }
@ -1813,14 +1806,14 @@ void HistoryInner::updateSize() {
if (width() != _scroll->width() || height() != newHeight) { if (width() != _scroll->width() || height() != newHeight) {
resize(_scroll->width(), newHeight); resize(_scroll->width(), newHeight);
dragActionUpdate(QCursor::pos()); mouseActionUpdate(QCursor::pos());
} else { } else {
update(); update();
} }
} }
void HistoryInner::enterEventHook(QEvent *e) { void HistoryInner::enterEventHook(QEvent *e) {
dragActionUpdate(QCursor::pos()); mouseActionUpdate(QCursor::pos());
return TWidget::enterEventHook(e); return TWidget::enterEventHook(e);
} }
@ -1840,7 +1833,7 @@ void HistoryInner::leaveEventHook(QEvent *e) {
HistoryInner::~HistoryInner() { HistoryInner::~HistoryInner() {
delete _menu; delete _menu;
_dragAction = NoDrag; _mouseAction = MouseAction::None;
} }
bool HistoryInner::focusNextPrevChild(bool next) { bool HistoryInner::focusNextPrevChild(bool next) {
@ -1992,7 +1985,7 @@ void HistoryInner::selectItem(HistoryItem *item) {
void HistoryInner::onTouchSelect() { void HistoryInner::onTouchSelect() {
_touchSelect = true; _touchSelect = true;
dragActionStart(_touchPos); mouseActionStart(_touchPos, Qt::LeftButton);
} }
void HistoryInner::onUpdateSelected() { void HistoryInner::onUpdateSelected() {
@ -2000,7 +1993,7 @@ void HistoryInner::onUpdateSelected() {
return; return;
} }
auto mousePos = mapFromGlobal(_dragPos); auto mousePos = mapFromGlobal(_mousePosition);
auto point = _widget->clampMousePosition(mousePos); auto point = _widget->clampMousePosition(mousePos);
HistoryBlock *block = 0; HistoryBlock *block = 0;
@ -2014,7 +2007,7 @@ void HistoryInner::onUpdateSelected() {
App::mousedItem(item); App::mousedItem(item);
m = mapMouseToItem(point, item); m = mapMouseToItem(point, item);
if (item->hasPoint(m.x(), m.y())) { if (item->hasPoint(m)) {
if (App::hoveredItem() != item) { if (App::hoveredItem() != item) {
repaintItem(App::hoveredItem()); repaintItem(App::hoveredItem());
App::hoveredItem(item); App::hoveredItem(item);
@ -2025,25 +2018,25 @@ void HistoryInner::onUpdateSelected() {
App::hoveredItem(0); App::hoveredItem(0);
} }
} }
if (_dragItem && _dragItem->detached()) { if (_mouseActionItem && _mouseActionItem->detached()) {
dragActionCancel(); mouseActionCancel();
} }
HistoryTextState dragState; HistoryTextState dragState;
ClickHandlerHost *lnkhost = nullptr; 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 (point.y() < _historyPaddingTop) {
if (_botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) { 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(); lnkhost = _botAbout.get();
} }
} else if (item) { } else if (item) {
if (item != _dragItem || (m - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()) { if (item != _mouseActionItem || (m - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
if (_dragAction == PrepareDrag) { if (_mouseAction == MouseAction::PrepareDrag) {
_dragAction = Dragging; _mouseAction = MouseAction::Dragging;
QTimer::singleShot(1, this, SLOT(onDragExec())); InvokeQueued(this, [this] { performDrag(); });
} else if (_dragAction == PrepareSelect) { } else if (_mouseAction == MouseAction::PrepareSelect) {
_dragAction = Selecting; _mouseAction = MouseAction::Selecting;
} }
} }
@ -2098,12 +2091,12 @@ void HistoryInner::onUpdateSelected() {
}); });
if (!dragState.link) { if (!dragState.link) {
HistoryStateRequest request; HistoryStateRequest request;
if (_dragAction == Selecting) { if (_mouseAction == MouseAction::Selecting) {
request.flags |= Text::StateRequest::Flag::LookupSymbol; request.flags |= Text::StateRequest::Flag::LookupSymbol;
} else { } else {
selectingText = false; selectingText = false;
} }
dragState = item->getState(m.x(), m.y(), request); dragState = item->getState(m, request);
lnkhost = item; lnkhost = item;
if (!dragState.link && m.x() >= st::historyPhotoLeft && m.x() < st::historyPhotoLeft + st::msgPhotoSize) { if (!dragState.link && m.x() >= st::historyPhotoLeft && m.x() < st::historyPhotoLeft + st::msgPhotoSize) {
if (auto msg = item->toHistoryMessage()) { if (auto msg = item->toHistoryMessage()) {
@ -2128,7 +2121,7 @@ void HistoryInner::onUpdateSelected() {
} }
} }
auto lnkChanged = ClickHandler::setActive(dragState.link, lnkhost); auto lnkChanged = ClickHandler::setActive(dragState.link, lnkhost);
if (lnkChanged || dragState.cursor != _dragCursorState) { if (lnkChanged || dragState.cursor != _mouseCursorState) {
Ui::Tooltip::Hide(); Ui::Tooltip::Hide();
} }
if (dragState.link || dragState.cursor == HistoryInDateCursorState || dragState.cursor == HistoryInForwardedCursorState) { if (dragState.link || dragState.cursor == HistoryInDateCursorState || dragState.cursor == HistoryInForwardedCursorState) {
@ -2136,27 +2129,27 @@ void HistoryInner::onUpdateSelected() {
} }
Qt::CursorShape cur = style::cur_default; Qt::CursorShape cur = style::cur_default;
if (_dragAction == NoDrag) { if (_mouseAction == MouseAction::None) {
_dragCursorState = dragState.cursor; _mouseCursorState = dragState.cursor;
if (dragState.link) { if (dragState.link) {
cur = style::cur_pointer; 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; cur = style::cur_text;
} else if (_dragCursorState == HistoryInDateCursorState) { } else if (_mouseCursorState == HistoryInDateCursorState) {
// cur = style::cur_cross; // cur = style::cur_cross;
} }
} else if (item) { } else if (item) {
if (_dragAction == Selecting) { if (_mouseAction == MouseAction::Selecting) {
auto canSelectMany = (_history != nullptr); auto canSelectMany = (_history != nullptr);
if (selectingText) { if (selectingText) {
uint16 second = dragState.symbol; uint16 second = dragState.symbol;
if (dragState.afterSymbol && _dragSelType == TextSelectType::Letters) { if (dragState.afterSymbol && _mouseSelectType == TextSelectType::Letters) {
++second; ++second;
} }
auto selState = _dragItem->adjustSelection({ qMin(second, _dragSymbol), qMax(second, _dragSymbol) }, _dragSelType); auto selState = _mouseActionItem->adjustSelection({ qMin(second, _mouseTextSymbol), qMax(second, _mouseTextSymbol) }, _mouseSelectType);
if (_selected[_dragItem] != selState) { if (_selected[_mouseActionItem] != selState) {
_selected[_dragItem] = selState; _selected[_mouseActionItem] = selState;
repaintItem(_dragItem); repaintItem(_mouseActionItem);
} }
if (!_wasSelectedText && (selState == FullSelection || selState.from != selState.to)) { if (!_wasSelectedText && (selState == FullSelection || selState.from != selState.to)) {
_wasSelectedText = true; _wasSelectedText = true;
@ -2164,20 +2157,20 @@ void HistoryInner::onUpdateSelected() {
} }
updateDragSelection(0, 0, false); updateDragSelection(0, 0, false);
} else if (canSelectMany) { } else if (canSelectMany) {
auto selectingDown = (itemTop(_dragItem) < itemTop(item)) || (_dragItem == item && _dragStartPos.y() < m.y()); auto selectingDown = (itemTop(_mouseActionItem) < itemTop(item)) || (_mouseActionItem == item && _dragStartPosition.y() < m.y());
auto dragSelFrom = _dragItem, dragSelTo = item; auto dragSelFrom = _mouseActionItem, dragSelTo = item;
if (!dragSelFrom->hasPoint(_dragStartPos.x(), _dragStartPos.y())) { // maybe exclude dragSelFrom if (!dragSelFrom->hasPoint(_dragStartPosition)) { // maybe exclude dragSelFrom
if (selectingDown) { 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); dragSelFrom = (dragSelFrom == dragSelTo) ? 0 : nextItem(dragSelFrom);
} }
} else { } 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); dragSelFrom = (dragSelFrom == dragSelTo) ? 0 : prevItem(dragSelFrom);
} }
} }
} }
if (_dragItem != item) { // maybe exclude dragSelTo if (_mouseActionItem != item) { // maybe exclude dragSelTo
if (selectingDown) { if (selectingDown) {
if (m.y() < dragSelTo->marginTop()) { if (m.y() < dragSelTo->marginTop()) {
dragSelTo = (dragSelFrom == dragSelTo) ? 0 : prevItem(dragSelTo); dragSelTo = (dragSelFrom == dragSelTo) ? 0 : prevItem(dragSelTo);
@ -2199,12 +2192,12 @@ void HistoryInner::onUpdateSelected() {
} }
updateDragSelection(dragSelFrom, dragSelTo, dragSelecting); updateDragSelection(dragSelFrom, dragSelTo, dragSelecting);
} }
} else if (_dragAction == Dragging) { } else if (_mouseAction == MouseAction::Dragging) {
} }
if (ClickHandler::getPressed()) { if (ClickHandler::getPressed()) {
cur = style::cur_pointer; 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) { if (!_dragSelFrom || !_dragSelTo) {
cur = style::cur_text; cur = style::cur_text;
} }
@ -2216,19 +2209,19 @@ void HistoryInner::onUpdateSelected() {
if (!pressedItem->detached()) { if (!pressedItem->detached()) {
if (pressedItem->history() == _history || pressedItem->history() == _migrated) { if (pressedItem->history() == _history || pressedItem->history() == _migrated) {
auto adjustedPoint = mapMouseToItem(point, pressedItem); auto adjustedPoint = mapMouseToItem(point, pressedItem);
pressedItem->updatePressed(adjustedPoint.x(), adjustedPoint.y()); pressedItem->updatePressed(adjustedPoint);
} }
} }
} }
if (_dragAction == Selecting) { if (_mouseAction == MouseAction::Selecting) {
_widget->checkSelectingScroll(mousePos); _widget->checkSelectingScroll(mousePos);
} else { } else {
updateDragSelection(0, 0, false); updateDragSelection(0, 0, false);
_widget->noSelectingScroll(); _widget->noSelectingScroll();
} }
if (_dragAction == NoDrag && (lnkChanged || cur != _cursor)) { if (_mouseAction == MouseAction::None && (lnkChanged || cur != _cursor)) {
setCursor(_cursor = cur); setCursor(_cursor = cur);
} }
} }
@ -2414,7 +2407,7 @@ void HistoryInner::applyDragSelection(SelectedItems *toItems) const {
} }
QString HistoryInner::tooltipText() const { QString HistoryInner::tooltipText() const {
if (_dragCursorState == HistoryInDateCursorState && _dragAction == NoDrag) { if (_mouseCursorState == HistoryInDateCursorState && _mouseAction == MouseAction::None) {
if (App::hoveredItem()) { if (App::hoveredItem()) {
auto dateText = App::hoveredItem()->date.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat)); auto dateText = App::hoveredItem()->date.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat));
if (auto edited = App::hoveredItem()->Get<HistoryMessageEdited>()) { if (auto edited = App::hoveredItem()->Get<HistoryMessageEdited>()) {
@ -2425,7 +2418,7 @@ QString HistoryInner::tooltipText() const {
} }
return dateText; return dateText;
} }
} else if (_dragCursorState == HistoryInForwardedCursorState && _dragAction == NoDrag) { } else if (_mouseCursorState == HistoryInForwardedCursorState && _mouseAction == MouseAction::None) {
if (App::hoveredItem()) { if (App::hoveredItem()) {
if (auto forwarded = App::hoveredItem()->Get<HistoryMessageForwarded>()) { if (auto forwarded = App::hoveredItem()->Get<HistoryMessageForwarded>()) {
return forwarded->_text.originalText(AllTextSelection, ExpandLinksNone); return forwarded->_text.originalText(AllTextSelection, ExpandLinksNone);
@ -2438,14 +2431,14 @@ QString HistoryInner::tooltipText() const {
} }
QPoint HistoryInner::tooltipPos() const { QPoint HistoryInner::tooltipPos() const {
return _dragPos; return _mousePosition;
} }
void HistoryInner::onParentGeometryChanged() { void HistoryInner::onParentGeometryChanged() {
auto mousePos = QCursor::pos(); auto mousePos = QCursor::pos();
auto mouseOver = _widget->rect().contains(_widget->mapFromGlobal(mousePos)); auto mouseOver = _widget->rect().contains(_widget->mapFromGlobal(mousePos));
auto needToUpdate = (_dragAction != NoDrag || _touchScroll || mouseOver); auto needToUpdate = (_mouseAction != MouseAction::None || _touchScroll || mouseOver);
if (needToUpdate) { if (needToUpdate) {
dragActionUpdate(mousePos); mouseActionUpdate(mousePos);
} }
} }

View File

@ -44,11 +44,6 @@ public:
TextWithEntities getSelectedText() const; 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); void touchScrollUpdated(const QPoint &screenPos);
QPoint mapMouseToItem(QPoint p, HistoryItem *item); QPoint mapMouseToItem(QPoint p, HistoryItem *item);
@ -125,13 +120,26 @@ public slots:
void onMenuDestroy(QObject *obj); void onMenuDestroy(QObject *obj);
void onTouchSelect(); void onTouchSelect();
void onTouchScrollTimer(); void onTouchScrollTimer();
void onDragExec();
private slots: private slots:
void onScrollDateCheck(); void onScrollDateCheck();
void onScrollDateHideByTimer(); void onScrollDateHideByTimer();
private: 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 showContextMenu(QContextMenuEvent *e, bool showFromTouch = false);
void itemRemoved(HistoryItem *item); void itemRemoved(HistoryItem *item);
@ -207,20 +215,14 @@ private:
return (_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems()); return (_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems());
} }
enum DragAction { MouseAction _mouseAction = MouseAction::None;
NoDrag = 0x00, TextSelectType _mouseSelectType = TextSelectType::Letters;
PrepareDrag = 0x01, QPoint _dragStartPosition;
Dragging = 0x02, QPoint _mousePosition;
PrepareSelect = 0x03, HistoryItem *_mouseActionItem = nullptr;
Selecting = 0x04, HistoryCursorState _mouseCursorState = HistoryDefaultCursorState;
}; uint16 _mouseTextSymbol = 0;
DragAction _dragAction = NoDrag; bool _pressWasInactive = false;
TextSelectType _dragSelType = TextSelectType::Letters;
QPoint _dragStartPos, _dragPos;
HistoryItem *_dragItem = nullptr;
HistoryCursorState _dragCursorState = HistoryDefaultCursorState;
uint16 _dragSymbol = 0;
bool _dragWasInactive = false;
QPoint _trippleClickPoint; QPoint _trippleClickPoint;
QTimer _trippleClickTimer; QTimer _trippleClickTimer;
@ -232,7 +234,7 @@ private:
bool _dragSelecting = false; bool _dragSelecting = false;
bool _wasSelectedText = false; // was some text selected in current drag action 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 _touchScroll = false;
bool _touchSelect = false; bool _touchSelect = false;
bool _touchInProgress = false; bool _touchInProgress = false;

View File

@ -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); t_assert(_width > 0);
for_const (auto &row, _rows) { 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 // just ignore the buttons that didn't layout well
if (rect.x() + rect.width() > _width) break; if (rect.x() + rect.width() > _width) break;
if (rect.contains(x, y)) { if (rect.contains(point)) {
_savedCoords = QPoint(x, y); _savedCoords = point;
return button.link; return button.link;
} }
} }

View File

@ -298,7 +298,7 @@ public:
int buttonHeight() const; int buttonHeight() const;
virtual int buttonRadius() const = 0; virtual int buttonRadius() const = 0;
virtual void repaint(const HistoryItem *item) const = 0; virtual void repaint(gsl::not_null<const HistoryItem*> item) const = 0;
virtual ~Style() { virtual ~Style() {
} }
@ -330,7 +330,7 @@ public:
int naturalHeight() const; int naturalHeight() const;
void paint(Painter &p, int outerWidth, const QRect &clip, TimeMs ms) 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 clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active);
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed); void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed);
@ -629,12 +629,12 @@ public:
virtual bool needCheck() const { virtual bool needCheck() const {
return out() || (id < 0 && history()->peer->isSelf()); return out() || (id < 0 && history()->peer->isSelf());
} }
virtual bool hasPoint(int x, int y) const { virtual bool hasPoint(QPoint point) const {
return false; return false;
} }
virtual HistoryTextState getState(int x, int y, HistoryStateRequest request) const = 0; virtual HistoryTextState getState(QPoint point, HistoryStateRequest request) const = 0;
virtual void updatePressed(int x, int y) { virtual void updatePressed(QPoint point) {
} }
virtual TextSelection adjustSelection(TextSelection selection, TextSelectType type) const { virtual TextSelection adjustSelection(TextSelection selection, TextSelectType type) const {
@ -745,14 +745,14 @@ public:
virtual int timeWidth() const { virtual int timeWidth() const {
return 0; 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; return false;
} }
int32 skipBlockWidth() const { int skipBlockWidth() const {
return st::msgDateSpace + infoWidth() - st::msgDateDelta.x(); return st::msgDateSpace + infoWidth() - st::msgDateDelta.x();
} }
int32 skipBlockHeight() const { int skipBlockHeight() const {
return st::msgDateFont->height - st::msgDateDelta.y(); return st::msgDateFont->height - st::msgDateDelta.y();
} }
QString skipBlock() const { QString skipBlock() const {

View File

@ -46,8 +46,8 @@ public:
} }
virtual TextWithEntities selectedText(TextSelection selection) const = 0; virtual TextWithEntities selectedText(TextSelection selection) const = 0;
bool hasPoint(int x, int y) const { bool hasPoint(QPoint point) const {
return (x >= 0 && y >= 0 && x < _width && y < _height); return QRect(0, 0, _width, _height).contains(point);
} }
virtual bool isDisplayed() const { virtual bool isDisplayed() const {
@ -65,8 +65,8 @@ public:
return _height; return _height;
} }
virtual void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const = 0; 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 HistoryTextState getState(QPoint point, HistoryStateRequest request) const = 0;
virtual void updatePressed(int x, int y) { virtual void updatePressed(QPoint point) {
} }
virtual int32 addToOverview(AddToOverviewMethod method) { virtual int32 addToOverview(AddToOverviewMethod method) {

View File

@ -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; HistoryTextState result;
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return 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()) { if (isBubbleBottom()) {
height -= st::msgPadding.bottom(); height -= st::msgPadding.bottom();
} }
if (x >= st::msgPadding.left() && y >= height && x < st::msgPadding.left() + captionw && y < _height) { if (QRect(st::msgPadding.left(), height, captionw, _height - height).contains(point)) {
result = _caption.getState(x - st::msgPadding.left(), y - height, captionw, request.forText()); result = _caption.getState(point - QPoint(st::msgPadding.left(), height), captionw, request.forText());
return result; return result;
} }
height -= st::mediaCaptionSkip; height -= st::mediaCaptionSkip;
@ -487,13 +487,13 @@ HistoryTextState HistoryPhoto::getState(int x, int y, HistoryStateRequest reques
width -= st::mediaPadding.left() + st::mediaPadding.right(); width -= st::mediaPadding.left() + st::mediaPadding.right();
height -= skipy + st::mediaPadding.bottom(); 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()) { if (_data->uploading()) {
result.link = _cancell; result.link = _cancell;
} else if (_data->loaded()) { } else if (_data->loaded()) {
result.link = _openl; result.link = _openl;
} else if (_data->loading()) { } else if (_data->loading()) {
DelayedStorageImage *delayed = _data->full->toDelayedStorageImage(); auto delayed = _data->full->toDelayedStorageImage();
if (!delayed || !delayed->location().isNull()) { if (!delayed || !delayed->location().isNull()) {
result.link = _cancell; result.link = _cancell;
} }
@ -501,9 +501,9 @@ HistoryTextState HistoryPhoto::getState(int x, int y, HistoryStateRequest reques
result.link = _savel; result.link = _savel;
} }
if (_caption.isEmpty() && _parent->getMedia() == this) { if (_caption.isEmpty() && _parent->getMedia() == this) {
int32 fullRight = skipx + width, fullBottom = skipy + height; auto fullRight = skipx + width;
bool inDate = _parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); auto fullBottom = skipy + height;
if (inDate) { if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayOverImage)) {
result.cursor = HistoryInDateCursorState; 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; HistoryTextState result;
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return 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()) { if (isBubbleBottom()) {
height -= st::msgPadding.bottom(); height -= st::msgPadding.bottom();
} }
if (x >= st::msgPadding.left() && y >= height && x < st::msgPadding.left() + captionw && y < _height) { if (QRect(st::msgPadding.left(), height, captionw, _height - height).contains(point)) {
result = _caption.getState(x - st::msgPadding.left(), y - height, captionw, request.forText()); result = _caption.getState(point - QPoint(st::msgPadding.left(), height), captionw, request.forText());
} }
height -= st::mediaCaptionSkip; height -= st::mediaCaptionSkip;
} }
width -= st::mediaPadding.left() + st::mediaPadding.right(); width -= st::mediaPadding.left() + st::mediaPadding.right();
height -= skipy + st::mediaPadding.bottom(); 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()) { if (_data->uploading()) {
result.link = _cancell; result.link = _cancell;
} else { } else {
result.link = loaded ? _openl : (_data->loading() ? _cancell : _savel); result.link = loaded ? _openl : (_data->loading() ? _cancell : _savel);
} }
if (_caption.isEmpty() && _parent->getMedia() == this) { if (_caption.isEmpty() && _parent->getMedia() == this) {
int32 fullRight = skipx + width, fullBottom = skipy + height; auto fullRight = skipx + width;
bool inDate = _parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); auto fullBottom = skipy + height;
if (inDate) { if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayOverImage)) {
result.cursor = HistoryInDateCursorState; 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; HistoryTextState result;
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return 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)); 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; result.link = (_data->loading() || _data->uploading()) ? _cancell : _savel;
return result; return result;
} }
if (_data->status != FileUploadFailed) { 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; result.link = (_data->loading() || _data->uploading()) ? thumbed->_linkcancell : thumbed->_linksavel;
return result; 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; 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)); 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; result.link = (_data->loading() || _data->uploading()) ? _cancell : _savel;
return result; return result;
} }
@ -1428,11 +1428,11 @@ HistoryTextState HistoryDocument::getState(int x, int y, HistoryStateRequest req
if (auto voice = Get<HistoryDocumentVoice>()) { if (auto voice = Get<HistoryDocumentVoice>()) {
auto namewidth = _width - nameleft - nameright; auto namewidth = _width - nameleft - nameright;
auto waveformbottom = st::msgFilePadding.top() - topMinus + st::msgWaveformMax + st::msgWaveformMin; 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); auto state = Media::Player::mixer()->currentState(AudioMsgId::Type::Voice);
if (state.id == AudioMsgId(_data, _parent->fullId()) && !Media::Player::IsStoppedOrStopping(state.state)) { if (state.id == AudioMsgId(_data, _parent->fullId()) && !Media::Player::IsStoppedOrStopping(state.state)) {
if (!voice->seeking()) { if (!voice->seeking()) {
voice->setSeekingStart((x - nameleft) / float64(namewidth)); voice->setSeekingStart((point.x() - nameleft) / float64(namewidth));
} }
result.link = voice->_seekl; result.link = voice->_seekl;
return result; 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<HistoryDocumentCaptioned>()) { if (auto captioned = Get<HistoryDocumentCaptioned>()) {
if (y >= bottom) { if (point.y() >= bottom) {
result = captioned->_caption.getState(x - st::msgPadding.left(), y - bottom, _width - st::msgPadding.left() - st::msgPadding.right(), request.forText()); result = captioned->_caption.getState(point - QPoint(st::msgPadding.left(), bottom), _width - st::msgPadding.left() - st::msgPadding.right(), request.forText());
return result; return result;
} }
auto captionw = _width - st::msgPadding.left() - st::msgPadding.right(); 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(); 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; result.link = _openl;
return result; return result;
} }
return result; return result;
} }
void HistoryDocument::updatePressed(int x, int y) { void HistoryDocument::updatePressed(QPoint point) {
if (auto voice = Get<HistoryDocumentVoice>()) { if (auto voice = Get<HistoryDocumentVoice>()) {
if (voice->seeking()) { if (voice->seeking()) {
auto nameleft = 0, nameright = 0; 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(); nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right();
nameright = st::msgFilePadding.left(); 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); 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; HistoryTextState result;
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return 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()) { if (isBubbleBottom()) {
height -= st::msgPadding.bottom(); height -= st::msgPadding.bottom();
} }
if (x >= st::msgPadding.left() && y >= height && x < st::msgPadding.left() + captionw && y < _height) { if (QRect(st::msgPadding.left(), height, captionw, _height - height).contains(point)) {
result = _caption.getState(x - st::msgPadding.left(), y - height, captionw, request.forText()); result = _caption.getState(point - QPoint(st::msgPadding.left(), height), captionw, request.forText());
return result; return result;
} }
height -= st::mediaCaptionSkip; height -= st::mediaCaptionSkip;
@ -2217,13 +2217,13 @@ HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request)
if (rtl()) rectx = _width - rectx - rectw; if (rtl()) rectx = _width - rectx - rectw;
if (forwarded) { 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 breakEverywhere = (forwardedHeightReal > forwardedHeight);
auto textRequest = request.forText(); auto textRequest = request.forText();
if (breakEverywhere) { if (breakEverywhere) {
textRequest.flags |= Text::StateRequest::Flag::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.symbol = 0;
result.afterSymbol = false; result.afterSymbol = false;
if (breakEverywhere) { if (breakEverywhere) {
@ -2236,23 +2236,23 @@ HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request)
recty += forwardedHeight; recty += forwardedHeight;
recth -= forwardedHeight; recth -= forwardedHeight;
} else if (via) { } else if (via) {
int viah = st::msgReplyPadding.top() + st::msgServiceNameFont->height + (reply ? 0 : st::msgReplyPadding.bottom()); auto 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; result.link = via->_lnk;
return result; 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; recty += skip;
recth -= skip; recth -= skip;
} }
if (reply) { 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(); result.link = reply->replyToLink();
return result; 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()) { if (_data->uploading()) {
result.link = _cancell; result.link = _cancell;
} else if (!_gif || !cAutoPlayGif() || _data->isRoundVideo()) { } else if (!_gif || !cAutoPlayGif() || _data->isRoundVideo()) {
@ -2261,9 +2261,9 @@ HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request)
result.link = _openInMediaviewLink; result.link = _openInMediaviewLink;
} }
if (!isChildMedia) { if (!isChildMedia) {
int32 fullRight = usex + skipx + usew, fullBottom = skipy + height; auto fullRight = usex + skipx + usew;
bool inDate = _parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); auto fullBottom = skipy + height;
if (inDate) { if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayOverImage)) {
result.cursor = HistoryInDateCursorState; 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; HistoryTextState result;
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return 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) { if (via) {
int viah = st::msgReplyPadding.top() + st::msgServiceNameFont->height + (reply ? 0 : st::msgReplyPadding.bottom()); 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; result.link = via->_lnk;
return result; return result;
} }
@ -2675,21 +2675,21 @@ HistoryTextState HistorySticker::getState(int x, int y, HistoryStateRequest requ
recth -= skip; recth -= skip;
} }
if (reply) { 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(); result.link = reply->replyToLink();
return result; return result;
} }
} }
} }
if (_parent->getMedia() == this) { if (_parent->getMedia() == this) {
bool inDate = _parent->pointInTime(usex + usew, _height, x, y, InfoDisplayOverImage); if (_parent->pointInTime(usex + usew, _height, point, InfoDisplayOverImage)) {
if (inDate) {
result.cursor = HistoryInDateCursorState; result.cursor = HistoryInDateCursorState;
} }
} }
int pixLeft = usex + (usew - _pixw) / 2, pixTop = (_minh - _pixh) / 2; auto pixLeft = usex + (usew - _pixw) / 2;
if (x >= pixLeft && x < pixLeft + _pixw && y >= pixTop && y < pixTop + _pixh) { auto pixTop = (_minh - _pixh) / 2;
if (QRect(pixLeft, pixTop, _pixw, _pixh).contains(point)) {
result.link = _packLink; result.link = _packLink;
return result; return result;
} }
@ -2885,7 +2885,7 @@ void HistoryContact::draw(Painter &p, const QRect &r, TextSelection selection, T
p.drawTextLeft(nameleft, statustop, width, _phone); 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; HistoryTextState result;
bool out = _parent->out(), isPost = _parent->isPost(), outbg = out && !isPost; 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) { if (_userId) {
nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right(); nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right();
linktop = st::msgFileThumbLinkTop - topMinus; 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; result.link = _linkl;
return result; 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(); result.link = _contact->openLink();
return result; 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); 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; HistoryTextState result;
if (x >= 0 && y >= 0 && x < _width && y < _height) { if (QRect(0, 0, _width, _height).contains(point)) {
result.link = _link; result.link = _link;
return result; 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; HistoryTextState result;
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return 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; auto inThumb = false;
if (_asArticle) { if (_asArticle) {
int32 pw = qMax(_pixw, int16(lineHeight)); 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; inThumb = true;
} }
width -= pw + st::webPagePhotoDelta; width -= pw + st::webPagePhotoDelta;
@ -3488,21 +3488,21 @@ HistoryTextState HistoryWebPage::getState(int x, int y, HistoryStateRequest requ
tshift += lineHeight; tshift += lineHeight;
} }
if (_titleLines) { if (_titleLines) {
if (y >= tshift && y < tshift + _titleLines * lineHeight) { if (point.y() >= tshift && point.y() < tshift + _titleLines * lineHeight) {
Text::StateRequestElided titleRequest = request.forText(); Text::StateRequestElided titleRequest = request.forText();
titleRequest.lines = _titleLines; titleRequest.lines = _titleLines;
result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest); result = _title.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, titleRequest);
} else if (y >= tshift + _titleLines * lineHeight) { } else if (point.y() >= tshift + _titleLines * lineHeight) {
symbolAdd += _title.length(); symbolAdd += _title.length();
} }
tshift += _titleLines * lineHeight; tshift += _titleLines * lineHeight;
} }
if (_descriptionLines) { if (_descriptionLines) {
if (y >= tshift && y < tshift + _descriptionLines * lineHeight) { if (point.y() >= tshift && point.y() < tshift + _descriptionLines * lineHeight) {
Text::StateRequestElided descriptionRequest = request.forText(); Text::StateRequestElided descriptionRequest = request.forText();
descriptionRequest.lines = _descriptionLines; descriptionRequest.lines = _descriptionLines;
result = _description.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, descriptionRequest); result = _description.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, descriptionRequest);
} else if (y >= tshift + _descriptionLines * lineHeight) { } else if (point.y() >= tshift + _descriptionLines * lineHeight) {
symbolAdd += _description.length(); symbolAdd += _description.length();
} }
tshift += _descriptionLines * lineHeight; tshift += _descriptionLines * lineHeight;
@ -3513,11 +3513,11 @@ HistoryTextState HistoryWebPage::getState(int x, int y, HistoryStateRequest requ
auto attachAtTop = !_siteNameWidth && !_titleLines && !_descriptionLines; auto attachAtTop = !_siteNameWidth && !_titleLines && !_descriptionLines;
if (!attachAtTop) tshift += st::mediaInBubbleSkip; 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 attachLeft = padding.left() - bubble.left();
auto attachTop = tshift - bubble.top(); auto attachTop = tshift - bubble.top();
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth(); 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 (result.link && !_data->document && _data->photo && _attach->isReadyForOpen()) {
if (_data->type == WebPageProfile || _data->type == WebPageVideo) { 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; HistoryTextState result;
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return 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 symbolAdd = 0;
auto lineHeight = unitedLineHeight(); auto lineHeight = unitedLineHeight();
if (_titleLines) { if (_titleLines) {
if (y >= tshift && y < tshift + _titleLines * lineHeight) { if (point.y() >= tshift && point.y() < tshift + _titleLines * lineHeight) {
Text::StateRequestElided titleRequest = request.forText(); Text::StateRequestElided titleRequest = request.forText();
titleRequest.lines = _titleLines; titleRequest.lines = _titleLines;
result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest); result = _title.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, titleRequest);
} else if (y >= tshift + _titleLines * lineHeight) { } else if (point.y() >= tshift + _titleLines * lineHeight) {
symbolAdd += _title.length(); symbolAdd += _title.length();
} }
tshift += _titleLines * lineHeight; tshift += _titleLines * lineHeight;
} }
if (_descriptionLines) { if (_descriptionLines) {
if (y >= tshift && y < tshift + _descriptionLines * lineHeight) { if (point.y() >= tshift && point.y() < tshift + _descriptionLines * lineHeight) {
Text::StateRequestElided descriptionRequest = request.forText(); Text::StateRequestElided descriptionRequest = request.forText();
descriptionRequest.lines = _descriptionLines; descriptionRequest.lines = _descriptionLines;
result = _description.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, descriptionRequest); result = _description.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, descriptionRequest);
} else if (y >= tshift + _descriptionLines * lineHeight) { } else if (point.y() >= tshift + _descriptionLines * lineHeight) {
symbolAdd += _description.length(); symbolAdd += _description.length();
} }
tshift += _descriptionLines * lineHeight; tshift += _descriptionLines * lineHeight;
@ -3879,11 +3879,11 @@ HistoryTextState HistoryGame::getState(int x, int y, HistoryStateRequest request
auto attachTop = tshift - bubble.top(); auto attachTop = tshift - bubble.top();
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth(); 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()) { if (_attach->isReadyForOpen()) {
result.link = _openl; result.link = _openl;
} else { } 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; HistoryTextState result;
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return 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 lineHeight = unitedLineHeight();
auto symbolAdd = 0; auto symbolAdd = 0;
if (_titleHeight) { if (_titleHeight) {
if (y >= tshift && y < tshift + _titleHeight) { if (point.y() >= tshift && point.y() < tshift + _titleHeight) {
Text::StateRequestElided titleRequest = request.forText(); Text::StateRequestElided titleRequest = request.forText();
titleRequest.lines = _titleHeight / lineHeight; titleRequest.lines = _titleHeight / lineHeight;
result = _title.getStateElidedLeft(x - padding.left(), y - tshift, width, _width, titleRequest); result = _title.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, titleRequest);
} else if (y >= tshift + _titleHeight) { } else if (point.y() >= tshift + _titleHeight) {
symbolAdd += _title.length(); symbolAdd += _title.length();
} }
tshift += _titleHeight; tshift += _titleHeight;
} }
if (_descriptionHeight) { if (_descriptionHeight) {
if (y >= tshift && y < tshift + _descriptionHeight) { if (point.y() >= tshift && point.y() < tshift + _descriptionHeight) {
result = _description.getStateLeft(x - padding.left(), y - tshift, width, _width, request.forText()); result = _description.getStateLeft(point - QPoint(padding.left(), tshift), width, _width, request.forText());
} else if (y >= tshift + _descriptionHeight) { } else if (point.y() >= tshift + _descriptionHeight) {
symbolAdd += _description.length(); symbolAdd += _description.length();
} }
tshift += _descriptionHeight; tshift += _descriptionHeight;
@ -4297,8 +4297,8 @@ HistoryTextState HistoryInvoice::getState(int x, int y, HistoryStateRequest requ
auto attachTop = tshift - bubble.top(); auto attachTop = tshift - bubble.top();
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth(); 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)) {
result = _attach->getState(x - attachLeft, y - attachTop, request); 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; HistoryTextState result;
auto symbolAdd = 0; auto symbolAdd = 0;
@ -4553,23 +4553,23 @@ HistoryTextState HistoryLocation::getState(int x, int y, HistoryStateRequest req
} }
width -= st::mediaPadding.left() + st::mediaPadding.right(); 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()) { if (!_title.isEmpty()) {
auto titleh = qMin(_title.countHeight(textw), 2 * st::webPageTitleFont->height); auto titleh = qMin(_title.countHeight(textw), 2 * st::webPageTitleFont->height);
if (y >= skipy && y < skipy + titleh) { if (point.y() >= skipy && point.y() < skipy + titleh) {
result = _title.getStateLeft(x - skipx - st::msgPadding.left(), y - skipy, textw, _width, request.forText()); result = _title.getStateLeft(point - QPoint(skipx + st::msgPadding.left(), skipy), textw, _width, request.forText());
return result; return result;
} else if (y >= skipy + titleh) { } else if (point.y() >= skipy + titleh) {
symbolAdd += _title.length(); symbolAdd += _title.length();
} }
skipy += titleh; skipy += titleh;
} }
if (!_description.isEmpty()) { if (!_description.isEmpty()) {
auto descriptionh = qMin(_description.countHeight(textw), 3 * st::webPageDescriptionFont->height); auto descriptionh = qMin(_description.countHeight(textw), 3 * st::webPageDescriptionFont->height);
if (y >= skipy && y < skipy + descriptionh) { if (point.y() >= skipy && point.y() < skipy + descriptionh) {
result = _description.getStateLeft(x - skipx - st::msgPadding.left(), y - skipy, textw, _width, request.forText()); result = _description.getStateLeft(point - QPoint(skipx + st::msgPadding.left(), skipy), textw, _width, request.forText());
} else if (y >= skipy + descriptionh) { } else if (point.y() >= skipy + descriptionh) {
symbolAdd += _description.length(); symbolAdd += _description.length();
} }
skipy += descriptionh; skipy += descriptionh;
@ -4579,12 +4579,12 @@ HistoryTextState HistoryLocation::getState(int x, int y, HistoryStateRequest req
} }
height -= skipy + st::mediaPadding.bottom(); 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; result.link = _link;
int32 fullRight = skipx + width, fullBottom = _height - (skipx ? st::mediaPadding.bottom() : 0); auto fullRight = skipx + width;
bool inDate = _parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); auto fullBottom = _height - (skipx ? st::mediaPadding.bottom() : 0);
if (inDate) { if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayOverImage)) {
result.cursor = HistoryInDateCursorState; result.cursor = HistoryInDateCursorState;
} }
} }

View File

@ -133,7 +133,7 @@ public:
int resizeGetHeight(int width) override; int resizeGetHeight(int width) override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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 { TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
return _caption.adjustSelection(selection, type); return _caption.adjustSelection(selection, type);
@ -226,7 +226,7 @@ public:
int resizeGetHeight(int width) override; int resizeGetHeight(int width) override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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 { TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
return _caption.adjustSelection(selection, type); return _caption.adjustSelection(selection, type);
@ -384,8 +384,8 @@ public:
int resizeGetHeight(int width) override; int resizeGetHeight(int width) override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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;
void updatePressed(int x, int y) override; void updatePressed(QPoint point) override;
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override { TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
if (auto captioned = Get<HistoryDocumentCaptioned>()) { if (auto captioned = Get<HistoryDocumentCaptioned>()) {
@ -491,7 +491,7 @@ public:
int resizeGetHeight(int width) override; int resizeGetHeight(int width) override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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 { TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
return _caption.adjustSelection(selection, type); return _caption.adjustSelection(selection, type);
@ -614,7 +614,7 @@ public:
int resizeGetHeight(int width) override; int resizeGetHeight(int width) override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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 { bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
return true; return true;
@ -682,7 +682,7 @@ public:
void initDimensions() override; void initDimensions() override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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 { bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
return true; return true;
@ -744,7 +744,7 @@ public:
void initDimensions() override; void initDimensions() override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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 { bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
return true; return true;
@ -801,7 +801,7 @@ public:
int resizeGetHeight(int width) override; int resizeGetHeight(int width) override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
bool hasTextForCopy() const override { bool hasTextForCopy() const override {
@ -900,7 +900,7 @@ public:
int resizeGetHeight(int width) override; int resizeGetHeight(int width) override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
bool isAboveMessage() const override { bool isAboveMessage() const override {
@ -1008,7 +1008,7 @@ public:
static QString fillAmountAndCurrency(int amount, const QString &currency); static QString fillAmountAndCurrency(int amount, const QString &currency);
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
bool hasTextForCopy() const override { bool hasTextForCopy() const override {
@ -1091,7 +1091,7 @@ public:
int resizeGetHeight(int32 width) override; int resizeGetHeight(int32 width) override;
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const 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; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
bool hasTextForCopy() const override { bool hasTextForCopy() const override {

View File

@ -350,7 +350,7 @@ const style::TextStyle &HistoryMessage::KeyboardStyle::textStyle() const {
return st::serviceTextStyle; return st::serviceTextStyle;
} }
void HistoryMessage::KeyboardStyle::repaint(const HistoryItem *item) const { void HistoryMessage::KeyboardStyle::repaint(gsl::not_null<const HistoryItem*> item) const {
Ui::repaintHistoryItem(item); Ui::repaintHistoryItem(item);
} }
@ -1640,23 +1640,24 @@ int HistoryMessage::performResizeGetHeight() {
return _height; return _height;
} }
bool HistoryMessage::hasPoint(int x, int y) const { bool HistoryMessage::hasPoint(QPoint point) const {
auto g = countGeometry(); auto g = countGeometry();
if (g.width() < 1) { if (g.width() < 1) {
return false; return false;
} }
if (drawBubble()) { if (drawBubble()) {
return g.contains(x, y); return g.contains(point);
} else if (_media) { } else if (_media) {
return _media->hasPoint(x - g.left(), y - g.top()); return _media->hasPoint(point - g.topLeft());
} else { } else {
return false; return false;
} }
} }
bool HistoryMessage::pointInTime(int32 right, int32 bottom, int x, int y, InfoDisplayType type) const { bool HistoryMessage::pointInTime(int right, int bottom, QPoint point, InfoDisplayType type) const {
int32 infoRight = right, infoBottom = bottom; auto infoRight = right;
auto infoBottom = bottom;
switch (type) { switch (type) {
case InfoDisplayDefault: case InfoDisplayDefault:
infoRight -= st::msgPadding.right() - st::msgDateDelta.x(); 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(); infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y();
break; break;
} }
int32 dateX = infoRight - HistoryMessage::infoWidth() + HistoryMessage::timeLeft(); auto dateX = infoRight - HistoryMessage::infoWidth() + HistoryMessage::timeLeft();
int32 dateY = infoBottom - st::msgDateFont->height; auto dateY = infoBottom - st::msgDateFont->height;
return QRect(dateX, dateY, HistoryMessage::timeWidth(), st::msgDateFont->height).contains(x, y); 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; HistoryTextState result;
auto g = countGeometry(); auto g = countGeometry();
@ -1693,10 +1694,10 @@ HistoryTextState HistoryMessage::getState(int x, int y, HistoryStateRequest requ
if (mediaDisplayed && _media->isBubbleTop()) { if (mediaDisplayed && _media->isBubbleTop()) {
trect.setY(trect.y() - st::msgPadding.top()); trect.setY(trect.y() - st::msgPadding.top());
} else { } else {
if (getStateFromName(x, y, trect, &result)) return result; if (getStateFromName(point, trect, &result)) return result;
if (getStateForwardedInfo(x, y, trect, &result, request)) return result; if (getStateForwardedInfo(point, trect, &result, request)) return result;
if (getStateReplyInfo(x, y, trect, &result)) return result; if (getStateReplyInfo(point, trect, &result)) return result;
if (getStateViaBotIdInfo(x, y, trect, &result)) return result; if (getStateViaBotIdInfo(point, trect, &result)) return result;
} }
if (mediaDisplayed && _media->isBubbleBottom()) { if (mediaDisplayed && _media->isBubbleBottom()) {
trect.setHeight(trect.height() + st::msgPadding.bottom()); 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 mediaLeft = trect.x() - st::msgPadding.left();
auto mediaTop = mediaAboveText ? trect.y() : (trect.y() + trect.height() - mediaHeight); auto mediaTop = mediaAboveText ? trect.y() : (trect.y() + trect.height() - mediaHeight);
if (y >= mediaTop && y < mediaTop + mediaHeight) { if (point.y() >= mediaTop && point.y() < mediaTop + mediaHeight) {
result = _media->getState(x - mediaLeft, y - mediaTop, request); result = _media->getState(point - QPoint(mediaLeft, mediaTop), request);
result.symbol += _text.length(); result.symbol += _text.length();
} else { } else {
if (mediaAboveText) { if (mediaAboveText) {
trect.setY(trect.y() + mediaHeight); trect.setY(trect.y() + mediaHeight);
} }
getStateText(x, y, trect, &result, request); getStateText(point, trect, &result, request);
} }
needDateCheck = !_media->customInfoLayout(); needDateCheck = !_media->customInfoLayout();
} else { } else {
getStateText(x, y, trect, &result, request); getStateText(point, trect, &result, request);
} }
if (needDateCheck) { 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; result.cursor = HistoryInDateCursorState;
} }
} }
} else if (_media) { } else if (_media) {
result = _media->getState(x - g.left(), y - g.top(), request); result = _media->getState(point - g.topLeft(), request);
result.symbol += _text.length(); result.symbol += _text.length();
} }
if (keyboard) { if (keyboard) {
auto keyboardTop = g.top() + g.height() + st::msgBotKbButton.margin; auto keyboardTop = g.top() + g.height() + st::msgBotKbButton.margin;
if (QRect(g.left(), keyboardTop, g.width(), keyboardHeight).contains(x, y)) { if (QRect(g.left(), keyboardTop, g.width(), keyboardHeight).contains(point)) {
result.link = keyboard->getState(x - g.left(), y - keyboardTop); result.link = keyboard->getState(point - g.topLeft());
return result; return result;
} }
} }
@ -1745,7 +1746,7 @@ HistoryTextState HistoryMessage::getState(int x, int y, HistoryStateRequest requ
} }
// Forward to _media. // Forward to _media.
void HistoryMessage::updatePressed(int x, int y) { void HistoryMessage::updatePressed(QPoint point) {
if (!_media) return; if (!_media) return;
auto g = countGeometry(); auto g = countGeometry();
@ -1788,23 +1789,23 @@ void HistoryMessage::updatePressed(int x, int y) {
auto mediaHeight = _media->height(); auto mediaHeight = _media->height();
auto mediaLeft = trect.x() - st::msgPadding.left(); auto mediaLeft = trect.x() - st::msgPadding.left();
auto mediaTop = mediaAboveText ? trect.y() : (trect.y() + trect.height() - mediaHeight); auto mediaTop = mediaAboveText ? trect.y() : (trect.y() + trect.height() - mediaHeight);
_media->updatePressed(x - mediaLeft, y - mediaTop); _media->updatePressed(point - QPoint(mediaLeft, mediaTop));
} }
} else { } 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 (displayFromName()) {
if (y >= trect.top() && y < trect.top() + st::msgNameFont->height) { if (point.y() >= trect.top() && point.y() < trect.top() + st::msgNameFont->height) {
if (x >= trect.left() && x < trect.left() + trect.width() && x < trect.left() + author()->nameText.maxWidth()) { if (point.x() >= trect.left() && point.x() < trect.left() + trect.width() && point.x() < trect.left() + author()->nameText.maxWidth()) {
outResult->link = author()->openLink(); outResult->link = author()->openLink();
return true; return true;
} }
auto forwarded = Get<HistoryMessageForwarded>(); auto forwarded = Get<HistoryMessageForwarded>();
auto via = Get<HistoryMessageVia>(); auto via = Get<HistoryMessageVia>();
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; outResult->link = via->_lnk;
return true; return true;
} }
@ -1814,17 +1815,17 @@ bool HistoryMessage::getStateFromName(int x, int y, QRect &trect, HistoryTextSta
return false; 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()) { if (displayForwardedFrom()) {
auto forwarded = Get<HistoryMessageForwarded>(); auto forwarded = Get<HistoryMessageForwarded>();
auto fwdheight = ((forwarded->_text.maxWidth() > trect.width()) ? 2 : 1) * st::semiboldFont->height; 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 breakEverywhere = (forwarded->_text.countHeight(trect.width()) > 2 * st::semiboldFont->height);
auto textRequest = request.forText(); auto textRequest = request.forText();
if (breakEverywhere) { if (breakEverywhere) {
textRequest.flags |= Text::StateRequest::Flag::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->symbol = 0;
outResult->afterSymbol = false; outResult->afterSymbol = false;
if (breakEverywhere) { if (breakEverywhere) {
@ -1839,11 +1840,11 @@ bool HistoryMessage::getStateForwardedInfo(int x, int y, QRect &trect, HistoryTe
return false; 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<HistoryMessageReply>()) { if (auto reply = Get<HistoryMessageReply>()) {
int32 h = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); int32 h = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
if (y >= trect.top() && y < trect.top() + h) { if (point.y() >= trect.top() && point.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 (reply->replyToMsg && QRect(trect.x(), trect.y() + st::msgReplyPadding.top(), trect.width(), st::msgReplyBarSize.height()).contains(point)) {
outResult->link = reply->replyToLink(); outResult->link = reply->replyToLink();
} }
return true; return true;
@ -1853,10 +1854,10 @@ bool HistoryMessage::getStateReplyInfo(int x, int y, QRect &trect, HistoryTextSt
return false; 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<HistoryMessageForwarded>()) { if (!displayFromName() && !Has<HistoryMessageForwarded>()) {
if (auto via = Get<HistoryMessageVia>()) { if (auto via = Get<HistoryMessageVia>()) {
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; outResult->link = via->_lnk;
return true; return true;
} }
@ -1866,9 +1867,9 @@ bool HistoryMessage::getStateViaBotIdInfo(int x, int y, QRect &trect, HistoryTex
return false; return false;
} }
bool HistoryMessage::getStateText(int x, int y, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const { bool HistoryMessage::getStateText(QPoint point, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const {
if (trect.contains(x, y)) { if (trect.contains(point)) {
*outResult = _text.getState(x - trect.x(), y - trect.y(), trect.width(), request.forText()); *outResult = _text.getState(point - trect.topLeft(), trect.width(), request.forText());
return true; return true;
} }
return false; return false;
@ -2370,7 +2371,7 @@ int HistoryService::resizeContentGetHeight() {
return _height; return _height;
} }
bool HistoryService::hasPoint(int x, int y) const { bool HistoryService::hasPoint(QPoint point) const {
auto g = countGeometry(); auto g = countGeometry();
if (g.width() < 1) { if (g.width() < 1) {
return false; return false;
@ -2385,10 +2386,10 @@ bool HistoryService::hasPoint(int x, int y) const {
if (_media) { if (_media) {
g.setHeight(g.height() - (st::msgServiceMargin.top() + _media->height())); 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; HistoryTextState result;
auto g = countGeometry(); auto g = countGeometry();
@ -2397,12 +2398,12 @@ HistoryTextState HistoryService::getState(int x, int y, HistoryStateRequest requ
} }
if (auto dateh = displayedDateHeight()) { if (auto dateh = displayedDateHeight()) {
y -= dateh; point.setY(point.y() - dateh);
g.setHeight(g.height() - dateh); g.setHeight(g.height() - dateh);
} }
if (auto unreadbar = Get<HistoryMessageUnreadBar>()) { if (auto unreadbar = Get<HistoryMessageUnreadBar>()) {
auto unreadbarh = unreadbar->height(); auto unreadbarh = unreadbar->height();
y -= unreadbarh; point.setY(point.y() - unreadbarh);
g.setHeight(g.height() - 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())); g.setHeight(g.height() - (st::msgServiceMargin.top() + _media->height()));
} }
auto trect = g.marginsAdded(-st::msgServicePadding); auto trect = g.marginsAdded(-st::msgServicePadding);
if (trect.contains(x, y)) { if (trect.contains(point)) {
auto textRequest = request.forText(); auto textRequest = request.forText();
textRequest.align = style::al_center; 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<HistoryServiceGameScore>()) { if (auto gamescore = Get<HistoryServiceGameScore>()) {
if (!result.link && result.cursor == HistoryInTextCursorState && g.contains(x, y)) { if (!result.link && result.cursor == HistoryInTextCursorState && g.contains(point)) {
result.link = gamescore->lnk; result.link = gamescore->lnk;
} }
} else if (auto payment = Get<HistoryServicePayment>()) { } else if (auto payment = Get<HistoryServicePayment>()) {
if (!result.link && result.cursor == HistoryInTextCursorState && g.contains(x, y)) { if (!result.link && result.cursor == HistoryInTextCursorState && g.contains(point)) {
result.link = payment->lnk; result.link = payment->lnk;
} }
} }
} else if (_media) { } 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; return result;
} }

View File

@ -75,11 +75,11 @@ public:
void dependencyItemRemoved(HistoryItem *dependency) override; void dependencyItemRemoved(HistoryItem *dependency) override;
bool hasPoint(int x, int y) const override; bool hasPoint(QPoint point) const override;
bool pointInTime(int32 right, int32 bottom, int x, int y, InfoDisplayType type) const override; bool pointInTime(int right, int bottom, QPoint point, InfoDisplayType type) const override;
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override; HistoryTextState getState(QPoint point, HistoryStateRequest request) const override;
void updatePressed(int x, int y) override; void updatePressed(QPoint point) override;
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override; TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
@ -184,11 +184,11 @@ private:
void paintViaBotIdInfo(Painter &p, QRect &trect, bool selected) const; void paintViaBotIdInfo(Painter &p, QRect &trect, bool selected) const;
void paintText(Painter &p, QRect &trect, TextSelection selection) const; void paintText(Painter &p, QRect &trect, TextSelection selection) const;
bool getStateFromName(int x, int y, QRect &trect, HistoryTextState *outResult) const; bool getStateFromName(QPoint point, QRect &trect, HistoryTextState *outResult) const;
bool getStateForwardedInfo(int x, int y, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const; bool getStateForwardedInfo(QPoint point, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const;
bool getStateReplyInfo(int x, int y, QRect &trect, HistoryTextState *outResult) const; bool getStateReplyInfo(QPoint point, QRect &trect, HistoryTextState *outResult) const;
bool getStateViaBotIdInfo(int x, int y, QRect &trect, HistoryTextState *outResult) const; bool getStateViaBotIdInfo(QPoint point, QRect &trect, HistoryTextState *outResult) const;
bool getStateText(int x, int y, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const; bool getStateText(QPoint point, QRect &trect, HistoryTextState *outResult, const HistoryStateRequest &request) const;
void setMedia(const MTPMessageMedia *media); void setMedia(const MTPMessageMedia *media);
void setReplyMarkup(const MTPReplyMarkup *markup); void setReplyMarkup(const MTPReplyMarkup *markup);
@ -223,7 +223,7 @@ private:
void startPaint(Painter &p) const override; void startPaint(Painter &p) const override;
const style::TextStyle &textStyle() const override; const style::TextStyle &textStyle() const override;
void repaint(const HistoryItem *item) const override; void repaint(gsl::not_null<const HistoryItem*> item) const override;
protected: protected:
void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const override; void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const override;
@ -300,8 +300,8 @@ public:
QRect countGeometry() const; QRect countGeometry() const;
void draw(Painter &p, QRect clip, TextSelection selection, TimeMs ms) const override; void draw(Painter &p, QRect clip, TextSelection selection, TimeMs ms) const override;
bool hasPoint(int x, int y) const override; bool hasPoint(QPoint point) 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 { TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
return _text.adjustSelection(selection, type); return _text.adjustSelection(selection, type);

View File

@ -665,7 +665,7 @@ HistoryWidget::HistoryWidget(QWidget *parent, gsl::not_null<Window::Controller*>
onPreviewCheck(); onPreviewCheck();
} }
})); }));
subscribe(controller->widgetGrabbed(), [this] { subscribe(controller->window()->widgetGrabbed(), [this] {
// Qt bug workaround: QWidget::render() for an arbitrary widget calls // Qt bug workaround: QWidget::render() for an arbitrary widget calls
// sendPendingMoveAndResizeEvents(true, true) for the whole window, // sendPendingMoveAndResizeEvents(true, true) for the whole window,
// which does something like: // which does something like:
@ -2047,10 +2047,6 @@ void HistoryWidget::clearAllLoadRequests() {
_preloadRequest = _preloadDownRequest = _firstLoadRequest = 0; _preloadRequest = _preloadDownRequest = _firstLoadRequest = 0;
} }
void HistoryWidget::updateAfterDrag() {
if (_list) _list->dragActionUpdate(QCursor::pos());
}
void HistoryWidget::updateFieldSubmitSettings() { void HistoryWidget::updateFieldSubmitSettings() {
auto settings = Ui::FlatTextarea::SubmitSettings::Enter; auto settings = Ui::FlatTextarea::SubmitSettings::Enter;
if (_isInlineBot) { 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) { bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId) {
if (MTP::isDefaultHandledError(error)) return false; 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<const HistoryItem*> msg, int row, int col) {
if (msg->id < 0 || _peer != msg->history()->peer) { if (msg->id < 0 || _peer != msg->history()->peer) {
return; return;
} }
@ -3520,7 +3510,7 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC
bool HistoryWidget::botCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req) { bool HistoryWidget::botCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req) {
// show error? // show error?
if (HistoryItem *item = App::histItemById(info.msgId)) { if (auto item = App::histItemById(info.msgId)) {
if (auto markup = item->Get<HistoryMessageReplyMarkup>()) { if (auto markup = item->Get<HistoryMessageReplyMarkup>()) {
if (info.row < markup->rows.size() && info.col < markup->rows.at(info.row).size()) { 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) { if (markup->rows.at(info.row).at(info.col).requestId == req) {
@ -4803,7 +4793,7 @@ bool HistoryWidget::isItemVisible(HistoryItem *item) {
return true; return true;
} }
void HistoryWidget::ui_repaintHistoryItem(const HistoryItem *item) { void HistoryWidget::ui_repaintHistoryItem(gsl::not_null<const HistoryItem*> item) {
if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) { if (_peer && _list && (item->history() == _history || (_migrated && item->history() == _migrated))) {
auto ms = getms(); auto ms = getms();
if (_lastScrolled + kSkipRepaintWhileScrollMs <= ms) { if (_lastScrolled + kSkipRepaintWhileScrollMs <= ms) {

View File

@ -199,7 +199,6 @@ public:
void newUnreadMsg(History *history, HistoryItem *item); void newUnreadMsg(History *history, HistoryItem *item);
void historyToDown(History *history); void historyToDown(History *history);
void historyWasRead(ReadServerHistoryChecks checks); void historyWasRead(ReadServerHistoryChecks checks);
void historyCleared(History *history);
void unreadCountChanged(History *history); void unreadCountChanged(History *history);
QRect historyRect() const; QRect historyRect() const;
@ -315,7 +314,6 @@ public:
void updateHistoryDownPosition(); void updateHistoryDownPosition();
void updateHistoryDownVisibility(); void updateHistoryDownVisibility();
void updateAfterDrag();
void updateFieldSubmitSettings(); void updateFieldSubmitSettings();
void setInnerFocus(); void setInnerFocus();
@ -345,9 +343,9 @@ public:
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override; bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(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<const HistoryItem*> msg, int row, int col);
void ui_repaintHistoryItem(const HistoryItem *item); void ui_repaintHistoryItem(gsl::not_null<const HistoryItem*> item);
PeerData *ui_getPeerForMouseAction(); PeerData *ui_getPeerForMouseAction();
void notify_historyItemLayoutChanged(const HistoryItem *item); void notify_historyItemLayoutChanged(const HistoryItem *item);

View File

@ -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 { void Gif::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
if (x >= 0 && x < _width && y >= 0 && y < st::inlineMediaHeight) { if (QRect(0, 0, _width, st::inlineMediaHeight).contains(point)) {
if (_delete && (rtl() ? _width - x : x) >= _width - st::stickerPanDelete.width() && y < st::stickerPanDelete.height()) { if (_delete && rtlpoint(point, _width).x() >= _width - st::stickerPanDelete.width() && point.y() < st::stickerPanDelete.height()) {
link = _delete; link = _delete;
} else { } else {
link = _send; 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 { void Sticker::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
if (x >= 0 && x < _width && y >= 0 && y < st::inlineMediaHeight) { if (QRect(0, 0, _width, st::inlineMediaHeight).contains(point)) {
link = _send; 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 { void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
if (x >= 0 && x < _width && y >= 0 && y < st::inlineMediaHeight) { if (QRect(0, 0, _width, st::inlineMediaHeight).contains(point)) {
link = _send; 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 { void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
if (x >= 0 && x < st::inlineThumbSize && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::inlineThumbSize) { if (QRect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize).contains(point)) {
link = _link; link = _link;
return; 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; link = _send;
return; 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 { void File::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
if (x >= 0 && x < st::msgFileSize && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::msgFileSize) { if (QRect(0, st::inlineRowMargin, st::msgFileSize, st::msgFileSize).contains(point)) {
link = getShownDocument()->loading() ? _cancel : _open; link = getShownDocument()->loading() ? _cancel : _open;
return; 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; link = _send;
return; 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 { void Contact::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
int left = (st::msgFileSize + st::inlineThumbSkip); if (QRect(0, st::inlineRowMargin, st::msgFileSize, st::inlineThumbSize).contains(point)) {
if (x >= 0 && x < left - st::inlineThumbSkip && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::inlineThumbSize) {
return; 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; link = _send;
return; 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 { void Article::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
int left = _withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : 0; if (_withThumb && QRect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize).contains(point)) {
if (x >= 0 && x < left - st::inlineThumbSkip && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::inlineThumbSize) {
link = _link; link = _link;
return; 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) { if (_url) {
int32 left = st::inlineThumbSize + st::inlineThumbSkip; auto left = st::inlineThumbSize + st::inlineThumbSkip;
int32 titleHeight = qMin(_title.countHeight(_width - left), st::semiboldFont->height * 2); auto titleHeight = qMin(_title.countHeight(_width - left), st::semiboldFont->height * 2);
int32 descriptionLines = 2; auto descriptionLines = 2;
int32 descriptionHeight = qMin(_description.countHeight(_width - left), st::normalFont->height * descriptionLines); auto 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)) { if (rtlrect(left, st::inlineRowMargin + titleHeight + descriptionHeight, _urlWidth, st::normalFont->height, _width).contains(point)) {
link = _url; link = _url;
return; 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; 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; link = _send;
return; return;
} }
if (x >= left && x < _width && y >= 0 && y < _height) { if (QRect(left, 0, _width - left, _height).contains(point)) {
link = _send; link = _send;
return; return;
} }

View File

@ -72,7 +72,7 @@ public:
} }
void paint(Painter &p, const QRect &clip, const PaintContext *context) 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 // ClickHandlerHost interface
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override; 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 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: private:
PhotoData *getShownPhoto() const; PhotoData *getShownPhoto() const;
@ -161,7 +161,7 @@ public:
void preload() const override; void preload() const override;
void paint(Painter &p, const QRect &clip, const PaintContext *context) 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 // ClickHandlerHost interface
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override; void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
@ -185,7 +185,7 @@ public:
void initDimensions() override; void initDimensions() override;
void paint(Painter &p, const QRect &clip, const PaintContext *context) 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;
private: private:
ClickHandlerPtr _link; ClickHandlerPtr _link;
@ -232,7 +232,7 @@ public:
void initDimensions() override; void initDimensions() override;
void paint(Painter &p, const QRect &clip, const PaintContext *context) 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 // ClickHandlerHost interface
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override; void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
@ -295,7 +295,7 @@ public:
int resizeGetHeight(int width) override; int resizeGetHeight(int width) override;
void paint(Painter &p, const QRect &clip, const PaintContext *context) 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;
private: private:
mutable QPixmap _thumb; mutable QPixmap _thumb;
@ -313,7 +313,7 @@ public:
int resizeGetHeight(int width) override; int resizeGetHeight(int width) override;
void paint(Painter &p, const QRect &clip, const PaintContext *context) 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;
private: private:
ClickHandlerPtr _url, _link; ClickHandlerPtr _url, _link;
@ -336,7 +336,7 @@ public:
void initDimensions() override; void initDimensions() override;
void paint(Painter &p, const QRect &clip, const PaintContext *context) 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;
private: private:
void countFrameSize(); void countFrameSize();

View File

@ -640,7 +640,7 @@ void Inner::updateSelected() {
} }
if (col < inlineItems.size()) { if (col < inlineItems.size()) {
sel = row * MatrixRowShift + col; 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); lnkhost = inlineItems.at(col);
} else { } else {
row = col = -1; row = col = -1;

View File

@ -108,38 +108,38 @@ public:
LayoutItemBase(const LayoutItemBase &other) = delete; LayoutItemBase(const LayoutItemBase &other) = delete;
LayoutItemBase &operator=(const LayoutItemBase &other) = delete; LayoutItemBase &operator=(const LayoutItemBase &other) = delete;
int32 maxWidth() const { int maxWidth() const {
return _maxw; return _maxw;
} }
int32 minHeight() const { int minHeight() const {
return _minh; return _minh;
} }
virtual void initDimensions() = 0; virtual void initDimensions() = 0;
virtual int32 resizeGetHeight(int32 width) { virtual int resizeGetHeight(int width) {
_width = qMin(width, _maxw); _width = qMin(width, _maxw);
_height = _minh; _height = _minh;
return _height; 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(); link.clear();
cursor = HistoryDefaultCursorState; cursor = HistoryDefaultCursorState;
} }
virtual void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const { // from text virtual void getSymbol(uint16 &symbol, bool &after, bool &upon, QPoint point) const { // from text
upon = hasPoint(x, y); upon = hasPoint(point);
symbol = upon ? 0xFFFF : 0; symbol = upon ? 0xFFFF : 0;
after = false; after = false;
} }
int32 width() const { int width() const {
return _width; return _width;
} }
int32 height() const { int height() const {
return _height; return _height;
} }
bool hasPoint(int x, int y) const { bool hasPoint(QPoint point) const {
return (x >= 0 && y >= 0 && x < width() && y < height()); return QRect(0, 0, width(), height()).contains(point);
} }
virtual ~LayoutItemBase() { virtual ~LayoutItemBase() {

View File

@ -872,13 +872,17 @@ void MainWidget::notify_migrateUpdated(PeerData *peer) {
_history->notify_migrateUpdated(peer); _history->notify_migrateUpdated(peer);
} }
void MainWidget::ui_repaintHistoryItem(const HistoryItem *item) { void MainWidget::ui_repaintHistoryItem(gsl::not_null<const HistoryItem*> item) {
_history->ui_repaintHistoryItem(item); if (item->isLogEntry()) {
if (item->history()->lastMsg == item) { AuthSession::Current().data().repaintLogEntry().notify(item, true);
item->history()->updateChatListEntry(); } 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 (_overview) _overview->ui_repaintHistoryItem(item);
if (auto last = currentFloatPlayer()) { if (auto last = currentFloatPlayer()) {
last->widget->ui_repaintHistoryItem(item); 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() { void MainWidget::ctrlEnterSubmitUpdated() {
_history->updateFieldSubmitSettings(); _history->updateFieldSubmitSettings();
} }
@ -3197,10 +3193,6 @@ void MainWidget::markActiveHistoryAsRead() {
_history->historyWasRead(ReadServerHistoryChecks::OnlyIfUnread); _history->historyWasRead(ReadServerHistoryChecks::OnlyIfUnread);
} }
void MainWidget::historyCleared(History *history) {
_history->historyCleared(history);
}
void MainWidget::showAnimated(const QPixmap &bgAnimCache, bool back) { void MainWidget::showAnimated(const QPixmap &bgAnimCache, bool back) {
_showBack = back; _showBack = back;
(_showBack ? _cacheOver : _cacheUnder) = bgAnimCache; (_showBack ? _cacheOver : _cacheUnder) = bgAnimCache;

View File

@ -203,7 +203,6 @@ public:
void dialogsToUp(); void dialogsToUp();
void newUnreadMsg(History *history, HistoryItem *item); void newUnreadMsg(History *history, HistoryItem *item);
void markActiveHistoryAsRead(); void markActiveHistoryAsRead();
void historyCleared(History *history);
void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg); void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg);
void peerAfter(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 ptsWaiterStartTimerFor(ChannelData *channel, int32 ms); // ms <= 0 - stop timer
void feedUpdates(const MTPUpdates &updates, uint64 randomId = 0); void feedUpdates(const MTPUpdates &updates, uint64 randomId = 0);
void feedUpdate(const MTPUpdate &update); void feedUpdate(const MTPUpdate &update);
void updateAfterDrag();
void ctrlEnterSubmitUpdated(); void ctrlEnterSubmitUpdated();
void setInnerFocus(); void setInnerFocus();
@ -386,7 +384,7 @@ public:
void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col); 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<const HistoryItem*> item);
void ui_showPeerHistory(quint64 peer, qint32 msgId, Ui::ShowWay way); void ui_showPeerHistory(quint64 peer, qint32 msgId, Ui::ShowWay way);
PeerData *ui_getPeerForMouseAction(); PeerData *ui_getPeerForMouseAction();

View File

@ -131,46 +131,16 @@ MainWindow::MainWindow() {
setLocale(QLocale(QLocale::English, QLocale::UnitedStates)); setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
_inactiveTimer.setSingleShot(true);
connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer()));
subscribe(Global::RefSelfChanged(), [this] { updateGlobalMenu(); }); subscribe(Global::RefSelfChanged(), [this] { updateGlobalMenu(); });
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &data) { subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &data) {
themeUpdated(data); themeUpdated(data);
}); });
subscribe(Messenger::Instance().authSessionChanged(), [this] { checkAuthSession(); });
subscribe(Messenger::Instance().passcodedChanged(), [this] { updateGlobalMenu(); }); subscribe(Messenger::Instance().passcodedChanged(), [this] { updateGlobalMenu(); });
checkAuthSession();
setAttribute(Qt::WA_NoSystemBackground); setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_OpaquePaintEvent);
} }
void MainWindow::checkAuthSession() {
if (AuthSession::Exists()) {
_controller = std::make_unique<Window::Controller>(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() { void MainWindow::initHook() {
Platform::MainWindow::initHook(); Platform::MainWindow::initHook();
@ -368,9 +338,9 @@ void MainWindow::showMainMenu() {
void MainWindow::ensureLayerCreated() { void MainWindow::ensureLayerCreated() {
if (!_layerBg) { if (!_layerBg) {
_layerBg.create(bodyWidget(), _controller.get()); _layerBg.create(bodyWidget(), controller());
if (_controller) { if (controller()) {
_controller->enableGifPauseReason(Window::GifPauseReason::Layer); controller()->enableGifPauseReason(Window::GifPauseReason::Layer);
} }
} }
} }
@ -378,8 +348,8 @@ void MainWindow::ensureLayerCreated() {
void MainWindow::destroyLayerDelayed() { void MainWindow::destroyLayerDelayed() {
if (_layerBg) { if (_layerBg) {
_layerBg.destroyDelayed(); _layerBg.destroyDelayed();
if (_controller) { if (controller()) {
_controller->disableGifPauseReason(Window::GifPauseReason::Layer); controller()->disableGifPauseReason(Window::GifPauseReason::Layer);
} }
} }
} }
@ -756,8 +726,8 @@ void MainWindow::noIntro(Intro::Widget *was) {
void MainWindow::noLayerStack(LayerStackWidget *was) { void MainWindow::noLayerStack(LayerStackWidget *was) {
if (was == _layerBg) { if (was == _layerBg) {
_layerBg = nullptr; _layerBg = nullptr;
if (_controller) { if (controller()) {
_controller->disableGifPauseReason(Window::GifPauseReason::Layer); controller()->disableGifPauseReason(Window::GifPauseReason::Layer);
} }
} }
} }

View File

@ -42,7 +42,6 @@ namespace Theme {
struct BackgroundUpdate; struct BackgroundUpdate;
class WarningWidget; class WarningWidget;
} // namespace Theme } // namespace Theme
class Controller;
} // namespace Window } // namespace Window
namespace Ui { namespace Ui {
@ -78,15 +77,8 @@ public:
MainWindow(); MainWindow();
~MainWindow(); ~MainWindow();
Window::Controller *controller() const {
return _controller.get();
}
void firstShow(); void firstShow();
void inactivePress(bool inactive);
bool inactivePress() const;
void setupPasscode(); void setupPasscode();
void clearPasscode(); void clearPasscode();
void setupIntro(); void setupIntro();
@ -169,8 +161,6 @@ public slots:
void toggleTray(QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Unknown); void toggleTray(QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Unknown);
void toggleDisplayNotifyFromTray(); void toggleDisplayNotifyFromTray();
void onInactiveTimer();
void onClearFinished(int task, void *manager); void onClearFinished(int task, void *manager);
void onClearFailed(int task, void *manager); void onClearFailed(int task, void *manager);
@ -187,7 +177,6 @@ signals:
void checkNewAuthorization(); void checkNewAuthorization();
private: private:
void checkAuthSession();
void showConnecting(const QString &text, const QString &reconnect = QString()); void showConnecting(const QString &text, const QString &reconnect = QString());
void hideConnecting(); void hideConnecting();
@ -211,7 +200,6 @@ private:
QList<DelayedServiceMsg> _delayedServiceMsgs; QList<DelayedServiceMsg> _delayedServiceMsgs;
mtpRequestId _serviceHistoryRequest = 0; mtpRequestId _serviceHistoryRequest = 0;
std::unique_ptr<Window::Controller> _controller;
object_ptr<PasscodeWidget> _passcode = { nullptr }; object_ptr<PasscodeWidget> _passcode = { nullptr };
object_ptr<Intro::Widget> _intro = { nullptr }; object_ptr<Intro::Widget> _intro = { nullptr };
object_ptr<MainWidget> _main = { nullptr }; object_ptr<MainWidget> _main = { nullptr };
@ -223,9 +211,6 @@ private:
Local::ClearManager *_clearManager = nullptr; Local::ClearManager *_clearManager = nullptr;
bool _inactivePress = false;
QTimer _inactiveTimer;
}; };
class PreLaunchWindow : public TWidget { class PreLaunchWindow : public TWidget {

View File

@ -56,7 +56,7 @@ public:
finishDrag(false); finishDrag(false);
} }
} }
void ui_repaintHistoryItem(const HistoryItem *item) { void ui_repaintHistoryItem(gsl::not_null<const HistoryItem*> item) {
if (item == _item) { if (item == _item) {
repaintItem(); repaintItem();
} }

View File

@ -95,7 +95,7 @@ void ListWidget::mouseMoveEvent(QMouseEvent *e) {
if (y <= m.y()) { if (y <= m.y()) {
if (auto media = layout->toMediaItem()) { if (auto media = layout->toMediaItem()) {
item = media->getItem(); item = media->getItem();
media->getState(lnk, cursorState, m.x(), m.y() - y); media->getState(lnk, cursorState, m - QPoint(0, y));
lnkhost = media; 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<const HistoryItem*> item) {
repaintItem(item); repaintItem(item);
} }

View File

@ -33,7 +33,7 @@ class ListWidget : public TWidget, private base::Subscriber {
public: public:
ListWidget(QWidget *parent); ListWidget(QWidget *parent);
void ui_repaintHistoryItem(const HistoryItem *item); void ui_repaintHistoryItem(gsl::not_null<const HistoryItem*> item);
QRect getCurrentTrackGeometry() const; QRect getCurrentTrackGeometry() const;

View File

@ -96,7 +96,7 @@ void Panel::updateControlsGeometry() {
} }
} }
void Panel::ui_repaintHistoryItem(const HistoryItem *item) { void Panel::ui_repaintHistoryItem(gsl::not_null<const HistoryItem*> item) {
if (auto list = static_cast<ListWidget*>(_scroll->widget())) { if (auto list = static_cast<ListWidget*>(_scroll->widget())) {
list->ui_repaintHistoryItem(item); list->ui_repaintHistoryItem(item);
} }

View File

@ -52,7 +52,7 @@ public:
void setPinCallback(ButtonCallback &&callback); void setPinCallback(ButtonCallback &&callback);
void setCloseCallback(ButtonCallback &&callback); void setCloseCallback(ButtonCallback &&callback);
void ui_repaintHistoryItem(const HistoryItem *item); void ui_repaintHistoryItem(gsl::not_null<const HistoryItem*> item);
int bestPositionFor(int left) const; int bestPositionFor(int left) const;

View File

@ -2458,13 +2458,12 @@ bool MediaView::updateOverState(OverState newState) {
void MediaView::updateOver(QPoint pos) { void MediaView::updateOver(QPoint pos) {
ClickHandlerPtr lnk; ClickHandlerPtr lnk;
ClickHandlerHost *lnkhost = nullptr; ClickHandlerHost *lnkhost = nullptr;
if (_saveMsgStarted && _saveMsg.contains(pos)) { 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; lnk = textState.link;
lnkhost = this; lnkhost = this;
} else if (_captionRect.contains(pos)) { } 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; lnk = textState.link;
lnkhost = this; lnkhost = this;
} }

View File

@ -282,8 +282,8 @@ void Photo::ensureCheckboxCreated() {
}); });
} }
void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
if (hasPoint(x, y)) { if (hasPoint(point)) {
link = _link; 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(); bool loaded = _data->loaded();
if (hasPoint(x, y)) { if (hasPoint(point)) {
link = loaded ? _openl : (_data->loading() ? _cancell : _savel); 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(); bool loaded = _data->loaded();
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0; 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; statustop = _st.songStatusTop;
auto inner = rtlrect(_st.songPadding.left(), _st.songPadding.top(), _st.songThumbSize, _st.songThumbSize, _width); 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); link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl);
return; 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) { 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; link = textState.link;
cursor = textState.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState; cursor = textState.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState;
} }
} }
if (hasPoint(x, y) && !link && !_data->loading()) { if (hasPoint(point) && !link && !_data->loading()) {
link = _namel; link = _namel;
return; 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()); bool loaded = _data->loaded() || Local::willStickerImageLoad(_data->mediaKey());
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0; 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; statustop = _st.songStatusTop;
auto inner = rtlrect(_st.songPadding.left(), _st.songPadding.top(), _st.songThumbSize, _st.songThumbSize, _width); 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); link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl);
return; return;
} }
if (hasPoint(x, y) && !_data->loading()) { if (hasPoint(point) && !_data->loading()) {
link = _namel; link = _namel;
return; 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); 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); link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _savel);
return; return;
} }
if (_data->status != FileUploadFailed) { 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; link = _msgl;
return; return;
} }
} }
if (!_data->loading() && _data->isValid()) { 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; link = _namel;
return; 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; link = _namel;
return; 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; 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; link = _photol;
return; 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; top += (st::linksPhotoSize - st::semiboldFont->height - st::normalFont->height) / 2;
} }
if (!_title.isEmpty()) { 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; link = _photol;
return; return;
} }
@ -1224,7 +1224,7 @@ void Link::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, in
top += qMin(st::normalFont->height * 3, _text.countHeight(w)); top += qMin(st::normalFont->height * 3, _text.countHeight(w));
} }
for (int32 i = 0, l = _links.size(); i < l; ++i) { 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; link = _links.at(i).lnk;
return; return;
} }

View File

@ -55,7 +55,7 @@ public:
return nullptr; return nullptr;
} }
MsgId msgId() const { MsgId msgId() const {
const HistoryItem *item = getItem(); auto item = getItem();
return item ? item->id : 0; return item ? item->id : 0;
} }
@ -184,7 +184,7 @@ public:
void initDimensions() override; void initDimensions() override;
int32 resizeGetHeight(int32 width) override; int32 resizeGetHeight(int32 width) override;
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) 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 clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override; void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
@ -211,7 +211,7 @@ public:
void initDimensions() override; void initDimensions() override;
int32 resizeGetHeight(int32 width) override; int32 resizeGetHeight(int32 width) override;
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) 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 clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override; void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
@ -254,7 +254,7 @@ public:
void initDimensions() override; void initDimensions() override;
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) 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: protected:
float64 dataProgress() const override { float64 dataProgress() const override {
@ -291,7 +291,7 @@ public:
void initDimensions() override; void initDimensions() override;
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) 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 { virtual DocumentData *getDocument() const override {
return _data; return _data;
@ -340,7 +340,7 @@ public:
void initDimensions() override; void initDimensions() override;
int32 resizeGetHeight(int32 width) override; int32 resizeGetHeight(int32 width) override;
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) 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: private:
ClickHandlerPtr _photol; ClickHandlerPtr _photol;

View File

@ -92,6 +92,9 @@ OverviewInner::OverviewInner(OverviewWidget *overview, Ui::ScrollArea *scroll, P
invalidateCache(); invalidateCache();
} }
}); });
subscribe(App::wnd()->dragFinished(), [this] {
dragActionUpdate(QCursor::pos());
});
if (_type == OverviewLinks || _type == OverviewFiles) { if (_type == OverviewLinks || _type == OverviewFiles) {
_search->show(); _search->show();
@ -469,8 +472,8 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but
_dragItem = _mousedItem; _dragItem = _mousedItem;
_dragItemIndex = _mousedItemIndex; _dragItemIndex = _mousedItemIndex;
_dragStartPos = mapMouseToItem(mapFromGlobal(screenPos), _dragItem, _dragItemIndex); _dragStartPos = mapMouseToItem(mapFromGlobal(screenPos), _dragItem, _dragItemIndex);
_dragWasInactive = App::wnd()->inactivePress(); _dragWasInactive = App::wnd()->wasInactivePress();
if (_dragWasInactive) App::wnd()->inactivePress(false); if (_dragWasInactive) App::wnd()->setInactivePress(false);
if (ClickHandler::getPressed() && _selected.isEmpty()) { if (ClickHandler::getPressed() && _selected.isEmpty()) {
_dragAction = PrepareDrag; _dragAction = PrepareDrag;
} else if (!_selected.isEmpty()) { } else if (!_selected.isEmpty()) {
@ -564,7 +567,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
_overview->updateTopBarSelection(); _overview->updateTopBarSelection();
} }
void OverviewInner::onDragExec() { void OverviewInner::performDrag() {
if (_dragAction != Dragging) return; if (_dragAction != Dragging) return;
bool uponSelected = false; bool uponSelected = false;
@ -596,25 +599,20 @@ void OverviewInner::onDragExec() {
updateDragSelection(0, -1, 0, -1, false); updateDragSelection(0, -1, 0, -1, false);
_overview->noSelectingScroll(); _overview->noSelectingScroll();
QDrag *drag = new QDrag(App::wnd()); auto mimeData = std::make_unique<QMimeData>();
QMimeData *mimeData = new QMimeData;
if (!sel.isEmpty()) mimeData->setText(sel); if (!sel.isEmpty()) mimeData->setText(sel);
if (!urls.isEmpty()) mimeData->setUrls(urls); if (!urls.isEmpty()) mimeData->setUrls(urls);
if (forwardSelected) { if (forwardSelected) {
mimeData->setData(qsl("application/x-td-forward-selected"), "1"); 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. // This call enters event loop and can destroy any QObject.
ClickHandler::unpressed(); App::wnd()->launchDrag(std::move(mimeData));
if (App::main()) App::main()->updateAfterDrag();
return; return;
} else { } else {
QString forwardMimeType; QString forwardMimeType;
HistoryMedia *pressedMedia = nullptr; HistoryMedia *pressedMedia = nullptr;
if (HistoryItem *pressedLnkItem = App::pressedLinkItem()) { if (auto pressedLnkItem = App::pressedLinkItem()) {
if ((pressedMedia = pressedLnkItem->getMedia())) { if ((pressedMedia = pressedLnkItem->getMedia())) {
if (forwardMimeType.isEmpty() && pressedMedia->dragItemByHandler(pressedHandler)) { if (forwardMimeType.isEmpty() && pressedMedia->dragItemByHandler(pressedHandler)) {
forwardMimeType = qsl("application/x-td-forward-pressed-link"); forwardMimeType = qsl("application/x-td-forward-pressed-link");
@ -622,12 +620,10 @@ void OverviewInner::onDragExec() {
} }
} }
if (!forwardMimeType.isEmpty()) { if (!forwardMimeType.isEmpty()) {
QDrag *drag = new QDrag(App::wnd()); auto mimeData = std::make_unique<QMimeData>();
QMimeData *mimeData = new QMimeData;
mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1"); mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1");
if (DocumentData *document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) { if (auto document = (pressedMedia ? pressedMedia->getDocument() : nullptr)) {
QString filepath = document->filepath(DocumentData::FilePathResolveChecked); auto filepath = document->filepath(DocumentData::FilePathResolveChecked);
if (!filepath.isEmpty()) { if (!filepath.isEmpty()) {
QList<QUrl> urls; QList<QUrl> urls;
urls.push_back(QUrl::fromLocalFile(filepath)); urls.push_back(QUrl::fromLocalFile(filepath));
@ -635,12 +631,8 @@ void OverviewInner::onDragExec() {
} }
} }
drag->setMimeData(mimeData); // This call enters event loop and can destroy any QObject.
drag->exec(Qt::CopyAction); App::wnd()->launchDrag(std::move(mimeData));
// We don't receive mouseReleaseEvent when drag is finished.
ClickHandler::unpressed();
if (App::main()) App::main()->updateAfterDrag();
return; return;
} }
} }
@ -904,7 +896,7 @@ void OverviewInner::onUpdateSelected() {
item = media->getItem(); item = media->getItem();
index = i; index = i;
if (upon) { 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; lnkhost = media;
} }
} }
@ -940,7 +932,7 @@ void OverviewInner::onUpdateSelected() {
if (auto media = _items.at(i)->toMediaItem()) { if (auto media = _items.at(i)->toMediaItem()) {
item = media->getItem(); item = media->getItem();
index = i; index = i;
media->getState(lnk, cursorState, m.x() - _rowsLeft, m.y() - _marginTop - top); media->getState(lnk, cursorState, m - QPoint(_rowsLeft, _marginTop + top));
lnkhost = media; lnkhost = media;
} }
break; break;
@ -989,7 +981,7 @@ void OverviewInner::onUpdateSelected() {
if (_mousedItem != _dragItem || (m - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()) { if (_mousedItem != _dragItem || (m - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()) {
if (_dragAction == PrepareDrag) { if (_dragAction == PrepareDrag) {
_dragAction = Dragging; _dragAction = Dragging;
QTimer::singleShot(1, this, SLOT(onDragExec())); InvokeQueued(this, [this] { performDrag(); });
} else if (_dragAction == PrepareSelect) { } else if (_dragAction == PrepareSelect) {
_dragAction = Selecting; _dragAction = Selecting;
} }
@ -2267,7 +2259,7 @@ void OverviewWidget::grabFinish() {
_topShadow->show(); _topShadow->show();
} }
void OverviewWidget::ui_repaintHistoryItem(const HistoryItem *item) { void OverviewWidget::ui_repaintHistoryItem(gsl::not_null<const HistoryItem*> item) {
if (peer() == item->history()->peer || migratePeer() == item->history()->peer) { if (peer() == item->history()->peer || migratePeer() == item->history()->peer) {
_inner->repaintItem(item); _inner->repaintItem(item);
} }
@ -2283,10 +2275,6 @@ SelectedItemSet OverviewWidget::getSelectedItems() const {
return _inner->getSelectedItems(); return _inner->getSelectedItems();
} }
void OverviewWidget::updateAfterDrag() {
_inner->dragActionUpdate(QCursor::pos());
}
OverviewWidget::~OverviewWidget() { OverviewWidget::~OverviewWidget() {
onClearSelected(); onClearSelected();
updateTopBarSelection(); updateTopBarSelection();

View File

@ -132,8 +132,6 @@ public slots:
void onTouchSelect(); void onTouchSelect();
void onTouchScrollTimer(); void onTouchScrollTimer();
void onDragExec();
bool onSearchMessages(bool searchCache = false); bool onSearchMessages(bool searchCache = false);
void onNeedSearchMessages(); void onNeedSearchMessages();
@ -142,6 +140,7 @@ private:
void invalidateCache(); void invalidateCache();
void resizeItems(); void resizeItems();
void resizeAndRepositionItems(); void resizeAndRepositionItems();
void performDrag();
void itemRemoved(HistoryItem *item); void itemRemoved(HistoryItem *item);
MsgId complexMsgId(const HistoryItem *item) const; MsgId complexMsgId(const HistoryItem *item) const;
@ -333,8 +332,6 @@ public:
SelectedItemSet getSelectedItems() const; SelectedItemSet getSelectedItems() const;
void updateAfterDrag();
void grabStart() override { void grabStart() override {
_inGrab = true; _inGrab = true;
resizeEvent(0); resizeEvent(0);
@ -355,7 +352,7 @@ public:
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override; bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(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<const HistoryItem*> item);
void notify_historyItemLayoutChanged(const HistoryItem *item); void notify_historyItemLayoutChanged(const HistoryItem *item);

View File

@ -93,7 +93,7 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
case WM_ACTIVATE: { case WM_ACTIVATE: {
if (LOWORD(wParam) == WA_CLICKACTIVE) { if (LOWORD(wParam) == WA_CLICKACTIVE) {
App::wnd()->inactivePress(true); App::wnd()->setInactivePress(true);
} }
if (LOWORD(wParam) != WA_INACTIVE) { if (LOWORD(wParam) != WA_INACTIVE) {
App::wnd()->shadowsActivate(); App::wnd()->shadowsActivate();

View File

@ -1020,11 +1020,11 @@ public:
draw(left, top, w, align, yFrom, yTo, selection); draw(left, top, w, align, yFrom, yTo, selection);
} }
Text::StateResult getState(int x, int y, int w, Text::StateRequest request) { Text::StateResult getState(QPoint point, int w, Text::StateRequest request) {
if (!_t->isNull() && y >= 0) { if (!_t->isNull() && point.y() >= 0) {
_lookupRequest = request; _lookupRequest = request;
_lookupX = x; _lookupX = point.x();
_lookupY = y; _lookupY = point.y();
_breakEverywhere = (_lookupRequest.flags & Text::StateRequest::Flag::BreakEverywhere); _breakEverywhere = (_lookupRequest.flags & Text::StateRequest::Flag::BreakEverywhere);
_lookupSymbol = (_lookupRequest.flags & Text::StateRequest::Flag::LookupSymbol); _lookupSymbol = (_lookupRequest.flags & Text::StateRequest::Flag::LookupSymbol);
@ -1036,11 +1036,11 @@ public:
return _lookupResult; return _lookupResult;
} }
Text::StateResult getStateElided(int x, int y, int w, Text::StateRequestElided request) { Text::StateResult getStateElided(QPoint point, int w, Text::StateRequestElided request) {
if (!_t->isNull() && y >= 0 && request.lines > 0) { if (!_t->isNull() && point.y() >= 0 && request.lines > 0) {
_lookupRequest = request; _lookupRequest = request;
_lookupX = x; _lookupX = point.x();
_lookupY = y; _lookupY = point.y();
_breakEverywhere = (_lookupRequest.flags & Text::StateRequest::Flag::BreakEverywhere); _breakEverywhere = (_lookupRequest.flags & Text::StateRequest::Flag::BreakEverywhere);
_lookupSymbol = (_lookupRequest.flags & Text::StateRequest::Flag::LookupSymbol); _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); 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); 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); 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 { TextSelection Text::adjustSelection(TextSelection selection, TextSelectType selectType) const {

View File

@ -146,9 +146,9 @@ public:
bool afterSymbol = false; bool afterSymbol = false;
uint16 symbol = 0; uint16 symbol = 0;
}; };
StateResult getState(int x, int y, int width, StateRequest request = StateRequest()) const; StateResult getState(QPoint point, int width, StateRequest request = StateRequest()) const;
StateResult getStateLeft(int x, int y, int width, int outerw, StateRequest request = StateRequest()) const { StateResult getStateLeft(QPoint point, int width, int outerw, StateRequest request = StateRequest()) const {
return getState(rtl() ? (outerw - x - width) : x, y, width, request); return getState(rtlpoint(point, outerw), width, request);
} }
struct StateRequestElided : public StateRequest { struct StateRequestElided : public StateRequest {
StateRequestElided() { StateRequestElided() {
@ -158,9 +158,9 @@ public:
int lines = 1; int lines = 1;
int removeFromEnd = 0; int removeFromEnd = 0;
}; };
StateResult getStateElided(int x, int y, int width, StateRequestElided request = StateRequestElided()) const; StateResult getStateElided(QPoint point, int width, StateRequestElided request = StateRequestElided()) const;
StateResult getStateElidedLeft(int x, int y, int width, int outerw, StateRequestElided request = StateRequestElided()) const { StateResult getStateElidedLeft(QPoint point, int width, int outerw, StateRequestElided request = StateRequestElided()) const {
return getStateElided(rtl() ? (outerw - x - width) : x, y, width, request); return getStateElided(rtlpoint(point, outerw), width, request);
} }
TextSelection adjustSelection(TextSelection selection, TextSelectType selectType) const; TextSelection adjustSelection(TextSelection selection, TextSelectType selectType) const;

View File

@ -22,7 +22,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "application.h" #include "application.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "window/window_controller.h"
namespace Fonts { namespace Fonts {
namespace { namespace {
@ -156,7 +155,7 @@ QPixmap myGrab(TWidget *target, QRect rect, QColor bg) {
result.fill(bg); result.fill(bg);
} }
App::wnd()->controller()->widgetGrabbed().notify(true); App::wnd()->widgetGrabbed().notify(true);
target->grabStart(); target->grabStart();
target->render(&result, QPoint(0, 0), rect, QWidget::DrawChildren | QWidget::IgnoreMask); target->render(&result, QPoint(0, 0), rect, QWidget::DrawChildren | QWidget::IgnoreMask);

View File

@ -262,8 +262,8 @@ Text::StateResult FlatLabel::dragActionStart(const QPoint &p, Qt::MouseButton bu
ClickHandler::pressed(); ClickHandler::pressed();
_dragAction = NoDrag; _dragAction = NoDrag;
_dragWasInactive = App::wnd()->inactivePress(); _dragWasInactive = App::wnd()->wasInactivePress();
if (_dragWasInactive) App::wnd()->inactivePress(false); if (_dragWasInactive) App::wnd()->setInactivePress(false);
if (ClickHandler::getPressed()) { if (ClickHandler::getPressed()) {
_dragStartPosition = mapFromGlobal(_lastMousePos); _dragStartPosition = mapFromGlobal(_lastMousePos);
@ -750,9 +750,9 @@ Text::StateResult FlatLabel::getTextState(const QPoint &m) const {
if (_breakEverywhere) { if (_breakEverywhere) {
request.flags |= Text::StateRequest::Flag::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 { } 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; return state;

View File

@ -24,12 +24,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_window.h" #include "styles/style_window.h"
#include "platform/platform_window_title.h" #include "platform/platform_window_title.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "window/window_controller.h"
#include "mediaview.h" #include "mediaview.h"
#include "messenger.h" #include "messenger.h"
#include "mainwindow.h" #include "mainwindow.h"
namespace Window { namespace Window {
constexpr auto kInactivePressTimeout = 200;
QImage LoadLogo() { QImage LoadLogo() {
return QImage(qsl(":/gui/art/logo_256.png")); return QImage(qsl(":/gui/art/logo_256.png"));
} }
@ -58,8 +61,7 @@ MainWindow::MainWindow() : QWidget()
, _positionUpdatedTimer(this) , _positionUpdatedTimer(this)
, _body(this) , _body(this)
, _icon(CreateIcon()) , _icon(CreateIcon())
, _titleText(qsl("Telegram")) , _titleText(qsl("Telegram")) {
, _isActiveTimer(this) {
subscribe(Theme::Background(), [this](const Theme::BackgroundUpdate &data) { subscribe(Theme::Background(), [this](const Theme::BackgroundUpdate &data) {
if (data.paletteChanged()) { if (data.paletteChanged()) {
if (_title) { if (_title) {
@ -70,9 +72,11 @@ MainWindow::MainWindow() : QWidget()
}); });
subscribe(Global::RefUnreadCounterUpdate(), [this] { updateUnreadCounter(); }); subscribe(Global::RefUnreadCounterUpdate(), [this] { updateUnreadCounter(); });
subscribe(Global::RefWorkMode(), [this](DBIWorkMode mode) { workmodeUpdated(mode); }); subscribe(Global::RefWorkMode(), [this](DBIWorkMode mode) { workmodeUpdated(mode); });
subscribe(Messenger::Instance().authSessionChanged(), [this] { checkAuthSession(); });
checkAuthSession();
_isActiveTimer->setSingleShot(true); _isActiveTimer.setCallback([this] { updateIsActive(0); });
connect(_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActiveByTimer())); _inactivePressTimer.setCallback([this] { setInactivePress(false); });
} }
bool MainWindow::hideNoQuit() { bool MainWindow::hideNoQuit() {
@ -140,8 +144,8 @@ bool MainWindow::ui_isMediaViewShown() {
} }
void MainWindow::updateIsActive(int timeout) { void MainWindow::updateIsActive(int timeout) {
if (timeout) { if (timeout > 0) {
return _isActiveTimer->start(timeout); return _isActiveTimer.callOnce(timeout);
} }
_isActive = computeIsActive(); _isActive = computeIsActive();
updateIsActiveHook(); updateIsActiveHook();
@ -433,6 +437,36 @@ PeerData *MainWindow::ui_getPeerForMouseAction() {
return nullptr; return nullptr;
} }
void MainWindow::launchDrag(std::unique_ptr<QMimeData> data) {
auto weak = QPointer<MainWindow>(this);
auto drag = std::make_unique<QDrag>(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<Window::Controller>(this);
} else {
_controller = nullptr;
}
}
void MainWindow::setInactivePress(bool inactive) {
_wasInactivePress = inactive;
if (_wasInactivePress) {
_inactivePressTimer.callOnce(kInactivePressTimeout);
} else {
_inactivePressTimer.cancel();
}
}
MainWindow::~MainWindow() = default; MainWindow::~MainWindow() = default;
} // namespace Window } // namespace Window

View File

@ -21,11 +21,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once #pragma once
#include "window/window_title.h" #include "window/window_title.h"
#include "base/timer.h"
class MediaView; class MediaView;
namespace Window { namespace Window {
class Controller;
class TitleWidget; class TitleWidget;
QImage LoadLogo(); QImage LoadLogo();
@ -38,6 +40,14 @@ class MainWindow : public QWidget, protected base::Subscriber {
public: public:
MainWindow(); MainWindow();
Window::Controller *controller() const {
return _controller.get();
}
void setInactivePress(bool inactive);
bool wasInactivePress() const {
return _wasInactivePress;
}
bool hideNoQuit(); bool hideNoQuit();
void hideMediaview(); void hideMediaview();
@ -90,6 +100,14 @@ public:
} }
virtual PeerData *ui_getPeerForMouseAction(); virtual PeerData *ui_getPeerForMouseAction();
void launchDrag(std::unique_ptr<QMimeData> data);
base::Observable<void> &dragFinished() {
return _dragFinished;
}
base::Observable<void> &widgetGrabbed() {
return _widgetGrabbed;
}
public slots: public slots:
bool minimizeToTray(); bool minimizeToTray();
void updateGlobalMenu() { void updateGlobalMenu() {
@ -154,11 +172,9 @@ private slots:
savePosition(); savePosition();
} }
void onReActivate(); void onReActivate();
void updateIsActiveByTimer() {
updateIsActive(0);
}
private: private:
void checkAuthSession();
void updatePalette(); void updatePalette();
void updateUnreadCounter(); void updateUnreadCounter();
void initSize(); void initSize();
@ -168,6 +184,7 @@ private:
object_ptr<QTimer> _positionUpdatedTimer; object_ptr<QTimer> _positionUpdatedTimer;
bool _positionInited = false; bool _positionInited = false;
std::unique_ptr<Window::Controller> _controller;
object_ptr<TitleWidget> _title = { nullptr }; object_ptr<TitleWidget> _title = { nullptr };
object_ptr<TWidget> _body; object_ptr<TWidget> _body;
object_ptr<TWidget> _rightColumn = { nullptr }; object_ptr<TWidget> _rightColumn = { nullptr };
@ -175,11 +192,16 @@ private:
QIcon _icon; QIcon _icon;
QString _titleText; QString _titleText;
object_ptr<QTimer> _isActiveTimer;
bool _isActive = false; bool _isActive = false;
base::Timer _isActiveTimer;
bool _wasInactivePress = false;
base::Timer _inactivePressTimer;
object_ptr<MediaView> _mediaView = { nullptr }; object_ptr<MediaView> _mediaView = { nullptr };
base::Observable<void> _dragFinished;
base::Observable<void> _widgetGrabbed;
}; };
} // namespace Window } // namespace Window

View File

@ -68,9 +68,6 @@ public:
base::Observable<void> &floatPlayerAreaUpdated() { base::Observable<void> &floatPlayerAreaUpdated() {
return _floatPlayerAreaUpdated; return _floatPlayerAreaUpdated;
} }
base::Observable<void> &widgetGrabbed() {
return _widgetGrabbed;
}
struct ColumnLayout { struct ColumnLayout {
int bodyWidth; int bodyWidth;
@ -111,7 +108,6 @@ private:
GifPauseReasons _gifPauseReasons = { 0 }; GifPauseReasons _gifPauseReasons = { 0 };
base::Observable<void> _gifPauseLevelChanged; base::Observable<void> _gifPauseLevelChanged;
base::Observable<void> _floatPlayerAreaUpdated; base::Observable<void> _floatPlayerAreaUpdated;
base::Observable<void> _widgetGrabbed;
base::Variable<float64> _dialogsWidthRatio = { kDefaultDialogsWidthRatio }; base::Variable<float64> _dialogsWidthRatio = { kDefaultDialogsWidthRatio };
base::Variable<bool> _dialogsListFocused = { false }; base::Variable<bool> _dialogsListFocused = { false };