7 Commits
Author SHA1 Message Date
Sangwoo Ko af6d879775 Serialize TreeTabNode data to session service (#36526)
* Serialize TreeTabNode data to session service

When a TreeTabNode has been created, updated or destroyed, we serialize the
TreeTabNode data to the session service. This data is used to restore the
TreeTabNode hierarchy when the browser is restarted, or when a tab is
restored from recently closed tabs.
2026-05-29 12:38:27 +01:00
cdesouza-chromium 78129286ae [docs] Include docs/ to md auto-format (#36521)
This is in conformance with the guidelines that `.md` files under
`docs/` must use 80-columns.
2026-05-19 20:02:22 +01:00
Sangwoo Ko e2924e8944 Add documentation for tree tab session restore (#36506)
For the first step, add documentation explaining how the existing group
and split tab metadata is persisted across browser restarts.

Part of https://github.com/brave/brave-browser/issues/49792
2026-05-19 14:03:57 +09:00
Sangwoo Ko ce0f439a19 [Tree Tabs] Support tab groups in tree tab strip (#34826)
* Support tab groups in tree tab strip

Integrate tab groups with the tree tab strip so that groups are represented
as a single tree node wrapping the group (not one tree node per tab). Tabs
inside a group remain direct children of the group collection.

Collection and delegate:
- BraveTreeTabStripCollectionDelegate: When adding a tab with new_group_id,
  add to collection without wrapping in a tree node; the group wraps it.
  MoveTabsRecursive: handle empty tab_indices (no-op when moving within same
  group), and route move-out-of-group and move-into-group to new helpers.
- MoveTabsIntoGroup: unwrap tabs from tree nodes (or detach from other
  groups), add to target group; when group is detached (new group), wrap
  group in a TreeTabNode and attach at the correct tree position.
- MoveTabsOutOfGroup: move tabs from TabGroupTabCollection back into the
  tree by wrapping each in a tree node at the destination index.
- BraveTabStripCollection: add PopDetachedGroupCollectionForDelegate and
  GetTreeTabNodeIdForGroup; chromium_src TabStripCollection gains virtual
  GetTreeTabNodeIdForGroup. BraveTabStripCollectionDelegate implements
  GetTreeTabNodeIdForGroup.

TreeTabNodeTabCollection:
- BuildTreeTabs: wrap entire groups in one tree node (processed_groups set);
  grouped tabs stay as direct children of the group.
- New constructor that wraps a TabGroupTabCollection (for creating a group
  in tree mode). Single-tab constructor allows null for GetEmptyTreeTabNode
  when a tab was moved into a group and the view still holds the old node id.

Model, controller, and UI:
- BraveTabStripModel::GetTreeTabNodeIdForGroup returns the tree node id for
  a group (or nullptr if tree tabs off). Wired through controller and
  BraveTabStripCollection.
- BraveBrowserTabStripController::GetTreeTabNode returns GetEmptyTreeTabNode()
  when the node is null (e.g. tab just moved into group, before
  TabGroupedStateChanged/AddTabToGroup updates the view).
- OnTreeTabChanged: handle tab index kNoTab and detached state during group
  creation; avoid double-clearing when AddTabToGroup will clear the node id.
- BraveTabStrip::AddTabToGroup override sets the tab's tree_tab_node from
  GetTreeTabNodeIdForGroup when adding to a group in tree mode.
2026-03-24 11:18:48 +01:00
Sangwoo Ko b7a3eeb712 [Tree Tabs] Add split tab support for tree tabs (#34659)
* Add split tab support for tree tabs

In order to support split tabs in tree tabs, mainly we need to reimplment
two methods - CreateSplit and Unsplit.

For CreateSplit, we need to wrap the split tabs in a tree node, and insert it
at the position.
For Unsplit, we need to extract the tabs back to the tree nodes.

- TabStripCollection: virtual CreateSplit, Unsplit, AddCollectionMapping,
  RemoveCollectionMapping; AddTabCollectionAtPosition for delegate.

- BraveTabStripCollection(delegate): override CreateSplit/Unsplit and
  AddCollectionMapping/RemoveCollectionMapping; PassKey overloads for
  AddTabCollectionAtPosition and collection mapping.

- BraveTreeTabStripCollectionDelegate: implement CreateSplit (wrap split in
  tree node, insert at position), Unsplit (extract tabs back to tree nodes),
  AddCollectionMapping/RemoveCollectionMapping for TREE_NODE holding split/group;
  MoveTabsRecursive same-position handling for split/group creation.

- Tab strip API: handle TREE_NODE in tab_converters (unpinned container).

- Docs: tree tabs + split tabs flow and MoveTabsRecursive behavior.
2026-03-17 16:02:52 +09:00
Sangwoo Ko 6a49c03cd0 [Tree Tabs] Make TreeTabModel::SetCollapsed/DoesBelongToCollapsedNode() (#34380)
* Make TreeTabModel::SetCollapsed/DoesBelongToCollapsedNode()

TreeTabModel:
- Cache closest collapsed ancestor per node for O(1) visibility checks.
- Add SetCollapsed(id, collapsed) as UI entry point; calls TreeTabNode::set_collapsed()
  and updates cache for affected descendants.
- Add DoesBelongToCollapsedNode(id) for quick "under collapsed" queries.
- Update cache in AddTreeTabNode (new node's closest collapsed), RemoveTreeTabNode
  (recompute nodes that had removed id as closest), and OnTreeTabNodeMoved (recompute
  moved node and its descendants after reparent).

TreeTabNode:
- Add GetClosestCollapsedAncestorId(), IsUnderCollapsedAncestor(), CollectDescendantIds()
  for cache maintenance and tree traversal.

TreeTabNodeTabCollection:
- Add on_move callback; BuildTreeTabs and constructor take on_move.
- OnReparented invokes on_move so TreeTabModel can refresh collapse cache.
- Change on_create signature from void(const TreeTabNode&) to void(TreeTabNode&) so
  delegate can pass AddTreeTabNode (non-const).

BraveTreeTabStripCollectionDelegate:
- Wire on_move to TreeTabModel::OnTreeTabNodeMoved in BuildTreeTabs and in
  single-node TreeTabNodeTabCollection creation sites.
2026-03-05 08:00:19 +09:00
Sangwoo Ko 046971c6be Add docs for tree tab architecture (#32520)
This document outlines the planned architecture and design principles
behind the tree tab feature. It covers the responsibilities of
various components, data structures, and interaction patterns to ensure
a cohesive and decoupled implementation.
2025-11-28 01:08:06 +01:00