Allow selecting text in webpage previews.
This commit is contained in:
parent
8e369a4aa5
commit
728ed02a1c
|
@ -1673,7 +1673,10 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
|
||||||
Ui::MarkInactivePress(_controller->widget(), false);
|
Ui::MarkInactivePress(_controller->widget(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ClickHandler::getPressed()) {
|
const auto pressed = ClickHandler::getPressed();
|
||||||
|
if (pressed
|
||||||
|
&& (!Element::Hovered()
|
||||||
|
|| !Element::Hovered()->allowTextSelectionByHandler(pressed))) {
|
||||||
_mouseAction = MouseAction::PrepareDrag;
|
_mouseAction = MouseAction::PrepareDrag;
|
||||||
} else if (inSelectionMode()) {
|
} else if (inSelectionMode()) {
|
||||||
if (_dragStateItem
|
if (_dragStateItem
|
||||||
|
@ -3837,6 +3840,10 @@ void HistoryInner::mouseActionUpdate() {
|
||||||
selState = view->adjustSelection(selState, _mouseSelectType);
|
selState = view->adjustSelection(selState, _mouseSelectType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!selState.empty()) {
|
||||||
|
// We started selecting text in web page preview.
|
||||||
|
ClickHandler::unpressed();
|
||||||
|
}
|
||||||
if (_selected[_mouseActionItem] != selState) {
|
if (_selected[_mouseActionItem] != selState) {
|
||||||
_selected[_mouseActionItem] = selState;
|
_selected[_mouseActionItem] = selState;
|
||||||
repaintItem(_mouseActionItem);
|
repaintItem(_mouseActionItem);
|
||||||
|
|
|
@ -1424,7 +1424,12 @@ HistoryMessageReply *Element::displayedReply() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Element::toggleSelectionByHandlerClick(
|
bool Element::toggleSelectionByHandlerClick(
|
||||||
const ClickHandlerPtr &handler) const {
|
const ClickHandlerPtr &handler) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Element::allowTextSelectionByHandler(
|
||||||
|
const ClickHandlerPtr &handler) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -462,6 +462,8 @@ public:
|
||||||
}
|
}
|
||||||
[[nodiscard]] virtual bool toggleSelectionByHandlerClick(
|
[[nodiscard]] virtual bool toggleSelectionByHandlerClick(
|
||||||
const ClickHandlerPtr &handler) const;
|
const ClickHandlerPtr &handler) const;
|
||||||
|
[[nodiscard]] virtual bool allowTextSelectionByHandler(
|
||||||
|
const ClickHandlerPtr &handler) const;
|
||||||
|
|
||||||
struct VerticalRepaintRange {
|
struct VerticalRepaintRange {
|
||||||
int top = 0;
|
int top = 0;
|
||||||
|
|
|
@ -3148,6 +3148,16 @@ bool Message::toggleSelectionByHandlerClick(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Message::allowTextSelectionByHandler(
|
||||||
|
const ClickHandlerPtr &handler) const {
|
||||||
|
if (const auto media = this->media()) {
|
||||||
|
if (media->allowTextSelectionByHandler(handler)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Message::hasFromName() const {
|
bool Message::hasFromName() const {
|
||||||
switch (context()) {
|
switch (context()) {
|
||||||
case Context::AdminLog:
|
case Context::AdminLog:
|
||||||
|
|
|
@ -140,6 +140,8 @@ public:
|
||||||
[[nodiscard]] HistoryMessageReply *displayedReply() const override;
|
[[nodiscard]] HistoryMessageReply *displayedReply() const override;
|
||||||
[[nodiscard]] bool toggleSelectionByHandlerClick(
|
[[nodiscard]] bool toggleSelectionByHandlerClick(
|
||||||
const ClickHandlerPtr &handler) const override;
|
const ClickHandlerPtr &handler) const override;
|
||||||
|
[[nodiscard]] bool allowTextSelectionByHandler(
|
||||||
|
const ClickHandlerPtr &handler) const override;
|
||||||
[[nodiscard]] int infoWidth() const override;
|
[[nodiscard]] int infoWidth() const override;
|
||||||
[[nodiscard]] int bottomInfoFirstLineWidth() const override;
|
[[nodiscard]] int bottomInfoFirstLineWidth() const override;
|
||||||
[[nodiscard]] bool bottomInfoIsWide() const override;
|
[[nodiscard]] bool bottomInfoIsWide() const override;
|
||||||
|
|
|
@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/cached_round_corners.h"
|
#include "ui/cached_round_corners.h"
|
||||||
#include "ui/chat/chat_style.h"
|
#include "ui/chat/chat_style.h"
|
||||||
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
#include "ui/power_saving.h"
|
#include "ui/power_saving.h"
|
||||||
#include "core/ui_integration.h"
|
#include "core/ui_integration.h"
|
||||||
|
@ -226,6 +227,13 @@ void Game::draw(Painter &p, const PaintContext &context) const {
|
||||||
Ui::Text::ValidateQuotePaintCache(*cache, _st);
|
Ui::Text::ValidateQuotePaintCache(*cache, _st);
|
||||||
Ui::Text::FillQuotePaint(p, outer, *cache, _st);
|
Ui::Text::FillQuotePaint(p, outer, *cache, _st);
|
||||||
|
|
||||||
|
if (_ripple) {
|
||||||
|
_ripple->paint(p, outer.x(), outer.y(), width(), &cache->bg);
|
||||||
|
if (_ripple->empty()) {
|
||||||
|
_ripple = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto lineHeight = UnitedLineHeight();
|
auto lineHeight = UnitedLineHeight();
|
||||||
if (_titleLines) {
|
if (_titleLines) {
|
||||||
p.setPen(cache->icon);
|
p.setPen(cache->icon);
|
||||||
|
@ -322,7 +330,6 @@ TextState Game::textState(QPoint point, StateRequest request) const {
|
||||||
auto tshift = inner.top();
|
auto tshift = inner.top();
|
||||||
auto paintw = inner.width();
|
auto paintw = inner.width();
|
||||||
|
|
||||||
auto inThumb = false;
|
|
||||||
auto symbolAdd = 0;
|
auto symbolAdd = 0;
|
||||||
auto lineHeight = UnitedLineHeight();
|
auto lineHeight = UnitedLineHeight();
|
||||||
if (_titleLines) {
|
if (_titleLines) {
|
||||||
|
@ -353,11 +360,7 @@ TextState Game::textState(QPoint point, StateRequest request) const {
|
||||||
}
|
}
|
||||||
tshift += _descriptionLines * lineHeight;
|
tshift += _descriptionLines * lineHeight;
|
||||||
}
|
}
|
||||||
if (inThumb) {
|
if (_attach) {
|
||||||
if (_parent->data()->isHistoryEntry()) {
|
|
||||||
result.link = _openl;
|
|
||||||
}
|
|
||||||
} else if (_attach) {
|
|
||||||
auto attachAtTop = !_titleLines && !_descriptionLines;
|
auto attachAtTop = !_titleLines && !_descriptionLines;
|
||||||
if (!attachAtTop) tshift += st::mediaInBubbleSkip;
|
if (!attachAtTop) tshift += st::mediaInBubbleSkip;
|
||||||
|
|
||||||
|
@ -375,6 +378,12 @@ TextState Game::textState(QPoint point, StateRequest request) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_parent->data()->isHistoryEntry()) {
|
||||||
|
if (!result.link && outer.contains(point)) {
|
||||||
|
result.link = _openl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_lastPoint = point - outer.topLeft();
|
||||||
|
|
||||||
result.symbol += symbolAdd;
|
result.symbol += symbolAdd;
|
||||||
return result;
|
return result;
|
||||||
|
@ -399,11 +408,41 @@ void Game::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
|
void Game::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
|
||||||
|
if (p == _openl) {
|
||||||
|
if (pressed) {
|
||||||
|
if (!_ripple) {
|
||||||
|
const auto full = QRect(0, 0, width(), height());
|
||||||
|
const auto outer = full.marginsRemoved(inBubblePadding());
|
||||||
|
const auto owner = &parent()->history()->owner();
|
||||||
|
_ripple = std::make_unique<Ui::RippleAnimation>(
|
||||||
|
st::defaultRippleAnimation,
|
||||||
|
Ui::RippleAnimation::RoundRectMask(
|
||||||
|
outer.size(),
|
||||||
|
_st.radius),
|
||||||
|
[=] { owner->requestViewRepaint(parent()); });
|
||||||
|
}
|
||||||
|
_ripple->add(_lastPoint);
|
||||||
|
} else if (_ripple) {
|
||||||
|
_ripple->lastStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (_attach) {
|
if (_attach) {
|
||||||
_attach->clickHandlerPressedChanged(p, pressed);
|
_attach->clickHandlerPressedChanged(p, pressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Game::toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const {
|
||||||
|
return _attach && _attach->toggleSelectionByHandlerClick(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Game::allowTextSelectionByHandler(const ClickHandlerPtr &p) const {
|
||||||
|
return (p == _openl);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Game::dragItemByHandler(const ClickHandlerPtr &p) const {
|
||||||
|
return _attach && _attach->dragItemByHandler(p);
|
||||||
|
}
|
||||||
|
|
||||||
TextForMimeData Game::selectedText(TextSelection selection) const {
|
TextForMimeData Game::selectedText(TextSelection selection) const {
|
||||||
auto titleResult = _title.toTextForMimeData(selection);
|
auto titleResult = _title.toTextForMimeData(selection);
|
||||||
auto descriptionResult = _description.toTextForMimeData(
|
auto descriptionResult = _description.toTextForMimeData(
|
||||||
|
|
|
@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
class ReplyMarkupClickHandler;
|
class ReplyMarkupClickHandler;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class RippleAnimation;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
|
|
||||||
class Game : public Media {
|
class Game : public Media {
|
||||||
|
@ -35,12 +39,11 @@ public:
|
||||||
return false; // we do not add _title and _description in FullSelection text copy.
|
return false; // we do not add _title and _description in FullSelection text copy.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
bool toggleSelectionByHandlerClick(
|
||||||
return _attach && _attach->toggleSelectionByHandlerClick(p);
|
const ClickHandlerPtr &p) const override;
|
||||||
}
|
bool allowTextSelectionByHandler(
|
||||||
bool dragItemByHandler(const ClickHandlerPtr &p) const override {
|
const ClickHandlerPtr &p) const override;
|
||||||
return _attach && _attach->dragItemByHandler(p);
|
bool dragItemByHandler(const ClickHandlerPtr &p) const override;
|
||||||
}
|
|
||||||
|
|
||||||
TextForMimeData selectedText(TextSelection selection) const override;
|
TextForMimeData selectedText(TextSelection selection) const override;
|
||||||
|
|
||||||
|
@ -102,7 +105,9 @@ private:
|
||||||
const not_null<GameData*> _data;
|
const not_null<GameData*> _data;
|
||||||
std::shared_ptr<ReplyMarkupClickHandler> _openl;
|
std::shared_ptr<ReplyMarkupClickHandler> _openl;
|
||||||
std::unique_ptr<Media> _attach;
|
std::unique_ptr<Media> _attach;
|
||||||
|
mutable std::unique_ptr<Ui::RippleAnimation> _ripple;
|
||||||
|
|
||||||
|
mutable QPoint _lastPoint;
|
||||||
int _gameTagWidth = 0;
|
int _gameTagWidth = 0;
|
||||||
int _descriptionLines = 0;
|
int _descriptionLines = 0;
|
||||||
int _titleLines = 0;
|
int _titleLines = 0;
|
||||||
|
|
|
@ -181,6 +181,11 @@ Storage::SharedMediaTypesMask Media::sharedMediaTypes() const {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Media::allowTextSelectionByHandler(
|
||||||
|
const ClickHandlerPtr &handler) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
not_null<Element*> Media::parent() const {
|
not_null<Element*> Media::parent() const {
|
||||||
return _parent;
|
return _parent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,8 @@ public:
|
||||||
// toggle selection instead of activating the pressed link
|
// toggle selection instead of activating the pressed link
|
||||||
[[nodiscard]] virtual bool toggleSelectionByHandlerClick(
|
[[nodiscard]] virtual bool toggleSelectionByHandlerClick(
|
||||||
const ClickHandlerPtr &p) const = 0;
|
const ClickHandlerPtr &p) const = 0;
|
||||||
|
[[nodiscard]] virtual bool allowTextSelectionByHandler(
|
||||||
|
const ClickHandlerPtr &p) const;
|
||||||
|
|
||||||
[[nodiscard]] virtual TextSelection adjustSelection(
|
[[nodiscard]] virtual TextSelection adjustSelection(
|
||||||
TextSelection selection,
|
TextSelection selection,
|
||||||
|
|
|
@ -904,6 +904,11 @@ bool WebPage::toggleSelectionByHandlerClick(
|
||||||
return _attach && _attach->toggleSelectionByHandlerClick(p);
|
return _attach && _attach->toggleSelectionByHandlerClick(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WebPage::allowTextSelectionByHandler(
|
||||||
|
const ClickHandlerPtr &p) const {
|
||||||
|
return (p == _openl);
|
||||||
|
}
|
||||||
|
|
||||||
bool WebPage::dragItemByHandler(const ClickHandlerPtr &p) const {
|
bool WebPage::dragItemByHandler(const ClickHandlerPtr &p) const {
|
||||||
return _attach && _attach->dragItemByHandler(p);
|
return _attach && _attach->dragItemByHandler(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,8 @@ public:
|
||||||
|
|
||||||
bool toggleSelectionByHandlerClick(
|
bool toggleSelectionByHandlerClick(
|
||||||
const ClickHandlerPtr &p) const override;
|
const ClickHandlerPtr &p) const override;
|
||||||
|
bool allowTextSelectionByHandler(
|
||||||
|
const ClickHandlerPtr &p) const override;
|
||||||
bool dragItemByHandler(const ClickHandlerPtr &p) const override;
|
bool dragItemByHandler(const ClickHandlerPtr &p) const override;
|
||||||
|
|
||||||
TextForMimeData selectedText(TextSelection selection) const override;
|
TextForMimeData selectedText(TextSelection selection) const override;
|
||||||
|
|
Loading…
Reference in New Issue