chore: improce performance (#9)
Reviewed-on: https://git.reya.su/reya/signed/pulls/9
This commit was merged in pull request #9.
This commit is contained in:
@@ -27,11 +27,7 @@ use crate::tiles::SignedTilesSkin;
|
||||
use crate::{TAB_BAR_HEIGHT, panel_handle};
|
||||
|
||||
/// What every part of the skin reads, and the dock area it belongs to.
|
||||
///
|
||||
/// The renderer is the only skin-owned object in the picture, so the settings
|
||||
/// the old `DockArea` carried live here. It is shared by reference with the
|
||||
/// per-container renderers, which are built once each and outlive any one
|
||||
/// frame.
|
||||
/// Shared by reference with the per-container renderers.
|
||||
pub(crate) struct SkinShared {
|
||||
area: WeakEntity<DockArea>,
|
||||
toggle_button_visible: Cell<bool>,
|
||||
@@ -201,10 +197,9 @@ impl DockAreaRenderer for SignedDockSkin {
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// The "unknown panel" message the old `InvalidPanel` drew.
|
||||
///
|
||||
/// It answers `dump` with the state it was handed, so a layout written by
|
||||
/// a build that knows the panel survives a load and save here.
|
||||
/// The "unknown panel" message the old `InvalidPanel` drew. It answers
|
||||
/// `dump` with the state it was handed, so a layout written by a build
|
||||
/// that knows the panel survives a load and save here.
|
||||
fn build_placeholder(
|
||||
&self,
|
||||
state: &PanelState,
|
||||
@@ -246,12 +241,10 @@ impl SignedDockSkin {
|
||||
}
|
||||
}
|
||||
|
||||
/// Turns the window's mouse stream into dock resizing.
|
||||
///
|
||||
/// A resize is driven by pointer moves that land anywhere in the window, not
|
||||
/// only on the handle, so it cannot be expressed as a listener on the handle
|
||||
/// itself. This element paints nothing and exists for its `paint` hook, which
|
||||
/// is the only place a window-level mouse listener can be registered.
|
||||
/// Turns the window's mouse stream into dock resizing. A resize is driven
|
||||
/// by pointer moves anywhere in the window, so this paints nothing and
|
||||
/// exists for its `paint` hook — the only place a window-level mouse
|
||||
/// listener can be registered.
|
||||
struct DockResizeTracker {
|
||||
dock: DockContext,
|
||||
shared: Rc<SkinShared>,
|
||||
@@ -317,10 +310,10 @@ impl Element for DockResizeTracker {
|
||||
if !phase.bubble() || shared.resizing_dock().get() != Some(placement) {
|
||||
return;
|
||||
}
|
||||
// Dragging a closed dock's handle reopens it, as the old dock
|
||||
// did. The live state is read rather than the render-time
|
||||
// snapshot in `dock`, which would still say closed for the
|
||||
// rest of the frame and toggle it shut again on the next move.
|
||||
// Dragging a closed dock's handle reopens it. The live
|
||||
// state is read rather than the render-time snapshot in
|
||||
// `dock`, which would still say closed for the rest of the
|
||||
// frame and toggle it shut again on the next move.
|
||||
let open = shared
|
||||
.area()
|
||||
.upgrade()
|
||||
|
||||
@@ -7,12 +7,10 @@ use gpui_component::ActiveTheme as _;
|
||||
|
||||
use crate::Panel;
|
||||
|
||||
/// Stands in for a panel this build cannot construct — one whose `panel_name`
|
||||
/// no [`PanelRegistry`](gpui_base::dock::PanelRegistry) builder answers to.
|
||||
///
|
||||
/// It reports the original [`PanelState`] from
|
||||
/// [`dump`](gpui_base::dock::Panel::dump), so a layout written by a build that
|
||||
/// knows the panel survives a load and a save here rather than losing it.
|
||||
/// Stands in for a panel this build cannot construct. It reports the
|
||||
/// original [`PanelState`] from [`dump`](gpui_base::dock::Panel::dump), so
|
||||
/// a layout written by a build that knows the panel survives a load and
|
||||
/// save here.
|
||||
pub(crate) struct InvalidPanel {
|
||||
name: SharedString,
|
||||
focus_handle: FocusHandle,
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
//! The Signed dock skin.
|
||||
//!
|
||||
//! The dock engine lives upstream: `gpui_base::dock` owns the layout tree,
|
||||
//! the drags, the zoom and the persistence, and `gpui_component::dock`
|
||||
//! supplies the default appearance. This crate is the appearance the app
|
||||
//! used to vendor from gpui-component — a 44px tab bar that doubles as the
|
||||
//! window title bar, with pill tabs, window controls, title-bar dragging and
|
||||
//! previous/next tab buttons — re-implemented against upstream's renderer
|
||||
//! traits.
|
||||
//! The dock engine lives upstream (`gpui_base::dock` owns the layout tree,
|
||||
//! drags, zoom and persistence); this crate is the appearance the app used
|
||||
//! to vendor from gpui-component — a 44px tab bar that doubles as the
|
||||
//! window title bar, with pill tabs, window controls, title-bar dragging
|
||||
//! and previous/next tab buttons.
|
||||
//!
|
||||
//! Everything `gpui_component::dock` exports is re-exported here, so the app
|
||||
//! keeps importing the dock from a single place.
|
||||
|
||||
@@ -84,11 +84,9 @@ impl Render for DragPanelPreview {
|
||||
}
|
||||
|
||||
/// Where the zoom affordance goes for the group's displayed panel, or `None`
|
||||
/// when there is none to offer.
|
||||
///
|
||||
/// Two questions, and both have to be asked. [`Panel::zoom_control`] says
|
||||
/// *where* the control appears; [`gpui_base::dock::Panel::zoomable`] says
|
||||
/// whether zooming happens at all, and base refuses a zoom that fails it.
|
||||
/// when there is none to offer. Both [`Panel::zoom_control`] (where) and
|
||||
/// [`gpui_base::dock::Panel::zoomable`] (whether) must pass; base refuses a
|
||||
/// zoom that fails the latter.
|
||||
fn zoom_control(group: &TabGroupContext, cx: &App) -> Option<PanelControl> {
|
||||
let panel = group.active_panel()?;
|
||||
panel
|
||||
@@ -122,11 +120,8 @@ fn right_top_group(node: &PaneNode) -> Option<NodeId> {
|
||||
}
|
||||
}
|
||||
|
||||
/// One tab group's appearance.
|
||||
///
|
||||
/// Built per group — `DockAreaRenderer::tab_group_renderer` is called once
|
||||
/// per container — so the tab bar's scroll position and the measured
|
||||
/// title-bar geometry belong to the group they describe.
|
||||
/// One tab group's appearance. Built once per container, so the tab bar's
|
||||
/// scroll position and measured title-bar geometry belong to the group.
|
||||
pub(crate) struct SignedTabGroupSkin {
|
||||
shared: Rc<SkinShared>,
|
||||
scroll_handle: ScrollHandle,
|
||||
@@ -177,9 +172,8 @@ impl SignedTabGroupSkin {
|
||||
/// The bottom or right dock whose root tab group this group is, if any.
|
||||
///
|
||||
/// Base bars a dock's only group from being dragged or closed, so the
|
||||
/// dock cannot be emptied. A bottom/right panel is supposed to be
|
||||
/// closable and movable, though — the vendored dock allowed exactly that
|
||||
/// — so the skin recognizes the group and routes around the bar.
|
||||
/// dock cannot be emptied — but a bottom/right panel is supposed to be
|
||||
/// closable, so the skin routes around the bar for these groups.
|
||||
fn is_dock_root_group(&self, group: &TabGroupContext, cx: &App) -> Option<DockPlacement> {
|
||||
let area = self.shared.area().upgrade()?;
|
||||
let area = area.read(cx);
|
||||
@@ -270,9 +264,7 @@ impl SignedTabGroupSkin {
|
||||
}
|
||||
|
||||
/// The previous/next tab buttons shown in the tab bar's leading prefix.
|
||||
///
|
||||
/// Unlike the dock toggle button they always render, but are disabled at
|
||||
/// the ends of the tab strip (or while the panel is collapsed).
|
||||
/// Always rendered, disabled at the ends of the strip (or collapsed).
|
||||
fn render_prev_next_tab_buttons(
|
||||
&self,
|
||||
group: &TabGroupContext,
|
||||
@@ -405,10 +397,9 @@ impl SignedTabGroupSkin {
|
||||
)
|
||||
}
|
||||
|
||||
/// One tab of the pill strip.
|
||||
///
|
||||
/// While collapsed, tabs lose the active style and all interactions, and
|
||||
/// the strip becomes the way a closed bottom dock is opened again.
|
||||
/// One tab of the pill strip. While collapsed, tabs lose the active
|
||||
/// style and all interactions, and the strip becomes the way a closed
|
||||
/// bottom dock is opened again.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn render_tab(
|
||||
&self,
|
||||
@@ -578,10 +569,8 @@ impl TabGroupRenderer for SignedTabGroupSkin {
|
||||
if group.panels().is_empty() {
|
||||
return div().id("tab-panel");
|
||||
}
|
||||
// Closing the only panel of a bottom/right dock would leave an empty
|
||||
// dock, which base refuses through the group. The skin removes the
|
||||
// whole dock instead — the vendored dock's close took its split
|
||||
// group away just the same.
|
||||
// Closing the only panel of a bottom/right dock would leave an
|
||||
// empty dock, which base refuses; the skin removes the dock instead.
|
||||
let dock_to_remove = (group.panels().len() <= 1)
|
||||
.then(|| self.is_dock_root_group(group, cx))
|
||||
.flatten();
|
||||
@@ -601,8 +590,8 @@ impl TabGroupRenderer for SignedTabGroupSkin {
|
||||
this.on_action({
|
||||
let group = group.clone();
|
||||
move |_: &ToggleZoom, window, cx| {
|
||||
// The affordance decides the control, so a panel that
|
||||
// offers none is not zoomed *in* by the keybinding
|
||||
// The affordance decides the control, so a panel
|
||||
// offering none is not zoomed *in* by the keybinding
|
||||
// either. Zooming out is never refused: a panel that
|
||||
// stopped offering the control while zoomed would
|
||||
// otherwise strand the user with no way back.
|
||||
@@ -671,12 +660,10 @@ impl TabGroupRenderer for SignedTabGroupSkin {
|
||||
let right_dock_button = self.dock_toggle_button(DockPlacement::Right, group, cx);
|
||||
let is_bottom_dock = bottom_dock_button.is_some();
|
||||
|
||||
// macOS: the traffic lights overlay the window's top-left corner. Only
|
||||
// the group whose tab bar actually sits under them must reserve the
|
||||
// space: the left dock (sidebar) normally clears them, and when it is
|
||||
// closed or absent it is the center's left-most, top-most tab group
|
||||
// that is in the corner. A bottom or right dock is never there, and
|
||||
// neither is the right panel of a center split.
|
||||
// macOS: the traffic lights overlay the window's top-left corner.
|
||||
// Only the group whose tab bar actually sits under them reserves the
|
||||
// space — the center's left-most, top-most group when the left dock
|
||||
// is closed or absent.
|
||||
let needs_traffic_light_padding = cfg!(target_os = "macos")
|
||||
&& self.shared.area().upgrade().is_some_and(|area| {
|
||||
let area = area.read(cx);
|
||||
@@ -703,11 +690,10 @@ impl TabGroupRenderer for SignedTabGroupSkin {
|
||||
self.scroll_handle.scroll_to_item(visible_ix);
|
||||
}
|
||||
|
||||
// The tab strip lays out its scrollable content at content width, so
|
||||
// the area after the last tab only spans `min_w_16` — the rest of the
|
||||
// tab bar has no element at all. Cover that dead zone with a
|
||||
// measured overlay so the whole non-interactive area can drag the
|
||||
// window. Its span is [last tab's right edge, suffix's left edge].
|
||||
// The tab strip lays out at content width, so the area after the
|
||||
// last tab has no element. Cover that dead zone (last tab's right
|
||||
// edge to suffix's left edge) with a measured overlay so the whole
|
||||
// non-interactive area can drag the window.
|
||||
let drag_overlay = match (
|
||||
self.title_bar_bounds.get(),
|
||||
self.title_bar_strip_bounds.get(),
|
||||
|
||||
@@ -101,13 +101,11 @@ impl SignedTilesSkin {
|
||||
})
|
||||
}
|
||||
|
||||
/// The trailing controls of a tile's title bar.
|
||||
///
|
||||
/// A tile has no tab bar to hang a toolbar off, so this is where its zoom,
|
||||
/// close and ellipsis menu live. The entries use click handlers rather
|
||||
/// than the [`ToggleZoom`](crate::ToggleZoom) and
|
||||
/// [`ClosePanel`](crate::ClosePanel) actions: those are dispatched to a
|
||||
/// focused tab group, and a tile is not one.
|
||||
/// The trailing controls of a tile's title bar: zoom, close and the
|
||||
/// ellipsis menu. They use click handlers rather than the
|
||||
/// [`ToggleZoom`](crate::ToggleZoom)/[`ClosePanel`](crate::ClosePanel)
|
||||
/// actions, which are dispatched to a focused tab group — a tile is
|
||||
/// not one.
|
||||
fn render_tile_controls(
|
||||
&self,
|
||||
tile: &TileContext,
|
||||
@@ -388,12 +386,9 @@ impl TilesRenderer for SignedTilesSkin {
|
||||
.size_full()
|
||||
}
|
||||
|
||||
/// The canvas scrollbar.
|
||||
///
|
||||
/// It has to be an overlay rather than one of the frame's own children:
|
||||
/// the frame is the scroll container and base appends the tiles after
|
||||
/// whatever the frame carries, so a scrollbar placed there would paint and
|
||||
/// hit-test underneath every tile.
|
||||
/// The canvas scrollbar. It must be an overlay: the frame is the scroll
|
||||
/// container and base appends the tiles after it, so a scrollbar placed
|
||||
/// inside would paint and hit-test underneath every tile.
|
||||
fn render_overlay(
|
||||
&self,
|
||||
content: Size<Pixels>,
|
||||
|
||||
Reference in New Issue
Block a user