From e1e49ce4ea99a3e111dac35eff210a0af235eb40 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 29 May 2026 21:38:32 +0400 Subject: [PATCH] Improve editor selection logic. --- .../iv/editor/iv_editor_widget.cpp | 85 +++++++++++++------ .../iv_markdown_history_view_media.cpp | 1 - 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/Telegram/SourceFiles/iv/editor/iv_editor_widget.cpp b/Telegram/SourceFiles/iv/editor/iv_editor_widget.cpp index 08e6af90fd..5c941b2d13 100644 --- a/Telegram/SourceFiles/iv/editor/iv_editor_widget.cpp +++ b/Telegram/SourceFiles/iv/editor/iv_editor_widget.cpp @@ -175,6 +175,24 @@ struct NormalizedIntegerRange { }; } +[[nodiscard]] PreparedEditSelection BlockSelectionFromIndexes( + PreparedEditBlockContainerPath container, + int first, + int second) { + const auto range = NormalizeIntegerRange(first, second); + if (range.empty()) { + return {}; + } + return { + .kind = PreparedEditSelectionKind::Blocks, + .blocks = { + .container = std::move(container), + .from = range.from, + .till = range.till, + }, + }; +} + [[nodiscard]] int CompareIntegers(int a, int b) { return (a < b) ? -1 : (a > b) ? 1 : 0; } @@ -393,6 +411,10 @@ struct StructuralOwner { return owner.listItem; } +[[nodiscard]] bool IsBlockOwner(const StructuralOwner &owner) { + return (owner.kind == StructuralOwnerKind::Block); +} + [[nodiscard]] std::optional BlockPathFromOwner( const StructuralOwner &owner) { if (owner.kind == StructuralOwnerKind::Block && owner.block) { @@ -475,6 +497,19 @@ LiftPreparedEditBlocksToCommonContainer( return result; } +[[nodiscard]] PreparedEditSelection LiftedBlockSelection( + const PreparedEditBlockPath &anchor, + const PreparedEditBlockPath &focus) { + const auto lifted = LiftPreparedEditBlocksToCommonContainer(anchor, focus); + if (!lifted) { + return {}; + } + return BlockSelectionFromIndexes( + lifted->container, + lifted->first, + lifted->second); +} + [[nodiscard]] auto ListItemSourcesFromBlockPath( const PreparedEditBlockPath &path) -> std::vector { @@ -547,6 +582,13 @@ LiftPreparedEditBlocksToCommonContainer( return {}; } +[[nodiscard]] bool IsMultiListItemSelection( + const PreparedEditSelection &selection) { + return !selection.empty() + && (selection.kind == PreparedEditSelectionKind::ListItems) + && (selection.listItems.till > selection.listItems.from + 1); +} + [[nodiscard]] int FieldNaturalHeight(not_null field) { const auto margins = field->fullTextMargins(); return std::max( @@ -2009,44 +2051,33 @@ PreparedEditSelection Widget::structuralSelectionFromHits( if (ComparePreparedEditBlockContainerPaths( anchorBlock->container, focusBlock->container) == 0) { - const auto range = NormalizeIntegerRange( + const auto blockSelection = BlockSelectionFromIndexes( + anchorBlock->container, anchorBlock->index, focusBlock->index); - if (!range.empty()) { - return { - .kind = PreparedEditSelectionKind::Blocks, - .blocks = { - .container = anchorBlock->container, - .from = range.from, - .till = range.till, - }, - }; + if (!blockSelection.empty()) { + return blockSelection; } } const auto listItemsFromChildren = ListItemSelectionFromSources( ListItemSourcesFromOwner(anchorOwner, anchorBlock), ListItemSourcesFromOwner(focusOwner, focusBlock)); + const auto liftedBlockSelection = LiftedBlockSelection( + *anchorBlock, + *focusBlock); + if (IsBlockOwner(anchorOwner) + && IsBlockOwner(focusOwner) + && !liftedBlockSelection.empty() + && !IsMultiListItemSelection(listItemsFromChildren)) { + return liftedBlockSelection; + } if (!listItemsFromChildren.empty()) { return listItemsFromChildren; } - const auto lifted = LiftPreparedEditBlocksToCommonContainer( - *anchorBlock, - *focusBlock); - if (!lifted) { - return {}; + if (!liftedBlockSelection.empty()) { + return liftedBlockSelection; } - const auto range = NormalizeIntegerRange(lifted->first, lifted->second); - if (range.empty()) { - return {}; - } - return { - .kind = PreparedEditSelectionKind::Blocks, - .blocks = { - .container = lifted->container, - .from = range.from, - .till = range.till, - }, - }; + return {}; } int Widget::editableOrdinalForSegment(int segmentIndex) const { diff --git a/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.cpp b/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.cpp index 8d75f0a203..8c30a0ad4b 100644 --- a/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.cpp +++ b/Telegram/SourceFiles/iv/markdown/iv_markdown_history_view_media.cpp @@ -321,7 +321,6 @@ void IvHistoryViewBlock::paint( p.translate(_geometry.topLeft()); auto local = context.translated(-_geometry.topLeft()); local.clip = visible.translated(-_geometry.topLeft()); - local.outbg = _host->view()->hasOutLayout(); _media->draw(p, local); p.restore(); }