Skip to content

Instantly share code, notes, and snippets.

@iamnbutler
Created May 13, 2025 08:30
Show Gist options
  • Save iamnbutler/1155b5a3c0a15f5a8398ff8e08d10c81 to your computer and use it in GitHub Desktop.
Save iamnbutler/1155b5a3c0a15f5a8398ff8e08d10c81 to your computer and use it in GitHub Desktop.

Adding Transform to Quad Struct

User

The following items were attached by the user. They are up-to-date and don't need to be re-read. ```rs zed/crates/gpui/src/scene.rs pub(crate) type PathVertex_ScaledPixels [L11] pub(crate) type DrawOrder [L13] pub(crate) struct Scene [L16-27] pub(crate) paint_operations [L17] primitive_bounds [L18] layer_stack [L19] pub(crate) shadows [L20] pub(crate) quads [L21] pub(crate) paths [L22] pub(crate) underlines [L23] pub(crate) monochrome_sprites [L24] pub(crate) polychrome_sprites [L25] pub(crate) surfaces [L26] impl Scene [L29-174] pub fn clear [L30-41] pub fn paths [L50-52] pub fn len [L54-56] pub fn push_layer [L58-63] pub fn pop_layer [L65-68] pub fn insert_primitive [L70-118] pub fn replay [L120-128] pub fn finish [L130-140] pub(crate) fn batches [L149-173] pub(crate) enum PrimitiveKind [L184-193] Shadow [L185] Quad [L187] Path [L188] Underline [L189] MonochromeSprite [L190] PolychromeSprite [L191] Surface [L192] pub(crate) enum PaintOperation [L195-199] Primitive [L196] StartLayer [L197] EndLayer [L198] pub(crate) enum Primitive [L202-210] Shadow [L203] Quad [L204] Path [L205] Underline [L206] MonochromeSprite [L207] PolychromeSprite [L208] Surface [L209] impl Primitive [L212-236] pub fn bounds [L213-223] pub fn content_mask [L225-235] struct BatchIterator [L245-267] shadows [L246] shadows_start [L247] shadows_iter [L248] quads [L249] quads_start [L250] quads_iter [L251] paths [L252] paths_start [L253] paths_iter [L254] underlines [L255] underlines_start [L256] underlines_iter [L257] monochrome_sprites [L258] monochrome_sprites_start [L259] monochrome_sprites_iter [L260] polychrome_sprites [L261] polychrome_sprites_start [L262] polychrome_sprites_iter [L263] surfaces [L264] surfaces_start [L265] surfaces_iter [L266] impl Iterator for BatchIterator<'a> [L269-428] type Item [L270] fn next [L272-427] pub(crate) enum PrimitiveBatch [L438-452] Shadows [L439] Quads [L440] Paths [L441] Underlines [L442] MonochromeSprites [L443-446] texture_id [L444] sprites [L445] PolychromeSprites [L447-450] texture_id [L448] sprites [L449] Surfaces [L451] pub(crate) struct Quad [L456-465] pub order [L457] pub border_style [L458] pub bounds [L459] pub content_mask [L460] pub background [L461] pub border_color [L462] pub corner_radii [L463] pub border_widths [L464] impl From for Primitive [L467-471] fn from [L468-470] pub(crate) struct Underline [L475-483] pub order [L476] pub pad [L477] pub bounds [L478] pub content_mask [L479] pub color [L480] pub thickness [L481] pub wavy [L482] impl From for Primitive [L485-489] fn from [L486-488] pub(crate) struct Shadow [L493-500] pub order [L494] pub blur_radius [L495] pub bounds [L496] pub corner_radii [L497] pub content_mask [L498] pub color [L499] impl From for Primitive [L502-506] fn from [L503-505] pub enum BorderStyle [L511-517] Solid [L514] Dashed [L516] pub struct TransformationMatrix [L522-528] pub rotation_scale [L525] pub translation [L527] impl Eq for TransformationMatrix [L530] impl TransformationMatrix [L532-614] pub fn unit [L534-539] pub fn translate [L542-547] pub fn rotate [L550-558] pub fn scale [L561-566] pub fn compose [L572-601] pub fn apply [L604-613] impl Default for TransformationMatrix [L616-620] fn default [L617-619] pub(crate) struct MonochromeSprite [L624-632] pub order [L625] pub pad [L626] pub bounds [L627] pub content_mask [L628] pub color [L629] pub tile [L630] pub transformation [L631] impl From for Primitive [L634-638] fn from [L635-637] pub(crate) struct PolychromeSprite [L642-651] pub order [L643] pub pad [L644] pub grayscale [L645] pub opacity [L646] pub bounds [L647] pub content_mask [L648] pub corner_radii [L649] pub tile [L650] impl From for Primitive [L653-657] fn from [L654-656] pub(crate) struct PaintSurface [L660-666] pub order [L661] pub bounds [L662] pub content_mask [L663] pub image_buffer [L665] impl From for Primitive [L668-672] fn from [L669-671] pub(crate) struct PathId [L675] pub struct Path [L679-689] pub(crate) id [L680] order [L681] pub(crate) bounds [L682] pub(crate) content_mask [L683] pub(crate) vertices [L684] pub(crate) color [L685] start [L686] current [L687] contour_count [L688] impl Path [L691-802] pub fn new [L693-708] pub fn scale [L711-727] pub fn move_to [L730-734] pub fn line_to [L737-746] pub fn curve_to [L749-763] pub fn push_triangle [L766-801] impl From> for Primitive [L804-808] fn from [L805-807] pub(crate) struct PathVertex [L812-816] pub(crate) xy_position [L813] pub(crate) st_position [L814] pub(crate) content_mask [L815] impl PathVertex [L818-826] pub fn scale [L819-825]

Showing symbols 1-183 (total symbols: 183)

</files>
</context>

How should I represent a Transform on the Quad struct?

scale, rotation, translation

## Agent



<think>
Let me analyze how to represent a transformation (scale, rotation, translation) on the `Quad` struct based on the provided code context. 

Looking at the code in `zed/crates/gpui/src/scene.rs`, I notice that there's already a `TransformationMatrix` struct defined around lines 522-528:

```rs
pub struct TransformationMatrix {
    pub rotation_scale: [f32; 4],  // Represents both rotation and scaling
    pub translation: [f32; 2],     // Represents translation
}

This TransformationMatrix structure already handles the three transformations you're asking about:

  1. Scale - handled by rotation_scale
  2. Rotation - also handled by rotation_scale
  3. Translation - handled by translation

Furthermore, I see this TransformationMatrix is already being used in some sprite types:

  • In MonochromeSprite at line 631, there's a field called transformation: TransformationMatrix

The Quad struct is defined around lines 456-465 but doesn't currently have a transformation field:

pub(crate) struct Quad {
    pub order: DrawOrder,
    pub border_style: BorderStyle,
    pub bounds: Bounds<Pixels>,
    pub content_mask: ContentMask,
    pub background: Hsla,
    pub border_color: Hsla,
    pub corner_radii: RoundedCorners<Pixels>,
    pub border_widths: EdgeInsets<Pixels>,
}

Based on how transformations are handled elsewhere in the codebase, the most consistent approach would be to add a transformation: TransformationMatrix field to the Quad struct, similar to how it's done in MonochromeSprite.

The TransformationMatrix struct has several helper methods for creating and composing transformations:

  • unit() - creates an identity transformation
  • translate(x, y) - creates a translation transformation
  • rotate(angle) - creates a rotation transformation
  • scale(x, y) - creates a scaling transformation
  • compose(other) - combines two transformations
  • apply(point) - applies the transformation to a point

This makes it easy to use and manipulate transformations.

Based on the code in scene.rs, I can see that there's already a well-defined transformation structure in the codebase that you can leverage: TransformationMatrix. This is the same approach used by MonochromeSprite in the file.

The TransformationMatrix struct encapsulates all three transformation components you need:

  1. Scale and rotation in the rotation_scale field (a 2x2 matrix represented as a flat array)
  2. Translation in the translation field (an x,y vector)

Here's how you should add the transformation to the Quad struct:

pub(crate) struct Quad {
    pub order: DrawOrder,
    pub border_style: BorderStyle,
    pub bounds: Bounds<Pixels>,
    pub content_mask: ContentMask,
    pub background: Hsla,
    pub border_color: Hsla,
    pub corner_radii: RoundedCorners<Pixels>,
    pub border_widths: EdgeInsets<Pixels>,
    pub transformation: TransformationMatrix,
}

The TransformationMatrix struct already includes methods to:

  • Create transformations: unit(), translate(), rotate(), scale()
  • Combine transformations with compose()
  • Apply transformations to points with apply()

This approach keeps your code consistent with the existing transformation system in the codebase, and gives you a complete solution for handling scale, rotation, and translation in a mathematically sound way.

User

The following items were attached by the user. They are up-to-date and don't need to be re-read. ```metal zed/crates/gpui/src/platform/mac/shaders.metal

Showing symbols 1-0 (total symbols: 0)

</files>
</context>

OK what do we need to do in the metal shader?

## Agent



<think>
I need to understand what needs to be modified in the Metal shader to handle the transformation matrix we added to the Quad struct. Let me examine the current Metal shader file to understand its structure and how quads are currently rendered.

Looking at the provided Metal shader file, it appears to be empty or the symbol information is not available. I'll need to read the actual content of the file to understand what changes are needed.

Before making specific suggestions, I need to:
1. See what vertex/fragment shaders already exist for quads
2. Understand how the current rendering pipeline for quads works
3. Determine where and how to apply the transformation matrix

Let me read the Metal shader file to get this information.
</think>

To implement the transformation matrix support in the Metal shader, I'll need to see the actual shader code to make the appropriate modifications. Let me examine the Metal shader file:

**Use Tool: read_file (toolu_01BuRwThQoBSDoi1xVfTgEvh)**
```json
{
  "path": "zed/crates/gpui/src/platform/mac/shaders.metal"
}

Tool Results: toolu_01BuRwThQoBSDoi1xVfTgEvh

This file was too big to read all at once.

Here is an outline of its symbols:

Showing symbols 1-0 (total symbols: 0)

Using the line numbers in this outline, you can call this tool again while specifying the start_line and end_line fields to see the implementations of symbols in the outline.

Agent

Let me try to understand the structure of this file by examining its content in manageable chunks:

Use Tool: terminal (toolu_0151QvF8WyS5F5jiYfDq1K1s)

{
  "cd": "zed",
  "command": "head -n 20 crates/gpui/src/platform/mac/shaders.metal"
}

Tool Results: toolu_0151QvF8WyS5F5jiYfDq1K1s

#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

float4 hsla_to_rgba(Hsla hsla);
float3 srgb_to_linear(float3 color);
float3 linear_to_srgb(float3 color);
float4 srgb_to_oklab(float4 color);
float4 oklab_to_srgb(float4 color);
float4 to_device_position(float2 unit_vertex, Bounds_ScaledPixels bounds,
                          constant Size_DevicePixels *viewport_size);
float4 to_device_position_transformed(float2 unit_vertex, Bounds_ScaledPixels bounds,
                          TransformationMatrix transformation,
                          constant Size_DevicePixels *input_viewport_size);

float2 to_tile_position(float2 unit_vertex, AtlasTile tile,
                        constant Size_DevicePixels *atlas_size);
float4 distance_from_clip_rect(float2 unit_vertex, Bounds_ScaledPixels bounds,
                               Bounds_ScaledPixels clip_bounds);

Agent

Let me find the quad-related code in the shaders:

Use Tool: grep (toolu_0114akZEqFgMWgjyNQW1AjUV)

{
  "regex": "quad|Quad",
  "include_pattern": "*.metal"
}

Tool Results: toolu_0114akZEqFgMWgjyNQW1AjUV

Found 19 matches:

Matches in zed/crates/debugger_ui/src/breakpoint.rs

impl RenderOnce for BreakpointIndicator › fn render › L123-127

        //             point(bounds.origin.x + square_width, bounds.origin.y + height),
        //         );
        //         window.paint_quad(fill(square_bounds, fill_color));

        //         // Align the triangle to the right of the square

Matches in zed/crates/gpui/src/platform/mac/shaders.metal

L24-30

float quarter_ellipse_sdf(float2 point, float2 radii);
float pick_corner_radius(float2 center_to_point, Corners_ScaledPixels corner_radii);
float quad_sdf(float2 point, Bounds_ScaledPixels bounds,
               Corners_ScaledPixels corner_radii);
float quad_sdf_impl(float2 center_to_point, float corner_radius);
float gaussian(float x, float sigma);
float2 erf(float2 x);

L43-48

GradientColor prepare_fill_color(uint tag, uint color_space, Hsla solid, Hsla color0, Hsla color1);

struct QuadVertexOutput {
  uint quad_id [[flat]];
  float4 position [[position]];
  float4 border_color [[flat]];

L53-58

};

struct QuadFragmentInput {
  uint quad_id [[flat]];
  float4 position [[position]];
  float4 border_color [[flat]];

L62-91

};

vertex QuadVertexOutput quad_vertex(uint unit_vertex_id [[vertex_id]],
                                    uint quad_id [[instance_id]],
                                    constant float2 *unit_vertices
                                    [[buffer(QuadInputIndex_Vertices)]],
                                    constant Quad *quads
                                    [[buffer(QuadInputIndex_Quads)]],
                                    constant Size_DevicePixels *viewport_size
                                    [[buffer(QuadInputIndex_ViewportSize)]]) {
  float2 unit_vertex = unit_vertices[unit_vertex_id];
  Quad quad = quads[quad_id];
  float4 device_position =
      to_device_position(unit_vertex, quad.bounds, viewport_size);
  float4 clip_distance = distance_from_clip_rect(unit_vertex, quad.bounds,
                                                 quad.content_mask.bounds);
  float4 border_color = hsla_to_rgba(quad.border_color);

  GradientColor gradient = prepare_fill_color(
    quad.background.tag,
    quad.background.color_space,
    quad.background.solid,
    quad.background.colors[0].color,
    quad.background.colors[1].color
  );

  return QuadVertexOutput{
      quad_id,
      device_position,
      border_color,

L96-116

}

fragment float4 quad_fragment(QuadFragmentInput input [[stage_in]],
                              constant Quad *quads
                              [[buffer(QuadInputIndex_Quads)]]) {
  Quad quad = quads[input.quad_id];
  float4 background_color = fill_color(quad.background, input.position.xy, quad.bounds,
    input.background_solid, input.background_color0, input.background_color1);

  bool unrounded = quad.corner_radii.top_left == 0.0 &&
    quad.corner_radii.bottom_left == 0.0 &&
    quad.corner_radii.top_right == 0.0 &&
    quad.corner_radii.bottom_right == 0.0;

  // Fast path when the quad is not rounded and doesn't have any border
  if (quad.border_widths.top == 0.0 &&
      quad.border_widths.left == 0.0 &&
      quad.border_widths.right == 0.0 &&
      quad.border_widths.bottom == 0.0 &&
      unrounded) {
    return background_color;

L117-123

  }

  float2 size = float2(quad.bounds.size.width, quad.bounds.size.height);
  float2 half_size = size / 2.0;
  float2 point = input.position.xy - float2(quad.bounds.origin.x, quad.bounds.origin.y);
  float2 center_to_point = point - half_size;

L127-136


  // Radius of the nearest corner
  float corner_radius = pick_corner_radius(center_to_point, quad.corner_radii);

  // Width of the nearest borders
  float2 border = float2(
    center_to_point.x < 0.0 ? quad.border_widths.left : quad.border_widths.right,
    center_to_point.y < 0.0 ? quad.border_widths.top : quad.border_widths.bottom
  );

L141-150

    border.y == 0.0 ? -antialias_threshold : border.y);

  // Vector from the corner of the quad bounds to the point, after mirroring
  // the point into the bottom right quadrant. Both components are <= 0.
  float2 corner_to_point = fabs(center_to_point) - half_size;

  // Vector from the point to the center of the rounded corner's circle, also
  // mirrored into bottom right quadrant.
  float2 corner_center_to_point = corner_to_point + corner_radius;

L166-170



  // Whether the point is far enough inside the quad, such that the pixels are
  // not affected by the straight border.
  bool is_within_inner_straight_border =

L177-184

  }

  // Signed distance of the point to the outside edge of the quad's border
  float outer_sdf = quad_sdf_impl(corner_center_to_point, corner_radius);

  // Approximate signed distance of the point to the inside edge of the quad's
  // border. It is negative outside this edge (within the border), and
  // positive inside.

L212-216


    // Dashed border logic when border_style == 1
    if (quad.border_style == 1) {
      // Position along the perimeter in "dash space", where each dash
      // period has length 1

L254-266

        // around the whole perimeter.

        float r_tr = quad.corner_radii.top_right;
        float r_br = quad.corner_radii.bottom_right;
        float r_bl = quad.corner_radii.bottom_left;
        float r_tl = quad.corner_radii.top_left;

        float w_t = quad.border_widths.top;
        float w_r = quad.border_widths.right;
        float w_b = quad.border_widths.bottom;
        float w_l = quad.border_widths.left;

        // Straight side dash velocities

L508-512

  float alpha;
  if (shadow.blur_radius == 0.) {
    float distance = quad_sdf(input.position.xy, shadow.bounds, shadow.corner_radii);
    alpha = saturate(0.5 - distance);
  } else {

L686-690

      atlas_texture.sample(atlas_texture_sampler, input.tile_position);
  float distance =
      quad_sdf(input.position.xy, sprite.bounds, sprite.corner_radii);

  float4 color = sample;

L999-1003

}

// Selects corner radius based on quadrant.
float pick_corner_radius(float2 center_to_point, Corners_ScaledPixels corner_radii) {
  if (center_to_point.x < 0.) {

L1016-1022

}

// Signed distance of the point to the quad's border - positive outside the
// border, and negative inside.
float quad_sdf(float2 point, Bounds_ScaledPixels bounds,
               Corners_ScaledPixels corner_radii) {
    float2 half_size = float2(bounds.size.width, bounds.size.height) / 2.0;

L1026-1034

    float2 corner_to_point = fabs(center_to_point) - half_size;
    float2 corner_center_to_point = corner_to_point + corner_radius;
    return quad_sdf_impl(corner_center_to_point, corner_radius);
}

// Implementation of quad signed distance field
float quad_sdf_impl(float2 corner_center_to_point, float corner_radius) {
    if (corner_radius == 0.0) {
        // Fast path for unrounded corners

L1035-1047

        return max(corner_center_to_point.x, corner_center_to_point.y);
    } else {
        // Signed distance of the point from a quad that is inset by corner_radius
        // It is negative inside this quad, and positive outside
        float signed_distance_to_inset_quad =
            // 0 inside the inset quad, and positive outside
            length(max(float2(0.0), corner_center_to_point)) +
            // 0 outside the inset quad, and negative inside
            min(0.0, max(corner_center_to_point.x, corner_center_to_point.y));

        return signed_distance_to_inset_quad - corner_radius;
    }
}

Agent

Now, let me look for the existing transformation-related code in the Metal shader:

Use Tool: grep (toolu_01N42xHXmds8JUVoqUas4Tnd)

{
  "include_pattern": "*.metal",
  "regex": "transform|Transformation"
}

Tool Results: toolu_01N42xHXmds8JUVoqUas4Tnd

Found 7 matches:

Matches in zed/crates/gpui/src/platform/mac/shaders.metal

L11-16

float4 to_device_position(float2 unit_vertex, Bounds_ScaledPixels bounds,
                          constant Size_DevicePixels *viewport_size);
float4 to_device_position_transformed(float2 unit_vertex, Bounds_ScaledPixels bounds,
                          TransformationMatrix transformation,
                          constant Size_DevicePixels *input_viewport_size);

L615-619

  MonochromeSprite sprite = sprites[sprite_id];
  float4 device_position =
      to_device_position_transformed(unit_vertex, sprite.bounds, sprite.transformation, viewport_size);
  float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds,
                                                 sprite.content_mask.bounds);

L845-849

                                 [[texture(SurfaceInputIndex_CbCrTexture)]]) {
  constexpr sampler texture_sampler(mag_filter::linear, min_filter::linear);
  const float4x4 ycbcrToRGBTransform =
      float4x4(float4(+1.0000f, +1.0000f, +1.0000f, +0.0000f),
               float4(+0.0000f, -0.3441f, +1.7720f, +0.0000f),

L854-858

      cb_cr_texture.sample(texture_sampler, input.texture_position).rg, 1.0);

  return ycbcrToRGBTransform * ycbcr;
}

L967-972

}

float4 to_device_position_transformed(float2 unit_vertex, Bounds_ScaledPixels bounds,
                          TransformationMatrix transformation,
                          constant Size_DevicePixels *input_viewport_size) {
  float2 position =

L974-985

      float2(bounds.origin.x, bounds.origin.y);

  // Apply the transformation matrix to the position via matrix multiplication.
  float2 transformed_position = float2(0, 0);
  transformed_position[0] = position[0] * transformation.rotation_scale[0][0] + position[1] * transformation.rotation_scale[0][1];
  transformed_position[1] = position[0] * transformation.rotation_scale[1][0] + position[1] * transformation.rotation_scale[1][1];

  // Add in the translation component of the transformation matrix.
  transformed_position[0] += transformation.translation[0];
  transformed_position[1] += transformation.translation[1];

  float2 viewport_size = float2((float)input_viewport_size->width,

L986-990

                                (float)input_viewport_size->height);
  float2 device_position =
      transformed_position / viewport_size * float2(2., -2.) + float2(-1., 1.);
  return float4(device_position, 0., 1.);
}

Agent

Based on my analysis of the code, here's what we need to do to support transformations in the quad renderer:

  1. Update the quad vertex shader to use the transformation matrix

Currently, in the quad_vertex function, there's a line:

float4 device_position = to_device_position(unit_vertex, quad.bounds, viewport_size);

We need to modify this to use the to_device_position_transformed function that already exists in the shader code but is currently only used by the MonochromeSprite. Here's what needs to be changed:

Use Tool: edit_file (toolu_01G4WbL9RU3imTXSzgzH9wcR)

{
  "path": "zed/crates/gpui/src/platform/mac/shaders.metal",
  "create_or_overwrite": false,
  "display_description": "Update quad_vertex function to use transformation matrix"
}

Tool Results: toolu_01G4WbL9RU3imTXSzgzH9wcR

Edited zed/crates/gpui/src/platform/mac/shaders.metal:

@@ -72,7 +72,7 @@
   float2 unit_vertex = unit_vertices[unit_vertex_id];
   Quad quad = quads[quad_id];
   float4 device_position =
-      to_device_position(unit_vertex, quad.bounds, viewport_size);
+      to_device_position_transformed(unit_vertex, quad.bounds, quad.transformation, viewport_size);
   float4 clip_distance = distance_from_clip_rect(unit_vertex, quad.bounds,
                                                  quad.content_mask.bounds);
   float4 border_color = hsla_to_rgba(quad.border_color);

Debug Output:

{
  "original_path": "crates/gpui/src/platform/mac/shaders.metal",
  "new_text": "#include <metal_stdlib>\n#include <simd/simd.h>\n\nusing namespace metal;\n\nfloat4 hsla_to_rgba(Hsla hsla);\nfloat3 srgb_to_linear(float3 color);\nfloat3 linear_to_srgb(float3 color);\nfloat4 srgb_to_oklab(float4 color);\nfloat4 oklab_to_srgb(float4 color);\nfloat4 to_device_position(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                          constant Size_DevicePixels *viewport_size);\nfloat4 to_device_position_transformed(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                          TransformationMatrix transformation,\n                          constant Size_DevicePixels *input_viewport_size);\n\nfloat2 to_tile_position(float2 unit_vertex, AtlasTile tile,\n                        constant Size_DevicePixels *atlas_size);\nfloat4 distance_from_clip_rect(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                               Bounds_ScaledPixels clip_bounds);\nfloat corner_dash_velocity(float dv1, float dv2);\nfloat dash_alpha(float t, float period, float length, float dash_velocity,\n                 float antialias_threshold);\nfloat quarter_ellipse_sdf(float2 point, float2 radii);\nfloat pick_corner_radius(float2 center_to_point, Corners_ScaledPixels corner_radii);\nfloat quad_sdf(float2 point, Bounds_ScaledPixels bounds,\n               Corners_ScaledPixels corner_radii);\nfloat quad_sdf_impl(float2 center_to_point, float corner_radius);\nfloat gaussian(float x, float sigma);\nfloat2 erf(float2 x);\nfloat blur_along_x(float x, float y, float sigma, float corner,\n                   float2 half_size);\nfloat4 over(float4 below, float4 above);\nfloat radians(float degrees);\nfloat4 fill_color(Background background, float2 position, Bounds_ScaledPixels bounds,\n  float4 solid_color, float4 color0, float4 color1);\n\nstruct GradientColor {\n  float4 solid;\n  float4 color0;\n  float4 color1;\n};\nGradientColor prepare_fill_color(uint tag, uint color_space, Hsla solid, Hsla color0, Hsla color1);\n\nstruct QuadVertexOutput {\n  uint quad_id [[flat]];\n  float4 position [[position]];\n  float4 border_color [[flat]];\n  float4 background_solid [[flat]];\n  float4 background_color0 [[flat]];\n  float4 background_color1 [[flat]];\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct QuadFragmentInput {\n  uint quad_id [[flat]];\n  float4 position [[position]];\n  float4 border_color [[flat]];\n  float4 background_solid [[flat]];\n  float4 background_color0 [[flat]];\n  float4 background_color1 [[flat]];\n};\n\nvertex QuadVertexOutput quad_vertex(uint unit_vertex_id [[vertex_id]],\n                                    uint quad_id [[instance_id]],\n                                    constant float2 *unit_vertices\n                                    [[buffer(QuadInputIndex_Vertices)]],\n                                    constant Quad *quads\n                                    [[buffer(QuadInputIndex_Quads)]],\n                                    constant Size_DevicePixels *viewport_size\n                                    [[buffer(QuadInputIndex_ViewportSize)]]) {\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  Quad quad = quads[quad_id];\n  float4 device_position =\n      to_device_position_transformed(unit_vertex, quad.bounds, quad.transformation, viewport_size);\n  float4 clip_distance = distance_from_clip_rect(unit_vertex, quad.bounds,\n                                                 quad.content_mask.bounds);\n  float4 border_color = hsla_to_rgba(quad.border_color);\n\n  GradientColor gradient = prepare_fill_color(\n    quad.background.tag,\n    quad.background.color_space,\n    quad.background.solid,\n    quad.background.colors[0].color,\n    quad.background.colors[1].color\n  );\n\n  return QuadVertexOutput{\n      quad_id,\n      device_position,\n      border_color,\n      gradient.solid,\n      gradient.color0,\n      gradient.color1,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 quad_fragment(QuadFragmentInput input [[stage_in]],\n                              constant Quad *quads\n                              [[buffer(QuadInputIndex_Quads)]]) {\n  Quad quad = quads[input.quad_id];\n  float4 background_color = fill_color(quad.background, input.position.xy, quad.bounds,\n    input.background_solid, input.background_color0, input.background_color1);\n\n  bool unrounded = quad.corner_radii.top_left == 0.0 &&\n    quad.corner_radii.bottom_left == 0.0 &&\n    quad.corner_radii.top_right == 0.0 &&\n    quad.corner_radii.bottom_right == 0.0;\n\n  // Fast path when the quad is not rounded and doesn't have any border\n  if (quad.border_widths.top == 0.0 &&\n      quad.border_widths.left == 0.0 &&\n      quad.border_widths.right == 0.0 &&\n      quad.border_widths.bottom == 0.0 &&\n      unrounded) {\n    return background_color;\n  }\n\n  float2 size = float2(quad.bounds.size.width, quad.bounds.size.height);\n  float2 half_size = size / 2.0;\n  float2 point = input.position.xy - float2(quad.bounds.origin.x, quad.bounds.origin.y);\n  float2 center_to_point = point - half_size;\n\n  // Signed distance field threshold for inclusion of pixels. 0.5 is the\n  // minimum distance between the center of the pixel and the edge.\n  const float antialias_threshold = 0.5;\n\n  // Radius of the nearest corner\n  float corner_radius = pick_corner_radius(center_to_point, quad.corner_radii);\n\n  // Width of the nearest borders\n  float2 border = float2(\n    center_to_point.x < 0.0 ? quad.border_widths.left : quad.border_widths.right,\n    center_to_point.y < 0.0 ? quad.border_widths.top : quad.border_widths.bottom\n  );\n\n  // 0-width borders are reduced so that `inner_sdf >= antialias_threshold`.\n  // The purpose of this is to not draw antialiasing pixels in this case.\n  float2 reduced_border = float2(\n    border.x == 0.0 ? -antialias_threshold : border.x,\n    border.y == 0.0 ? -antialias_threshold : border.y);\n\n  // Vector from the corner of the quad bounds to the point, after mirroring\n  // the point into the bottom right quadrant. Both components are <= 0.\n  float2 corner_to_point = fabs(center_to_point) - half_size;\n\n  // Vector from the point to the center of the rounded corner's circle, also\n  // mirrored into bottom right quadrant.\n  float2 corner_center_to_point = corner_to_point + corner_radius;\n\n  // Whether the nearest point on the border is rounded\n  bool is_near_rounded_corner =\n    corner_center_to_point.x >= 0.0 &&\n    corner_center_to_point.y >= 0.0;\n\n  // Vector from straight border inner corner to point.\n  //\n  // 0-width borders are turned into width -1 so that inner_sdf is > 1.0 near\n  // the border. Without this, antialiasing pixels would be drawn.\n  float2 straight_border_inner_corner_to_point = corner_to_point + reduced_border;\n\n  // Whether the point is beyond the inner edge of the straight border\n  bool is_beyond_inner_straight_border =\n    straight_border_inner_corner_to_point.x > 0.0 ||\n    straight_border_inner_corner_to_point.y > 0.0;\n\n\n  // Whether the point is far enough inside the quad, such that the pixels are\n  // not affected by the straight border.\n  bool is_within_inner_straight_border =\n    straight_border_inner_corner_to_point.x < -antialias_threshold &&\n    straight_border_inner_corner_to_point.y < -antialias_threshold;\n\n  // Fast path for points that must be part of the background\n  if (is_within_inner_straight_border && !is_near_rounded_corner) {\n    return background_color;\n  }\n\n  // Signed distance of the point to the outside edge of the quad's border\n  float outer_sdf = quad_sdf_impl(corner_center_to_point, corner_radius);\n\n  // Approximate signed distance of the point to the inside edge of the quad's\n  // border. It is negative outside this edge (within the border), and\n  // positive inside.\n  //\n  // This is not always an accurate signed distance:\n  // * The rounded portions with varying border width use an approximation of\n  //   nearest-point-on-ellipse.\n  // * When it is quickly known to be outside the edge, -1.0 is used.\n  float inner_sdf = 0.0;\n  if (corner_center_to_point.x <= 0.0 || corner_center_to_point.y <= 0.0) {\n    // Fast paths for straight borders\n    inner_sdf = -max(straight_border_inner_corner_to_point.x,\n                     straight_border_inner_corner_to_point.y);\n  } else if (is_beyond_inner_straight_border) {\n    // Fast path for points that must be outside the inner edge\n    inner_sdf = -1.0;\n  } else if (reduced_border.x == reduced_border.y) {\n    // Fast path for circular inner edge.\n    inner_sdf = -(outer_sdf + reduced_border.x);\n  } else {\n    float2 ellipse_radii = max(float2(0.0), float2(corner_radius) - reduced_border);\n    inner_sdf = quarter_ellipse_sdf(corner_center_to_point, ellipse_radii);\n  }\n\n  // Negative when inside the border\n  float border_sdf = max(inner_sdf, outer_sdf);\n\n  float4 color = background_color;\n  if (border_sdf < antialias_threshold) {\n    float4 border_color = input.border_color;\n\n    // Dashed border logic when border_style == 1\n    if (quad.border_style == 1) {\n      // Position along the perimeter in \"dash space\", where each dash\n      // period has length 1\n      float t = 0.0;\n\n      // Total number of dash periods, so that the dash spacing can be\n      // adjusted to evenly divide it\n      float max_t = 0.0;\n\n      // Border width is proportional to dash size. This is the behavior\n      // used by browsers, but also avoids dashes from different segments\n      // overlapping when dash size is smaller than the border width.\n      //\n      // Dash pattern: (2 * border width) dash, (1 * border width) gap\n      const float dash_length_per_width = 2.0;\n      const float dash_gap_per_width = 1.0;\n      const float dash_period_per_width = dash_length_per_width + dash_gap_per_width;\n\n      // Since the dash size is determined by border width, the density of\n      // dashes varies. Multiplying a pixel distance by this returns a\n      // position in dash space - it has units (dash period / pixels). So\n      // a dash velocity of (1 / 10) is 1 dash every 10 pixels.\n      float dash_velocity = 0.0;\n\n      // Dividing this by the border width gives the dash velocity\n      const float dv_numerator = 1.0 / dash_period_per_width;\n\n      if (unrounded) {\n        // When corners aren't rounded, the dashes are separately laid\n        // out on each straight line, rather than around the whole\n        // perimeter. This way each line starts and ends with a dash.\n        bool is_horizontal = corner_center_to_point.x < corner_center_to_point.y;\n        float border_width = is_horizontal ? border.x : border.y;\n        dash_velocity = dv_numerator / border_width;\n        t = is_horizontal ? point.x : point.y;\n        t *= dash_velocity;\n        max_t = is_horizontal ? size.x : size.y;\n        max_t *= dash_velocity;\n      } else {\n        // When corners are rounded, the dashes are laid out clockwise\n        // around the whole perimeter.\n\n        float r_tr = quad.corner_radii.top_right;\n        float r_br = quad.corner_radii.bottom_right;\n        float r_bl = quad.corner_radii.bottom_left;\n        float r_tl = quad.corner_radii.top_left;\n\n        float w_t = quad.border_widths.top;\n        float w_r = quad.border_widths.right;\n        float w_b = quad.border_widths.bottom;\n        float w_l = quad.border_widths.left;\n\n        // Straight side dash velocities\n        float dv_t = w_t <= 0.0 ? 0.0 : dv_numerator / w_t;\n        float dv_r = w_r <= 0.0 ? 0.0 : dv_numerator / w_r;\n        float dv_b = w_b <= 0.0 ? 0.0 : dv_numerator / w_b;\n        float dv_l = w_l <= 0.0 ? 0.0 : dv_numerator / w_l;\n\n        // Straight side lengths in dash space\n        float s_t = (size.x - r_tl - r_tr) * dv_t;\n        float s_r = (size.y - r_tr - r_br) * dv_r;\n        float s_b = (size.x - r_br - r_bl) * dv_b;\n        float s_l = (size.y - r_bl - r_tl) * dv_l;\n\n        float corner_dash_velocity_tr = corner_dash_velocity(dv_t, dv_r);\n        float corner_dash_velocity_br = corner_dash_velocity(dv_b, dv_r);\n        float corner_dash_velocity_bl = corner_dash_velocity(dv_b, dv_l);\n        float corner_dash_velocity_tl = corner_dash_velocity(dv_t, dv_l);\n\n        // Corner lengths in dash space\n        float c_tr = r_tr * (M_PI_F / 2.0) * corner_dash_velocity_tr;\n        float c_br = r_br * (M_PI_F / 2.0) * corner_dash_velocity_br;\n        float c_bl = r_bl * (M_PI_F / 2.0) * corner_dash_velocity_bl;\n        float c_tl = r_tl * (M_PI_F / 2.0) * corner_dash_velocity_tl;\n\n        // Cumulative dash space upto each segment\n        float upto_tr = s_t;\n        float upto_r = upto_tr + c_tr;\n        float upto_br = upto_r + s_r;\n        float upto_b = upto_br + c_br;\n        float upto_bl = upto_b + s_b;\n        float upto_l = upto_bl + c_bl;\n        float upto_tl = upto_l + s_l;\n        max_t = upto_tl + c_tl;\n\n        if (is_near_rounded_corner) {\n          float radians = atan2(corner_center_to_point.y, corner_center_to_point.x);\n          float corner_t = radians * corner_radius;\n\n          if (center_to_point.x >= 0.0) {\n            if (center_to_point.y < 0.0) {\n              dash_velocity = corner_dash_velocity_tr;\n              // Subtracted because radians is pi/2 to 0 when\n              // going clockwise around the top right corner,\n              // since the y axis has been flipped\n              t = upto_r - corner_t * dash_velocity;\n            } else {\n              dash_velocity = corner_dash_velocity_br;\n              // Added because radians is 0 to pi/2 when going\n              // clockwise around the bottom-right corner\n              t = upto_br + corner_t * dash_velocity;\n            }\n          } else {\n            if (center_to_point.y >= 0.0) {\n              dash_velocity = corner_dash_velocity_bl;\n              // Subtracted because radians is pi/1 to 0 when\n              // going clockwise around the bottom-left corner,\n              // since the x axis has been flipped\n              t = upto_l - corner_t * dash_velocity;\n            } else {\n              dash_velocity = corner_dash_velocity_tl;\n              // Added because radians is 0 to pi/2 when going\n              // clockwise around the top-left corner, since both\n              // axis were flipped\n              t = upto_tl + corner_t * dash_velocity;\n            }\n          }\n        } else {\n          // Straight borders\n          bool is_horizontal = corner_center_to_point.x < corner_center_to_point.y;\n          if (is_horizontal) {\n            if (center_to_point.y < 0.0) {\n              dash_velocity = dv_t;\n              t = (point.x - r_tl) * dash_velocity;\n            } else {\n              dash_velocity = dv_b;\n              t = upto_bl - (point.x - r_bl) * dash_velocity;\n            }\n          } else {\n            if (center_to_point.x < 0.0) {\n              dash_velocity = dv_l;\n              t = upto_tl - (point.y - r_tl) * dash_velocity;\n            } else {\n              dash_velocity = dv_r;\n              t = upto_r + (point.y - r_tr) * dash_velocity;\n            }\n          }\n        }\n      }\n\n      float dash_length = dash_length_per_width / dash_period_per_width;\n      float desired_dash_gap = dash_gap_per_width / dash_period_per_width;\n\n      // Straight borders should start and end with a dash, so max_t is\n      // reduced to cause this.\n      max_t -= unrounded ? dash_length : 0.0;\n      if (max_t >= 1.0) {\n        // Adjust dash gap to evenly divide max_t\n        float dash_count = floor(max_t);\n        float dash_period = max_t / dash_count;\n        border_color.a *= dash_alpha(t, dash_period, dash_length, dash_velocity,\n                                     antialias_threshold);\n      } else if (unrounded) {\n        // When there isn't enough space for the full gap between the\n        // two start / end dashes of a straight border, reduce gap to\n        // make them fit.\n        float dash_gap = max_t - dash_length;\n        if (dash_gap > 0.0) {\n          float dash_period = dash_length + dash_gap;\n          border_color.a *= dash_alpha(t, dash_period, dash_length, dash_velocity,\n                                       antialias_threshold);\n        }\n      }\n    }\n\n    // Blend the border on top of the background and then linearly interpolate\n    // between the two as we slide inside the background.\n    float4 blended_border = over(background_color, border_color);\n    color = mix(background_color, blended_border,\n                saturate(antialias_threshold - inner_sdf));\n  }\n\n  return color * float4(1.0, 1.0, 1.0, saturate(antialias_threshold - outer_sdf));\n}\n\n// Returns the dash velocity of a corner given the dash velocity of the two\n// sides, by returning the slower velocity (larger dashes).\n//\n// Since 0 is used for dash velocity when the border width is 0 (instead of\n// +inf), this returns the other dash velocity in that case.\n//\n// An alternative to this might be to appropriately interpolate the dash\n// velocity around the corner, but that seems overcomplicated.\nfloat corner_dash_velocity(float dv1, float dv2) {\n  if (dv1 == 0.0) {\n    return dv2;\n  } else if (dv2 == 0.0) {\n    return dv1;\n  } else {\n    return min(dv1, dv2);\n  }\n}\n\n// Returns alpha used to render antialiased dashes.\n// `t` is within the dash when `fmod(t, period) < length`.\nfloat dash_alpha(\n    float t, float period, float length, float dash_velocity,\n    float antialias_threshold) {\n  float half_period = period / 2.0;\n  float half_length = length / 2.0;\n  // Value in [-half_period, half_period]\n  // The dash is in [-half_length, half_length]\n  float centered = fmod(t + half_period - half_length, period) - half_period;\n  // Signed distance for the dash, negative values are inside the dash\n  float signed_distance = abs(centered) - half_length;\n  // Antialiased alpha based on the signed distance\n  return saturate(antialias_threshold - signed_distance / dash_velocity);\n}\n\n// This approximates distance to the nearest point to a quarter ellipse in a way\n// that is sufficient for anti-aliasing when the ellipse is not very eccentric.\n// The components of `point` are expected to be positive.\n//\n// Negative on the outside and positive on the inside.\nfloat quarter_ellipse_sdf(float2 point, float2 radii) {\n  // Scale the space to treat the ellipse like a unit circle\n  float2 circle_vec = point / radii;\n  float unit_circle_sdf = length(circle_vec) - 1.0;\n  // Approximate up-scaling of the length by using the average of the radii.\n  //\n  // TODO: A better solution would be to use the gradient of the implicit\n  // function for an ellipse to approximate a scaling factor.\n  return unit_circle_sdf * (radii.x + radii.y) * -0.5;\n}\n\nstruct ShadowVertexOutput {\n  float4 position [[position]];\n  float4 color [[flat]];\n  uint shadow_id [[flat]];\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct ShadowFragmentInput {\n  float4 position [[position]];\n  float4 color [[flat]];\n  uint shadow_id [[flat]];\n};\n\nvertex ShadowVertexOutput shadow_vertex(\n    uint unit_vertex_id [[vertex_id]], uint shadow_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(ShadowInputIndex_Vertices)]],\n    constant Shadow *shadows [[buffer(ShadowInputIndex_Shadows)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(ShadowInputIndex_ViewportSize)]]) {\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  Shadow shadow = shadows[shadow_id];\n\n  float margin = 3. * shadow.blur_radius;\n  // Set the bounds of the shadow and adjust its size based on the shadow's\n  // spread radius to achieve the spreading effect\n  Bounds_ScaledPixels bounds = shadow.bounds;\n  bounds.origin.x -= margin;\n  bounds.origin.y -= margin;\n  bounds.size.width += 2. * margin;\n  bounds.size.height += 2. * margin;\n\n  float4 device_position =\n      to_device_position(unit_vertex, bounds, viewport_size);\n  float4 clip_distance =\n      distance_from_clip_rect(unit_vertex, bounds, shadow.content_mask.bounds);\n  float4 color = hsla_to_rgba(shadow.color);\n\n  return ShadowVertexOutput{\n      device_position,\n      color,\n      shadow_id,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 shadow_fragment(ShadowFragmentInput input [[stage_in]],\n                                constant Shadow *shadows\n                                [[buffer(ShadowInputIndex_Shadows)]]) {\n  Shadow shadow = shadows[input.shadow_id];\n\n  float2 origin = float2(shadow.bounds.origin.x, shadow.bounds.origin.y);\n  float2 size = float2(shadow.bounds.size.width, shadow.bounds.size.height);\n  float2 half_size = size / 2.;\n  float2 center = origin + half_size;\n  float2 point = input.position.xy - center;\n  float corner_radius;\n  if (point.x < 0.) {\n    if (point.y < 0.) {\n      corner_radius = shadow.corner_radii.top_left;\n    } else {\n      corner_radius = shadow.corner_radii.bottom_left;\n    }\n  } else {\n    if (point.y < 0.) {\n      corner_radius = shadow.corner_radii.top_right;\n    } else {\n      corner_radius = shadow.corner_radii.bottom_right;\n    }\n  }\n\n  float alpha;\n  if (shadow.blur_radius == 0.) {\n    float distance = quad_sdf(input.position.xy, shadow.bounds, shadow.corner_radii);\n    alpha = saturate(0.5 - distance);\n  } else {\n    // The signal is only non-zero in a limited range, so don't waste samples\n    float low = point.y - half_size.y;\n    float high = point.y + half_size.y;\n    float start = clamp(-3. * shadow.blur_radius, low, high);\n    float end = clamp(3. * shadow.blur_radius, low, high);\n\n    // Accumulate samples (we can get away with surprisingly few samples)\n    float step = (end - start) / 4.;\n    float y = start + step * 0.5;\n    alpha = 0.;\n    for (int i = 0; i < 4; i++) {\n      alpha += blur_along_x(point.x, point.y - y, shadow.blur_radius,\n                            corner_radius, half_size) *\n               gaussian(y, shadow.blur_radius) * step;\n      y += step;\n    }\n  }\n\n  return input.color * float4(1., 1., 1., alpha);\n}\n\nstruct UnderlineVertexOutput {\n  float4 position [[position]];\n  float4 color [[flat]];\n  uint underline_id [[flat]];\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct UnderlineFragmentInput {\n  float4 position [[position]];\n  float4 color [[flat]];\n  uint underline_id [[flat]];\n};\n\nvertex UnderlineVertexOutput underline_vertex(\n    uint unit_vertex_id [[vertex_id]], uint underline_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(UnderlineInputIndex_Vertices)]],\n    constant Underline *underlines [[buffer(UnderlineInputIndex_Underlines)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(ShadowInputIndex_ViewportSize)]]) {\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  Underline underline = underlines[underline_id];\n  float4 device_position =\n      to_device_position(unit_vertex, underline.bounds, viewport_size);\n  float4 clip_distance = distance_from_clip_rect(unit_vertex, underline.bounds,\n                                                 underline.content_mask.bounds);\n  float4 color = hsla_to_rgba(underline.color);\n  return UnderlineVertexOutput{\n      device_position,\n      color,\n      underline_id,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 underline_fragment(UnderlineFragmentInput input [[stage_in]],\n                                   constant Underline *underlines\n                                   [[buffer(UnderlineInputIndex_Underlines)]]) {\n  Underline underline = underlines[input.underline_id];\n  if (underline.wavy) {\n    float half_thickness = underline.thickness * 0.5;\n    float2 origin =\n        float2(underline.bounds.origin.x, underline.bounds.origin.y);\n    float2 st = ((input.position.xy - origin) / underline.bounds.size.height) -\n                float2(0., 0.5);\n    float frequency = (M_PI_F * (3. * underline.thickness)) / 8.;\n    float amplitude = 1. / (2. * underline.thickness);\n    float sine = sin(st.x * frequency) * amplitude;\n    float dSine = cos(st.x * frequency) * amplitude * frequency;\n    float distance = (st.y - sine) / sqrt(1. + dSine * dSine);\n    float distance_in_pixels = distance * underline.bounds.size.height;\n    float distance_from_top_border = distance_in_pixels - half_thickness;\n    float distance_from_bottom_border = distance_in_pixels + half_thickness;\n    float alpha = saturate(\n        0.5 - max(-distance_from_bottom_border, distance_from_top_border));\n    return input.color * float4(1., 1., 1., alpha);\n  } else {\n    return input.color;\n  }\n}\n\nstruct MonochromeSpriteVertexOutput {\n  float4 position [[position]];\n  float2 tile_position;\n  float4 color [[flat]];\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct MonochromeSpriteFragmentInput {\n  float4 position [[position]];\n  float2 tile_position;\n  float4 color [[flat]];\n};\n\nvertex MonochromeSpriteVertexOutput monochrome_sprite_vertex(\n    uint unit_vertex_id [[vertex_id]], uint sprite_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(SpriteInputIndex_Vertices)]],\n    constant MonochromeSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(SpriteInputIndex_ViewportSize)]],\n    constant Size_DevicePixels *atlas_size\n    [[buffer(SpriteInputIndex_AtlasTextureSize)]]) {\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  MonochromeSprite sprite = sprites[sprite_id];\n  float4 device_position =\n      to_device_position_transformed(unit_vertex, sprite.bounds, sprite.transformation, viewport_size);\n  float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds,\n                                                 sprite.content_mask.bounds);\n  float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);\n  float4 color = hsla_to_rgba(sprite.color);\n  return MonochromeSpriteVertexOutput{\n      device_position,\n      tile_position,\n      color,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 monochrome_sprite_fragment(\n    MonochromeSpriteFragmentInput input [[stage_in]],\n    constant MonochromeSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    texture2d<float> atlas_texture [[texture(SpriteInputIndex_AtlasTexture)]]) {\n  constexpr sampler atlas_texture_sampler(mag_filter::linear,\n                                          min_filter::linear);\n  float4 sample =\n      atlas_texture.sample(atlas_texture_sampler, input.tile_position);\n  float4 color = input.color;\n  color.a *= sample.a;\n  return color;\n}\n\nstruct PolychromeSpriteVertexOutput {\n  float4 position [[position]];\n  float2 tile_position;\n  uint sprite_id [[flat]];\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct PolychromeSpriteFragmentInput {\n  float4 position [[position]];\n  float2 tile_position;\n  uint sprite_id [[flat]];\n};\n\nvertex PolychromeSpriteVertexOutput polychrome_sprite_vertex(\n    uint unit_vertex_id [[vertex_id]], uint sprite_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(SpriteInputIndex_Vertices)]],\n    constant PolychromeSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(SpriteInputIndex_ViewportSize)]],\n    constant Size_DevicePixels *atlas_size\n    [[buffer(SpriteInputIndex_AtlasTextureSize)]]) {\n\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  PolychromeSprite sprite = sprites[sprite_id];\n  float4 device_position =\n      to_device_position(unit_vertex, sprite.bounds, viewport_size);\n  float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds,\n                                                 sprite.content_mask.bounds);\n  float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);\n  return PolychromeSpriteVertexOutput{\n      device_position,\n      tile_position,\n      sprite_id,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 polychrome_sprite_fragment(\n    PolychromeSpriteFragmentInput input [[stage_in]],\n    constant PolychromeSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    texture2d<float> atlas_texture [[texture(SpriteInputIndex_AtlasTexture)]]) {\n  PolychromeSprite sprite = sprites[input.sprite_id];\n  constexpr sampler atlas_texture_sampler(mag_filter::linear,\n                                          min_filter::linear);\n  float4 sample =\n      atlas_texture.sample(atlas_texture_sampler, input.tile_position);\n  float distance =\n      quad_sdf(input.position.xy, sprite.bounds, sprite.corner_radii);\n\n  float4 color = sample;\n  if (sprite.grayscale) {\n    float grayscale = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;\n    color.r = grayscale;\n    color.g = grayscale;\n    color.b = grayscale;\n  }\n  color.a *= sprite.opacity * saturate(0.5 - distance);\n  return color;\n}\n\nstruct PathRasterizationVertexOutput {\n  float4 position [[position]];\n  float2 st_position;\n  float clip_rect_distance [[clip_distance]][4];\n};\n\nstruct PathRasterizationFragmentInput {\n  float4 position [[position]];\n  float2 st_position;\n};\n\nvertex PathRasterizationVertexOutput path_rasterization_vertex(\n    uint vertex_id [[vertex_id]],\n    constant PathVertex_ScaledPixels *vertices\n    [[buffer(PathRasterizationInputIndex_Vertices)]],\n    constant Size_DevicePixels *atlas_size\n    [[buffer(PathRasterizationInputIndex_AtlasTextureSize)]]) {\n  PathVertex_ScaledPixels v = vertices[vertex_id];\n  float2 vertex_position = float2(v.xy_position.x, v.xy_position.y);\n  float2 viewport_size = float2(atlas_size->width, atlas_size->height);\n  return PathRasterizationVertexOutput{\n      float4(vertex_position / viewport_size * float2(2., -2.) +\n                 float2(-1., 1.),\n             0., 1.),\n      float2(v.st_position.x, v.st_position.y),\n      {v.xy_position.x - v.content_mask.bounds.origin.x,\n       v.content_mask.bounds.origin.x + v.content_mask.bounds.size.width -\n           v.xy_position.x,\n       v.xy_position.y - v.content_mask.bounds.origin.y,\n       v.content_mask.bounds.origin.y + v.content_mask.bounds.size.height -\n           v.xy_position.y}};\n}\n\nfragment float4 path_rasterization_fragment(PathRasterizationFragmentInput input\n                                            [[stage_in]]) {\n  float2 dx = dfdx(input.st_position);\n  float2 dy = dfdy(input.st_position);\n  float2 gradient = float2((2. * input.st_position.x) * dx.x - dx.y,\n                           (2. * input.st_position.x) * dy.x - dy.y);\n  float f = (input.st_position.x * input.st_position.x) - input.st_position.y;\n  float distance = f / length(gradient);\n  float alpha = saturate(0.5 - distance);\n  return float4(alpha, 0., 0., 1.);\n}\n\nstruct PathSpriteVertexOutput {\n  float4 position [[position]];\n  float2 tile_position;\n  uint sprite_id [[flat]];\n  float4 solid_color [[flat]];\n  float4 color0 [[flat]];\n  float4 color1 [[flat]];\n};\n\nvertex PathSpriteVertexOutput path_sprite_vertex(\n    uint unit_vertex_id [[vertex_id]], uint sprite_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(SpriteInputIndex_Vertices)]],\n    constant PathSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(SpriteInputIndex_ViewportSize)]],\n    constant Size_DevicePixels *atlas_size\n    [[buffer(SpriteInputIndex_AtlasTextureSize)]]) {\n\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  PathSprite sprite = sprites[sprite_id];\n  // Don't apply content mask because it was already accounted for when\n  // rasterizing the path.\n  float4 device_position =\n      to_device_position(unit_vertex, sprite.bounds, viewport_size);\n  float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);\n\n  GradientColor gradient = prepare_fill_color(\n    sprite.color.tag,\n    sprite.color.color_space,\n    sprite.color.solid,\n    sprite.color.colors[0].color,\n    sprite.color.colors[1].color\n  );\n\n  return PathSpriteVertexOutput{\n    device_position,\n    tile_position,\n    sprite_id,\n    gradient.solid,\n    gradient.color0,\n    gradient.color1\n  };\n}\n\nfragment float4 path_sprite_fragment(\n    PathSpriteVertexOutput input [[stage_in]],\n    constant PathSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    texture2d<float> atlas_texture [[texture(SpriteInputIndex_AtlasTexture)]]) {\n  constexpr sampler atlas_texture_sampler(mag_filter::linear,\n                                          min_filter::linear);\n  float4 sample =\n      atlas_texture.sample(atlas_texture_sampler, input.tile_position);\n  float mask = 1. - abs(1. - fmod(sample.r, 2.));\n  PathSprite sprite = sprites[input.sprite_id];\n  Background background = sprite.color;\n  float4 color = fill_color(background, input.position.xy, sprite.bounds,\n    input.solid_color, input.color0, input.color1);\n  color.a *= mask;\n  return color;\n}\n\nstruct SurfaceVertexOutput {\n  float4 position [[position]];\n  float2 texture_position;\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct SurfaceFragmentInput {\n  float4 position [[position]];\n  float2 texture_position;\n};\n\nvertex SurfaceVertexOutput surface_vertex(\n    uint unit_vertex_id [[vertex_id]], uint surface_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(SurfaceInputIndex_Vertices)]],\n    constant SurfaceBounds *surfaces [[buffer(SurfaceInputIndex_Surfaces)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(SurfaceInputIndex_ViewportSize)]],\n    constant Size_DevicePixels *texture_size\n    [[buffer(SurfaceInputIndex_TextureSize)]]) {\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  SurfaceBounds surface = surfaces[surface_id];\n  float4 device_position =\n      to_device_position(unit_vertex, surface.bounds, viewport_size);\n  float4 clip_distance = distance_from_clip_rect(unit_vertex, surface.bounds,\n                                                 surface.content_mask.bounds);\n  // We are going to copy the whole texture, so the texture position corresponds\n  // to the current vertex of the unit triangle.\n  float2 texture_position = unit_vertex;\n  return SurfaceVertexOutput{\n      device_position,\n      texture_position,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 surface_fragment(SurfaceFragmentInput input [[stage_in]],\n                                 texture2d<float> y_texture\n                                 [[texture(SurfaceInputIndex_YTexture)]],\n                                 texture2d<float> cb_cr_texture\n                                 [[texture(SurfaceInputIndex_CbCrTexture)]]) {\n  constexpr sampler texture_sampler(mag_filter::linear, min_filter::linear);\n  const float4x4 ycbcrToRGBTransform =\n      float4x4(float4(+1.0000f, +1.0000f, +1.0000f, +0.0000f),\n               float4(+0.0000f, -0.3441f, +1.7720f, +0.0000f),\n               float4(+1.4020f, -0.7141f, +0.0000f, +0.0000f),\n               float4(-0.7010f, +0.5291f, -0.8860f, +1.0000f));\n  float4 ycbcr = float4(\n      y_texture.sample(texture_sampler, input.texture_position).r,\n      cb_cr_texture.sample(texture_sampler, input.texture_position).rg, 1.0);\n\n  return ycbcrToRGBTransform * ycbcr;\n}\n\nfloat4 hsla_to_rgba(Hsla hsla) {\n  float h = hsla.h * 6.0; // Now, it's an angle but scaled in [0, 6) range\n  float s = hsla.s;\n  float l = hsla.l;\n  float a = hsla.a;\n\n  float c = (1.0 - fabs(2.0 * l - 1.0)) * s;\n  float x = c * (1.0 - fabs(fmod(h, 2.0) - 1.0));\n  float m = l - c / 2.0;\n\n  float r = 0.0;\n  float g = 0.0;\n  float b = 0.0;\n\n  if (h >= 0.0 && h < 1.0) {\n    r = c;\n    g = x;\n    b = 0.0;\n  } else if (h >= 1.0 && h < 2.0) {\n    r = x;\n    g = c;\n    b = 0.0;\n  } else if (h >= 2.0 && h < 3.0) {\n    r = 0.0;\n    g = c;\n    b = x;\n  } else if (h >= 3.0 && h < 4.0) {\n    r = 0.0;\n    g = x;\n    b = c;\n  } else if (h >= 4.0 && h < 5.0) {\n    r = x;\n    g = 0.0;\n    b = c;\n  } else {\n    r = c;\n    g = 0.0;\n    b = x;\n  }\n\n  float4 rgba;\n  rgba.x = (r + m);\n  rgba.y = (g + m);\n  rgba.z = (b + m);\n  rgba.w = a;\n  return rgba;\n}\n\nfloat3 srgb_to_linear(float3 color) {\n  return pow(color, float3(2.2));\n}\n\nfloat3 linear_to_srgb(float3 color) {\n  return pow(color, float3(1.0 / 2.2));\n}\n\n// Converts a sRGB color to the Oklab color space.\n// Reference: https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab\nfloat4 srgb_to_oklab(float4 color) {\n  // Convert non-linear sRGB to linear sRGB\n  color = float4(srgb_to_linear(color.rgb), color.a);\n\n  float l = 0.4122214708 * color.r + 0.5363325363 * color.g + 0.0514459929 * color.b;\n  float m = 0.2119034982 * color.r + 0.6806995451 * color.g + 0.1073969566 * color.b;\n  float s = 0.0883024619 * color.r + 0.2817188376 * color.g + 0.6299787005 * color.b;\n\n  float l_ = pow(l, 1.0/3.0);\n  float m_ = pow(m, 1.0/3.0);\n  float s_ = pow(s, 1.0/3.0);\n\n  return float4(\n   \t0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_,\n   \t1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_,\n   \t0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_,\n   \tcolor.a\n  );\n}\n\n// Converts an Oklab color to the sRGB color space.\nfloat4 oklab_to_srgb(float4 color) {\n  float l_ = color.r + 0.3963377774 * color.g + 0.2158037573 * color.b;\n  float m_ = color.r - 0.1055613458 * color.g - 0.0638541728 * color.b;\n  float s_ = color.r - 0.0894841775 * color.g - 1.2914855480 * color.b;\n\n  float l = l_ * l_ * l_;\n  float m = m_ * m_ * m_;\n  float s = s_ * s_ * s_;\n\n  float3 linear_rgb = float3(\n   \t4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n   \t-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n   \t-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s\n  );\n\n  // Convert linear sRGB to non-linear sRGB\n  return float4(linear_to_srgb(linear_rgb), color.a);\n}\n\nfloat4 to_device_position(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                          constant Size_DevicePixels *input_viewport_size) {\n  float2 position =\n      unit_vertex * float2(bounds.size.width, bounds.size.height) +\n      float2(bounds.origin.x, bounds.origin.y);\n  float2 viewport_size = float2((float)input_viewport_size->width,\n                                (float)input_viewport_size->height);\n  float2 device_position =\n      position / viewport_size * float2(2., -2.) + float2(-1., 1.);\n  return float4(device_position, 0., 1.);\n}\n\nfloat4 to_device_position_transformed(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                          TransformationMatrix transformation,\n                          constant Size_DevicePixels *input_viewport_size) {\n  float2 position =\n      unit_vertex * float2(bounds.size.width, bounds.size.height) +\n      float2(bounds.origin.x, bounds.origin.y);\n\n  // Apply the transformation matrix to the position via matrix multiplication.\n  float2 transformed_position = float2(0, 0);\n  transformed_position[0] = position[0] * transformation.rotation_scale[0][0] + position[1] * transformation.rotation_scale[0][1];\n  transformed_position[1] = position[0] * transformation.rotation_scale[1][0] + position[1] * transformation.rotation_scale[1][1];\n\n  // Add in the translation component of the transformation matrix.\n  transformed_position[0] += transformation.translation[0];\n  transformed_position[1] += transformation.translation[1];\n\n  float2 viewport_size = float2((float)input_viewport_size->width,\n                                (float)input_viewport_size->height);\n  float2 device_position =\n      transformed_position / viewport_size * float2(2., -2.) + float2(-1., 1.);\n  return float4(device_position, 0., 1.);\n}\n\n\nfloat2 to_tile_position(float2 unit_vertex, AtlasTile tile,\n                        constant Size_DevicePixels *atlas_size) {\n  float2 tile_origin = float2(tile.bounds.origin.x, tile.bounds.origin.y);\n  float2 tile_size = float2(tile.bounds.size.width, tile.bounds.size.height);\n  return (tile_origin + unit_vertex * tile_size) /\n         float2((float)atlas_size->width, (float)atlas_size->height);\n}\n\n// Selects corner radius based on quadrant.\nfloat pick_corner_radius(float2 center_to_point, Corners_ScaledPixels corner_radii) {\n  if (center_to_point.x < 0.) {\n    if (center_to_point.y < 0.) {\n      return corner_radii.top_left;\n    } else {\n      return corner_radii.bottom_left;\n    }\n  } else {\n    if (center_to_point.y < 0.) {\n      return corner_radii.top_right;\n    } else {\n      return corner_radii.bottom_right;\n    }\n  }\n}\n\n// Signed distance of the point to the quad's border - positive outside the\n// border, and negative inside.\nfloat quad_sdf(float2 point, Bounds_ScaledPixels bounds,\n               Corners_ScaledPixels corner_radii) {\n    float2 half_size = float2(bounds.size.width, bounds.size.height) / 2.0;\n    float2 center = float2(bounds.origin.x, bounds.origin.y) + half_size;\n    float2 center_to_point = point - center;\n    float corner_radius = pick_corner_radius(center_to_point, corner_radii);\n    float2 corner_to_point = fabs(center_to_point) - half_size;\n    float2 corner_center_to_point = corner_to_point + corner_radius;\n    return quad_sdf_impl(corner_center_to_point, corner_radius);\n}\n\n// Implementation of quad signed distance field\nfloat quad_sdf_impl(float2 corner_center_to_point, float corner_radius) {\n    if (corner_radius == 0.0) {\n        // Fast path for unrounded corners\n        return max(corner_center_to_point.x, corner_center_to_point.y);\n    } else {\n        // Signed distance of the point from a quad that is inset by corner_radius\n        // It is negative inside this quad, and positive outside\n        float signed_distance_to_inset_quad =\n            // 0 inside the inset quad, and positive outside\n            length(max(float2(0.0), corner_center_to_point)) +\n            // 0 outside the inset quad, and negative inside\n            min(0.0, max(corner_center_to_point.x, corner_center_to_point.y));\n\n        return signed_distance_to_inset_quad - corner_radius;\n    }\n}\n\n// A standard gaussian function, used for weighting samples\nfloat gaussian(float x, float sigma) {\n  return exp(-(x * x) / (2. * sigma * sigma)) / (sqrt(2. * M_PI_F) * sigma);\n}\n\n// This approximates the error function, needed for the gaussian integral\nfloat2 erf(float2 x) {\n  float2 s = sign(x);\n  float2 a = abs(x);\n  float2 r1 = 1. + (0.278393 + (0.230389 + (0.000972 + 0.078108 * a) * a) * a) * a;\n  float2 r2 = r1 * r1;\n  return s - s / (r2 * r2);\n}\n\nfloat blur_along_x(float x, float y, float sigma, float corner,\n                   float2 half_size) {\n  float delta = min(half_size.y - corner - abs(y), 0.);\n  float curved =\n      half_size.x - corner + sqrt(max(0., corner * corner - delta * delta));\n  float2 integral =\n      0.5 + 0.5 * erf((x + float2(-curved, curved)) * (sqrt(0.5) / sigma));\n  return integral.y - integral.x;\n}\n\nfloat4 distance_from_clip_rect(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                               Bounds_ScaledPixels clip_bounds) {\n  float2 position =\n      unit_vertex * float2(bounds.size.width, bounds.size.height) +\n      float2(bounds.origin.x, bounds.origin.y);\n  return float4(position.x - clip_bounds.origin.x,\n                clip_bounds.origin.x + clip_bounds.size.width - position.x,\n                position.y - clip_bounds.origin.y,\n                clip_bounds.origin.y + clip_bounds.size.height - position.y);\n}\n\nfloat4 over(float4 below, float4 above) {\n  float4 result;\n  float alpha = above.a + below.a * (1.0 - above.a);\n  result.rgb =\n      (above.rgb * above.a + below.rgb * below.a * (1.0 - above.a)) / alpha;\n  result.a = alpha;\n  return result;\n}\n\nGradientColor prepare_fill_color(uint tag, uint color_space, Hsla solid,\n                                     Hsla color0, Hsla color1) {\n  GradientColor out;\n  if (tag == 0 || tag == 2) {\n    out.solid = hsla_to_rgba(solid);\n  } else if (tag == 1) {\n    out.color0 = hsla_to_rgba(color0);\n    out.color1 = hsla_to_rgba(color1);\n\n    // Prepare color space in vertex for avoid conversion\n    // in fragment shader for performance reasons\n    if (color_space == 1) {\n      // Oklab\n      out.color0 = srgb_to_oklab(out.color0);\n      out.color1 = srgb_to_oklab(out.color1);\n    }\n  }\n\n  return out;\n}\n\nfloat2x2 rotate2d(float angle) {\n    float s = sin(angle);\n    float c = cos(angle);\n    return float2x2(c, -s, s, c);\n}\n\nfloat4 fill_color(Background background,\n                      float2 position,\n                      Bounds_ScaledPixels bounds,\n                      float4 solid_color, float4 color0, float4 color1) {\n  float4 color;\n\n  switch (background.tag) {\n    case 0:\n      color = solid_color;\n      break;\n    case 1: {\n      // -90 degrees to match the CSS gradient angle.\n      float gradient_angle = background.gradient_angle_or_pattern_height;\n      float radians = (fmod(gradient_angle, 360.0) - 90.0) * (M_PI_F / 180.0);\n      float2 direction = float2(cos(radians), sin(radians));\n\n      // Expand the short side to be the same as the long side\n      if (bounds.size.width > bounds.size.height) {\n          direction.y *= bounds.size.height / bounds.size.width;\n      } else {\n          direction.x *=  bounds.size.width / bounds.size.height;\n      }\n\n      // Get the t value for the linear gradient with the color stop percentages.\n      float2 half_size = float2(bounds.size.width, bounds.size.height) / 2.;\n      float2 center = float2(bounds.origin.x, bounds.origin.y) + half_size;\n      float2 center_to_point = position - center;\n      float t = dot(center_to_point, direction) / length(direction);\n      // Check the direction to determine whether to use x or y\n      if (abs(direction.x) > abs(direction.y)) {\n          t = (t + half_size.x) / bounds.size.width;\n      } else {\n          t = (t + half_size.y) / bounds.size.height;\n      }\n\n      // Adjust t based on the stop percentages\n      t = (t - background.colors[0].percentage)\n        / (background.colors[1].percentage\n        - background.colors[0].percentage);\n      t = clamp(t, 0.0, 1.0);\n\n      switch (background.color_space) {\n        case 0:\n          color = mix(color0, color1, t);\n          break;\n        case 1: {\n          float4 oklab_color = mix(color0, color1, t);\n          color = oklab_to_srgb(oklab_color);\n          break;\n        }\n      }\n      break;\n    }\n    case 2: {\n        float gradient_angle_or_pattern_height = background.gradient_angle_or_pattern_height;\n        float pattern_width = (gradient_angle_or_pattern_height / 65535.0f) / 255.0f;\n        float pattern_interval = fmod(gradient_angle_or_pattern_height, 65535.0f) / 255.0f;\n        float pattern_height = pattern_width + pattern_interval;\n        float stripe_angle = M_PI_F / 4.0;\n        float pattern_period = pattern_height * sin(stripe_angle);\n        float2x2 rotation = rotate2d(stripe_angle);\n        float2 relative_position = position - float2(bounds.origin.x, bounds.origin.y);\n        float2 rotated_point = rotation * relative_position;\n        float pattern = fmod(rotated_point.x, pattern_period);\n        float distance = min(pattern, pattern_period - pattern) - pattern_period * (pattern_width / pattern_height) /  2.0f;\n        color = solid_color;\n        color.a *= saturate(0.5 - distance);\n        break;\n    }\n  }\n\n  return color;\n}\n",
  "old_text": "#include <metal_stdlib>\n#include <simd/simd.h>\n\nusing namespace metal;\n\nfloat4 hsla_to_rgba(Hsla hsla);\nfloat3 srgb_to_linear(float3 color);\nfloat3 linear_to_srgb(float3 color);\nfloat4 srgb_to_oklab(float4 color);\nfloat4 oklab_to_srgb(float4 color);\nfloat4 to_device_position(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                          constant Size_DevicePixels *viewport_size);\nfloat4 to_device_position_transformed(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                          TransformationMatrix transformation,\n                          constant Size_DevicePixels *input_viewport_size);\n\nfloat2 to_tile_position(float2 unit_vertex, AtlasTile tile,\n                        constant Size_DevicePixels *atlas_size);\nfloat4 distance_from_clip_rect(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                               Bounds_ScaledPixels clip_bounds);\nfloat corner_dash_velocity(float dv1, float dv2);\nfloat dash_alpha(float t, float period, float length, float dash_velocity,\n                 float antialias_threshold);\nfloat quarter_ellipse_sdf(float2 point, float2 radii);\nfloat pick_corner_radius(float2 center_to_point, Corners_ScaledPixels corner_radii);\nfloat quad_sdf(float2 point, Bounds_ScaledPixels bounds,\n               Corners_ScaledPixels corner_radii);\nfloat quad_sdf_impl(float2 center_to_point, float corner_radius);\nfloat gaussian(float x, float sigma);\nfloat2 erf(float2 x);\nfloat blur_along_x(float x, float y, float sigma, float corner,\n                   float2 half_size);\nfloat4 over(float4 below, float4 above);\nfloat radians(float degrees);\nfloat4 fill_color(Background background, float2 position, Bounds_ScaledPixels bounds,\n  float4 solid_color, float4 color0, float4 color1);\n\nstruct GradientColor {\n  float4 solid;\n  float4 color0;\n  float4 color1;\n};\nGradientColor prepare_fill_color(uint tag, uint color_space, Hsla solid, Hsla color0, Hsla color1);\n\nstruct QuadVertexOutput {\n  uint quad_id [[flat]];\n  float4 position [[position]];\n  float4 border_color [[flat]];\n  float4 background_solid [[flat]];\n  float4 background_color0 [[flat]];\n  float4 background_color1 [[flat]];\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct QuadFragmentInput {\n  uint quad_id [[flat]];\n  float4 position [[position]];\n  float4 border_color [[flat]];\n  float4 background_solid [[flat]];\n  float4 background_color0 [[flat]];\n  float4 background_color1 [[flat]];\n};\n\nvertex QuadVertexOutput quad_vertex(uint unit_vertex_id [[vertex_id]],\n                                    uint quad_id [[instance_id]],\n                                    constant float2 *unit_vertices\n                                    [[buffer(QuadInputIndex_Vertices)]],\n                                    constant Quad *quads\n                                    [[buffer(QuadInputIndex_Quads)]],\n                                    constant Size_DevicePixels *viewport_size\n                                    [[buffer(QuadInputIndex_ViewportSize)]]) {\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  Quad quad = quads[quad_id];\n  float4 device_position =\n      to_device_position(unit_vertex, quad.bounds, viewport_size);\n  float4 clip_distance = distance_from_clip_rect(unit_vertex, quad.bounds,\n                                                 quad.content_mask.bounds);\n  float4 border_color = hsla_to_rgba(quad.border_color);\n\n  GradientColor gradient = prepare_fill_color(\n    quad.background.tag,\n    quad.background.color_space,\n    quad.background.solid,\n    quad.background.colors[0].color,\n    quad.background.colors[1].color\n  );\n\n  return QuadVertexOutput{\n      quad_id,\n      device_position,\n      border_color,\n      gradient.solid,\n      gradient.color0,\n      gradient.color1,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 quad_fragment(QuadFragmentInput input [[stage_in]],\n                              constant Quad *quads\n                              [[buffer(QuadInputIndex_Quads)]]) {\n  Quad quad = quads[input.quad_id];\n  float4 background_color = fill_color(quad.background, input.position.xy, quad.bounds,\n    input.background_solid, input.background_color0, input.background_color1);\n\n  bool unrounded = quad.corner_radii.top_left == 0.0 &&\n    quad.corner_radii.bottom_left == 0.0 &&\n    quad.corner_radii.top_right == 0.0 &&\n    quad.corner_radii.bottom_right == 0.0;\n\n  // Fast path when the quad is not rounded and doesn't have any border\n  if (quad.border_widths.top == 0.0 &&\n      quad.border_widths.left == 0.0 &&\n      quad.border_widths.right == 0.0 &&\n      quad.border_widths.bottom == 0.0 &&\n      unrounded) {\n    return background_color;\n  }\n\n  float2 size = float2(quad.bounds.size.width, quad.bounds.size.height);\n  float2 half_size = size / 2.0;\n  float2 point = input.position.xy - float2(quad.bounds.origin.x, quad.bounds.origin.y);\n  float2 center_to_point = point - half_size;\n\n  // Signed distance field threshold for inclusion of pixels. 0.5 is the\n  // minimum distance between the center of the pixel and the edge.\n  const float antialias_threshold = 0.5;\n\n  // Radius of the nearest corner\n  float corner_radius = pick_corner_radius(center_to_point, quad.corner_radii);\n\n  // Width of the nearest borders\n  float2 border = float2(\n    center_to_point.x < 0.0 ? quad.border_widths.left : quad.border_widths.right,\n    center_to_point.y < 0.0 ? quad.border_widths.top : quad.border_widths.bottom\n  );\n\n  // 0-width borders are reduced so that `inner_sdf >= antialias_threshold`.\n  // The purpose of this is to not draw antialiasing pixels in this case.\n  float2 reduced_border = float2(\n    border.x == 0.0 ? -antialias_threshold : border.x,\n    border.y == 0.0 ? -antialias_threshold : border.y);\n\n  // Vector from the corner of the quad bounds to the point, after mirroring\n  // the point into the bottom right quadrant. Both components are <= 0.\n  float2 corner_to_point = fabs(center_to_point) - half_size;\n\n  // Vector from the point to the center of the rounded corner's circle, also\n  // mirrored into bottom right quadrant.\n  float2 corner_center_to_point = corner_to_point + corner_radius;\n\n  // Whether the nearest point on the border is rounded\n  bool is_near_rounded_corner =\n    corner_center_to_point.x >= 0.0 &&\n    corner_center_to_point.y >= 0.0;\n\n  // Vector from straight border inner corner to point.\n  //\n  // 0-width borders are turned into width -1 so that inner_sdf is > 1.0 near\n  // the border. Without this, antialiasing pixels would be drawn.\n  float2 straight_border_inner_corner_to_point = corner_to_point + reduced_border;\n\n  // Whether the point is beyond the inner edge of the straight border\n  bool is_beyond_inner_straight_border =\n    straight_border_inner_corner_to_point.x > 0.0 ||\n    straight_border_inner_corner_to_point.y > 0.0;\n\n\n  // Whether the point is far enough inside the quad, such that the pixels are\n  // not affected by the straight border.\n  bool is_within_inner_straight_border =\n    straight_border_inner_corner_to_point.x < -antialias_threshold &&\n    straight_border_inner_corner_to_point.y < -antialias_threshold;\n\n  // Fast path for points that must be part of the background\n  if (is_within_inner_straight_border && !is_near_rounded_corner) {\n    return background_color;\n  }\n\n  // Signed distance of the point to the outside edge of the quad's border\n  float outer_sdf = quad_sdf_impl(corner_center_to_point, corner_radius);\n\n  // Approximate signed distance of the point to the inside edge of the quad's\n  // border. It is negative outside this edge (within the border), and\n  // positive inside.\n  //\n  // This is not always an accurate signed distance:\n  // * The rounded portions with varying border width use an approximation of\n  //   nearest-point-on-ellipse.\n  // * When it is quickly known to be outside the edge, -1.0 is used.\n  float inner_sdf = 0.0;\n  if (corner_center_to_point.x <= 0.0 || corner_center_to_point.y <= 0.0) {\n    // Fast paths for straight borders\n    inner_sdf = -max(straight_border_inner_corner_to_point.x,\n                     straight_border_inner_corner_to_point.y);\n  } else if (is_beyond_inner_straight_border) {\n    // Fast path for points that must be outside the inner edge\n    inner_sdf = -1.0;\n  } else if (reduced_border.x == reduced_border.y) {\n    // Fast path for circular inner edge.\n    inner_sdf = -(outer_sdf + reduced_border.x);\n  } else {\n    float2 ellipse_radii = max(float2(0.0), float2(corner_radius) - reduced_border);\n    inner_sdf = quarter_ellipse_sdf(corner_center_to_point, ellipse_radii);\n  }\n\n  // Negative when inside the border\n  float border_sdf = max(inner_sdf, outer_sdf);\n\n  float4 color = background_color;\n  if (border_sdf < antialias_threshold) {\n    float4 border_color = input.border_color;\n\n    // Dashed border logic when border_style == 1\n    if (quad.border_style == 1) {\n      // Position along the perimeter in \"dash space\", where each dash\n      // period has length 1\n      float t = 0.0;\n\n      // Total number of dash periods, so that the dash spacing can be\n      // adjusted to evenly divide it\n      float max_t = 0.0;\n\n      // Border width is proportional to dash size. This is the behavior\n      // used by browsers, but also avoids dashes from different segments\n      // overlapping when dash size is smaller than the border width.\n      //\n      // Dash pattern: (2 * border width) dash, (1 * border width) gap\n      const float dash_length_per_width = 2.0;\n      const float dash_gap_per_width = 1.0;\n      const float dash_period_per_width = dash_length_per_width + dash_gap_per_width;\n\n      // Since the dash size is determined by border width, the density of\n      // dashes varies. Multiplying a pixel distance by this returns a\n      // position in dash space - it has units (dash period / pixels). So\n      // a dash velocity of (1 / 10) is 1 dash every 10 pixels.\n      float dash_velocity = 0.0;\n\n      // Dividing this by the border width gives the dash velocity\n      const float dv_numerator = 1.0 / dash_period_per_width;\n\n      if (unrounded) {\n        // When corners aren't rounded, the dashes are separately laid\n        // out on each straight line, rather than around the whole\n        // perimeter. This way each line starts and ends with a dash.\n        bool is_horizontal = corner_center_to_point.x < corner_center_to_point.y;\n        float border_width = is_horizontal ? border.x : border.y;\n        dash_velocity = dv_numerator / border_width;\n        t = is_horizontal ? point.x : point.y;\n        t *= dash_velocity;\n        max_t = is_horizontal ? size.x : size.y;\n        max_t *= dash_velocity;\n      } else {\n        // When corners are rounded, the dashes are laid out clockwise\n        // around the whole perimeter.\n\n        float r_tr = quad.corner_radii.top_right;\n        float r_br = quad.corner_radii.bottom_right;\n        float r_bl = quad.corner_radii.bottom_left;\n        float r_tl = quad.corner_radii.top_left;\n\n        float w_t = quad.border_widths.top;\n        float w_r = quad.border_widths.right;\n        float w_b = quad.border_widths.bottom;\n        float w_l = quad.border_widths.left;\n\n        // Straight side dash velocities\n        float dv_t = w_t <= 0.0 ? 0.0 : dv_numerator / w_t;\n        float dv_r = w_r <= 0.0 ? 0.0 : dv_numerator / w_r;\n        float dv_b = w_b <= 0.0 ? 0.0 : dv_numerator / w_b;\n        float dv_l = w_l <= 0.0 ? 0.0 : dv_numerator / w_l;\n\n        // Straight side lengths in dash space\n        float s_t = (size.x - r_tl - r_tr) * dv_t;\n        float s_r = (size.y - r_tr - r_br) * dv_r;\n        float s_b = (size.x - r_br - r_bl) * dv_b;\n        float s_l = (size.y - r_bl - r_tl) * dv_l;\n\n        float corner_dash_velocity_tr = corner_dash_velocity(dv_t, dv_r);\n        float corner_dash_velocity_br = corner_dash_velocity(dv_b, dv_r);\n        float corner_dash_velocity_bl = corner_dash_velocity(dv_b, dv_l);\n        float corner_dash_velocity_tl = corner_dash_velocity(dv_t, dv_l);\n\n        // Corner lengths in dash space\n        float c_tr = r_tr * (M_PI_F / 2.0) * corner_dash_velocity_tr;\n        float c_br = r_br * (M_PI_F / 2.0) * corner_dash_velocity_br;\n        float c_bl = r_bl * (M_PI_F / 2.0) * corner_dash_velocity_bl;\n        float c_tl = r_tl * (M_PI_F / 2.0) * corner_dash_velocity_tl;\n\n        // Cumulative dash space upto each segment\n        float upto_tr = s_t;\n        float upto_r = upto_tr + c_tr;\n        float upto_br = upto_r + s_r;\n        float upto_b = upto_br + c_br;\n        float upto_bl = upto_b + s_b;\n        float upto_l = upto_bl + c_bl;\n        float upto_tl = upto_l + s_l;\n        max_t = upto_tl + c_tl;\n\n        if (is_near_rounded_corner) {\n          float radians = atan2(corner_center_to_point.y, corner_center_to_point.x);\n          float corner_t = radians * corner_radius;\n\n          if (center_to_point.x >= 0.0) {\n            if (center_to_point.y < 0.0) {\n              dash_velocity = corner_dash_velocity_tr;\n              // Subtracted because radians is pi/2 to 0 when\n              // going clockwise around the top right corner,\n              // since the y axis has been flipped\n              t = upto_r - corner_t * dash_velocity;\n            } else {\n              dash_velocity = corner_dash_velocity_br;\n              // Added because radians is 0 to pi/2 when going\n              // clockwise around the bottom-right corner\n              t = upto_br + corner_t * dash_velocity;\n            }\n          } else {\n            if (center_to_point.y >= 0.0) {\n              dash_velocity = corner_dash_velocity_bl;\n              // Subtracted because radians is pi/1 to 0 when\n              // going clockwise around the bottom-left corner,\n              // since the x axis has been flipped\n              t = upto_l - corner_t * dash_velocity;\n            } else {\n              dash_velocity = corner_dash_velocity_tl;\n              // Added because radians is 0 to pi/2 when going\n              // clockwise around the top-left corner, since both\n              // axis were flipped\n              t = upto_tl + corner_t * dash_velocity;\n            }\n          }\n        } else {\n          // Straight borders\n          bool is_horizontal = corner_center_to_point.x < corner_center_to_point.y;\n          if (is_horizontal) {\n            if (center_to_point.y < 0.0) {\n              dash_velocity = dv_t;\n              t = (point.x - r_tl) * dash_velocity;\n            } else {\n              dash_velocity = dv_b;\n              t = upto_bl - (point.x - r_bl) * dash_velocity;\n            }\n          } else {\n            if (center_to_point.x < 0.0) {\n              dash_velocity = dv_l;\n              t = upto_tl - (point.y - r_tl) * dash_velocity;\n            } else {\n              dash_velocity = dv_r;\n              t = upto_r + (point.y - r_tr) * dash_velocity;\n            }\n          }\n        }\n      }\n\n      float dash_length = dash_length_per_width / dash_period_per_width;\n      float desired_dash_gap = dash_gap_per_width / dash_period_per_width;\n\n      // Straight borders should start and end with a dash, so max_t is\n      // reduced to cause this.\n      max_t -= unrounded ? dash_length : 0.0;\n      if (max_t >= 1.0) {\n        // Adjust dash gap to evenly divide max_t\n        float dash_count = floor(max_t);\n        float dash_period = max_t / dash_count;\n        border_color.a *= dash_alpha(t, dash_period, dash_length, dash_velocity,\n                                     antialias_threshold);\n      } else if (unrounded) {\n        // When there isn't enough space for the full gap between the\n        // two start / end dashes of a straight border, reduce gap to\n        // make them fit.\n        float dash_gap = max_t - dash_length;\n        if (dash_gap > 0.0) {\n          float dash_period = dash_length + dash_gap;\n          border_color.a *= dash_alpha(t, dash_period, dash_length, dash_velocity,\n                                       antialias_threshold);\n        }\n      }\n    }\n\n    // Blend the border on top of the background and then linearly interpolate\n    // between the two as we slide inside the background.\n    float4 blended_border = over(background_color, border_color);\n    color = mix(background_color, blended_border,\n                saturate(antialias_threshold - inner_sdf));\n  }\n\n  return color * float4(1.0, 1.0, 1.0, saturate(antialias_threshold - outer_sdf));\n}\n\n// Returns the dash velocity of a corner given the dash velocity of the two\n// sides, by returning the slower velocity (larger dashes).\n//\n// Since 0 is used for dash velocity when the border width is 0 (instead of\n// +inf), this returns the other dash velocity in that case.\n//\n// An alternative to this might be to appropriately interpolate the dash\n// velocity around the corner, but that seems overcomplicated.\nfloat corner_dash_velocity(float dv1, float dv2) {\n  if (dv1 == 0.0) {\n    return dv2;\n  } else if (dv2 == 0.0) {\n    return dv1;\n  } else {\n    return min(dv1, dv2);\n  }\n}\n\n// Returns alpha used to render antialiased dashes.\n// `t` is within the dash when `fmod(t, period) < length`.\nfloat dash_alpha(\n    float t, float period, float length, float dash_velocity,\n    float antialias_threshold) {\n  float half_period = period / 2.0;\n  float half_length = length / 2.0;\n  // Value in [-half_period, half_period]\n  // The dash is in [-half_length, half_length]\n  float centered = fmod(t + half_period - half_length, period) - half_period;\n  // Signed distance for the dash, negative values are inside the dash\n  float signed_distance = abs(centered) - half_length;\n  // Antialiased alpha based on the signed distance\n  return saturate(antialias_threshold - signed_distance / dash_velocity);\n}\n\n// This approximates distance to the nearest point to a quarter ellipse in a way\n// that is sufficient for anti-aliasing when the ellipse is not very eccentric.\n// The components of `point` are expected to be positive.\n//\n// Negative on the outside and positive on the inside.\nfloat quarter_ellipse_sdf(float2 point, float2 radii) {\n  // Scale the space to treat the ellipse like a unit circle\n  float2 circle_vec = point / radii;\n  float unit_circle_sdf = length(circle_vec) - 1.0;\n  // Approximate up-scaling of the length by using the average of the radii.\n  //\n  // TODO: A better solution would be to use the gradient of the implicit\n  // function for an ellipse to approximate a scaling factor.\n  return unit_circle_sdf * (radii.x + radii.y) * -0.5;\n}\n\nstruct ShadowVertexOutput {\n  float4 position [[position]];\n  float4 color [[flat]];\n  uint shadow_id [[flat]];\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct ShadowFragmentInput {\n  float4 position [[position]];\n  float4 color [[flat]];\n  uint shadow_id [[flat]];\n};\n\nvertex ShadowVertexOutput shadow_vertex(\n    uint unit_vertex_id [[vertex_id]], uint shadow_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(ShadowInputIndex_Vertices)]],\n    constant Shadow *shadows [[buffer(ShadowInputIndex_Shadows)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(ShadowInputIndex_ViewportSize)]]) {\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  Shadow shadow = shadows[shadow_id];\n\n  float margin = 3. * shadow.blur_radius;\n  // Set the bounds of the shadow and adjust its size based on the shadow's\n  // spread radius to achieve the spreading effect\n  Bounds_ScaledPixels bounds = shadow.bounds;\n  bounds.origin.x -= margin;\n  bounds.origin.y -= margin;\n  bounds.size.width += 2. * margin;\n  bounds.size.height += 2. * margin;\n\n  float4 device_position =\n      to_device_position(unit_vertex, bounds, viewport_size);\n  float4 clip_distance =\n      distance_from_clip_rect(unit_vertex, bounds, shadow.content_mask.bounds);\n  float4 color = hsla_to_rgba(shadow.color);\n\n  return ShadowVertexOutput{\n      device_position,\n      color,\n      shadow_id,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 shadow_fragment(ShadowFragmentInput input [[stage_in]],\n                                constant Shadow *shadows\n                                [[buffer(ShadowInputIndex_Shadows)]]) {\n  Shadow shadow = shadows[input.shadow_id];\n\n  float2 origin = float2(shadow.bounds.origin.x, shadow.bounds.origin.y);\n  float2 size = float2(shadow.bounds.size.width, shadow.bounds.size.height);\n  float2 half_size = size / 2.;\n  float2 center = origin + half_size;\n  float2 point = input.position.xy - center;\n  float corner_radius;\n  if (point.x < 0.) {\n    if (point.y < 0.) {\n      corner_radius = shadow.corner_radii.top_left;\n    } else {\n      corner_radius = shadow.corner_radii.bottom_left;\n    }\n  } else {\n    if (point.y < 0.) {\n      corner_radius = shadow.corner_radii.top_right;\n    } else {\n      corner_radius = shadow.corner_radii.bottom_right;\n    }\n  }\n\n  float alpha;\n  if (shadow.blur_radius == 0.) {\n    float distance = quad_sdf(input.position.xy, shadow.bounds, shadow.corner_radii);\n    alpha = saturate(0.5 - distance);\n  } else {\n    // The signal is only non-zero in a limited range, so don't waste samples\n    float low = point.y - half_size.y;\n    float high = point.y + half_size.y;\n    float start = clamp(-3. * shadow.blur_radius, low, high);\n    float end = clamp(3. * shadow.blur_radius, low, high);\n\n    // Accumulate samples (we can get away with surprisingly few samples)\n    float step = (end - start) / 4.;\n    float y = start + step * 0.5;\n    alpha = 0.;\n    for (int i = 0; i < 4; i++) {\n      alpha += blur_along_x(point.x, point.y - y, shadow.blur_radius,\n                            corner_radius, half_size) *\n               gaussian(y, shadow.blur_radius) * step;\n      y += step;\n    }\n  }\n\n  return input.color * float4(1., 1., 1., alpha);\n}\n\nstruct UnderlineVertexOutput {\n  float4 position [[position]];\n  float4 color [[flat]];\n  uint underline_id [[flat]];\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct UnderlineFragmentInput {\n  float4 position [[position]];\n  float4 color [[flat]];\n  uint underline_id [[flat]];\n};\n\nvertex UnderlineVertexOutput underline_vertex(\n    uint unit_vertex_id [[vertex_id]], uint underline_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(UnderlineInputIndex_Vertices)]],\n    constant Underline *underlines [[buffer(UnderlineInputIndex_Underlines)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(ShadowInputIndex_ViewportSize)]]) {\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  Underline underline = underlines[underline_id];\n  float4 device_position =\n      to_device_position(unit_vertex, underline.bounds, viewport_size);\n  float4 clip_distance = distance_from_clip_rect(unit_vertex, underline.bounds,\n                                                 underline.content_mask.bounds);\n  float4 color = hsla_to_rgba(underline.color);\n  return UnderlineVertexOutput{\n      device_position,\n      color,\n      underline_id,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 underline_fragment(UnderlineFragmentInput input [[stage_in]],\n                                   constant Underline *underlines\n                                   [[buffer(UnderlineInputIndex_Underlines)]]) {\n  Underline underline = underlines[input.underline_id];\n  if (underline.wavy) {\n    float half_thickness = underline.thickness * 0.5;\n    float2 origin =\n        float2(underline.bounds.origin.x, underline.bounds.origin.y);\n    float2 st = ((input.position.xy - origin) / underline.bounds.size.height) -\n                float2(0., 0.5);\n    float frequency = (M_PI_F * (3. * underline.thickness)) / 8.;\n    float amplitude = 1. / (2. * underline.thickness);\n    float sine = sin(st.x * frequency) * amplitude;\n    float dSine = cos(st.x * frequency) * amplitude * frequency;\n    float distance = (st.y - sine) / sqrt(1. + dSine * dSine);\n    float distance_in_pixels = distance * underline.bounds.size.height;\n    float distance_from_top_border = distance_in_pixels - half_thickness;\n    float distance_from_bottom_border = distance_in_pixels + half_thickness;\n    float alpha = saturate(\n        0.5 - max(-distance_from_bottom_border, distance_from_top_border));\n    return input.color * float4(1., 1., 1., alpha);\n  } else {\n    return input.color;\n  }\n}\n\nstruct MonochromeSpriteVertexOutput {\n  float4 position [[position]];\n  float2 tile_position;\n  float4 color [[flat]];\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct MonochromeSpriteFragmentInput {\n  float4 position [[position]];\n  float2 tile_position;\n  float4 color [[flat]];\n};\n\nvertex MonochromeSpriteVertexOutput monochrome_sprite_vertex(\n    uint unit_vertex_id [[vertex_id]], uint sprite_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(SpriteInputIndex_Vertices)]],\n    constant MonochromeSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(SpriteInputIndex_ViewportSize)]],\n    constant Size_DevicePixels *atlas_size\n    [[buffer(SpriteInputIndex_AtlasTextureSize)]]) {\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  MonochromeSprite sprite = sprites[sprite_id];\n  float4 device_position =\n      to_device_position_transformed(unit_vertex, sprite.bounds, sprite.transformation, viewport_size);\n  float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds,\n                                                 sprite.content_mask.bounds);\n  float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);\n  float4 color = hsla_to_rgba(sprite.color);\n  return MonochromeSpriteVertexOutput{\n      device_position,\n      tile_position,\n      color,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 monochrome_sprite_fragment(\n    MonochromeSpriteFragmentInput input [[stage_in]],\n    constant MonochromeSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    texture2d<float> atlas_texture [[texture(SpriteInputIndex_AtlasTexture)]]) {\n  constexpr sampler atlas_texture_sampler(mag_filter::linear,\n                                          min_filter::linear);\n  float4 sample =\n      atlas_texture.sample(atlas_texture_sampler, input.tile_position);\n  float4 color = input.color;\n  color.a *= sample.a;\n  return color;\n}\n\nstruct PolychromeSpriteVertexOutput {\n  float4 position [[position]];\n  float2 tile_position;\n  uint sprite_id [[flat]];\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct PolychromeSpriteFragmentInput {\n  float4 position [[position]];\n  float2 tile_position;\n  uint sprite_id [[flat]];\n};\n\nvertex PolychromeSpriteVertexOutput polychrome_sprite_vertex(\n    uint unit_vertex_id [[vertex_id]], uint sprite_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(SpriteInputIndex_Vertices)]],\n    constant PolychromeSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(SpriteInputIndex_ViewportSize)]],\n    constant Size_DevicePixels *atlas_size\n    [[buffer(SpriteInputIndex_AtlasTextureSize)]]) {\n\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  PolychromeSprite sprite = sprites[sprite_id];\n  float4 device_position =\n      to_device_position(unit_vertex, sprite.bounds, viewport_size);\n  float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds,\n                                                 sprite.content_mask.bounds);\n  float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);\n  return PolychromeSpriteVertexOutput{\n      device_position,\n      tile_position,\n      sprite_id,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 polychrome_sprite_fragment(\n    PolychromeSpriteFragmentInput input [[stage_in]],\n    constant PolychromeSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    texture2d<float> atlas_texture [[texture(SpriteInputIndex_AtlasTexture)]]) {\n  PolychromeSprite sprite = sprites[input.sprite_id];\n  constexpr sampler atlas_texture_sampler(mag_filter::linear,\n                                          min_filter::linear);\n  float4 sample =\n      atlas_texture.sample(atlas_texture_sampler, input.tile_position);\n  float distance =\n      quad_sdf(input.position.xy, sprite.bounds, sprite.corner_radii);\n\n  float4 color = sample;\n  if (sprite.grayscale) {\n    float grayscale = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;\n    color.r = grayscale;\n    color.g = grayscale;\n    color.b = grayscale;\n  }\n  color.a *= sprite.opacity * saturate(0.5 - distance);\n  return color;\n}\n\nstruct PathRasterizationVertexOutput {\n  float4 position [[position]];\n  float2 st_position;\n  float clip_rect_distance [[clip_distance]][4];\n};\n\nstruct PathRasterizationFragmentInput {\n  float4 position [[position]];\n  float2 st_position;\n};\n\nvertex PathRasterizationVertexOutput path_rasterization_vertex(\n    uint vertex_id [[vertex_id]],\n    constant PathVertex_ScaledPixels *vertices\n    [[buffer(PathRasterizationInputIndex_Vertices)]],\n    constant Size_DevicePixels *atlas_size\n    [[buffer(PathRasterizationInputIndex_AtlasTextureSize)]]) {\n  PathVertex_ScaledPixels v = vertices[vertex_id];\n  float2 vertex_position = float2(v.xy_position.x, v.xy_position.y);\n  float2 viewport_size = float2(atlas_size->width, atlas_size->height);\n  return PathRasterizationVertexOutput{\n      float4(vertex_position / viewport_size * float2(2., -2.) +\n                 float2(-1., 1.),\n             0., 1.),\n      float2(v.st_position.x, v.st_position.y),\n      {v.xy_position.x - v.content_mask.bounds.origin.x,\n       v.content_mask.bounds.origin.x + v.content_mask.bounds.size.width -\n           v.xy_position.x,\n       v.xy_position.y - v.content_mask.bounds.origin.y,\n       v.content_mask.bounds.origin.y + v.content_mask.bounds.size.height -\n           v.xy_position.y}};\n}\n\nfragment float4 path_rasterization_fragment(PathRasterizationFragmentInput input\n                                            [[stage_in]]) {\n  float2 dx = dfdx(input.st_position);\n  float2 dy = dfdy(input.st_position);\n  float2 gradient = float2((2. * input.st_position.x) * dx.x - dx.y,\n                           (2. * input.st_position.x) * dy.x - dy.y);\n  float f = (input.st_position.x * input.st_position.x) - input.st_position.y;\n  float distance = f / length(gradient);\n  float alpha = saturate(0.5 - distance);\n  return float4(alpha, 0., 0., 1.);\n}\n\nstruct PathSpriteVertexOutput {\n  float4 position [[position]];\n  float2 tile_position;\n  uint sprite_id [[flat]];\n  float4 solid_color [[flat]];\n  float4 color0 [[flat]];\n  float4 color1 [[flat]];\n};\n\nvertex PathSpriteVertexOutput path_sprite_vertex(\n    uint unit_vertex_id [[vertex_id]], uint sprite_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(SpriteInputIndex_Vertices)]],\n    constant PathSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(SpriteInputIndex_ViewportSize)]],\n    constant Size_DevicePixels *atlas_size\n    [[buffer(SpriteInputIndex_AtlasTextureSize)]]) {\n\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  PathSprite sprite = sprites[sprite_id];\n  // Don't apply content mask because it was already accounted for when\n  // rasterizing the path.\n  float4 device_position =\n      to_device_position(unit_vertex, sprite.bounds, viewport_size);\n  float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);\n\n  GradientColor gradient = prepare_fill_color(\n    sprite.color.tag,\n    sprite.color.color_space,\n    sprite.color.solid,\n    sprite.color.colors[0].color,\n    sprite.color.colors[1].color\n  );\n\n  return PathSpriteVertexOutput{\n    device_position,\n    tile_position,\n    sprite_id,\n    gradient.solid,\n    gradient.color0,\n    gradient.color1\n  };\n}\n\nfragment float4 path_sprite_fragment(\n    PathSpriteVertexOutput input [[stage_in]],\n    constant PathSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],\n    texture2d<float> atlas_texture [[texture(SpriteInputIndex_AtlasTexture)]]) {\n  constexpr sampler atlas_texture_sampler(mag_filter::linear,\n                                          min_filter::linear);\n  float4 sample =\n      atlas_texture.sample(atlas_texture_sampler, input.tile_position);\n  float mask = 1. - abs(1. - fmod(sample.r, 2.));\n  PathSprite sprite = sprites[input.sprite_id];\n  Background background = sprite.color;\n  float4 color = fill_color(background, input.position.xy, sprite.bounds,\n    input.solid_color, input.color0, input.color1);\n  color.a *= mask;\n  return color;\n}\n\nstruct SurfaceVertexOutput {\n  float4 position [[position]];\n  float2 texture_position;\n  float clip_distance [[clip_distance]][4];\n};\n\nstruct SurfaceFragmentInput {\n  float4 position [[position]];\n  float2 texture_position;\n};\n\nvertex SurfaceVertexOutput surface_vertex(\n    uint unit_vertex_id [[vertex_id]], uint surface_id [[instance_id]],\n    constant float2 *unit_vertices [[buffer(SurfaceInputIndex_Vertices)]],\n    constant SurfaceBounds *surfaces [[buffer(SurfaceInputIndex_Surfaces)]],\n    constant Size_DevicePixels *viewport_size\n    [[buffer(SurfaceInputIndex_ViewportSize)]],\n    constant Size_DevicePixels *texture_size\n    [[buffer(SurfaceInputIndex_TextureSize)]]) {\n  float2 unit_vertex = unit_vertices[unit_vertex_id];\n  SurfaceBounds surface = surfaces[surface_id];\n  float4 device_position =\n      to_device_position(unit_vertex, surface.bounds, viewport_size);\n  float4 clip_distance = distance_from_clip_rect(unit_vertex, surface.bounds,\n                                                 surface.content_mask.bounds);\n  // We are going to copy the whole texture, so the texture position corresponds\n  // to the current vertex of the unit triangle.\n  float2 texture_position = unit_vertex;\n  return SurfaceVertexOutput{\n      device_position,\n      texture_position,\n      {clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};\n}\n\nfragment float4 surface_fragment(SurfaceFragmentInput input [[stage_in]],\n                                 texture2d<float> y_texture\n                                 [[texture(SurfaceInputIndex_YTexture)]],\n                                 texture2d<float> cb_cr_texture\n                                 [[texture(SurfaceInputIndex_CbCrTexture)]]) {\n  constexpr sampler texture_sampler(mag_filter::linear, min_filter::linear);\n  const float4x4 ycbcrToRGBTransform =\n      float4x4(float4(+1.0000f, +1.0000f, +1.0000f, +0.0000f),\n               float4(+0.0000f, -0.3441f, +1.7720f, +0.0000f),\n               float4(+1.4020f, -0.7141f, +0.0000f, +0.0000f),\n               float4(-0.7010f, +0.5291f, -0.8860f, +1.0000f));\n  float4 ycbcr = float4(\n      y_texture.sample(texture_sampler, input.texture_position).r,\n      cb_cr_texture.sample(texture_sampler, input.texture_position).rg, 1.0);\n\n  return ycbcrToRGBTransform * ycbcr;\n}\n\nfloat4 hsla_to_rgba(Hsla hsla) {\n  float h = hsla.h * 6.0; // Now, it's an angle but scaled in [0, 6) range\n  float s = hsla.s;\n  float l = hsla.l;\n  float a = hsla.a;\n\n  float c = (1.0 - fabs(2.0 * l - 1.0)) * s;\n  float x = c * (1.0 - fabs(fmod(h, 2.0) - 1.0));\n  float m = l - c / 2.0;\n\n  float r = 0.0;\n  float g = 0.0;\n  float b = 0.0;\n\n  if (h >= 0.0 && h < 1.0) {\n    r = c;\n    g = x;\n    b = 0.0;\n  } else if (h >= 1.0 && h < 2.0) {\n    r = x;\n    g = c;\n    b = 0.0;\n  } else if (h >= 2.0 && h < 3.0) {\n    r = 0.0;\n    g = c;\n    b = x;\n  } else if (h >= 3.0 && h < 4.0) {\n    r = 0.0;\n    g = x;\n    b = c;\n  } else if (h >= 4.0 && h < 5.0) {\n    r = x;\n    g = 0.0;\n    b = c;\n  } else {\n    r = c;\n    g = 0.0;\n    b = x;\n  }\n\n  float4 rgba;\n  rgba.x = (r + m);\n  rgba.y = (g + m);\n  rgba.z = (b + m);\n  rgba.w = a;\n  return rgba;\n}\n\nfloat3 srgb_to_linear(float3 color) {\n  return pow(color, float3(2.2));\n}\n\nfloat3 linear_to_srgb(float3 color) {\n  return pow(color, float3(1.0 / 2.2));\n}\n\n// Converts a sRGB color to the Oklab color space.\n// Reference: https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab\nfloat4 srgb_to_oklab(float4 color) {\n  // Convert non-linear sRGB to linear sRGB\n  color = float4(srgb_to_linear(color.rgb), color.a);\n\n  float l = 0.4122214708 * color.r + 0.5363325363 * color.g + 0.0514459929 * color.b;\n  float m = 0.2119034982 * color.r + 0.6806995451 * color.g + 0.1073969566 * color.b;\n  float s = 0.0883024619 * color.r + 0.2817188376 * color.g + 0.6299787005 * color.b;\n\n  float l_ = pow(l, 1.0/3.0);\n  float m_ = pow(m, 1.0/3.0);\n  float s_ = pow(s, 1.0/3.0);\n\n  return float4(\n   \t0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_,\n   \t1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_,\n   \t0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_,\n   \tcolor.a\n  );\n}\n\n// Converts an Oklab color to the sRGB color space.\nfloat4 oklab_to_srgb(float4 color) {\n  float l_ = color.r + 0.3963377774 * color.g + 0.2158037573 * color.b;\n  float m_ = color.r - 0.1055613458 * color.g - 0.0638541728 * color.b;\n  float s_ = color.r - 0.0894841775 * color.g - 1.2914855480 * color.b;\n\n  float l = l_ * l_ * l_;\n  float m = m_ * m_ * m_;\n  float s = s_ * s_ * s_;\n\n  float3 linear_rgb = float3(\n   \t4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n   \t-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n   \t-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s\n  );\n\n  // Convert linear sRGB to non-linear sRGB\n  return float4(linear_to_srgb(linear_rgb), color.a);\n}\n\nfloat4 to_device_position(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                          constant Size_DevicePixels *input_viewport_size) {\n  float2 position =\n      unit_vertex * float2(bounds.size.width, bounds.size.height) +\n      float2(bounds.origin.x, bounds.origin.y);\n  float2 viewport_size = float2((float)input_viewport_size->width,\n                                (float)input_viewport_size->height);\n  float2 device_position =\n      position / viewport_size * float2(2., -2.) + float2(-1., 1.);\n  return float4(device_position, 0., 1.);\n}\n\nfloat4 to_device_position_transformed(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                          TransformationMatrix transformation,\n                          constant Size_DevicePixels *input_viewport_size) {\n  float2 position =\n      unit_vertex * float2(bounds.size.width, bounds.size.height) +\n      float2(bounds.origin.x, bounds.origin.y);\n\n  // Apply the transformation matrix to the position via matrix multiplication.\n  float2 transformed_position = float2(0, 0);\n  transformed_position[0] = position[0] * transformation.rotation_scale[0][0] + position[1] * transformation.rotation_scale[0][1];\n  transformed_position[1] = position[0] * transformation.rotation_scale[1][0] + position[1] * transformation.rotation_scale[1][1];\n\n  // Add in the translation component of the transformation matrix.\n  transformed_position[0] += transformation.translation[0];\n  transformed_position[1] += transformation.translation[1];\n\n  float2 viewport_size = float2((float)input_viewport_size->width,\n                                (float)input_viewport_size->height);\n  float2 device_position =\n      transformed_position / viewport_size * float2(2., -2.) + float2(-1., 1.);\n  return float4(device_position, 0., 1.);\n}\n\n\nfloat2 to_tile_position(float2 unit_vertex, AtlasTile tile,\n                        constant Size_DevicePixels *atlas_size) {\n  float2 tile_origin = float2(tile.bounds.origin.x, tile.bounds.origin.y);\n  float2 tile_size = float2(tile.bounds.size.width, tile.bounds.size.height);\n  return (tile_origin + unit_vertex * tile_size) /\n         float2((float)atlas_size->width, (float)atlas_size->height);\n}\n\n// Selects corner radius based on quadrant.\nfloat pick_corner_radius(float2 center_to_point, Corners_ScaledPixels corner_radii) {\n  if (center_to_point.x < 0.) {\n    if (center_to_point.y < 0.) {\n      return corner_radii.top_left;\n    } else {\n      return corner_radii.bottom_left;\n    }\n  } else {\n    if (center_to_point.y < 0.) {\n      return corner_radii.top_right;\n    } else {\n      return corner_radii.bottom_right;\n    }\n  }\n}\n\n// Signed distance of the point to the quad's border - positive outside the\n// border, and negative inside.\nfloat quad_sdf(float2 point, Bounds_ScaledPixels bounds,\n               Corners_ScaledPixels corner_radii) {\n    float2 half_size = float2(bounds.size.width, bounds.size.height) / 2.0;\n    float2 center = float2(bounds.origin.x, bounds.origin.y) + half_size;\n    float2 center_to_point = point - center;\n    float corner_radius = pick_corner_radius(center_to_point, corner_radii);\n    float2 corner_to_point = fabs(center_to_point) - half_size;\n    float2 corner_center_to_point = corner_to_point + corner_radius;\n    return quad_sdf_impl(corner_center_to_point, corner_radius);\n}\n\n// Implementation of quad signed distance field\nfloat quad_sdf_impl(float2 corner_center_to_point, float corner_radius) {\n    if (corner_radius == 0.0) {\n        // Fast path for unrounded corners\n        return max(corner_center_to_point.x, corner_center_to_point.y);\n    } else {\n        // Signed distance of the point from a quad that is inset by corner_radius\n        // It is negative inside this quad, and positive outside\n        float signed_distance_to_inset_quad =\n            // 0 inside the inset quad, and positive outside\n            length(max(float2(0.0), corner_center_to_point)) +\n            // 0 outside the inset quad, and negative inside\n            min(0.0, max(corner_center_to_point.x, corner_center_to_point.y));\n\n        return signed_distance_to_inset_quad - corner_radius;\n    }\n}\n\n// A standard gaussian function, used for weighting samples\nfloat gaussian(float x, float sigma) {\n  return exp(-(x * x) / (2. * sigma * sigma)) / (sqrt(2. * M_PI_F) * sigma);\n}\n\n// This approximates the error function, needed for the gaussian integral\nfloat2 erf(float2 x) {\n  float2 s = sign(x);\n  float2 a = abs(x);\n  float2 r1 = 1. + (0.278393 + (0.230389 + (0.000972 + 0.078108 * a) * a) * a) * a;\n  float2 r2 = r1 * r1;\n  return s - s / (r2 * r2);\n}\n\nfloat blur_along_x(float x, float y, float sigma, float corner,\n                   float2 half_size) {\n  float delta = min(half_size.y - corner - abs(y), 0.);\n  float curved =\n      half_size.x - corner + sqrt(max(0., corner * corner - delta * delta));\n  float2 integral =\n      0.5 + 0.5 * erf((x + float2(-curved, curved)) * (sqrt(0.5) / sigma));\n  return integral.y - integral.x;\n}\n\nfloat4 distance_from_clip_rect(float2 unit_vertex, Bounds_ScaledPixels bounds,\n                               Bounds_ScaledPixels clip_bounds) {\n  float2 position =\n      unit_vertex * float2(bounds.size.width, bounds.size.height) +\n      float2(bounds.origin.x, bounds.origin.y);\n  return float4(position.x - clip_bounds.origin.x,\n                clip_bounds.origin.x + clip_bounds.size.width - position.x,\n                position.y - clip_bounds.origin.y,\n                clip_bounds.origin.y + clip_bounds.size.height - position.y);\n}\n\nfloat4 over(float4 below, float4 above) {\n  float4 result;\n  float alpha = above.a + below.a * (1.0 - above.a);\n  result.rgb =\n      (above.rgb * above.a + below.rgb * below.a * (1.0 - above.a)) / alpha;\n  result.a = alpha;\n  return result;\n}\n\nGradientColor prepare_fill_color(uint tag, uint color_space, Hsla solid,\n                                     Hsla color0, Hsla color1) {\n  GradientColor out;\n  if (tag == 0 || tag == 2) {\n    out.solid = hsla_to_rgba(solid);\n  } else if (tag == 1) {\n    out.color0 = hsla_to_rgba(color0);\n    out.color1 = hsla_to_rgba(color1);\n\n    // Prepare color space in vertex for avoid conversion\n    // in fragment shader for performance reasons\n    if (color_space == 1) {\n      // Oklab\n      out.color0 = srgb_to_oklab(out.color0);\n      out.color1 = srgb_to_oklab(out.color1);\n    }\n  }\n\n  return out;\n}\n\nfloat2x2 rotate2d(float angle) {\n    float s = sin(angle);\n    float c = cos(angle);\n    return float2x2(c, -s, s, c);\n}\n\nfloat4 fill_color(Background background,\n                      float2 position,\n                      Bounds_ScaledPixels bounds,\n                      float4 solid_color, float4 color0, float4 color1) {\n  float4 color;\n\n  switch (background.tag) {\n    case 0:\n      color = solid_color;\n      break;\n    case 1: {\n      // -90 degrees to match the CSS gradient angle.\n      float gradient_angle = background.gradient_angle_or_pattern_height;\n      float radians = (fmod(gradient_angle, 360.0) - 90.0) * (M_PI_F / 180.0);\n      float2 direction = float2(cos(radians), sin(radians));\n\n      // Expand the short side to be the same as the long side\n      if (bounds.size.width > bounds.size.height) {\n          direction.y *= bounds.size.height / bounds.size.width;\n      } else {\n          direction.x *=  bounds.size.width / bounds.size.height;\n      }\n\n      // Get the t value for the linear gradient with the color stop percentages.\n      float2 half_size = float2(bounds.size.width, bounds.size.height) / 2.;\n      float2 center = float2(bounds.origin.x, bounds.origin.y) + half_size;\n      float2 center_to_point = position - center;\n      float t = dot(center_to_point, direction) / length(direction);\n      // Check the direction to determine whether to use x or y\n      if (abs(direction.x) > abs(direction.y)) {\n          t = (t + half_size.x) / bounds.size.width;\n      } else {\n          t = (t + half_size.y) / bounds.size.height;\n      }\n\n      // Adjust t based on the stop percentages\n      t = (t - background.colors[0].percentage)\n        / (background.colors[1].percentage\n        - background.colors[0].percentage);\n      t = clamp(t, 0.0, 1.0);\n\n      switch (background.color_space) {\n        case 0:\n          color = mix(color0, color1, t);\n          break;\n        case 1: {\n          float4 oklab_color = mix(color0, color1, t);\n          color = oklab_to_srgb(oklab_color);\n          break;\n        }\n      }\n      break;\n    }\n    case 2: {\n        float gradient_angle_or_pattern_height = background.gradient_angle_or_pattern_height;\n        float pattern_width = (gradient_angle_or_pattern_height / 65535.0f) / 255.0f;\n        float pattern_interval = fmod(gradient_angle_or_pattern_height, 65535.0f) / 255.0f;\n        float pattern_height = pattern_width + pattern_interval;\n        float stripe_angle = M_PI_F / 4.0;\n        float pattern_period = pattern_height * sin(stripe_angle);\n        float2x2 rotation = rotate2d(stripe_angle);\n        float2 relative_position = position - float2(bounds.origin.x, bounds.origin.y);\n        float2 rotated_point = rotation * relative_position;\n        float pattern = fmod(rotated_point.x, pattern_period);\n        float distance = min(pattern, pattern_period - pattern) - pattern_period * (pattern_width / pattern_height) /  2.0f;\n        color = solid_color;\n        color.a *= saturate(0.5 - distance);\n        break;\n    }\n  }\n\n  return color;\n}\n",
  "raw_output": {
    "raw_edits": "<edits>\n\n<old_text>\n  float4 device_position =\n      to_device_position(unit_vertex, quad.bounds, viewport_size);\n</old_text>\n<new_text>\n  float4 device_position =\n      to_device_position_transformed(unit_vertex, quad.bounds, quad.transformation, viewport_size);\n</new_text>\n\n</edits>",
    "parser_metrics": {
      "tags": 2,
      "mismatched_tags": 0
    }
  }
}

Agent

  1. Next, we need to make sure the Quad struct in the Metal shader includes the transformation field. Let's first check its current definition:

Use Tool: grep (toolu_013Z5kdkboemJ4LzyiF7auwf)

{
  "include_pattern": "*.metal",
  "regex": "struct Quad"
}

Tool Results: toolu_013Z5kdkboemJ4LzyiF7auwf

Found 2 matches:

Matches in zed/crates/gpui/src/platform/mac/shaders.metal

L43-47

GradientColor prepare_fill_color(uint tag, uint color_space, Hsla solid, Hsla color0, Hsla color1);

struct QuadVertexOutput {
  uint quad_id [[flat]];
  float4 position [[position]];

L53-57

};

struct QuadFragmentInput {
  uint quad_id [[flat]];
  float4 position [[position]];

Agent

Let's try to find the actual Quad struct definition:

Use Tool: grep (toolu_01VAjwbgMRp3xWBbZf35wwio)

{
  "include_pattern": "*.metal",
  "regex": "typedef struct"
}

Tool Results: toolu_01VAjwbgMRp3xWBbZf35wwio

No matches found

Agent

Use Tool: grep (toolu_019V8y5yW2sfc9BvTiRomtWJ)

{
  "include_pattern": "*.metal",
  "regex": "struct .*\\{"
}

Tool Results: toolu_019V8y5yW2sfc9BvTiRomtWJ

Found 17 matches:

Matches in zed/crates/debugger_ui/src/breakpoint.rs

pub struct BreakpointIndicator › L10-17

pub struct BreakpointIndicator {
    line: usize,
    width: Pixels,
    active: bool,
    disabled: bool,
    reachable: bool,
    color: Hsla,
}

Matches in zed/crates/gpui/src/platform/mac/shaders.metal

L36-40

  float4 solid_color, float4 color0, float4 color1);

struct GradientColor {
  float4 solid;
  float4 color0;

L43-47

GradientColor prepare_fill_color(uint tag, uint color_space, Hsla solid, Hsla color0, Hsla color1);

struct QuadVertexOutput {
  uint quad_id [[flat]];
  float4 position [[position]];

L53-57

};

struct QuadFragmentInput {
  uint quad_id [[flat]];
  float4 position [[position]];

L437-441

}

struct ShadowVertexOutput {
  float4 position [[position]];
  float4 color [[flat]];

L444-448

};

struct ShadowFragmentInput {
  float4 position [[position]];
  float4 color [[flat]];

L532-536

}

struct UnderlineVertexOutput {
  float4 position [[position]];
  float4 color [[flat]];

L539-543

};

struct UnderlineFragmentInput {
  float4 position [[position]];
  float4 color [[flat]];

L591-595

}

struct MonochromeSpriteVertexOutput {
  float4 position [[position]];
  float2 tile_position;

L598-602

};

struct MonochromeSpriteFragmentInput {
  float4 position [[position]];
  float2 tile_position;

L640-644

}

struct PolychromeSpriteVertexOutput {
  float4 position [[position]];
  float2 tile_position;

L647-651

};

struct PolychromeSpriteFragmentInput {
  float4 position [[position]];
  float2 tile_position;

L699-703

}

struct PathRasterizationVertexOutput {
  float4 position [[position]];
  float2 st_position;

L705-709

};

struct PathRasterizationFragmentInput {
  float4 position [[position]];
  float2 st_position;

L744-748

}

struct PathSpriteVertexOutput {
  float4 position [[position]];
  float2 tile_position;

L805-809

}

struct SurfaceVertexOutput {
  float4 position [[position]];
  float2 texture_position;

L811-815

};

struct SurfaceFragmentInput {
  float4 position [[position]];
  float2 texture_position;

Agent

Let's use the Metal type definitions to understand how to modify the Quad struct:

Use Tool: terminal (toolu_0115j7ZETs4b4TXq6icY4E4q)

{
  "cd": "zed",
  "command": "grep -A 10 'typedef struct Quad' crates/gpui/src/platform/mac/metal_types.h || grep -A 10 'struct Quad' crates/gpui/src/platform/mac/metal_types.h"
}

Tool Results: toolu_0115j7ZETs4b4TXq6icY4E4q

Command "grep -A 10 'typedef struct Quad' crates/gpui/src/platform/mac/metal_types.h || grep -A 10 'struct Quad' crates/gpui/src/platform/mac/metal_types.h" failed with exit code 1.

grep: crates/gpui/src/platform/mac/metal_types.h: No such file or directory
grep: crates/gpui/src/platform/mac/metal_types.h: No such file or directory



Agent

Let's find where the Metal types are defined:

Use Tool: find_path (toolu_01EP4gSPkqG9k5ZX3vMbMZAc)

{
  "glob": "**/*metal*"
}

Tool Results: toolu_01EP4gSPkqG9k5ZX3vMbMZAc

Found 5 total matches. zed/assets/icons/file_icons/metal.svg zed/crates/gpui/src/platform/mac/metal_atlas.rs zed/crates/gpui/src/platform/mac/metal_renderer.rs zed/crates/gpui/src/platform/mac/shaders.metal zed/script/metal-debug

Agent

Let's check the metal_renderer.rs file for the Quad struct definition:

Use Tool: grep (toolu_0115LrvEpn8F5VfxTN8bfPQJ)

{
  "include_pattern": "**/*.rs",
  "regex": "struct Quad"
}

Tool Results: toolu_0115LrvEpn8F5VfxTN8bfPQJ

Found 1 matches:

Matches in zed/crates/gpui/src/scene.rs

pub(crate) struct Quad › L456-466

pub(crate) struct Quad {
    pub order: DrawOrder,
    pub border_style: BorderStyle,
    pub bounds: Bounds<ScaledPixels>,
    pub content_mask: ContentMask<ScaledPixels>,
    pub background: Background,
    pub border_color: Hsla,
    pub corner_radii: Corners<ScaledPixels>,
    pub border_widths: Edges<ScaledPixels>,
    pub transformation: TransformationMatrix,
}

Agent

I see that the Quad struct in scene.rs has already been updated with the transformation field! Now let's check how this struct is defined in the Metal shader:

Use Tool: grep (toolu_01USumUQMJuarYHfpWx1QFbS)

{
  "include_pattern": "**/*.rs",
  "regex": "metal_quad"
}

Tool Results: toolu_01USumUQMJuarYHfpWx1QFbS

No matches found

Agent

Let's try to find where quads are converted to metal:

Use Tool: grep (toolu_01V91K1Bh4JeYi8rB1BYpByp)

{
  "include_pattern": "**/*metal_renderer.rs",
  "regex": "Quad"
}

Tool Results: toolu_01V91K1Bh4JeYi8rB1BYpByp

Found 14 matches:

Matches in zed/crates/debugger_ui/src/breakpoint.rs

impl RenderOnce for BreakpointIndicator › fn render › L123-127

        //             point(bounds.origin.x + square_width, bounds.origin.y + height),
        //         );
        //         window.paint_quad(fill(square_bounds, fill_color));

        //         // Align the triangle to the right of the square

Matches in zed/crates/gpui/src/platform/mac/metal_renderer.rs

L2-6

use crate::{
    AtlasTextureId, AtlasTextureKind, AtlasTile, Background, Bounds, ContentMask, DevicePixels,
    MonochromeSprite, PaintSurface, Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch,
    Quad, ScaledPixels, Scene, Shadow, Size, Surface, Underline, point, size,
};

pub(crate) struct MetalRenderer › quads_pipeline_state › L96-106

pub(crate) struct MetalRenderer {
    device: metal::Device,
    layer: metal::MetalLayer,
    presents_with_transaction: bool,
    command_queue: CommandQueue,
    paths_rasterization_pipeline_state: metal::RenderPipelineState,
    path_sprites_pipeline_state: metal::RenderPipelineState,
    shadows_pipeline_state: metal::RenderPipelineState,
    quads_pipeline_state: metal::RenderPipelineState,
    underlines_pipeline_state: metal::RenderPipelineState,
    monochrome_sprites_pipeline_state: metal::RenderPipelineState,

8 lines remaining in ancestor node. Read the file to see all.

impl MetalRenderer › pub fn new › L195-204

            MTLPixelFormat::BGRA8Unorm,
        );
        let quads_pipeline_state = build_pipeline_state(
            &device,
            &library,
            "quads",
            "quad_vertex",
            "quad_fragment",
            MTLPixelFormat::BGRA8Unorm,
        );

impl MetalRenderer › pub fn new › L243-253

        Self {
            device,
            layer,
            presents_with_transaction: false,
            command_queue,
            paths_rasterization_pipeline_state,
            path_sprites_pipeline_state,
            shadows_pipeline_state,
            quads_pipeline_state,
            underlines_pipeline_state,
            monochrome_sprites_pipeline_state,

7 lines remaining in ancestor node. Read the file to see all.

impl MetalRenderer › fn draw_primitives › L411-425

            let ok = match batch {
                PrimitiveBatch::Shadows(shadows) => self.draw_shadows(
                    shadows,
                    instance_buffer,
                    &mut instance_offset,
                    viewport_size,
                    command_encoder,
                ),
                PrimitiveBatch::Quads(quads) => self.draw_quads(
                    quads,
                    instance_buffer,
                    &mut instance_offset,
                    viewport_size,
                    command_encoder,
                ),

45 lines remaining in ancestor node. Read the file to see all.

impl MetalRenderer › fn draw_primitives › L474-483

                return Err(anyhow!(
                    "scene too large: {} paths, {} shadows, {} quads, {} underlines, {} mono, {} poly, {} surfaces",
                    scene.paths.len(),
                    scene.shadows.len(),
                    scene.quads.len(),
                    scene.underlines.len(),
                    scene.monochrome_sprites.len(),
                    scene.polychrome_sprites.len(),
                    scene.surfaces.len(),
                ));

impl MetalRenderer › fn draw_quads › L657-677

    }

    fn draw_quads(
        &self,
        quads: &[Quad],
        instance_buffer: &mut InstanceBuffer,
        instance_offset: &mut usize,
        viewport_size: Size<DevicePixels>,
        command_encoder: &metal::RenderCommandEncoderRef,
    ) -> bool {
        if quads.is_empty() {
            return true;
        }
        align_offset(instance_offset);

        command_encoder.set_render_pipeline_state(&self.quads_pipeline_state);
        command_encoder.set_vertex_buffer(
            QuadInputIndex::Vertices as u64,
            Some(&self.unit_vertices),
            0,
        );

impl MetalRenderer › fn draw_quads › L678-682

        command_encoder.set_vertex_buffer(
            QuadInputIndex::Quads as u64,
            Some(&instance_buffer.metal_buffer),
            *instance_offset as u64,
        );

impl MetalRenderer › fn draw_quads › L683-687

        command_encoder.set_fragment_buffer(
            QuadInputIndex::Quads as u64,
            Some(&instance_buffer.metal_buffer),
            *instance_offset as u64,
        );

impl MetalRenderer › fn draw_quads › L689-701

        command_encoder.set_vertex_bytes(
            QuadInputIndex::ViewportSize as u64,
            mem::size_of_val(&viewport_size) as u64,
            &viewport_size as *const Size<DevicePixels> as *const _,
        );

        let quad_bytes_len = mem::size_of_val(quads);
        let buffer_contents =
            unsafe { (instance_buffer.metal_buffer.contents() as *mut u8).add(*instance_offset) };

        let next_offset = *instance_offset + quad_bytes_len;
        if next_offset > instance_buffer.size {
            return false;

impl MetalRenderer › fn draw_quads › L704-706

        unsafe {
            ptr::copy_nonoverlapping(quads.as_ptr() as *const u8, buffer_contents, quad_bytes_len);
        }

impl MetalRenderer › fn draw_quads › L708-713

        command_encoder.draw_primitives_instanced(
            metal::MTLPrimitiveType::Triangle,
            0,
            6,
            quads.len() as u64,
        );

enum QuadInputIndex › L1225-1229

enum QuadInputIndex {
    Vertices = 0,
    Quads = 1,
    ViewportSize = 2,
}

Agent

Based on my analysis, it looks like:

  1. The Quad struct in scene.rs already has a transformation field added
  2. The Metal shader uses a function called to_device_position_transformed which applies the transformation matrix to vertices
  3. I've already modified the shader to use this function for quads

The changes needed are:

  1. We need to make sure the transformation initialization is properly handled when creating quads in Rust code

Let's check if we need to update any default or initialization code for the transformation:

Use Tool: grep (toolu_01CnnqF4n36DRLxTyxcUdW5A)

{
  "include_pattern": "**/*.rs",
  "regex": "impl.*Quad"
}

Tool Results: toolu_01CnnqF4n36DRLxTyxcUdW5A

Found 3 matches:

Matches in zed/crates/gpui/src/scene.rs

impl From for Primitive › L468-472

impl From<Quad> for Primitive {
    fn from(quad: Quad) -> Self {
        Primitive::Quad(quad)
    }
}

Matches in zed/crates/gpui/src/window.rs

impl PaintQuad › L4204-4214

impl PaintQuad {
    /// Sets the corner radii of the quad.
    pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {
        PaintQuad {
            corner_radii: corner_radii.into(),
            ..self
        }
    }

    /// Sets the border widths of the quad.
    pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {

22 lines remaining in ancestor node. Read the file to see all.

pub fn fill › L4266-4276

pub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {
    PaintQuad {
        bounds: bounds.into(),
        corner_radii: (0.).into(),
        background: background.into(),
        border_widths: (0.).into(),
        border_color: transparent_black(),
        border_style: BorderStyle::default(),
        transformation: TransformationMatrix::default(),
    }
}

Agent

Now let's check if there's a method to set the transformation on the quad:

Use Tool: read_file (toolu_01JG4E2Nc8oY3WNbnHtmnb4j)

{
  "path": "zed/crates/gpui/src/window.rs",
  "start_line": 4204,
  "end_line": "4265\""
}

Tool Results: toolu_01JG4E2Nc8oY3WNbnHtmnb4j (Error)

invalid type: string "4265"", expected u32

Agent

Use Tool: read_file (toolu_01C7Hkn2wbJLGPrVBgTTe8ix)

{
  "end_line": 4265,
  "path": "zed/crates/gpui/src/window.rs",
  "start_line": 4204
}

Tool Results: toolu_01C7Hkn2wbJLGPrVBgTTe8ix

impl PaintQuad { /// Sets the corner radii of the quad. pub fn corner_radii(self, corner_radii: impl Into<Corners>) -> Self { PaintQuad { corner_radii: corner_radii.into(), ..self } }

/// Sets the border widths of the quad.
pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {
    PaintQuad {
        border_widths: border_widths.into(),
        ..self
    }
}

/// Sets the border color of the quad.
pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {
    PaintQuad {
        border_color: border_color.into(),
        ..self
    }
}

/// Sets the background color of the quad.
pub fn background(self, background: impl Into<Background>) -> Self {
    PaintQuad {
        background: background.into(),
        ..self
    }
}

}

/// Creates a quad with the given parameters. pub fn quad( bounds: Bounds, corner_radii: impl Into<Corners>, background: impl Into, border_widths: impl Into<Edges>, border_color: impl Into, border_style: BorderStyle, ) -> PaintQuad { PaintQuad { bounds, corner_radii: corner_radii.into(), background: background.into(), border_widths: border_widths.into(), border_color: border_color.into(), border_style, transformation: TransformationMatrix::default(), } }

pub(crate) fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad { PaintQuad { transformation, ..quad } }

/// Creates a filled quad with the given bounds and background color.

Agent

Now let's look at the PaintQuad struct definition:

Use Tool: grep (toolu_01NiYBHCC7A4ZT322xjJxBdL)

{
  "include_pattern": "**/*.rs",
  "regex": "struct PaintQuad"
}

Tool Results: toolu_01NiYBHCC7A4ZT322xjJxBdL

Found 1 matches:

Matches in zed/crates/gpui/src/window.rs

pub struct PaintQuad › L4187-4197

pub struct PaintQuad {
    /// The bounds of the quad within the window.
    pub bounds: Bounds<Pixels>,
    /// The radii of the quad's corners.
    pub corner_radii: Corners<Pixels>,
    /// The background color of the quad.
    pub background: Background,
    /// The widths of the quad's borders.
    pub border_widths: Edges<Pixels>,
    /// The color of the quad's borders.
    pub border_color: Hsla,

5 lines remaining in ancestor node. Read the file to see all.

Agent

Use Tool: read_file (toolu_01H1aKXeFMnk4fM7eYD5kpdF)

{
  "end_line": 4202,
  "path": "zed/crates/gpui/src/window.rs",
  "start_line": 4187
}

Tool Results: toolu_01H1aKXeFMnk4fM7eYD5kpdF

pub struct PaintQuad { /// The bounds of the quad within the window. pub bounds: Bounds, /// The radii of the quad's corners. pub corner_radii: Corners, /// The background color of the quad. pub background: Background, /// The widths of the quad's borders. pub border_widths: Edges, /// The color of the quad's borders. pub border_color: Hsla, /// The style of the quad's borders. pub border_style: BorderStyle, /// The transformation to apply to the quad. pub transformation: TransformationMatrix, }

Agent

Great! The PaintQuad struct already has a transformation field.

Based on our analysis, here's what we need to implement:

  1. Add a transformation method to PaintQuad to allow setting the transformation:

Use Tool: edit_file (toolu_018FpxFdctMcj79xkpDxErPg)

{
  "create_or_overwrite": false,
  "display_description": "Add transformation method to PaintQuad",
  "path": "zed/crates/gpui/src/window.rs"
}

Tool Results: toolu_018FpxFdctMcj79xkpDxErPg

Edited zed/crates/gpui/src/window.rs:

@@ -4233,6 +4233,14 @@
             ..self
         }
     }
+
+    /// Sets the transformation matrix to apply to the quad.
+    pub fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {
+        PaintQuad {
+            transformation: transformation.into(),
+            ..self
+        }
+    }
 }
 
 /// Creates a quad with the given parameters.

Debug Output:

{
  "original_path": "crates/gpui/src/window.rs",
  "new_text": "use crate::{\n    Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,\n    AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Context,\n    Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId,\n    DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, FontId,\n    Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero, KeyBinding, KeyContext,\n    KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers,\n    ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent,\n    Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler,\n    PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams,\n    RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR,\n    SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style,\n    SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement,\n    TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance,\n    WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem,\n    point, prelude::*, px, size, transparent_black,\n};\nuse anyhow::{Context as _, Result, anyhow};\nuse collections::{FxHashMap, FxHashSet};\n#[cfg(target_os = \"macos\")]\nuse core_video::pixel_buffer::CVPixelBuffer;\nuse derive_more::{Deref, DerefMut};\nuse futures::FutureExt;\nuse futures::channel::oneshot;\nuse parking_lot::RwLock;\nuse raw_window_handle::{HandleError, HasWindowHandle};\nuse refineable::Refineable;\nuse slotmap::SlotMap;\nuse smallvec::SmallVec;\nuse std::{\n    any::{Any, TypeId},\n    borrow::Cow,\n    cell::{Cell, RefCell},\n    cmp,\n    fmt::{Debug, Display},\n    hash::{Hash, Hasher},\n    marker::PhantomData,\n    mem,\n    ops::{DerefMut, Range},\n    rc::Rc,\n    sync::{\n        Arc, Weak,\n        atomic::{AtomicUsize, Ordering::SeqCst},\n    },\n    time::{Duration, Instant},\n};\nuse util::post_inc;\nuse util::{ResultExt, measure};\nuse uuid::Uuid;\n\nmod prompts;\n\npub use prompts::*;\n\npub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1024.), px(700.));\n\n/// Represents the two different phases when dispatching events.\n#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]\npub enum DispatchPhase {\n    /// After the capture phase comes the bubble phase, in which mouse event listeners are\n    /// invoked front to back and keyboard event listeners are invoked from the focused element\n    /// to the root of the element tree. This is the phase you'll most commonly want to use when\n    /// registering event listeners.\n    #[default]\n    Bubble,\n    /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard\n    /// listeners are invoked from the root of the tree downward toward the focused element. This phase\n    /// is used for special purposes such as clearing the \"pressed\" state for click events. If\n    /// you stop event propagation during this phase, you need to know what you're doing. Handlers\n    /// outside of the immediate region may rely on detecting non-local events during this phase.\n    Capture,\n}\n\nimpl DispatchPhase {\n    /// Returns true if this represents the \"bubble\" phase.\n    pub fn bubble(self) -> bool {\n        self == DispatchPhase::Bubble\n    }\n\n    /// Returns true if this represents the \"capture\" phase.\n    pub fn capture(self) -> bool {\n        self == DispatchPhase::Capture\n    }\n}\n\nstruct WindowInvalidatorInner {\n    pub dirty: bool,\n    pub draw_phase: DrawPhase,\n    pub dirty_views: FxHashSet<EntityId>,\n}\n\n#[derive(Clone)]\npub(crate) struct WindowInvalidator {\n    inner: Rc<RefCell<WindowInvalidatorInner>>,\n}\n\nimpl WindowInvalidator {\n    pub fn new() -> Self {\n        WindowInvalidator {\n            inner: Rc::new(RefCell::new(WindowInvalidatorInner {\n                dirty: true,\n                draw_phase: DrawPhase::None,\n                dirty_views: FxHashSet::default(),\n            })),\n        }\n    }\n\n    pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {\n        let mut inner = self.inner.borrow_mut();\n        inner.dirty_views.insert(entity);\n        if inner.draw_phase == DrawPhase::None {\n            inner.dirty = true;\n            cx.push_effect(Effect::Notify { emitter: entity });\n            true\n        } else {\n            false\n        }\n    }\n\n    pub fn is_dirty(&self) -> bool {\n        self.inner.borrow().dirty\n    }\n\n    pub fn set_dirty(&self, dirty: bool) {\n        self.inner.borrow_mut().dirty = dirty\n    }\n\n    pub fn set_phase(&self, phase: DrawPhase) {\n        self.inner.borrow_mut().draw_phase = phase\n    }\n\n    pub fn take_views(&self) -> FxHashSet<EntityId> {\n        mem::take(&mut self.inner.borrow_mut().dirty_views)\n    }\n\n    pub fn replace_views(&self, views: FxHashSet<EntityId>) {\n        self.inner.borrow_mut().dirty_views = views;\n    }\n\n    pub fn not_drawing(&self) -> bool {\n        self.inner.borrow().draw_phase == DrawPhase::None\n    }\n\n    #[track_caller]\n    pub fn debug_assert_paint(&self) {\n        debug_assert!(\n            matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),\n            \"this method can only be called during paint\"\n        );\n    }\n\n    #[track_caller]\n    pub fn debug_assert_prepaint(&self) {\n        debug_assert!(\n            matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),\n            \"this method can only be called during request_layout, or prepaint\"\n        );\n    }\n\n    #[track_caller]\n    pub fn debug_assert_paint_or_prepaint(&self) {\n        debug_assert!(\n            matches!(\n                self.inner.borrow().draw_phase,\n                DrawPhase::Paint | DrawPhase::Prepaint\n            ),\n            \"this method can only be called during request_layout, prepaint, or paint\"\n        );\n    }\n}\n\ntype AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;\n\npub(crate) type AnyWindowFocusListener =\n    Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;\n\npub(crate) struct WindowFocusEvent {\n    pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,\n    pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,\n}\n\nimpl WindowFocusEvent {\n    pub fn is_focus_in(&self, focus_id: FocusId) -> bool {\n        !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id)\n    }\n\n    pub fn is_focus_out(&self, focus_id: FocusId) -> bool {\n        self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id)\n    }\n}\n\n/// This is provided when subscribing for `Context::on_focus_out` events.\npub struct FocusOutEvent {\n    /// A weak focus handle representing what was blurred.\n    pub blurred: WeakFocusHandle,\n}\n\nslotmap::new_key_type! {\n    /// A globally unique identifier for a focusable element.\n    pub struct FocusId;\n}\n\nthread_local! {\n    /// 8MB wasn't quite enough...\n    pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(32 * 1024 * 1024));\n}\n\npub(crate) type FocusMap = RwLock<SlotMap<FocusId, AtomicUsize>>;\n\nimpl FocusId {\n    /// Obtains whether the element associated with this handle is currently focused.\n    pub fn is_focused(&self, window: &Window) -> bool {\n        window.focus == Some(*self)\n    }\n\n    /// Obtains whether the element associated with this handle contains the focused\n    /// element or is itself focused.\n    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {\n        window\n            .focused(cx)\n            .map_or(false, |focused| self.contains(focused.id, window))\n    }\n\n    /// Obtains whether the element associated with this handle is contained within the\n    /// focused element or is itself focused.\n    pub fn within_focused(&self, window: &Window, cx: &App) -> bool {\n        let focused = window.focused(cx);\n        focused.map_or(false, |focused| focused.id.contains(*self, window))\n    }\n\n    /// Obtains whether this handle contains the given handle in the most recently rendered frame.\n    pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {\n        window\n            .rendered_frame\n            .dispatch_tree\n            .focus_contains(*self, other)\n    }\n}\n\n/// A handle which can be used to track and manipulate the focused element in a window.\npub struct FocusHandle {\n    pub(crate) id: FocusId,\n    handles: Arc<FocusMap>,\n}\n\nimpl std::fmt::Debug for FocusHandle {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.write_fmt(format_args!(\"FocusHandle({:?})\", self.id))\n    }\n}\n\nimpl FocusHandle {\n    pub(crate) fn new(handles: &Arc<FocusMap>) -> Self {\n        let id = handles.write().insert(AtomicUsize::new(1));\n        Self {\n            id,\n            handles: handles.clone(),\n        }\n    }\n\n    pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {\n        let lock = handles.read();\n        let ref_count = lock.get(id)?;\n        if ref_count.load(SeqCst) == 0 {\n            None\n        } else {\n            ref_count.fetch_add(1, SeqCst);\n            Some(Self {\n                id,\n                handles: handles.clone(),\n            })\n        }\n    }\n\n    /// Converts this focus handle into a weak variant, which does not prevent it from being released.\n    pub fn downgrade(&self) -> WeakFocusHandle {\n        WeakFocusHandle {\n            id: self.id,\n            handles: Arc::downgrade(&self.handles),\n        }\n    }\n\n    /// Moves the focus to the element associated with this handle.\n    pub fn focus(&self, window: &mut Window) {\n        window.focus(self)\n    }\n\n    /// Obtains whether the element associated with this handle is currently focused.\n    pub fn is_focused(&self, window: &Window) -> bool {\n        self.id.is_focused(window)\n    }\n\n    /// Obtains whether the element associated with this handle contains the focused\n    /// element or is itself focused.\n    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {\n        self.id.contains_focused(window, cx)\n    }\n\n    /// Obtains whether the element associated with this handle is contained within the\n    /// focused element or is itself focused.\n    pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {\n        self.id.within_focused(window, cx)\n    }\n\n    /// Obtains whether this handle contains the given handle in the most recently rendered frame.\n    pub fn contains(&self, other: &Self, window: &Window) -> bool {\n        self.id.contains(other.id, window)\n    }\n\n    /// Dispatch an action on the element that rendered this focus handle\n    pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {\n        if let Some(node_id) = window\n            .rendered_frame\n            .dispatch_tree\n            .focusable_node_id(self.id)\n        {\n            window.dispatch_action_on_node(node_id, action, cx)\n        }\n    }\n}\n\nimpl Clone for FocusHandle {\n    fn clone(&self) -> Self {\n        Self::for_id(self.id, &self.handles).unwrap()\n    }\n}\n\nimpl PartialEq for FocusHandle {\n    fn eq(&self, other: &Self) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for FocusHandle {}\n\nimpl Drop for FocusHandle {\n    fn drop(&mut self) {\n        self.handles\n            .read()\n            .get(self.id)\n            .unwrap()\n            .fetch_sub(1, SeqCst);\n    }\n}\n\n/// A weak reference to a focus handle.\n#[derive(Clone, Debug)]\npub struct WeakFocusHandle {\n    pub(crate) id: FocusId,\n    pub(crate) handles: Weak<FocusMap>,\n}\n\nimpl WeakFocusHandle {\n    /// Attempts to upgrade the [WeakFocusHandle] to a [FocusHandle].\n    pub fn upgrade(&self) -> Option<FocusHandle> {\n        let handles = self.handles.upgrade()?;\n        FocusHandle::for_id(self.id, &handles)\n    }\n}\n\nimpl PartialEq for WeakFocusHandle {\n    fn eq(&self, other: &WeakFocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for WeakFocusHandle {}\n\nimpl PartialEq<FocusHandle> for WeakFocusHandle {\n    fn eq(&self, other: &FocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl PartialEq<WeakFocusHandle> for FocusHandle {\n    fn eq(&self, other: &WeakFocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\n/// Focusable allows users of your view to easily\n/// focus it (using window.focus_view(cx, view))\npub trait Focusable: 'static {\n    /// Returns the focus handle associated with this view.\n    fn focus_handle(&self, cx: &App) -> FocusHandle;\n}\n\nimpl<V: Focusable> Focusable for Entity<V> {\n    fn focus_handle(&self, cx: &App) -> FocusHandle {\n        self.read(cx).focus_handle(cx)\n    }\n}\n\n/// ManagedView is a view (like a Modal, Popover, Menu, etc.)\n/// where the lifecycle of the view is handled by another view.\npub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}\n\nimpl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}\n\n/// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal.\npub struct DismissEvent;\n\ntype FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;\n\npub(crate) type AnyMouseListener =\n    Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;\n\n#[derive(Clone)]\npub(crate) struct CursorStyleRequest {\n    pub(crate) hitbox_id: Option<HitboxId>, // None represents whole window\n    pub(crate) style: CursorStyle,\n}\n\n/// An identifier for a [Hitbox].\n#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]\npub struct HitboxId(usize);\n\nimpl HitboxId {\n    /// Checks if the hitbox with this id is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        window.mouse_hit_test.0.contains(self)\n    }\n}\n\n/// A rectangular region that potentially blocks hitboxes inserted prior.\n/// See [Window::insert_hitbox] for more details.\n#[derive(Clone, Debug, Deref)]\npub struct Hitbox {\n    /// A unique identifier for the hitbox.\n    pub id: HitboxId,\n    /// The bounds of the hitbox.\n    #[deref]\n    pub bounds: Bounds<Pixels>,\n    /// The content mask when the hitbox was inserted.\n    pub content_mask: ContentMask<Pixels>,\n    /// Whether the hitbox occludes other hitboxes inserted prior.\n    pub opaque: bool,\n}\n\nimpl Hitbox {\n    /// Checks if the hitbox is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        self.id.is_hovered(window)\n    }\n}\n\n#[derive(Default, Eq, PartialEq)]\npub(crate) struct HitTest(SmallVec<[HitboxId; 8]>);\n\n/// An identifier for a tooltip.\n#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]\npub struct TooltipId(usize);\n\nimpl TooltipId {\n    /// Checks if the tooltip is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        window\n            .tooltip_bounds\n            .as_ref()\n            .map_or(false, |tooltip_bounds| {\n                tooltip_bounds.id == *self\n                    && tooltip_bounds.bounds.contains(&window.mouse_position())\n            })\n    }\n}\n\npub(crate) struct TooltipBounds {\n    id: TooltipId,\n    bounds: Bounds<Pixels>,\n}\n\n#[derive(Clone)]\npub(crate) struct TooltipRequest {\n    id: TooltipId,\n    tooltip: AnyTooltip,\n}\n\npub(crate) struct DeferredDraw {\n    current_view: EntityId,\n    priority: usize,\n    parent_node: DispatchNodeId,\n    element_id_stack: SmallVec<[ElementId; 32]>,\n    text_style_stack: Vec<TextStyleRefinement>,\n    element: Option<AnyElement>,\n    absolute_offset: Point<Pixels>,\n    prepaint_range: Range<PrepaintStateIndex>,\n    paint_range: Range<PaintIndex>,\n}\n\npub(crate) struct Frame {\n    pub(crate) focus: Option<FocusId>,\n    pub(crate) window_active: bool,\n    pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,\n    accessed_element_states: Vec<(GlobalElementId, TypeId)>,\n    pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,\n    pub(crate) dispatch_tree: DispatchTree,\n    pub(crate) scene: Scene,\n    pub(crate) hitboxes: Vec<Hitbox>,\n    pub(crate) deferred_draws: Vec<DeferredDraw>,\n    pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,\n    pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,\n    pub(crate) cursor_styles: Vec<CursorStyleRequest>,\n    #[cfg(any(test, feature = \"test-support\"))]\n    pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,\n}\n\n#[derive(Clone, Default)]\npub(crate) struct PrepaintStateIndex {\n    hitboxes_index: usize,\n    tooltips_index: usize,\n    deferred_draws_index: usize,\n    dispatch_tree_index: usize,\n    accessed_element_states_index: usize,\n    line_layout_index: LineLayoutIndex,\n}\n\n#[derive(Clone, Default)]\npub(crate) struct PaintIndex {\n    scene_index: usize,\n    mouse_listeners_index: usize,\n    input_handlers_index: usize,\n    cursor_styles_index: usize,\n    accessed_element_states_index: usize,\n    line_layout_index: LineLayoutIndex,\n}\n\nimpl Frame {\n    pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {\n        Frame {\n            focus: None,\n            window_active: false,\n            element_states: FxHashMap::default(),\n            accessed_element_states: Vec::new(),\n            mouse_listeners: Vec::new(),\n            dispatch_tree,\n            scene: Scene::default(),\n            hitboxes: Vec::new(),\n            deferred_draws: Vec::new(),\n            input_handlers: Vec::new(),\n            tooltip_requests: Vec::new(),\n            cursor_styles: Vec::new(),\n\n            #[cfg(any(test, feature = \"test-support\"))]\n            debug_bounds: FxHashMap::default(),\n        }\n    }\n\n    pub(crate) fn clear(&mut self) {\n        self.element_states.clear();\n        self.accessed_element_states.clear();\n        self.mouse_listeners.clear();\n        self.dispatch_tree.clear();\n        self.scene.clear();\n        self.input_handlers.clear();\n        self.tooltip_requests.clear();\n        self.cursor_styles.clear();\n        self.hitboxes.clear();\n        self.deferred_draws.clear();\n        self.focus = None;\n    }\n\n    pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {\n        let mut hit_test = HitTest::default();\n        for hitbox in self.hitboxes.iter().rev() {\n            let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds);\n            if bounds.contains(&position) {\n                hit_test.0.push(hitbox.id);\n                if hitbox.opaque {\n                    break;\n                }\n            }\n        }\n        hit_test\n    }\n\n    pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {\n        self.focus\n            .map(|focus_id| self.dispatch_tree.focus_path(focus_id))\n            .unwrap_or_default()\n    }\n\n    pub(crate) fn finish(&mut self, prev_frame: &mut Self) {\n        for element_state_key in &self.accessed_element_states {\n            if let Some((element_state_key, element_state)) =\n                prev_frame.element_states.remove_entry(element_state_key)\n            {\n                self.element_states.insert(element_state_key, element_state);\n            }\n        }\n\n        self.scene.finish();\n    }\n}\n\n/// Holds the state for a specific window.\npub struct Window {\n    pub(crate) handle: AnyWindowHandle,\n    pub(crate) invalidator: WindowInvalidator,\n    pub(crate) removed: bool,\n    pub(crate) platform_window: Box<dyn PlatformWindow>,\n    display_id: Option<DisplayId>,\n    sprite_atlas: Arc<dyn PlatformAtlas>,\n    text_system: Arc<WindowTextSystem>,\n    rem_size: Pixels,\n    /// The stack of override values for the window's rem size.\n    ///\n    /// This is used by `with_rem_size` to allow rendering an element tree with\n    /// a given rem size.\n    rem_size_override_stack: SmallVec<[Pixels; 8]>,\n    pub(crate) viewport_size: Size<Pixels>,\n    layout_engine: Option<TaffyLayoutEngine>,\n    pub(crate) root: Option<AnyView>,\n    pub(crate) element_id_stack: SmallVec<[ElementId; 32]>,\n    pub(crate) text_style_stack: Vec<TextStyleRefinement>,\n    pub(crate) rendered_entity_stack: Vec<EntityId>,\n    pub(crate) element_offset_stack: Vec<Point<Pixels>>,\n    pub(crate) element_opacity: Option<f32>,\n    pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,\n    pub(crate) requested_autoscroll: Option<Bounds<Pixels>>,\n    pub(crate) image_cache_stack: Vec<AnyImageCache>,\n    pub(crate) rendered_frame: Frame,\n    pub(crate) next_frame: Frame,\n    pub(crate) next_hitbox_id: HitboxId,\n    pub(crate) next_tooltip_id: TooltipId,\n    pub(crate) tooltip_bounds: Option<TooltipBounds>,\n    next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,\n    pub(crate) dirty_views: FxHashSet<EntityId>,\n    focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,\n    pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,\n    default_prevented: bool,\n    mouse_position: Point<Pixels>,\n    mouse_hit_test: HitTest,\n    modifiers: Modifiers,\n    scale_factor: f32,\n    pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,\n    appearance: WindowAppearance,\n    pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,\n    active: Rc<Cell<bool>>,\n    hovered: Rc<Cell<bool>>,\n    pub(crate) needs_present: Rc<Cell<bool>>,\n    pub(crate) last_input_timestamp: Rc<Cell<Instant>>,\n    pub(crate) refreshing: bool,\n    pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,\n    pub(crate) focus: Option<FocusId>,\n    focus_enabled: bool,\n    pending_input: Option<PendingInput>,\n    pending_modifier: ModifierState,\n    pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,\n    prompt: Option<RenderablePromptHandle>,\n    pub(crate) client_inset: Option<Pixels>,\n}\n\n#[derive(Clone, Debug, Default)]\nstruct ModifierState {\n    modifiers: Modifiers,\n    saw_keystroke: bool,\n}\n\n#[derive(Clone, Copy, Debug, Eq, PartialEq)]\npub(crate) enum DrawPhase {\n    None,\n    Prepaint,\n    Paint,\n    Focus,\n}\n\n#[derive(Default, Debug)]\nstruct PendingInput {\n    keystrokes: SmallVec<[Keystroke; 1]>,\n    focus: Option<FocusId>,\n    timer: Option<Task<()>>,\n}\n\npub(crate) struct ElementStateBox {\n    pub(crate) inner: Box<dyn Any>,\n    #[cfg(debug_assertions)]\n    pub(crate) type_name: &'static str,\n}\n\nfn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> Bounds<Pixels> {\n    const DEFAULT_WINDOW_OFFSET: Point<Pixels> = point(px(0.), px(35.));\n\n    // TODO, BUG: if you open a window with the currently active window\n    // on the stack, this will erroneously select the 'unwrap_or_else'\n    // code path\n    cx.active_window()\n        .and_then(|w| w.update(cx, |_, window, _| window.bounds()).ok())\n        .map(|mut bounds| {\n            bounds.origin += DEFAULT_WINDOW_OFFSET;\n            bounds\n        })\n        .unwrap_or_else(|| {\n            let display = display_id\n                .map(|id| cx.find_display(id))\n                .unwrap_or_else(|| cx.primary_display());\n\n            display\n                .map(|display| display.default_bounds())\n                .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE))\n        })\n}\n\nimpl Window {\n    pub(crate) fn new(\n        handle: AnyWindowHandle,\n        options: WindowOptions,\n        cx: &mut App,\n    ) -> Result<Self> {\n        let WindowOptions {\n            window_bounds,\n            titlebar,\n            focus,\n            show,\n            kind,\n            is_movable,\n            display_id,\n            window_background,\n            app_id,\n            window_min_size,\n            window_decorations,\n        } = options;\n\n        let bounds = window_bounds\n            .map(|bounds| bounds.get_bounds())\n            .unwrap_or_else(|| default_bounds(display_id, cx));\n        let mut platform_window = cx.platform.open_window(\n            handle,\n            WindowParams {\n                bounds,\n                titlebar,\n                kind,\n                is_movable,\n                focus,\n                show,\n                display_id,\n                window_min_size,\n            },\n        )?;\n        let display_id = platform_window.display().map(|display| display.id());\n        let sprite_atlas = platform_window.sprite_atlas();\n        let mouse_position = platform_window.mouse_position();\n        let modifiers = platform_window.modifiers();\n        let content_size = platform_window.content_size();\n        let scale_factor = platform_window.scale_factor();\n        let appearance = platform_window.appearance();\n        let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));\n        let invalidator = WindowInvalidator::new();\n        let active = Rc::new(Cell::new(platform_window.is_active()));\n        let hovered = Rc::new(Cell::new(platform_window.is_hovered()));\n        let needs_present = Rc::new(Cell::new(false));\n        let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();\n        let last_input_timestamp = Rc::new(Cell::new(Instant::now()));\n\n        platform_window\n            .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server));\n        platform_window.set_background_appearance(window_background);\n\n        if let Some(ref window_open_state) = window_bounds {\n            match window_open_state {\n                WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),\n                WindowBounds::Maximized(_) => platform_window.zoom(),\n                WindowBounds::Windowed(_) => {}\n            }\n        }\n\n        platform_window.on_close(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                let _ = handle.update(&mut cx, |_, window, _| window.remove_window());\n            }\n        }));\n        platform_window.on_request_frame(Box::new({\n            let mut cx = cx.to_async();\n            let invalidator = invalidator.clone();\n            let active = active.clone();\n            let needs_present = needs_present.clone();\n            let next_frame_callbacks = next_frame_callbacks.clone();\n            let last_input_timestamp = last_input_timestamp.clone();\n            move |request_frame_options| {\n                let next_frame_callbacks = next_frame_callbacks.take();\n                if !next_frame_callbacks.is_empty() {\n                    handle\n                        .update(&mut cx, |_, window, cx| {\n                            for callback in next_frame_callbacks {\n                                callback(window, cx);\n                            }\n                        })\n                        .log_err();\n                }\n\n                // Keep presenting the current scene for 1 extra second since the\n                // last input to prevent the display from underclocking the refresh rate.\n                let needs_present = request_frame_options.require_presentation\n                    || needs_present.get()\n                    || (active.get()\n                        && last_input_timestamp.get().elapsed() < Duration::from_secs(1));\n\n                if invalidator.is_dirty() {\n                    measure(\"frame duration\", || {\n                        handle\n                            .update(&mut cx, |_, window, cx| {\n                                window.draw(cx);\n                                window.present();\n                            })\n                            .log_err();\n                    })\n                } else if needs_present {\n                    handle\n                        .update(&mut cx, |_, window, _| window.present())\n                        .log_err();\n                }\n\n                handle\n                    .update(&mut cx, |_, window, _| {\n                        window.complete_frame();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_resize(Box::new({\n            let mut cx = cx.to_async();\n            move |_, _| {\n                handle\n                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_moved(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                handle\n                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_appearance_changed(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                handle\n                    .update(&mut cx, |_, window, cx| window.appearance_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_active_status_change(Box::new({\n            let mut cx = cx.to_async();\n            move |active| {\n                handle\n                    .update(&mut cx, |_, window, cx| {\n                        window.active.set(active);\n                        window.modifiers = window.platform_window.modifiers();\n                        window\n                            .activation_observers\n                            .clone()\n                            .retain(&(), |callback| callback(window, cx));\n                        window.refresh();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_hover_status_change(Box::new({\n            let mut cx = cx.to_async();\n            move |active| {\n                handle\n                    .update(&mut cx, |_, window, _| {\n                        window.hovered.set(active);\n                        window.refresh();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_input({\n            let mut cx = cx.to_async();\n            Box::new(move |event| {\n                handle\n                    .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))\n                    .log_err()\n                    .unwrap_or(DispatchEventResult::default())\n            })\n        });\n\n        if let Some(app_id) = app_id {\n            platform_window.set_app_id(&app_id);\n        }\n\n        platform_window.map_window().unwrap();\n\n        Ok(Window {\n            handle,\n            invalidator,\n            removed: false,\n            platform_window,\n            display_id,\n            sprite_atlas,\n            text_system,\n            rem_size: px(16.),\n            rem_size_override_stack: SmallVec::new(),\n            viewport_size: content_size,\n            layout_engine: Some(TaffyLayoutEngine::new()),\n            root: None,\n            element_id_stack: SmallVec::default(),\n            text_style_stack: Vec::new(),\n            rendered_entity_stack: Vec::new(),\n            element_offset_stack: Vec::new(),\n            content_mask_stack: Vec::new(),\n            element_opacity: None,\n            requested_autoscroll: None,\n            rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),\n            next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),\n            next_frame_callbacks,\n            next_hitbox_id: HitboxId::default(),\n            next_tooltip_id: TooltipId::default(),\n            tooltip_bounds: None,\n            dirty_views: FxHashSet::default(),\n            focus_listeners: SubscriberSet::new(),\n            focus_lost_listeners: SubscriberSet::new(),\n            default_prevented: true,\n            mouse_position,\n            mouse_hit_test: HitTest::default(),\n            modifiers,\n            scale_factor,\n            bounds_observers: SubscriberSet::new(),\n            appearance,\n            appearance_observers: SubscriberSet::new(),\n            active,\n            hovered,\n            needs_present,\n            last_input_timestamp,\n            refreshing: false,\n            activation_observers: SubscriberSet::new(),\n            focus: None,\n            focus_enabled: true,\n            pending_input: None,\n            pending_modifier: ModifierState::default(),\n            pending_input_observers: SubscriberSet::new(),\n            prompt: None,\n            client_inset: None,\n            image_cache_stack: Vec::new(),\n        })\n    }\n\n    pub(crate) fn new_focus_listener(\n        &self,\n        value: AnyWindowFocusListener,\n    ) -> (Subscription, impl FnOnce() + use<>) {\n        self.focus_listeners.insert((), value)\n    }\n}\n\n#[derive(Clone, Debug, Default, PartialEq, Eq)]\npub(crate) struct DispatchEventResult {\n    pub propagate: bool,\n    pub default_prevented: bool,\n}\n\n/// Indicates which region of the window is visible. Content falling outside of this mask will not be\n/// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type\n/// to leave room to support more complex shapes in the future.\n#[derive(Clone, Debug, Default, PartialEq, Eq)]\n#[repr(C)]\npub struct ContentMask<P: Clone + Default + Debug> {\n    /// The bounds\n    pub bounds: Bounds<P>,\n}\n\nimpl ContentMask<Pixels> {\n    /// Scale the content mask's pixel units by the given scaling factor.\n    pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {\n        ContentMask {\n            bounds: self.bounds.scale(factor),\n        }\n    }\n\n    /// Intersect the content mask with the given content mask.\n    pub fn intersect(&self, other: &Self) -> Self {\n        let bounds = self.bounds.intersect(&other.bounds);\n        ContentMask { bounds }\n    }\n}\n\nimpl Window {\n    fn mark_view_dirty(&mut self, view_id: EntityId) {\n        // Mark ancestor views as dirty. If already in the `dirty_views` set, then all its ancestors\n        // should already be dirty.\n        for view_id in self\n            .rendered_frame\n            .dispatch_tree\n            .view_path(view_id)\n            .into_iter()\n            .rev()\n        {\n            if !self.dirty_views.insert(view_id) {\n                break;\n            }\n        }\n    }\n\n    /// Registers a callback to be invoked when the window appearance changes.\n    pub fn observe_window_appearance(\n        &self,\n        mut callback: impl FnMut(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let (subscription, activate) = self.appearance_observers.insert(\n            (),\n            Box::new(move |window, cx| {\n                callback(window, cx);\n                true\n            }),\n        );\n        activate();\n        subscription\n    }\n\n    /// Replaces the root entity of the window with a new one.\n    pub fn replace_root<E>(\n        &mut self,\n        cx: &mut App,\n        build_view: impl FnOnce(&mut Window, &mut Context<E>) -> E,\n    ) -> Entity<E>\n    where\n        E: 'static + Render,\n    {\n        let view = cx.new(|cx| build_view(self, cx));\n        self.root = Some(view.clone().into());\n        self.refresh();\n        view\n    }\n\n    /// Returns the root entity of the window, if it has one.\n    pub fn root<E>(&self) -> Option<Option<Entity<E>>>\n    where\n        E: 'static + Render,\n    {\n        self.root\n            .as_ref()\n            .map(|view| view.clone().downcast::<E>().ok())\n    }\n\n    /// Obtain a handle to the window that belongs to this context.\n    pub fn window_handle(&self) -> AnyWindowHandle {\n        self.handle\n    }\n\n    /// Mark the window as dirty, scheduling it to be redrawn on the next frame.\n    pub fn refresh(&mut self) {\n        if self.invalidator.not_drawing() {\n            self.refreshing = true;\n            self.invalidator.set_dirty(true);\n        }\n    }\n\n    /// Close this window.\n    pub fn remove_window(&mut self) {\n        self.removed = true;\n    }\n\n    /// Obtain the currently focused [`FocusHandle`]. If no elements are focused, returns `None`.\n    pub fn focused(&self, cx: &App) -> Option<FocusHandle> {\n        self.focus\n            .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))\n    }\n\n    /// Move focus to the element associated with the given [`FocusHandle`].\n    pub fn focus(&mut self, handle: &FocusHandle) {\n        if !self.focus_enabled || self.focus == Some(handle.id) {\n            return;\n        }\n\n        self.focus = Some(handle.id);\n        self.clear_pending_keystrokes();\n        self.refresh();\n    }\n\n    /// Remove focus from all elements within this context's window.\n    pub fn blur(&mut self) {\n        if !self.focus_enabled {\n            return;\n        }\n\n        self.focus = None;\n        self.refresh();\n    }\n\n    /// Blur the window and don't allow anything in it to be focused again.\n    pub fn disable_focus(&mut self) {\n        self.blur();\n        self.focus_enabled = false;\n    }\n\n    /// Accessor for the text system.\n    pub fn text_system(&self) -> &Arc<WindowTextSystem> {\n        &self.text_system\n    }\n\n    /// The current text style. Which is composed of all the style refinements provided to `with_text_style`.\n    pub fn text_style(&self) -> TextStyle {\n        let mut style = TextStyle::default();\n        for refinement in &self.text_style_stack {\n            style.refine(refinement);\n        }\n        style\n    }\n\n    /// Check if the platform window is maximized\n    /// On some platforms (namely Windows) this is different than the bounds being the size of the display\n    pub fn is_maximized(&self) -> bool {\n        self.platform_window.is_maximized()\n    }\n\n    /// request a certain window decoration (Wayland)\n    pub fn request_decorations(&self, decorations: WindowDecorations) {\n        self.platform_window.request_decorations(decorations);\n    }\n\n    /// Start a window resize operation (Wayland)\n    pub fn start_window_resize(&self, edge: ResizeEdge) {\n        self.platform_window.start_window_resize(edge);\n    }\n\n    /// Return the `WindowBounds` to indicate that how a window should be opened\n    /// after it has been closed\n    pub fn window_bounds(&self) -> WindowBounds {\n        self.platform_window.window_bounds()\n    }\n\n    /// Return the `WindowBounds` excluding insets (Wayland and X11)\n    pub fn inner_window_bounds(&self) -> WindowBounds {\n        self.platform_window.inner_window_bounds()\n    }\n\n    /// Dispatch the given action on the currently focused element.\n    pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {\n        let focus_handle = self.focused(cx);\n\n        let window = self.handle;\n        cx.defer(move |cx| {\n            window\n                .update(cx, |_, window, cx| {\n                    let node_id = focus_handle\n                        .and_then(|handle| {\n                            window\n                                .rendered_frame\n                                .dispatch_tree\n                                .focusable_node_id(handle.id)\n                        })\n                        .unwrap_or_else(|| window.rendered_frame.dispatch_tree.root_node_id());\n\n                    window.dispatch_action_on_node(node_id, action.as_ref(), cx);\n                })\n                .log_err();\n        })\n    }\n\n    pub(crate) fn dispatch_keystroke_observers(\n        &mut self,\n        event: &dyn Any,\n        action: Option<Box<dyn Action>>,\n        context_stack: Vec<KeyContext>,\n        cx: &mut App,\n    ) {\n        let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {\n            return;\n        };\n\n        cx.keystroke_observers.clone().retain(&(), move |callback| {\n            (callback)(\n                &KeystrokeEvent {\n                    keystroke: key_down_event.keystroke.clone(),\n                    action: action.as_ref().map(|action| action.boxed_clone()),\n                    context_stack: context_stack.clone(),\n                },\n                self,\n                cx,\n            )\n        });\n    }\n\n    /// Schedules the given function to be run at the end of the current effect cycle, allowing entities\n    /// that are currently on the stack to be returned to the app.\n    pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {\n        let handle = self.handle;\n        cx.defer(move |cx| {\n            handle.update(cx, |_, window, cx| f(window, cx)).ok();\n        });\n    }\n\n    /// Subscribe to events emitted by a entity.\n    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.\n    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.\n    pub fn observe<T: 'static>(\n        &mut self,\n        observed: &Entity<T>,\n        cx: &mut App,\n        mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let entity_id = observed.entity_id();\n        let observed = observed.downgrade();\n        let window_handle = self.handle;\n        cx.new_observer(\n            entity_id,\n            Box::new(move |cx| {\n                window_handle\n                    .update(cx, |_, window, cx| {\n                        if let Some(handle) = observed.upgrade() {\n                            on_notify(handle, window, cx);\n                            true\n                        } else {\n                            false\n                        }\n                    })\n                    .unwrap_or(false)\n            }),\n        )\n    }\n\n    /// Subscribe to events emitted by a entity.\n    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.\n    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.\n    pub fn subscribe<Emitter, Evt>(\n        &mut self,\n        entity: &Entity<Emitter>,\n        cx: &mut App,\n        mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,\n    ) -> Subscription\n    where\n        Emitter: EventEmitter<Evt>,\n        Evt: 'static,\n    {\n        let entity_id = entity.entity_id();\n        let handle = entity.downgrade();\n        let window_handle = self.handle;\n        cx.new_subscription(\n            entity_id,\n            (\n                TypeId::of::<Evt>(),\n                Box::new(move |event, cx| {\n                    window_handle\n                        .update(cx, |_, window, cx| {\n                            if let Some(entity) = handle.upgrade() {\n                                let event = event.downcast_ref().expect(\"invalid event type\");\n                                on_event(entity, event, window, cx);\n                                true\n                            } else {\n                                false\n                            }\n                        })\n                        .unwrap_or(false)\n                }),\n            ),\n        )\n    }\n\n    /// Register a callback to be invoked when the given `Entity` is released.\n    pub fn observe_release<T>(\n        &self,\n        entity: &Entity<T>,\n        cx: &mut App,\n        mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,\n    ) -> Subscription\n    where\n        T: 'static,\n    {\n        let entity_id = entity.entity_id();\n        let window_handle = self.handle;\n        let (subscription, activate) = cx.release_listeners.insert(\n            entity_id,\n            Box::new(move |entity, cx| {\n                let entity = entity.downcast_mut().expect(\"invalid entity type\");\n                let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));\n            }),\n        );\n        activate();\n        subscription\n    }\n\n    /// Creates an [`AsyncWindowContext`], which has a static lifetime and can be held across\n    /// await points in async code.\n    pub fn to_async(&self, cx: &App) -> AsyncWindowContext {\n        AsyncWindowContext::new_context(cx.to_async(), self.handle)\n    }\n\n    /// Schedule the given closure to be run directly after the current frame is rendered.\n    pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) {\n        RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback));\n    }\n\n    /// Schedule a frame to be drawn on the next animation frame.\n    ///\n    /// This is useful for elements that need to animate continuously, such as a video player or an animated GIF.\n    /// It will cause the window to redraw on the next frame, even if no other changes have occurred.\n    ///\n    /// If called from within a view, it will notify that view on the next frame. Otherwise, it will refresh the entire window.\n    pub fn request_animation_frame(&self) {\n        let entity = self.current_view();\n        self.on_next_frame(move |_, cx| cx.notify(entity));\n    }\n\n    /// Spawn the future returned by the given closure on the application thread pool.\n    /// The closure is provided a handle to the current window and an `AsyncWindowContext` for\n    /// use within your future.\n    #[track_caller]\n    pub fn spawn<AsyncFn, R>(&self, cx: &App, f: AsyncFn) -> Task<R>\n    where\n        R: 'static,\n        AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,\n    {\n        let handle = self.handle;\n        cx.spawn(async move |app| {\n            let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);\n            f(&mut async_window_cx).await\n        })\n    }\n\n    fn bounds_changed(&mut self, cx: &mut App) {\n        self.scale_factor = self.platform_window.scale_factor();\n        self.viewport_size = self.platform_window.content_size();\n        self.display_id = self.platform_window.display().map(|display| display.id());\n\n        self.refresh();\n\n        self.bounds_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    /// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays.\n    pub fn bounds(&self) -> Bounds<Pixels> {\n        self.platform_window.bounds()\n    }\n\n    /// Set the content size of the window.\n    pub fn resize(&mut self, size: Size<Pixels>) {\n        self.platform_window.resize(size);\n    }\n\n    /// Returns whether or not the window is currently fullscreen\n    pub fn is_fullscreen(&self) -> bool {\n        self.platform_window.is_fullscreen()\n    }\n\n    pub(crate) fn appearance_changed(&mut self, cx: &mut App) {\n        self.appearance = self.platform_window.appearance();\n\n        self.appearance_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    /// Returns the appearance of the current window.\n    pub fn appearance(&self) -> WindowAppearance {\n        self.appearance\n    }\n\n    /// Returns the size of the drawable area within the window.\n    pub fn viewport_size(&self) -> Size<Pixels> {\n        self.viewport_size\n    }\n\n    /// Returns whether this window is focused by the operating system (receiving key events).\n    pub fn is_window_active(&self) -> bool {\n        self.active.get()\n    }\n\n    /// Returns whether this window is considered to be the window\n    /// that currently owns the mouse cursor.\n    /// On mac, this is equivalent to `is_window_active`.\n    pub fn is_window_hovered(&self) -> bool {\n        if cfg!(any(\n            target_os = \"windows\",\n            target_os = \"linux\",\n            target_os = \"freebsd\"\n        )) {\n            self.hovered.get()\n        } else {\n            self.is_window_active()\n        }\n    }\n\n    /// Toggle zoom on the window.\n    pub fn zoom_window(&self) {\n        self.platform_window.zoom();\n    }\n\n    /// Opens the native title bar context menu, useful when implementing client side decorations (Wayland and X11)\n    pub fn show_window_menu(&self, position: Point<Pixels>) {\n        self.platform_window.show_window_menu(position)\n    }\n\n    /// Tells the compositor to take control of window movement (Wayland and X11)\n    ///\n    /// Events may not be received during a move operation.\n    pub fn start_window_move(&self) {\n        self.platform_window.start_window_move()\n    }\n\n    /// When using client side decorations, set this to the width of the invisible decorations (Wayland and X11)\n    pub fn set_client_inset(&mut self, inset: Pixels) {\n        self.client_inset = Some(inset);\n        self.platform_window.set_client_inset(inset);\n    }\n\n    /// Returns the client_inset value by [`Self::set_client_inset`].\n    pub fn client_inset(&self) -> Option<Pixels> {\n        self.client_inset\n    }\n\n    /// Returns whether the title bar window controls need to be rendered by the application (Wayland and X11)\n    pub fn window_decorations(&self) -> Decorations {\n        self.platform_window.window_decorations()\n    }\n\n    /// Returns which window controls are currently visible (Wayland)\n    pub fn window_controls(&self) -> WindowControls {\n        self.platform_window.window_controls()\n    }\n\n    /// Updates the window's title at the platform level.\n    pub fn set_window_title(&mut self, title: &str) {\n        self.platform_window.set_title(title);\n    }\n\n    /// Sets the application identifier.\n    pub fn set_app_id(&mut self, app_id: &str) {\n        self.platform_window.set_app_id(app_id);\n    }\n\n    /// Sets the window background appearance.\n    pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {\n        self.platform_window\n            .set_background_appearance(background_appearance);\n    }\n\n    /// Mark the window as dirty at the platform level.\n    pub fn set_window_edited(&mut self, edited: bool) {\n        self.platform_window.set_edited(edited);\n    }\n\n    /// Determine the display on which the window is visible.\n    pub fn display(&self, cx: &App) -> Option<Rc<dyn PlatformDisplay>> {\n        cx.platform\n            .displays()\n            .into_iter()\n            .find(|display| Some(display.id()) == self.display_id)\n    }\n\n    /// Show the platform character palette.\n    pub fn show_character_palette(&self) {\n        self.platform_window.show_character_palette();\n    }\n\n    /// The scale factor of the display associated with the window. For example, it could\n    /// return 2.0 for a \"retina\" display, indicating that each logical pixel should actually\n    /// be rendered as two pixels on screen.\n    pub fn scale_factor(&self) -> f32 {\n        self.scale_factor\n    }\n\n    /// The size of an em for the base font of the application. Adjusting this value allows the\n    /// UI to scale, just like zooming a web page.\n    pub fn rem_size(&self) -> Pixels {\n        self.rem_size_override_stack\n            .last()\n            .copied()\n            .unwrap_or(self.rem_size)\n    }\n\n    /// Sets the size of an em for the base font of the application. Adjusting this value allows the\n    /// UI to scale, just like zooming a web page.\n    pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {\n        self.rem_size = rem_size.into();\n    }\n\n    /// Acquire a globally unique identifier for the given ElementId.\n    /// Only valid for the duration of the provided closure.\n    pub fn with_global_id<R>(\n        &mut self,\n        element_id: ElementId,\n        f: impl FnOnce(&GlobalElementId, &mut Self) -> R,\n    ) -> R {\n        self.element_id_stack.push(element_id);\n        let global_id = GlobalElementId(self.element_id_stack.clone());\n        let result = f(&global_id, self);\n        self.element_id_stack.pop();\n        result\n    }\n\n    /// Executes the provided function with the specified rem size.\n    ///\n    /// This method must only be called as part of element drawing.\n    pub fn with_rem_size<F, R>(&mut self, rem_size: Option<impl Into<Pixels>>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        if let Some(rem_size) = rem_size {\n            self.rem_size_override_stack.push(rem_size.into());\n            let result = f(self);\n            self.rem_size_override_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// The line height associated with the current text style.\n    pub fn line_height(&self) -> Pixels {\n        self.text_style().line_height_in_pixels(self.rem_size())\n    }\n\n    /// Call to prevent the default action of an event. Currently only used to prevent\n    /// parent elements from becoming focused on mouse down.\n    pub fn prevent_default(&mut self) {\n        self.default_prevented = true;\n    }\n\n    /// Obtain whether default has been prevented for the event currently being dispatched.\n    pub fn default_prevented(&self) -> bool {\n        self.default_prevented\n    }\n\n    /// Determine whether the given action is available along the dispatch path to the currently focused element.\n    pub fn is_action_available(&self, action: &dyn Action, cx: &mut App) -> bool {\n        let target = self\n            .focused(cx)\n            .and_then(|focused_handle| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focused_handle.id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n        self.rendered_frame\n            .dispatch_tree\n            .is_action_available(action, target)\n    }\n\n    /// The position of the mouse relative to the window.\n    pub fn mouse_position(&self) -> Point<Pixels> {\n        self.mouse_position\n    }\n\n    /// The current state of the keyboard's modifiers\n    pub fn modifiers(&self) -> Modifiers {\n        self.modifiers\n    }\n\n    fn complete_frame(&self) {\n        self.platform_window.completed_frame();\n    }\n\n    /// Produces a new frame and assigns it to `rendered_frame`. To actually show\n    /// the contents of the new [Scene], use [present].\n    #[profiling::function]\n    pub fn draw(&mut self, cx: &mut App) {\n        self.invalidate_entities();\n        cx.entities.clear_accessed();\n        debug_assert!(self.rendered_entity_stack.is_empty());\n        self.invalidator.set_dirty(false);\n        self.requested_autoscroll = None;\n\n        // Restore the previously-used input handler.\n        if let Some(input_handler) = self.platform_window.take_input_handler() {\n            self.rendered_frame.input_handlers.push(Some(input_handler));\n        }\n        self.draw_roots(cx);\n        self.dirty_views.clear();\n        self.next_frame.window_active = self.active.get();\n\n        // Register requested input handler with the platform window.\n        if let Some(input_handler) = self.next_frame.input_handlers.pop() {\n            self.platform_window\n                .set_input_handler(input_handler.unwrap());\n        }\n\n        self.layout_engine.as_mut().unwrap().clear();\n        self.text_system().finish_frame();\n        self.next_frame.finish(&mut self.rendered_frame);\n        ELEMENT_ARENA.with_borrow_mut(|element_arena| {\n            let percentage = (element_arena.len() as f32 / element_arena.capacity() as f32) * 100.;\n            if percentage >= 80. {\n                log::warn!(\"elevated element arena occupation: {}.\", percentage);\n            }\n            element_arena.clear();\n        });\n\n        self.invalidator.set_phase(DrawPhase::Focus);\n        let previous_focus_path = self.rendered_frame.focus_path();\n        let previous_window_active = self.rendered_frame.window_active;\n        mem::swap(&mut self.rendered_frame, &mut self.next_frame);\n        self.next_frame.clear();\n        let current_focus_path = self.rendered_frame.focus_path();\n        let current_window_active = self.rendered_frame.window_active;\n\n        if previous_focus_path != current_focus_path\n            || previous_window_active != current_window_active\n        {\n            if !previous_focus_path.is_empty() && current_focus_path.is_empty() {\n                self.focus_lost_listeners\n                    .clone()\n                    .retain(&(), |listener| listener(self, cx));\n            }\n\n            let event = WindowFocusEvent {\n                previous_focus_path: if previous_window_active {\n                    previous_focus_path\n                } else {\n                    Default::default()\n                },\n                current_focus_path: if current_window_active {\n                    current_focus_path\n                } else {\n                    Default::default()\n                },\n            };\n            self.focus_listeners\n                .clone()\n                .retain(&(), |listener| listener(&event, self, cx));\n        }\n\n        debug_assert!(self.rendered_entity_stack.is_empty());\n        self.record_entities_accessed(cx);\n        self.reset_cursor_style(cx);\n        self.refreshing = false;\n        self.invalidator.set_phase(DrawPhase::None);\n        self.needs_present.set(true);\n    }\n\n    fn record_entities_accessed(&mut self, cx: &mut App) {\n        let mut entities_ref = cx.entities.accessed_entities.borrow_mut();\n        let mut entities = mem::take(entities_ref.deref_mut());\n        drop(entities_ref);\n        let handle = self.handle;\n        cx.record_entities_accessed(\n            handle,\n            // Try moving window invalidator into the Window\n            self.invalidator.clone(),\n            &entities,\n        );\n        let mut entities_ref = cx.entities.accessed_entities.borrow_mut();\n        mem::swap(&mut entities, entities_ref.deref_mut());\n    }\n\n    fn invalidate_entities(&mut self) {\n        let mut views = self.invalidator.take_views();\n        for entity in views.drain() {\n            self.mark_view_dirty(entity);\n        }\n        self.invalidator.replace_views(views);\n    }\n\n    #[profiling::function]\n    fn present(&self) {\n        self.platform_window.draw(&self.rendered_frame.scene);\n        self.needs_present.set(false);\n        profiling::finish_frame!();\n    }\n\n    fn draw_roots(&mut self, cx: &mut App) {\n        self.invalidator.set_phase(DrawPhase::Prepaint);\n        self.tooltip_bounds.take();\n\n        // Layout all root elements.\n        let mut root_element = self.root.as_ref().unwrap().clone().into_any();\n        root_element.prepaint_as_root(Point::default(), self.viewport_size.into(), self, cx);\n\n        let mut sorted_deferred_draws =\n            (0..self.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>();\n        sorted_deferred_draws.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);\n        self.prepaint_deferred_draws(&sorted_deferred_draws, cx);\n\n        let mut prompt_element = None;\n        let mut active_drag_element = None;\n        let mut tooltip_element = None;\n        if let Some(prompt) = self.prompt.take() {\n            let mut element = prompt.view.any_view().into_any();\n            element.prepaint_as_root(Point::default(), self.viewport_size.into(), self, cx);\n            prompt_element = Some(element);\n            self.prompt = Some(prompt);\n        } else if let Some(active_drag) = cx.active_drag.take() {\n            let mut element = active_drag.view.clone().into_any();\n            let offset = self.mouse_position() - active_drag.cursor_offset;\n            element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx);\n            active_drag_element = Some(element);\n            cx.active_drag = Some(active_drag);\n        } else {\n            tooltip_element = self.prepaint_tooltip(cx);\n        }\n\n        self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position);\n\n        // Now actually paint the elements.\n        self.invalidator.set_phase(DrawPhase::Paint);\n        root_element.paint(self, cx);\n\n        self.paint_deferred_draws(&sorted_deferred_draws, cx);\n\n        if let Some(mut prompt_element) = prompt_element {\n            prompt_element.paint(self, cx);\n        } else if let Some(mut drag_element) = active_drag_element {\n            drag_element.paint(self, cx);\n        } else if let Some(mut tooltip_element) = tooltip_element {\n            tooltip_element.paint(self, cx);\n        }\n    }\n\n    fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {\n        // Use indexing instead of iteration to avoid borrowing self for the duration of the loop.\n        for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() {\n            let Some(Some(tooltip_request)) = self\n                .next_frame\n                .tooltip_requests\n                .get(tooltip_request_index)\n                .cloned()\n            else {\n                log::error!(\"Unexpectedly absent TooltipRequest\");\n                continue;\n            };\n            let mut element = tooltip_request.tooltip.view.clone().into_any();\n            let mouse_position = tooltip_request.tooltip.mouse_position;\n            let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);\n\n            let mut tooltip_bounds =\n                Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);\n            let window_bounds = Bounds {\n                origin: Point::default(),\n                size: self.viewport_size(),\n            };\n\n            if tooltip_bounds.right() > window_bounds.right() {\n                let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);\n                if new_x >= Pixels::ZERO {\n                    tooltip_bounds.origin.x = new_x;\n                } else {\n                    tooltip_bounds.origin.x = cmp::max(\n                        Pixels::ZERO,\n                        tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),\n                    );\n                }\n            }\n\n            if tooltip_bounds.bottom() > window_bounds.bottom() {\n                let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);\n                if new_y >= Pixels::ZERO {\n                    tooltip_bounds.origin.y = new_y;\n                } else {\n                    tooltip_bounds.origin.y = cmp::max(\n                        Pixels::ZERO,\n                        tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),\n                    );\n                }\n            }\n\n            // It's possible for an element to have an active tooltip while not being painted (e.g.\n            // via the `visible_on_hover` method). Since mouse listeners are not active in this\n            // case, instead update the tooltip's visibility here.\n            let is_visible =\n                (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);\n            if !is_visible {\n                continue;\n            }\n\n            self.with_absolute_element_offset(tooltip_bounds.origin, |window| {\n                element.prepaint(window, cx)\n            });\n\n            self.tooltip_bounds = Some(TooltipBounds {\n                id: tooltip_request.id,\n                bounds: tooltip_bounds,\n            });\n            return Some(element);\n        }\n        None\n    }\n\n    fn prepaint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {\n        assert_eq!(self.element_id_stack.len(), 0);\n\n        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);\n        for deferred_draw_ix in deferred_draw_indices {\n            let deferred_draw = &mut deferred_draws[*deferred_draw_ix];\n            self.element_id_stack\n                .clone_from(&deferred_draw.element_id_stack);\n            self.text_style_stack\n                .clone_from(&deferred_draw.text_style_stack);\n            self.next_frame\n                .dispatch_tree\n                .set_active_node(deferred_draw.parent_node);\n\n            let prepaint_start = self.prepaint_index();\n            if let Some(element) = deferred_draw.element.as_mut() {\n                self.with_rendered_view(deferred_draw.current_view, |window| {\n                    window.with_absolute_element_offset(deferred_draw.absolute_offset, |window| {\n                        element.prepaint(window, cx)\n                    });\n                })\n            } else {\n                self.reuse_prepaint(deferred_draw.prepaint_range.clone());\n            }\n            let prepaint_end = self.prepaint_index();\n            deferred_draw.prepaint_range = prepaint_start..prepaint_end;\n        }\n        assert_eq!(\n            self.next_frame.deferred_draws.len(),\n            0,\n            \"cannot call defer_draw during deferred drawing\"\n        );\n        self.next_frame.deferred_draws = deferred_draws;\n        self.element_id_stack.clear();\n        self.text_style_stack.clear();\n    }\n\n    fn paint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {\n        assert_eq!(self.element_id_stack.len(), 0);\n\n        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);\n        for deferred_draw_ix in deferred_draw_indices {\n            let mut deferred_draw = &mut deferred_draws[*deferred_draw_ix];\n            self.element_id_stack\n                .clone_from(&deferred_draw.element_id_stack);\n            self.next_frame\n                .dispatch_tree\n                .set_active_node(deferred_draw.parent_node);\n\n            let paint_start = self.paint_index();\n            if let Some(element) = deferred_draw.element.as_mut() {\n                self.with_rendered_view(deferred_draw.current_view, |window| {\n                    element.paint(window, cx);\n                })\n            } else {\n                self.reuse_paint(deferred_draw.paint_range.clone());\n            }\n            let paint_end = self.paint_index();\n            deferred_draw.paint_range = paint_start..paint_end;\n        }\n        self.next_frame.deferred_draws = deferred_draws;\n        self.element_id_stack.clear();\n    }\n\n    pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {\n        PrepaintStateIndex {\n            hitboxes_index: self.next_frame.hitboxes.len(),\n            tooltips_index: self.next_frame.tooltip_requests.len(),\n            deferred_draws_index: self.next_frame.deferred_draws.len(),\n            dispatch_tree_index: self.next_frame.dispatch_tree.len(),\n            accessed_element_states_index: self.next_frame.accessed_element_states.len(),\n            line_layout_index: self.text_system.layout_index(),\n        }\n    }\n\n    pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {\n        self.next_frame.hitboxes.extend(\n            self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]\n                .iter()\n                .cloned(),\n        );\n        self.next_frame.tooltip_requests.extend(\n            self.rendered_frame.tooltip_requests\n                [range.start.tooltips_index..range.end.tooltips_index]\n                .iter_mut()\n                .map(|request| request.take()),\n        );\n        self.next_frame.accessed_element_states.extend(\n            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index\n                ..range.end.accessed_element_states_index]\n                .iter()\n                .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),\n        );\n        self.text_system\n            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);\n\n        let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree(\n            range.start.dispatch_tree_index..range.end.dispatch_tree_index,\n            &mut self.rendered_frame.dispatch_tree,\n            self.focus,\n        );\n\n        if reused_subtree.contains_focus() {\n            self.next_frame.focus = self.focus;\n        }\n\n        self.next_frame.deferred_draws.extend(\n            self.rendered_frame.deferred_draws\n                [range.start.deferred_draws_index..range.end.deferred_draws_index]\n                .iter()\n                .map(|deferred_draw| DeferredDraw {\n                    current_view: deferred_draw.current_view,\n                    parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),\n                    element_id_stack: deferred_draw.element_id_stack.clone(),\n                    text_style_stack: deferred_draw.text_style_stack.clone(),\n                    priority: deferred_draw.priority,\n                    element: None,\n                    absolute_offset: deferred_draw.absolute_offset,\n                    prepaint_range: deferred_draw.prepaint_range.clone(),\n                    paint_range: deferred_draw.paint_range.clone(),\n                }),\n        );\n    }\n\n    pub(crate) fn paint_index(&self) -> PaintIndex {\n        PaintIndex {\n            scene_index: self.next_frame.scene.len(),\n            mouse_listeners_index: self.next_frame.mouse_listeners.len(),\n            input_handlers_index: self.next_frame.input_handlers.len(),\n            cursor_styles_index: self.next_frame.cursor_styles.len(),\n            accessed_element_states_index: self.next_frame.accessed_element_states.len(),\n            line_layout_index: self.text_system.layout_index(),\n        }\n    }\n\n    pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {\n        self.next_frame.cursor_styles.extend(\n            self.rendered_frame.cursor_styles\n                [range.start.cursor_styles_index..range.end.cursor_styles_index]\n                .iter()\n                .cloned(),\n        );\n        self.next_frame.input_handlers.extend(\n            self.rendered_frame.input_handlers\n                [range.start.input_handlers_index..range.end.input_handlers_index]\n                .iter_mut()\n                .map(|handler| handler.take()),\n        );\n        self.next_frame.mouse_listeners.extend(\n            self.rendered_frame.mouse_listeners\n                [range.start.mouse_listeners_index..range.end.mouse_listeners_index]\n                .iter_mut()\n                .map(|listener| listener.take()),\n        );\n        self.next_frame.accessed_element_states.extend(\n            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index\n                ..range.end.accessed_element_states_index]\n                .iter()\n                .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),\n        );\n\n        self.text_system\n            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);\n        self.next_frame.scene.replay(\n            range.start.scene_index..range.end.scene_index,\n            &self.rendered_frame.scene,\n        );\n    }\n\n    /// Push a text style onto the stack, and call a function with that style active.\n    /// Use [`Window::text_style`] to get the current, combined text style. This method\n    /// should only be called as part of element drawing.\n    pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        if let Some(style) = style {\n            self.text_style_stack.push(style);\n            let result = f(self);\n            self.text_style_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Updates the cursor style at the platform level. This method should only be called\n    /// during the prepaint phase of element drawing.\n    pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: Option<&Hitbox>) {\n        self.invalidator.debug_assert_paint();\n        self.next_frame.cursor_styles.push(CursorStyleRequest {\n            hitbox_id: hitbox.map(|hitbox| hitbox.id),\n            style,\n        });\n    }\n\n    /// Sets a tooltip to be rendered for the upcoming frame. This method should only be called\n    /// during the paint phase of element drawing.\n    pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {\n        self.invalidator.debug_assert_prepaint();\n        let id = TooltipId(post_inc(&mut self.next_tooltip_id.0));\n        self.next_frame\n            .tooltip_requests\n            .push(Some(TooltipRequest { id, tooltip }));\n        id\n    }\n\n    /// Invoke the given function with the given content mask after intersecting it\n    /// with the current mask. This method should only be called during element drawing.\n    pub fn with_content_mask<R>(\n        &mut self,\n        mask: Option<ContentMask<Pixels>>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        if let Some(mask) = mask {\n            let mask = mask.intersect(&self.content_mask());\n            self.content_mask_stack.push(mask);\n            let result = f(self);\n            self.content_mask_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Updates the global element offset relative to the current offset. This is used to implement\n    /// scrolling. This method should only be called during the prepaint phase of element drawing.\n    pub fn with_element_offset<R>(\n        &mut self,\n        offset: Point<Pixels>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_prepaint();\n\n        if offset.is_zero() {\n            return f(self);\n        };\n\n        let abs_offset = self.element_offset() + offset;\n        self.with_absolute_element_offset(abs_offset, f)\n    }\n\n    /// Updates the global element offset based on the given offset. This is used to implement\n    /// drag handles and other manual painting of elements. This method should only be called during\n    /// the prepaint phase of element drawing.\n    pub fn with_absolute_element_offset<R>(\n        &mut self,\n        offset: Point<Pixels>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_prepaint();\n        self.element_offset_stack.push(offset);\n        let result = f(self);\n        self.element_offset_stack.pop();\n        result\n    }\n\n    pub(crate) fn with_element_opacity<R>(\n        &mut self,\n        opacity: Option<f32>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        if opacity.is_none() {\n            return f(self);\n        }\n\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.element_opacity = opacity;\n        let result = f(self);\n        self.element_opacity = None;\n        result\n    }\n\n    /// Perform prepaint on child elements in a \"retryable\" manner, so that any side effects\n    /// of prepaints can be discarded before prepainting again. This is used to support autoscroll\n    /// where we need to prepaint children to detect the autoscroll bounds, then adjust the\n    /// element offset and prepaint again. See [`List`] for an example. This method should only be\n    /// called during the prepaint phase of element drawing.\n    pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {\n        self.invalidator.debug_assert_prepaint();\n        let index = self.prepaint_index();\n        let result = f(self);\n        if result.is_err() {\n            self.next_frame.hitboxes.truncate(index.hitboxes_index);\n            self.next_frame\n                .tooltip_requests\n                .truncate(index.tooltips_index);\n            self.next_frame\n                .deferred_draws\n                .truncate(index.deferred_draws_index);\n            self.next_frame\n                .dispatch_tree\n                .truncate(index.dispatch_tree_index);\n            self.next_frame\n                .accessed_element_states\n                .truncate(index.accessed_element_states_index);\n            self.text_system.truncate_layouts(index.line_layout_index);\n        }\n        result\n    }\n\n    /// When you call this method during [`prepaint`], containing elements will attempt to\n    /// scroll to cause the specified bounds to become visible. When they decide to autoscroll, they will call\n    /// [`prepaint`] again with a new set of bounds. See [`List`] for an example of an element\n    /// that supports this method being called on the elements it contains. This method should only be\n    /// called during the prepaint phase of element drawing.\n    pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {\n        self.invalidator.debug_assert_prepaint();\n        self.requested_autoscroll = Some(bounds);\n    }\n\n    /// This method can be called from a containing element such as [`List`] to support the autoscroll behavior\n    /// described in [`request_autoscroll`].\n    pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {\n        self.invalidator.debug_assert_prepaint();\n        self.requested_autoscroll.take()\n    }\n\n    /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.\n    /// Your view will be re-drawn once the asset has finished loading.\n    ///\n    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a\n    /// time.\n    pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {\n        let (task, is_first) = cx.fetch_asset::<A>(source);\n        task.clone().now_or_never().or_else(|| {\n            if is_first {\n                let entity_id = self.current_view();\n                self.spawn(cx, {\n                    let task = task.clone();\n                    async move |cx| {\n                        task.await;\n\n                        cx.on_next_frame(move |_, cx| {\n                            cx.notify(entity_id);\n                        });\n                    }\n                })\n                .detach();\n            }\n\n            None\n        })\n    }\n\n    /// Asynchronously load an asset, if the asset hasn't finished loading or doesn't exist this will return None.\n    /// Your view will not be re-drawn once the asset has finished loading.\n    ///\n    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a\n    /// time.\n    pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {\n        let (task, _) = cx.fetch_asset::<A>(source);\n        task.clone().now_or_never()\n    }\n    /// Obtain the current element offset. This method should only be called during the\n    /// prepaint phase of element drawing.\n    pub fn element_offset(&self) -> Point<Pixels> {\n        self.invalidator.debug_assert_prepaint();\n        self.element_offset_stack\n            .last()\n            .copied()\n            .unwrap_or_default()\n    }\n\n    /// Obtain the current element opacity. This method should only be called during the\n    /// prepaint phase of element drawing.\n    pub(crate) fn element_opacity(&self) -> f32 {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.element_opacity.unwrap_or(1.0)\n    }\n\n    /// Obtain the current content mask. This method should only be called during element drawing.\n    pub fn content_mask(&self) -> ContentMask<Pixels> {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.content_mask_stack\n            .last()\n            .cloned()\n            .unwrap_or_else(|| ContentMask {\n                bounds: Bounds {\n                    origin: Point::default(),\n                    size: self.viewport_size,\n                },\n            })\n    }\n\n    /// Provide elements in the called function with a new namespace in which their identifiers must be unique.\n    /// This can be used within a custom element to distinguish multiple sets of child elements.\n    pub fn with_element_namespace<R>(\n        &mut self,\n        element_id: impl Into<ElementId>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.element_id_stack.push(element_id.into());\n        let result = f(self);\n        self.element_id_stack.pop();\n        result\n    }\n\n    /// Updates or initializes state for an element with the given id that lives across multiple\n    /// frames. If an element with this ID existed in the rendered frame, its state will be passed\n    /// to the given closure. The state returned by the closure will be stored so it can be referenced\n    /// when drawing the next frame. This method should only be called as part of element drawing.\n    pub fn with_element_state<S, R>(\n        &mut self,\n        global_id: &GlobalElementId,\n        f: impl FnOnce(Option<S>, &mut Self) -> (R, S),\n    ) -> R\n    where\n        S: 'static,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        let key = (GlobalElementId(global_id.0.clone()), TypeId::of::<S>());\n        self.next_frame\n            .accessed_element_states\n            .push((GlobalElementId(key.0.clone()), TypeId::of::<S>()));\n\n        if let Some(any) = self\n            .next_frame\n            .element_states\n            .remove(&key)\n            .or_else(|| self.rendered_frame.element_states.remove(&key))\n        {\n            let ElementStateBox {\n                inner,\n                #[cfg(debug_assertions)]\n                type_name,\n            } = any;\n            // Using the extra inner option to avoid needing to reallocate a new box.\n            let mut state_box = inner\n                .downcast::<Option<S>>()\n                .map_err(|_| {\n                    #[cfg(debug_assertions)]\n                    {\n                        anyhow::anyhow!(\n                            \"invalid element state type for id, requested {:?}, actual: {:?}\",\n                            std::any::type_name::<S>(),\n                            type_name\n                        )\n                    }\n\n                    #[cfg(not(debug_assertions))]\n                    {\n                        anyhow::anyhow!(\n                            \"invalid element state type for id, requested {:?}\",\n                            std::any::type_name::<S>(),\n                        )\n                    }\n                })\n                .unwrap();\n\n            let state = state_box.take().expect(\n                \"reentrant call to with_element_state for the same state type and element id\",\n            );\n            let (result, state) = f(Some(state), self);\n            state_box.replace(state);\n            self.next_frame.element_states.insert(\n                key,\n                ElementStateBox {\n                    inner: state_box,\n                    #[cfg(debug_assertions)]\n                    type_name,\n                },\n            );\n            result\n        } else {\n            let (result, state) = f(None, self);\n            self.next_frame.element_states.insert(\n                key,\n                ElementStateBox {\n                    inner: Box::new(Some(state)),\n                    #[cfg(debug_assertions)]\n                    type_name: std::any::type_name::<S>(),\n                },\n            );\n            result\n        }\n    }\n\n    /// A variant of `with_element_state` that allows the element's id to be optional. This is a convenience\n    /// method for elements where the element id may or may not be assigned. Prefer using `with_element_state`\n    /// when the element is guaranteed to have an id.\n    ///\n    /// The first option means 'no ID provided'\n    /// The second option means 'not yet initialized'\n    pub fn with_optional_element_state<S, R>(\n        &mut self,\n        global_id: Option<&GlobalElementId>,\n        f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),\n    ) -> R\n    where\n        S: 'static,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        if let Some(global_id) = global_id {\n            self.with_element_state(global_id, |state, cx| {\n                let (result, state) = f(Some(state), cx);\n                let state =\n                    state.expect(\"you must return some state when you pass some element id\");\n                (result, state)\n            })\n        } else {\n            let (result, state) = f(None, self);\n            debug_assert!(\n                state.is_none(),\n                \"you must not return an element state when passing None for the global id\"\n            );\n            result\n        }\n    }\n\n    /// Defers the drawing of the given element, scheduling it to be painted on top of the currently-drawn tree\n    /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements,\n    /// with higher values being drawn on top.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn defer_draw(\n        &mut self,\n        element: AnyElement,\n        absolute_offset: Point<Pixels>,\n        priority: usize,\n    ) {\n        self.invalidator.debug_assert_prepaint();\n        let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();\n        self.next_frame.deferred_draws.push(DeferredDraw {\n            current_view: self.current_view(),\n            parent_node,\n            element_id_stack: self.element_id_stack.clone(),\n            text_style_stack: self.text_style_stack.clone(),\n            priority,\n            element: Some(element),\n            absolute_offset,\n            prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),\n            paint_range: PaintIndex::default()..PaintIndex::default(),\n        });\n    }\n\n    /// Creates a new painting layer for the specified bounds. A \"layer\" is a batch\n    /// of geometry that are non-overlapping and have the same draw order. This is typically used\n    /// for performance reasons.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let clipped_bounds = bounds.intersect(&content_mask.bounds);\n        if !clipped_bounds.is_empty() {\n            self.next_frame\n                .scene\n                .push_layer(clipped_bounds.scale(scale_factor));\n        }\n\n        let result = f(self);\n\n        if !clipped_bounds.is_empty() {\n            self.next_frame.scene.pop_layer();\n        }\n\n        result\n    }\n\n    /// Paint one or more drop shadows into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_shadows(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        corner_radii: Corners<Pixels>,\n        shadows: &[BoxShadow],\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        for shadow in shadows {\n            let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius);\n            self.next_frame.scene.insert_primitive(Shadow {\n                order: 0,\n                blur_radius: shadow.blur_radius.scale(scale_factor),\n                bounds: shadow_bounds.scale(scale_factor),\n                content_mask: content_mask.scale(scale_factor),\n                corner_radii: corner_radii.scale(scale_factor),\n                color: shadow.color.opacity(opacity),\n            });\n        }\n    }\n\n    /// Paint one or more quads into the scene for the next frame at the current stacking context.\n    /// Quads are colored rectangular regions with an optional background, border, and corner radius.\n    /// see [`fill`](crate::fill), [`outline`](crate::outline), and [`quad`](crate::quad) to construct this type.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    ///\n    /// Note that the `quad.corner_radii` are allowed to exceed the bounds, creating sharp corners\n    /// where the circular arcs meet. This will not display well when combined with dashed borders.\n    /// Use `Corners::clamp_radii_for_quad_size` if the radii should fit within the bounds.\n    pub fn paint_quad(&mut self, quad: PaintQuad) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        self.next_frame.scene.insert_primitive(Quad {\n            order: 0,\n            bounds: quad.bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            background: quad.background.opacity(opacity),\n            border_color: quad.border_color.opacity(opacity),\n            corner_radii: quad.corner_radii.scale(scale_factor),\n            border_widths: quad.border_widths.scale(scale_factor),\n            border_style: quad.border_style,\n            transformation: quad.transformation,\n        });\n    }\n\n    /// Paint the given `Path` into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        path.content_mask = content_mask;\n        let color: Background = color.into();\n        path.color = color.opacity(opacity);\n        self.next_frame\n            .scene\n            .insert_primitive(path.scale(scale_factor));\n    }\n\n    /// Paint an underline into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_underline(\n        &mut self,\n        origin: Point<Pixels>,\n        width: Pixels,\n        style: &UnderlineStyle,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let height = if style.wavy {\n            style.thickness * 3.\n        } else {\n            style.thickness\n        };\n        let bounds = Bounds {\n            origin,\n            size: size(width, height),\n        };\n        let content_mask = self.content_mask();\n        let element_opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(Underline {\n            order: 0,\n            pad: 0,\n            bounds: bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            color: style.color.unwrap_or_default().opacity(element_opacity),\n            thickness: style.thickness.scale(scale_factor),\n            wavy: style.wavy,\n        });\n    }\n\n    /// Paint a strikethrough into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_strikethrough(\n        &mut self,\n        origin: Point<Pixels>,\n        width: Pixels,\n        style: &StrikethroughStyle,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let height = style.thickness;\n        let bounds = Bounds {\n            origin,\n            size: size(width, height),\n        };\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(Underline {\n            order: 0,\n            pad: 0,\n            bounds: bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            thickness: style.thickness.scale(scale_factor),\n            color: style.color.unwrap_or_default().opacity(opacity),\n            wavy: false,\n        });\n    }\n\n    /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.\n    ///\n    /// The y component of the origin is the baseline of the glyph.\n    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or\n    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).\n    /// This method is only useful if you need to paint a single glyph that has already been shaped.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_glyph(\n        &mut self,\n        origin: Point<Pixels>,\n        font_id: FontId,\n        glyph_id: GlyphId,\n        font_size: Pixels,\n        color: Hsla,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let element_opacity = self.element_opacity();\n        let scale_factor = self.scale_factor();\n        let glyph_origin = origin.scale(scale_factor);\n        let subpixel_variant = Point {\n            x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,\n            y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,\n        };\n        let params = RenderGlyphParams {\n            font_id,\n            glyph_id,\n            font_size,\n            subpixel_variant,\n            scale_factor,\n            is_emoji: false,\n        };\n\n        let raster_bounds = self.text_system().raster_bounds(&params)?;\n        if !raster_bounds.is_zero() {\n            let tile = self\n                .sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;\n                    Ok(Some((size, Cow::Owned(bytes))))\n                })?\n                .expect(\"Callback above only errors or returns Some\");\n            let bounds = Bounds {\n                origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),\n                size: tile.bounds.size.map(Into::into),\n            };\n            let content_mask = self.content_mask().scale(scale_factor);\n            self.next_frame.scene.insert_primitive(MonochromeSprite {\n                order: 0,\n                pad: 0,\n                bounds,\n                content_mask,\n                color: color.opacity(element_opacity),\n                tile,\n                transformation: TransformationMatrix::unit(),\n            });\n        }\n        Ok(())\n    }\n\n    /// Paints an emoji glyph into the scene for the next frame at the current z-index.\n    ///\n    /// The y component of the origin is the baseline of the glyph.\n    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or\n    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).\n    /// This method is only useful if you need to paint a single emoji that has already been shaped.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_emoji(\n        &mut self,\n        origin: Point<Pixels>,\n        font_id: FontId,\n        glyph_id: GlyphId,\n        font_size: Pixels,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let glyph_origin = origin.scale(scale_factor);\n        let params = RenderGlyphParams {\n            font_id,\n            glyph_id,\n            font_size,\n            // We don't render emojis with subpixel variants.\n            subpixel_variant: Default::default(),\n            scale_factor,\n            is_emoji: true,\n        };\n\n        let raster_bounds = self.text_system().raster_bounds(&params)?;\n        if !raster_bounds.is_zero() {\n            let tile = self\n                .sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;\n                    Ok(Some((size, Cow::Owned(bytes))))\n                })?\n                .expect(\"Callback above only errors or returns Some\");\n\n            let bounds = Bounds {\n                origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),\n                size: tile.bounds.size.map(Into::into),\n            };\n            let content_mask = self.content_mask().scale(scale_factor);\n            let opacity = self.element_opacity();\n\n            self.next_frame.scene.insert_primitive(PolychromeSprite {\n                order: 0,\n                pad: 0,\n                grayscale: false,\n                bounds,\n                corner_radii: Default::default(),\n                content_mask,\n                tile,\n                opacity,\n            });\n        }\n        Ok(())\n    }\n\n    /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_svg(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        path: SharedString,\n        transformation: TransformationMatrix,\n        color: Hsla,\n        cx: &App,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let element_opacity = self.element_opacity();\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let params = RenderSvgParams {\n            path,\n            size: bounds.size.map(|pixels| {\n                DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)\n            }),\n        };\n\n        let Some(tile) =\n            self.sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let Some(bytes) = cx.svg_renderer.render(&params)? else {\n                        return Ok(None);\n                    };\n                    Ok(Some((params.size, Cow::Owned(bytes))))\n                })?\n        else {\n            return Ok(());\n        };\n        let content_mask = self.content_mask().scale(scale_factor);\n\n        self.next_frame.scene.insert_primitive(MonochromeSprite {\n            order: 0,\n            pad: 0,\n            bounds: bounds\n                .map_origin(|origin| origin.floor())\n                .map_size(|size| size.ceil()),\n            content_mask,\n            color: color.opacity(element_opacity),\n            tile,\n            transformation,\n        });\n\n        Ok(())\n    }\n\n    /// Paint an image into the scene for the next frame at the current z-index.\n    /// This method will panic if the frame_index is not valid\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_image(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        corner_radii: Corners<Pixels>,\n        data: Arc<RenderImage>,\n        frame_index: usize,\n        grayscale: bool,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let params = RenderImageParams {\n            image_id: data.id,\n            frame_index,\n        };\n\n        let tile = self\n            .sprite_atlas\n            .get_or_insert_with(&params.clone().into(), &mut || {\n                Ok(Some((\n                    data.size(frame_index),\n                    Cow::Borrowed(\n                        data.as_bytes(frame_index)\n                            .expect(\"It's the caller's job to pass a valid frame index\"),\n                    ),\n                )))\n            })?\n            .expect(\"Callback above only returns Some\");\n        let content_mask = self.content_mask().scale(scale_factor);\n        let corner_radii = corner_radii.scale(scale_factor);\n        let opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(PolychromeSprite {\n            order: 0,\n            pad: 0,\n            grayscale,\n            bounds: bounds\n                .map_origin(|origin| origin.floor())\n                .map_size(|size| size.ceil()),\n            content_mask,\n            corner_radii,\n            tile,\n            opacity,\n        });\n        Ok(())\n    }\n\n    /// Paint a surface into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    #[cfg(target_os = \"macos\")]\n    pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVPixelBuffer) {\n        use crate::PaintSurface;\n\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let content_mask = self.content_mask().scale(scale_factor);\n        self.next_frame.scene.insert_primitive(PaintSurface {\n            order: 0,\n            bounds,\n            content_mask,\n            image_buffer,\n        });\n    }\n\n    /// Removes an image from the sprite atlas.\n    pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {\n        for frame_index in 0..data.frame_count() {\n            let params = RenderImageParams {\n                image_id: data.id,\n                frame_index,\n            };\n\n            self.sprite_atlas.remove(&params.clone().into());\n        }\n\n        Ok(())\n    }\n\n    /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which\n    /// layout is being requested, along with the layout ids of any children. This method is called during\n    /// calls to the [`Element::request_layout`] trait method and enables any element to participate in layout.\n    ///\n    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.\n    #[must_use]\n    pub fn request_layout(\n        &mut self,\n        style: Style,\n        children: impl IntoIterator<Item = LayoutId>,\n        cx: &mut App,\n    ) -> LayoutId {\n        self.invalidator.debug_assert_prepaint();\n\n        cx.layout_id_buffer.clear();\n        cx.layout_id_buffer.extend(children);\n        let rem_size = self.rem_size();\n\n        self.layout_engine\n            .as_mut()\n            .unwrap()\n            .request_layout(style, rem_size, &cx.layout_id_buffer)\n    }\n\n    /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,\n    /// this variant takes a function that is invoked during layout so you can use arbitrary logic to\n    /// determine the element's size. One place this is used internally is when measuring text.\n    ///\n    /// The given closure is invoked at layout time with the known dimensions and available space and\n    /// returns a `Size`.\n    ///\n    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.\n    pub fn request_measured_layout<\n        F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>\n            + 'static,\n    >(\n        &mut self,\n        style: Style,\n        measure: F,\n    ) -> LayoutId {\n        self.invalidator.debug_assert_prepaint();\n\n        let rem_size = self.rem_size();\n        self.layout_engine\n            .as_mut()\n            .unwrap()\n            .request_measured_layout(style, rem_size, measure)\n    }\n\n    /// Compute the layout for the given id within the given available space.\n    /// This method is called for its side effect, typically by the framework prior to painting.\n    /// After calling it, you can request the bounds of the given layout node id or any descendant.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn compute_layout(\n        &mut self,\n        layout_id: LayoutId,\n        available_space: Size<AvailableSpace>,\n        cx: &mut App,\n    ) {\n        self.invalidator.debug_assert_prepaint();\n\n        let mut layout_engine = self.layout_engine.take().unwrap();\n        layout_engine.compute_layout(layout_id, available_space, self, cx);\n        self.layout_engine = Some(layout_engine);\n    }\n\n    /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by\n    /// GPUI itself automatically in order to pass your element its `Bounds` automatically.\n    ///\n    /// This method should only be called as part of element drawing.\n    pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {\n        self.invalidator.debug_assert_prepaint();\n\n        let mut bounds = self\n            .layout_engine\n            .as_mut()\n            .unwrap()\n            .layout_bounds(layout_id)\n            .map(Into::into);\n        bounds.origin += self.element_offset();\n        bounds\n    }\n\n    /// This method should be called during `prepaint`. You can use\n    /// the returned [Hitbox] during `paint` or in an event handler\n    /// to determine whether the inserted hitbox was the topmost.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, opaque: bool) -> Hitbox {\n        self.invalidator.debug_assert_prepaint();\n\n        let content_mask = self.content_mask();\n        let id = self.next_hitbox_id;\n        self.next_hitbox_id.0 += 1;\n        let hitbox = Hitbox {\n            id,\n            bounds,\n            content_mask,\n            opaque,\n        };\n        self.next_frame.hitboxes.push(hitbox.clone());\n        hitbox\n    }\n\n    /// Sets the key context for the current element. This context will be used to translate\n    /// keybindings into actions.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn set_key_context(&mut self, context: KeyContext) {\n        self.invalidator.debug_assert_paint();\n        self.next_frame.dispatch_tree.set_key_context(context);\n    }\n\n    /// Sets the focus handle for the current element. This handle will be used to manage focus state\n    /// and keyboard event dispatch for the element.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {\n        self.invalidator.debug_assert_prepaint();\n        if focus_handle.is_focused(self) {\n            self.next_frame.focus = Some(focus_handle.id);\n        }\n        self.next_frame.dispatch_tree.set_focus_id(focus_handle.id);\n    }\n\n    /// Sets the view id for the current element, which will be used to manage view caching.\n    ///\n    /// This method should only be called as part of element prepaint. We plan on removing this\n    /// method eventually when we solve some issues that require us to construct editor elements\n    /// directly instead of always using editors via views.\n    pub fn set_view_id(&mut self, view_id: EntityId) {\n        self.invalidator.debug_assert_prepaint();\n        self.next_frame.dispatch_tree.set_view_id(view_id);\n    }\n\n    /// Get the entity ID for the currently rendering view\n    pub fn current_view(&self) -> EntityId {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.rendered_entity_stack.last().copied().unwrap()\n    }\n\n    pub(crate) fn with_rendered_view<R>(\n        &mut self,\n        id: EntityId,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.rendered_entity_stack.push(id);\n        let result = f(self);\n        self.rendered_entity_stack.pop();\n        result\n    }\n\n    /// Executes the provided function with the specified image cache.\n    pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        if let Some(image_cache) = image_cache {\n            self.image_cache_stack.push(image_cache);\n            let result = f(self);\n            self.image_cache_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the\n    /// platform to receive textual input with proper integration with concerns such\n    /// as IME interactions. This handler will be active for the upcoming frame until the following frame is\n    /// rendered.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    ///\n    /// [element_input_handler]: crate::ElementInputHandler\n    pub fn handle_input(\n        &mut self,\n        focus_handle: &FocusHandle,\n        input_handler: impl InputHandler,\n        cx: &App,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        if focus_handle.is_focused(self) {\n            let cx = self.to_async(cx);\n            self.next_frame\n                .input_handlers\n                .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));\n        }\n    }\n\n    /// Register a mouse event listener on the window for the next frame. The type of event\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_mouse_event<Event: MouseEvent>(\n        &mut self,\n        mut handler: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.mouse_listeners.push(Some(Box::new(\n            move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {\n                if let Some(event) = event.downcast_ref() {\n                    handler(event, phase, window, cx)\n                }\n            },\n        )));\n    }\n\n    /// Register a key event listener on the window for the next frame. The type of event\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have\n    /// a specific need to register a global listener.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_key_event<Event: KeyEvent>(\n        &mut self,\n        listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.dispatch_tree.on_key_event(Rc::new(\n            move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {\n                if let Some(event) = event.downcast_ref::<Event>() {\n                    listener(event, phase, window, cx)\n                }\n            },\n        ));\n    }\n\n    /// Register a modifiers changed event listener on the window for the next frame.\n    ///\n    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have\n    /// a specific need to register a global listener.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_modifiers_changed(\n        &mut self,\n        listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new(\n            move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {\n                listener(event, window, cx)\n            },\n        ));\n    }\n\n    /// Register a listener to be called when the given focus handle or one of its descendants receives focus.\n    /// This does not fire if the given focus handle - or one of its descendants - was previously focused.\n    /// Returns a subscription and persists until the subscription is dropped.\n    pub fn on_focus_in(\n        &mut self,\n        handle: &FocusHandle,\n        cx: &mut App,\n        mut listener: impl FnMut(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let focus_id = handle.id;\n        let (subscription, activate) =\n            self.new_focus_listener(Box::new(move |event, window, cx| {\n                if event.is_focus_in(focus_id) {\n                    listener(window, cx);\n                }\n                true\n            }));\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    /// Register a listener to be called when the given focus handle or one of its descendants loses focus.\n    /// Returns a subscription and persists until the subscription is dropped.\n    pub fn on_focus_out(\n        &mut self,\n        handle: &FocusHandle,\n        cx: &mut App,\n        mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let focus_id = handle.id;\n        let (subscription, activate) =\n            self.new_focus_listener(Box::new(move |event, window, cx| {\n                if let Some(blurred_id) = event.previous_focus_path.last().copied() {\n                    if event.is_focus_out(focus_id) {\n                        let event = FocusOutEvent {\n                            blurred: WeakFocusHandle {\n                                id: blurred_id,\n                                handles: Arc::downgrade(&cx.focus_handles),\n                            },\n                        };\n                        listener(event, window, cx)\n                    }\n                }\n                true\n            }));\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    fn reset_cursor_style(&self, cx: &mut App) {\n        // Set the cursor only if we're the active window.\n        if self.is_window_hovered() {\n            let style = self\n                .rendered_frame\n                .cursor_styles\n                .iter()\n                .rev()\n                .find(|request| {\n                    request\n                        .hitbox_id\n                        .map_or(true, |hitbox_id| hitbox_id.is_hovered(self))\n                })\n                .map(|request| request.style)\n                .unwrap_or(CursorStyle::Arrow);\n            cx.platform.set_cursor_style(style);\n        }\n    }\n\n    /// Dispatch a given keystroke as though the user had typed it.\n    /// You can create a keystroke with Keystroke::parse(\"\").\n    pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {\n        let keystroke = keystroke.with_simulated_ime();\n        let result = self.dispatch_event(\n            PlatformInput::KeyDown(KeyDownEvent {\n                keystroke: keystroke.clone(),\n                is_held: false,\n            }),\n            cx,\n        );\n        if !result.propagate {\n            return true;\n        }\n\n        if let Some(input) = keystroke.key_char {\n            if let Some(mut input_handler) = self.platform_window.take_input_handler() {\n                input_handler.dispatch_input(&input, self, cx);\n                self.platform_window.set_input_handler(input_handler);\n                return true;\n            }\n        }\n\n        false\n    }\n\n    /// Return a key binding string for an action, to display in the UI. Uses the highest precedence\n    /// binding for the action (last binding added to the keymap).\n    pub fn keystroke_text_for(&self, action: &dyn Action) -> String {\n        self.bindings_for_action(action)\n            .last()\n            .map(|binding| {\n                binding\n                    .keystrokes()\n                    .iter()\n                    .map(ToString::to_string)\n                    .collect::<Vec<_>>()\n                    .join(\" \")\n            })\n            .unwrap_or_else(|| action.name().to_string())\n    }\n\n    /// Dispatch a mouse or keyboard event on the window.\n    #[profiling::function]\n    pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {\n        self.last_input_timestamp.set(Instant::now());\n        // Handlers may set this to false by calling `stop_propagation`.\n        cx.propagate_event = true;\n        // Handlers may set this to true by calling `prevent_default`.\n        self.default_prevented = false;\n\n        let event = match event {\n            // Track the mouse position with our own state, since accessing the platform\n            // API for the mouse position can only occur on the main thread.\n            PlatformInput::MouseMove(mouse_move) => {\n                self.mouse_position = mouse_move.position;\n                self.modifiers = mouse_move.modifiers;\n                PlatformInput::MouseMove(mouse_move)\n            }\n            PlatformInput::MouseDown(mouse_down) => {\n                self.mouse_position = mouse_down.position;\n                self.modifiers = mouse_down.modifiers;\n                PlatformInput::MouseDown(mouse_down)\n            }\n            PlatformInput::MouseUp(mouse_up) => {\n                self.mouse_position = mouse_up.position;\n                self.modifiers = mouse_up.modifiers;\n                PlatformInput::MouseUp(mouse_up)\n            }\n            PlatformInput::MouseExited(mouse_exited) => {\n                self.modifiers = mouse_exited.modifiers;\n                PlatformInput::MouseExited(mouse_exited)\n            }\n            PlatformInput::ModifiersChanged(modifiers_changed) => {\n                self.modifiers = modifiers_changed.modifiers;\n                PlatformInput::ModifiersChanged(modifiers_changed)\n            }\n            PlatformInput::ScrollWheel(scroll_wheel) => {\n                self.mouse_position = scroll_wheel.position;\n                self.modifiers = scroll_wheel.modifiers;\n                PlatformInput::ScrollWheel(scroll_wheel)\n            }\n            // Translate dragging and dropping of external files from the operating system\n            // to internal drag and drop events.\n            PlatformInput::FileDrop(file_drop) => match file_drop {\n                FileDropEvent::Entered { position, paths } => {\n                    self.mouse_position = position;\n                    if cx.active_drag.is_none() {\n                        cx.active_drag = Some(AnyDrag {\n                            value: Arc::new(paths.clone()),\n                            view: cx.new(|_| paths).into(),\n                            cursor_offset: position,\n                            cursor_style: None,\n                        });\n                    }\n                    PlatformInput::MouseMove(MouseMoveEvent {\n                        position,\n                        pressed_button: Some(MouseButton::Left),\n                        modifiers: Modifiers::default(),\n                    })\n                }\n                FileDropEvent::Pending { position } => {\n                    self.mouse_position = position;\n                    PlatformInput::MouseMove(MouseMoveEvent {\n                        position,\n                        pressed_button: Some(MouseButton::Left),\n                        modifiers: Modifiers::default(),\n                    })\n                }\n                FileDropEvent::Submit { position } => {\n                    cx.activate(true);\n                    self.mouse_position = position;\n                    PlatformInput::MouseUp(MouseUpEvent {\n                        button: MouseButton::Left,\n                        position,\n                        modifiers: Modifiers::default(),\n                        click_count: 1,\n                    })\n                }\n                FileDropEvent::Exited => {\n                    cx.active_drag.take();\n                    PlatformInput::FileDrop(FileDropEvent::Exited)\n                }\n            },\n            PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,\n        };\n\n        if let Some(any_mouse_event) = event.mouse_event() {\n            self.dispatch_mouse_event(any_mouse_event, cx);\n        } else if let Some(any_key_event) = event.keyboard_event() {\n            self.dispatch_key_event(any_key_event, cx);\n        }\n\n        DispatchEventResult {\n            propagate: cx.propagate_event,\n            default_prevented: self.default_prevented,\n        }\n    }\n\n    fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {\n        let hit_test = self.rendered_frame.hit_test(self.mouse_position());\n        if hit_test != self.mouse_hit_test {\n            self.mouse_hit_test = hit_test;\n            self.reset_cursor_style(cx);\n        }\n\n        let mut mouse_listeners = mem::take(&mut self.rendered_frame.mouse_listeners);\n\n        // Capture phase, events bubble from back to front. Handlers for this phase are used for\n        // special purposes, such as detecting events outside of a given Bounds.\n        for listener in &mut mouse_listeners {\n            let listener = listener.as_mut().unwrap();\n            listener(event, DispatchPhase::Capture, self, cx);\n            if !cx.propagate_event {\n                break;\n            }\n        }\n\n        // Bubble phase, where most normal handlers do their work.\n        if cx.propagate_event {\n            for listener in mouse_listeners.iter_mut().rev() {\n                let listener = listener.as_mut().unwrap();\n                listener(event, DispatchPhase::Bubble, self, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n        }\n\n        self.rendered_frame.mouse_listeners = mouse_listeners;\n\n        if cx.has_active_drag() {\n            if event.is::<MouseMoveEvent>() {\n                // If this was a mouse move event, redraw the window so that the\n                // active drag can follow the mouse cursor.\n                self.refresh();\n            } else if event.is::<MouseUpEvent>() {\n                // If this was a mouse up event, cancel the active drag and redraw\n                // the window.\n                cx.active_drag = None;\n                self.refresh();\n            }\n        }\n    }\n\n    fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) {\n        if self.invalidator.is_dirty() {\n            self.draw(cx);\n        }\n\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        let mut keystroke: Option<Keystroke> = None;\n\n        if let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() {\n            if event.modifiers.number_of_modifiers() == 0\n                && self.pending_modifier.modifiers.number_of_modifiers() == 1\n                && !self.pending_modifier.saw_keystroke\n            {\n                let key = match self.pending_modifier.modifiers {\n                    modifiers if modifiers.shift => Some(\"shift\"),\n                    modifiers if modifiers.control => Some(\"control\"),\n                    modifiers if modifiers.alt => Some(\"alt\"),\n                    modifiers if modifiers.platform => Some(\"platform\"),\n                    modifiers if modifiers.function => Some(\"function\"),\n                    _ => None,\n                };\n                if let Some(key) = key {\n                    keystroke = Some(Keystroke {\n                        key: key.to_string(),\n                        key_char: None,\n                        modifiers: Modifiers::default(),\n                    });\n                }\n            }\n\n            if self.pending_modifier.modifiers.number_of_modifiers() == 0\n                && event.modifiers.number_of_modifiers() == 1\n            {\n                self.pending_modifier.saw_keystroke = false\n            }\n            self.pending_modifier.modifiers = event.modifiers\n        } else if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {\n            self.pending_modifier.saw_keystroke = true;\n            keystroke = Some(key_down_event.keystroke.clone());\n        }\n\n        let Some(keystroke) = keystroke else {\n            self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);\n            return;\n        };\n\n        let mut currently_pending = self.pending_input.take().unwrap_or_default();\n        if currently_pending.focus.is_some() && currently_pending.focus != self.focus {\n            currently_pending = PendingInput::default();\n        }\n\n        let match_result = self.rendered_frame.dispatch_tree.dispatch_key(\n            currently_pending.keystrokes,\n            keystroke,\n            &dispatch_path,\n        );\n\n        if !match_result.to_replay.is_empty() {\n            self.replay_pending_input(match_result.to_replay, cx)\n        }\n\n        if !match_result.pending.is_empty() {\n            currently_pending.keystrokes = match_result.pending;\n            currently_pending.focus = self.focus;\n            currently_pending.timer = Some(self.spawn(cx, async move |cx| {\n                cx.background_executor.timer(Duration::from_secs(1)).await;\n                cx.update(move |window, cx| {\n                    let Some(currently_pending) = window\n                        .pending_input\n                        .take()\n                        .filter(|pending| pending.focus == window.focus)\n                    else {\n                        return;\n                    };\n\n                    let dispatch_path = window.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n                    let to_replay = window\n                        .rendered_frame\n                        .dispatch_tree\n                        .flush_dispatch(currently_pending.keystrokes, &dispatch_path);\n\n                    window.replay_pending_input(to_replay, cx)\n                })\n                .log_err();\n            }));\n            self.pending_input = Some(currently_pending);\n            self.pending_input_changed(cx);\n            cx.propagate_event = false;\n            return;\n        }\n\n        cx.propagate_event = true;\n        for binding in match_result.bindings {\n            self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);\n            if !cx.propagate_event {\n                self.dispatch_keystroke_observers(\n                    event,\n                    Some(binding.action),\n                    match_result.context_stack.clone(),\n                    cx,\n                );\n                self.pending_input_changed(cx);\n                return;\n            }\n        }\n\n        self.finish_dispatch_key_event(event, dispatch_path, match_result.context_stack, cx);\n        self.pending_input_changed(cx);\n    }\n\n    fn finish_dispatch_key_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: SmallVec<[DispatchNodeId; 32]>,\n        context_stack: Vec<KeyContext>,\n        cx: &mut App,\n    ) {\n        self.dispatch_key_down_up_event(event, &dispatch_path, cx);\n        if !cx.propagate_event {\n            return;\n        }\n\n        self.dispatch_modifiers_changed_event(event, &dispatch_path, cx);\n        if !cx.propagate_event {\n            return;\n        }\n\n        self.dispatch_keystroke_observers(event, None, context_stack, cx);\n    }\n\n    fn pending_input_changed(&mut self, cx: &mut App) {\n        self.pending_input_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    fn dispatch_key_down_up_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,\n        cx: &mut App,\n    ) {\n        // Capture phase\n        for node_id in dispatch_path {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n\n            for key_listener in node.key_listeners.clone() {\n                key_listener(event, DispatchPhase::Capture, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n\n        // Bubble phase\n        for node_id in dispatch_path.iter().rev() {\n            // Handle low level key events\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for key_listener in node.key_listeners.clone() {\n                key_listener(event, DispatchPhase::Bubble, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n    }\n\n    fn dispatch_modifiers_changed_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,\n        cx: &mut App,\n    ) {\n        let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() else {\n            return;\n        };\n        for node_id in dispatch_path.iter().rev() {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for listener in node.modifiers_changed_listeners.clone() {\n                listener(event, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n    }\n\n    /// Determine whether a potential multi-stroke key binding is in progress on this window.\n    pub fn has_pending_keystrokes(&self) -> bool {\n        self.pending_input.is_some()\n    }\n\n    pub(crate) fn clear_pending_keystrokes(&mut self) {\n        self.pending_input.take();\n    }\n\n    /// Returns the currently pending input keystrokes that might result in a multi-stroke key binding.\n    pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> {\n        self.pending_input\n            .as_ref()\n            .map(|pending_input| pending_input.keystrokes.as_slice())\n    }\n\n    fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) {\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        'replay: for replay in replays {\n            let event = KeyDownEvent {\n                keystroke: replay.keystroke.clone(),\n                is_held: false,\n            };\n\n            cx.propagate_event = true;\n            for binding in replay.bindings {\n                self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);\n                if !cx.propagate_event {\n                    self.dispatch_keystroke_observers(\n                        &event,\n                        Some(binding.action),\n                        Vec::default(),\n                        cx,\n                    );\n                    continue 'replay;\n                }\n            }\n\n            self.dispatch_key_down_up_event(&event, &dispatch_path, cx);\n            if !cx.propagate_event {\n                continue 'replay;\n            }\n            if let Some(input) = replay.keystroke.key_char.as_ref().cloned() {\n                if let Some(mut input_handler) = self.platform_window.take_input_handler() {\n                    input_handler.dispatch_input(&input, self, cx);\n                    self.platform_window.set_input_handler(input_handler)\n                }\n            }\n        }\n    }\n\n    fn dispatch_action_on_node(\n        &mut self,\n        node_id: DispatchNodeId,\n        action: &dyn Action,\n        cx: &mut App,\n    ) {\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        // Capture phase for global actions.\n        cx.propagate_event = true;\n        if let Some(mut global_listeners) = cx\n            .global_action_listeners\n            .remove(&action.as_any().type_id())\n        {\n            for listener in &global_listeners {\n                listener(action.as_any(), DispatchPhase::Capture, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n\n            global_listeners.extend(\n                cx.global_action_listeners\n                    .remove(&action.as_any().type_id())\n                    .unwrap_or_default(),\n            );\n\n            cx.global_action_listeners\n                .insert(action.as_any().type_id(), global_listeners);\n        }\n\n        if !cx.propagate_event {\n            return;\n        }\n\n        // Capture phase for window actions.\n        for node_id in &dispatch_path {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for DispatchActionListener {\n                action_type,\n                listener,\n            } in node.action_listeners.clone()\n            {\n                let any_action = action.as_any();\n                if action_type == any_action.type_id() {\n                    listener(any_action, DispatchPhase::Capture, self, cx);\n\n                    if !cx.propagate_event {\n                        return;\n                    }\n                }\n            }\n        }\n\n        // Bubble phase for window actions.\n        for node_id in dispatch_path.iter().rev() {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for DispatchActionListener {\n                action_type,\n                listener,\n            } in node.action_listeners.clone()\n            {\n                let any_action = action.as_any();\n                if action_type == any_action.type_id() {\n                    cx.propagate_event = false; // Actions stop propagation by default during the bubble phase\n                    listener(any_action, DispatchPhase::Bubble, self, cx);\n\n                    if !cx.propagate_event {\n                        return;\n                    }\n                }\n            }\n        }\n\n        // Bubble phase for global actions.\n        if let Some(mut global_listeners) = cx\n            .global_action_listeners\n            .remove(&action.as_any().type_id())\n        {\n            for listener in global_listeners.iter().rev() {\n                cx.propagate_event = false; // Actions stop propagation by default during the bubble phase\n\n                listener(action.as_any(), DispatchPhase::Bubble, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n\n            global_listeners.extend(\n                cx.global_action_listeners\n                    .remove(&action.as_any().type_id())\n                    .unwrap_or_default(),\n            );\n\n            cx.global_action_listeners\n                .insert(action.as_any().type_id(), global_listeners);\n        }\n    }\n\n    /// Register the given handler to be invoked whenever the global of the given type\n    /// is updated.\n    pub fn observe_global<G: Global>(\n        &mut self,\n        cx: &mut App,\n        f: impl Fn(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let window_handle = self.handle;\n        let (subscription, activate) = cx.global_observers.insert(\n            TypeId::of::<G>(),\n            Box::new(move |cx| {\n                window_handle\n                    .update(cx, |_, window, cx| f(window, cx))\n                    .is_ok()\n            }),\n        );\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    /// Focus the current window and bring it to the foreground at the platform level.\n    pub fn activate_window(&self) {\n        self.platform_window.activate();\n    }\n\n    /// Minimize the current window at the platform level.\n    pub fn minimize_window(&self) {\n        self.platform_window.minimize();\n    }\n\n    /// Toggle full screen status on the current window at the platform level.\n    pub fn toggle_fullscreen(&self) {\n        self.platform_window.toggle_fullscreen();\n    }\n\n    /// Updates the IME panel position suggestions for languages like japanese, chinese.\n    pub fn invalidate_character_coordinates(&self) {\n        self.on_next_frame(|window, cx| {\n            if let Some(mut input_handler) = window.platform_window.take_input_handler() {\n                if let Some(bounds) = input_handler.selected_bounds(window, cx) {\n                    window\n                        .platform_window\n                        .update_ime_position(bounds.scale(window.scale_factor()));\n                }\n                window.platform_window.set_input_handler(input_handler);\n            }\n        });\n    }\n\n    /// Present a platform dialog.\n    /// The provided message will be presented, along with buttons for each answer.\n    /// When a button is clicked, the returned Receiver will receive the index of the clicked button.\n    pub fn prompt(\n        &mut self,\n        level: PromptLevel,\n        message: &str,\n        detail: Option<&str>,\n        answers: &[&str],\n        cx: &mut App,\n    ) -> oneshot::Receiver<usize> {\n        let prompt_builder = cx.prompt_builder.take();\n        let Some(prompt_builder) = prompt_builder else {\n            unreachable!(\"Re-entrant window prompting is not supported by GPUI\");\n        };\n\n        let receiver = match &prompt_builder {\n            PromptBuilder::Default => self\n                .platform_window\n                .prompt(level, message, detail, answers)\n                .unwrap_or_else(|| {\n                    self.build_custom_prompt(&prompt_builder, level, message, detail, answers, cx)\n                }),\n            PromptBuilder::Custom(_) => {\n                self.build_custom_prompt(&prompt_builder, level, message, detail, answers, cx)\n            }\n        };\n\n        cx.prompt_builder = Some(prompt_builder);\n\n        receiver\n    }\n\n    fn build_custom_prompt(\n        &mut self,\n        prompt_builder: &PromptBuilder,\n        level: PromptLevel,\n        message: &str,\n        detail: Option<&str>,\n        answers: &[&str],\n        cx: &mut App,\n    ) -> oneshot::Receiver<usize> {\n        let (sender, receiver) = oneshot::channel();\n        let handle = PromptHandle::new(sender);\n        let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx);\n        self.prompt = Some(handle);\n        receiver\n    }\n\n    /// Returns the current context stack.\n    pub fn context_stack(&self) -> Vec<KeyContext> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n        let node_id = self\n            .focus\n            .and_then(|focus_id| dispatch_tree.focusable_node_id(focus_id))\n            .unwrap_or_else(|| dispatch_tree.root_node_id());\n\n        dispatch_tree\n            .dispatch_path(node_id)\n            .iter()\n            .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone())\n            .collect()\n    }\n\n    /// Returns all available actions for the focused element.\n    pub fn available_actions(&self, cx: &App) -> Vec<Box<dyn Action>> {\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let mut actions = self.rendered_frame.dispatch_tree.available_actions(node_id);\n        for action_type in cx.global_action_listeners.keys() {\n            if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) {\n                let action = cx.actions.build_action_type(action_type).ok();\n                if let Some(action) = action {\n                    actions.insert(ix, action);\n                }\n            }\n        }\n        actions\n    }\n\n    /// Returns key bindings that invoke an action on the currently focused element. Bindings are\n    /// returned in the order they were added. For display, the last binding should take precedence.\n    pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {\n        self.rendered_frame\n            .dispatch_tree\n            .bindings_for_action(action, &self.rendered_frame.dispatch_tree.context_stack)\n    }\n\n    /// Returns any bindings that would invoke an action on the given focus handle if it were\n    /// focused. Bindings are returned in the order they were added. For display, the last binding\n    /// should take precedence.\n    pub fn bindings_for_action_in(\n        &self,\n        action: &dyn Action,\n        focus_handle: &FocusHandle,\n    ) -> Vec<KeyBinding> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n\n        let Some(node_id) = dispatch_tree.focusable_node_id(focus_handle.id) else {\n            return vec![];\n        };\n        let context_stack: Vec<_> = dispatch_tree\n            .dispatch_path(node_id)\n            .into_iter()\n            .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())\n            .collect();\n        dispatch_tree.bindings_for_action(action, &context_stack)\n    }\n\n    /// Returns the key bindings for the given action in the given context.\n    pub fn bindings_for_action_in_context(\n        &self,\n        action: &dyn Action,\n        context: KeyContext,\n    ) -> Vec<KeyBinding> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n        dispatch_tree.bindings_for_action(action, &[context])\n    }\n\n    /// Returns a generic event listener that invokes the given listener with the view and context associated with the given view handle.\n    pub fn listener_for<V: Render, E>(\n        &self,\n        view: &Entity<V>,\n        f: impl Fn(&mut V, &E, &mut Window, &mut Context<V>) + 'static,\n    ) -> impl Fn(&E, &mut Window, &mut App) + 'static {\n        let view = view.downgrade();\n        move |e: &E, window: &mut Window, cx: &mut App| {\n            view.update(cx, |view, cx| f(view, e, window, cx)).ok();\n        }\n    }\n\n    /// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle.\n    pub fn handler_for<V: Render, Callback: Fn(&mut V, &mut Window, &mut Context<V>) + 'static>(\n        &self,\n        view: &Entity<V>,\n        f: Callback,\n    ) -> impl Fn(&mut Window, &mut App) + use<V, Callback> {\n        let view = view.downgrade();\n        move |window: &mut Window, cx: &mut App| {\n            view.update(cx, |view, cx| f(view, window, cx)).ok();\n        }\n    }\n\n    /// Register a callback that can interrupt the closing of the current window based the returned boolean.\n    /// If the callback returns false, the window won't be closed.\n    pub fn on_window_should_close(\n        &self,\n        cx: &App,\n        f: impl Fn(&mut Window, &mut App) -> bool + 'static,\n    ) {\n        let mut cx = self.to_async(cx);\n        self.platform_window.on_should_close(Box::new(move || {\n            cx.update(|window, cx| f(window, cx)).unwrap_or(true)\n        }))\n    }\n\n    /// Register an action listener on the window for the next frame. The type of action\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This is a fairly low-level method, so prefer using action handlers on elements unless you have\n    /// a specific need to register a global listener.\n    pub fn on_action(\n        &mut self,\n        action_type: TypeId,\n        listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.next_frame\n            .dispatch_tree\n            .on_action(action_type, Rc::new(listener));\n    }\n\n    /// Read information about the GPU backing this window.\n    /// Currently returns None on Mac and Windows.\n    pub fn gpu_specs(&self) -> Option<GpuSpecs> {\n        self.platform_window.gpu_specs()\n    }\n}\n\n// #[derive(Clone, Copy, Eq, PartialEq, Hash)]\nslotmap::new_key_type! {\n    /// A unique identifier for a window.\n    pub struct WindowId;\n}\n\nimpl WindowId {\n    /// Converts this window ID to a `u64`.\n    pub fn as_u64(&self) -> u64 {\n        self.0.as_ffi()\n    }\n}\n\nimpl From<u64> for WindowId {\n    fn from(value: u64) -> Self {\n        WindowId(slotmap::KeyData::from_ffi(value))\n    }\n}\n\n/// A handle to a window with a specific root view type.\n/// Note that this does not keep the window alive on its own.\n#[derive(Deref, DerefMut)]\npub struct WindowHandle<V> {\n    #[deref]\n    #[deref_mut]\n    pub(crate) any_handle: AnyWindowHandle,\n    state_type: PhantomData<V>,\n}\n\nimpl<V: 'static + Render> WindowHandle<V> {\n    /// Creates a new handle from a window ID.\n    /// This does not check if the root type of the window is `V`.\n    pub fn new(id: WindowId) -> Self {\n        WindowHandle {\n            any_handle: AnyWindowHandle {\n                id,\n                state_type: TypeId::of::<V>(),\n            },\n            state_type: PhantomData,\n        }\n    }\n\n    /// Get the root view out of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    #[cfg(any(test, feature = \"test-support\"))]\n    pub fn root<C>(&self, cx: &mut C) -> Result<Entity<V>>\n    where\n        C: AppContext,\n    {\n        crate::Flatten::flatten(cx.update_window(self.any_handle, |root_view, _, _| {\n            root_view\n                .downcast::<V>()\n                .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))\n        }))\n    }\n\n    /// Updates the root view of this window.\n    ///\n    /// This will fail if the window has been closed or if the root view's type does not match\n    pub fn update<C, R>(\n        &self,\n        cx: &mut C,\n        update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,\n    ) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.update_window(self.any_handle, |root_view, window, cx| {\n            let view = root_view\n                .downcast::<V>()\n                .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))?;\n\n            Ok(view.update(cx, |view, cx| update(view, window, cx)))\n        })?\n    }\n\n    /// Read the root view out of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> {\n        let x = cx\n            .windows\n            .get(self.id)\n            .and_then(|window| {\n                window\n                    .as_ref()\n                    .and_then(|window| window.root.clone())\n                    .map(|root_view| root_view.downcast::<V>())\n            })\n            .ok_or_else(|| anyhow!(\"window not found\"))?\n            .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))?;\n\n        Ok(x.read(cx))\n    }\n\n    /// Read the root view out of this window, with a callback\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))\n    }\n\n    /// Read the root view pointer off of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn entity<C>(&self, cx: &C) -> Result<Entity<V>>\n    where\n        C: AppContext,\n    {\n        cx.read_window(self, |root_view, _cx| root_view.clone())\n    }\n\n    /// Check if this window is 'active'.\n    ///\n    /// Will return `None` if the window is closed or currently\n    /// borrowed.\n    pub fn is_active(&self, cx: &mut App) -> Option<bool> {\n        cx.update_window(self.any_handle, |_, window, _| window.is_window_active())\n            .ok()\n    }\n}\n\nimpl<V> Copy for WindowHandle<V> {}\n\nimpl<V> Clone for WindowHandle<V> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<V> PartialEq for WindowHandle<V> {\n    fn eq(&self, other: &Self) -> bool {\n        self.any_handle == other.any_handle\n    }\n}\n\nimpl<V> Eq for WindowHandle<V> {}\n\nimpl<V> Hash for WindowHandle<V> {\n    fn hash<H: Hasher>(&self, state: &mut H) {\n        self.any_handle.hash(state);\n    }\n}\n\nimpl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {\n    fn from(val: WindowHandle<V>) -> Self {\n        val.any_handle\n    }\n}\n\nunsafe impl<V> Send for WindowHandle<V> {}\nunsafe impl<V> Sync for WindowHandle<V> {}\n\n/// A handle to a window with any root view type, which can be downcast to a window with a specific root view type.\n#[derive(Copy, Clone, PartialEq, Eq, Hash)]\npub struct AnyWindowHandle {\n    pub(crate) id: WindowId,\n    state_type: TypeId,\n}\n\nimpl AnyWindowHandle {\n    /// Get the ID of this window.\n    pub fn window_id(&self) -> WindowId {\n        self.id\n    }\n\n    /// Attempt to convert this handle to a window handle with a specific root view type.\n    /// If the types do not match, this will return `None`.\n    pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {\n        if TypeId::of::<T>() == self.state_type {\n            Some(WindowHandle {\n                any_handle: *self,\n                state_type: PhantomData,\n            })\n        } else {\n            None\n        }\n    }\n\n    /// Updates the state of the root view of this window.\n    ///\n    /// This will fail if the window has been closed.\n    pub fn update<C, R>(\n        self,\n        cx: &mut C,\n        update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,\n    ) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.update_window(self, update)\n    }\n\n    /// Read the state of the root view of this window.\n    ///\n    /// This will fail if the window has been closed.\n    pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(Entity<T>, &App) -> R) -> Result<R>\n    where\n        C: AppContext,\n        T: 'static,\n    {\n        let view = self\n            .downcast::<T>()\n            .context(\"the type of the window's root view has changed\")?;\n\n        cx.read_window(&view, read)\n    }\n}\n\nimpl HasWindowHandle for Window {\n    fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, HandleError> {\n        self.platform_window.window_handle()\n    }\n}\n\n/// An identifier for an [`Element`](crate::Element).\n///\n/// Can be constructed with a string, a number, or both, as well\n/// as other internal representations.\n#[derive(Clone, Debug, Eq, PartialEq, Hash)]\npub enum ElementId {\n    /// The ID of a View element\n    View(EntityId),\n    /// An integer ID.\n    Integer(u64),\n    /// A string based ID.\n    Name(SharedString),\n    /// A UUID.\n    Uuid(Uuid),\n    /// An ID that's equated with a focus handle.\n    FocusHandle(FocusId),\n    /// A combination of a name and an integer.\n    NamedInteger(SharedString, u64),\n    /// A path\n    Path(Arc<std::path::Path>),\n}\n\nimpl ElementId {\n    /// Constructs an `ElementId::NamedInteger` from a name and `usize`.\n    pub fn named_usize(name: impl Into<SharedString>, integer: usize) -> ElementId {\n        Self::NamedInteger(name.into(), integer as u64)\n    }\n}\n\nimpl Display for ElementId {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            ElementId::View(entity_id) => write!(f, \"view-{}\", entity_id)?,\n            ElementId::Integer(ix) => write!(f, \"{}\", ix)?,\n            ElementId::Name(name) => write!(f, \"{}\", name)?,\n            ElementId::FocusHandle(_) => write!(f, \"FocusHandle\")?,\n            ElementId::NamedInteger(s, i) => write!(f, \"{}-{}\", s, i)?,\n            ElementId::Uuid(uuid) => write!(f, \"{}\", uuid)?,\n            ElementId::Path(path) => write!(f, \"{}\", path.display())?,\n        }\n\n        Ok(())\n    }\n}\n\nimpl TryInto<SharedString> for ElementId {\n    type Error = anyhow::Error;\n\n    fn try_into(self) -> anyhow::Result<SharedString> {\n        if let ElementId::Name(name) = self {\n            Ok(name)\n        } else {\n            Err(anyhow!(\"element id is not string\"))\n        }\n    }\n}\n\nimpl From<usize> for ElementId {\n    fn from(id: usize) -> Self {\n        ElementId::Integer(id as u64)\n    }\n}\n\nimpl From<i32> for ElementId {\n    fn from(id: i32) -> Self {\n        Self::Integer(id as u64)\n    }\n}\n\nimpl From<SharedString> for ElementId {\n    fn from(name: SharedString) -> Self {\n        ElementId::Name(name)\n    }\n}\n\nimpl From<Arc<std::path::Path>> for ElementId {\n    fn from(path: Arc<std::path::Path>) -> Self {\n        ElementId::Path(path)\n    }\n}\n\nimpl From<&'static str> for ElementId {\n    fn from(name: &'static str) -> Self {\n        ElementId::Name(name.into())\n    }\n}\n\nimpl<'a> From<&'a FocusHandle> for ElementId {\n    fn from(handle: &'a FocusHandle) -> Self {\n        ElementId::FocusHandle(handle.id)\n    }\n}\n\nimpl From<(&'static str, EntityId)> for ElementId {\n    fn from((name, id): (&'static str, EntityId)) -> Self {\n        ElementId::NamedInteger(name.into(), id.as_u64())\n    }\n}\n\nimpl From<(&'static str, usize)> for ElementId {\n    fn from((name, id): (&'static str, usize)) -> Self {\n        ElementId::NamedInteger(name.into(), id as u64)\n    }\n}\n\nimpl From<(SharedString, usize)> for ElementId {\n    fn from((name, id): (SharedString, usize)) -> Self {\n        ElementId::NamedInteger(name, id as u64)\n    }\n}\n\nimpl From<(&'static str, u64)> for ElementId {\n    fn from((name, id): (&'static str, u64)) -> Self {\n        ElementId::NamedInteger(name.into(), id)\n    }\n}\n\nimpl From<Uuid> for ElementId {\n    fn from(value: Uuid) -> Self {\n        Self::Uuid(value)\n    }\n}\n\nimpl From<(&'static str, u32)> for ElementId {\n    fn from((name, id): (&'static str, u32)) -> Self {\n        ElementId::NamedInteger(name.into(), id.into())\n    }\n}\n\n/// A rectangle to be rendered in the window at the given position and size.\n/// Passed as an argument [`Window::paint_quad`].\n#[derive(Clone)]\npub struct PaintQuad {\n    /// The bounds of the quad within the window.\n    pub bounds: Bounds<Pixels>,\n    /// The radii of the quad's corners.\n    pub corner_radii: Corners<Pixels>,\n    /// The background color of the quad.\n    pub background: Background,\n    /// The widths of the quad's borders.\n    pub border_widths: Edges<Pixels>,\n    /// The color of the quad's borders.\n    pub border_color: Hsla,\n    /// The style of the quad's borders.\n    pub border_style: BorderStyle,\n    /// The transformation to apply to the quad.\n    pub transformation: TransformationMatrix,\n}\n\nimpl PaintQuad {\n    /// Sets the corner radii of the quad.\n    pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {\n        PaintQuad {\n            corner_radii: corner_radii.into(),\n            ..self\n        }\n    }\n\n    /// Sets the border widths of the quad.\n    pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {\n        PaintQuad {\n            border_widths: border_widths.into(),\n            ..self\n        }\n    }\n\n    /// Sets the border color of the quad.\n    pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {\n        PaintQuad {\n            border_color: border_color.into(),\n            ..self\n        }\n    }\n\n    /// Sets the background color of the quad.\n    pub fn background(self, background: impl Into<Background>) -> Self {\n        PaintQuad {\n            background: background.into(),\n            ..self\n        }\n    }\n\n    /// Sets the transformation matrix to apply to the quad.\n    pub fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {\n        PaintQuad {\n            transformation: transformation.into(),\n            ..self\n        }\n    }\n}\n\n/// Creates a quad with the given parameters.\npub fn quad(\n    bounds: Bounds<Pixels>,\n    corner_radii: impl Into<Corners<Pixels>>,\n    background: impl Into<Background>,\n    border_widths: impl Into<Edges<Pixels>>,\n    border_color: impl Into<Hsla>,\n    border_style: BorderStyle,\n) -> PaintQuad {\n    PaintQuad {\n        bounds,\n        corner_radii: corner_radii.into(),\n        background: background.into(),\n        border_widths: border_widths.into(),\n        border_color: border_color.into(),\n        border_style,\n        transformation: TransformationMatrix::default(),\n    }\n}\n\npub(crate) fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad {\n    PaintQuad {\n        transformation,\n        ..quad\n    }\n}\n\n/// Creates a filled quad with the given bounds and background color.\npub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {\n    PaintQuad {\n        bounds: bounds.into(),\n        corner_radii: (0.).into(),\n        background: background.into(),\n        border_widths: (0.).into(),\n        border_color: transparent_black(),\n        border_style: BorderStyle::default(),\n        transformation: TransformationMatrix::default(),\n    }\n}\n\n/// Creates a rectangle outline with the given bounds, border color, and a 1px border width\npub fn outline(\n    bounds: impl Into<Bounds<Pixels>>,\n    border_color: impl Into<Hsla>,\n    border_style: BorderStyle,\n) -> PaintQuad {\n    PaintQuad {\n        bounds: bounds.into(),\n        corner_radii: (0.).into(),\n        background: transparent_black().into(),\n        border_widths: (1.).into(),\n        border_color: border_color.into(),\n        border_style,\n        transformation: TransformationMatrix::default(),\n    }\n}\n",
  "old_text": "use crate::{\n    Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,\n    AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Context,\n    Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId,\n    DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, FontId,\n    Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero, KeyBinding, KeyContext,\n    KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers,\n    ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent,\n    Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler,\n    PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams,\n    RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR,\n    SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style,\n    SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement,\n    TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance,\n    WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem,\n    point, prelude::*, px, size, transparent_black,\n};\nuse anyhow::{Context as _, Result, anyhow};\nuse collections::{FxHashMap, FxHashSet};\n#[cfg(target_os = \"macos\")]\nuse core_video::pixel_buffer::CVPixelBuffer;\nuse derive_more::{Deref, DerefMut};\nuse futures::FutureExt;\nuse futures::channel::oneshot;\nuse parking_lot::RwLock;\nuse raw_window_handle::{HandleError, HasWindowHandle};\nuse refineable::Refineable;\nuse slotmap::SlotMap;\nuse smallvec::SmallVec;\nuse std::{\n    any::{Any, TypeId},\n    borrow::Cow,\n    cell::{Cell, RefCell},\n    cmp,\n    fmt::{Debug, Display},\n    hash::{Hash, Hasher},\n    marker::PhantomData,\n    mem,\n    ops::{DerefMut, Range},\n    rc::Rc,\n    sync::{\n        Arc, Weak,\n        atomic::{AtomicUsize, Ordering::SeqCst},\n    },\n    time::{Duration, Instant},\n};\nuse util::post_inc;\nuse util::{ResultExt, measure};\nuse uuid::Uuid;\n\nmod prompts;\n\npub use prompts::*;\n\npub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1024.), px(700.));\n\n/// Represents the two different phases when dispatching events.\n#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]\npub enum DispatchPhase {\n    /// After the capture phase comes the bubble phase, in which mouse event listeners are\n    /// invoked front to back and keyboard event listeners are invoked from the focused element\n    /// to the root of the element tree. This is the phase you'll most commonly want to use when\n    /// registering event listeners.\n    #[default]\n    Bubble,\n    /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard\n    /// listeners are invoked from the root of the tree downward toward the focused element. This phase\n    /// is used for special purposes such as clearing the \"pressed\" state for click events. If\n    /// you stop event propagation during this phase, you need to know what you're doing. Handlers\n    /// outside of the immediate region may rely on detecting non-local events during this phase.\n    Capture,\n}\n\nimpl DispatchPhase {\n    /// Returns true if this represents the \"bubble\" phase.\n    pub fn bubble(self) -> bool {\n        self == DispatchPhase::Bubble\n    }\n\n    /// Returns true if this represents the \"capture\" phase.\n    pub fn capture(self) -> bool {\n        self == DispatchPhase::Capture\n    }\n}\n\nstruct WindowInvalidatorInner {\n    pub dirty: bool,\n    pub draw_phase: DrawPhase,\n    pub dirty_views: FxHashSet<EntityId>,\n}\n\n#[derive(Clone)]\npub(crate) struct WindowInvalidator {\n    inner: Rc<RefCell<WindowInvalidatorInner>>,\n}\n\nimpl WindowInvalidator {\n    pub fn new() -> Self {\n        WindowInvalidator {\n            inner: Rc::new(RefCell::new(WindowInvalidatorInner {\n                dirty: true,\n                draw_phase: DrawPhase::None,\n                dirty_views: FxHashSet::default(),\n            })),\n        }\n    }\n\n    pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {\n        let mut inner = self.inner.borrow_mut();\n        inner.dirty_views.insert(entity);\n        if inner.draw_phase == DrawPhase::None {\n            inner.dirty = true;\n            cx.push_effect(Effect::Notify { emitter: entity });\n            true\n        } else {\n            false\n        }\n    }\n\n    pub fn is_dirty(&self) -> bool {\n        self.inner.borrow().dirty\n    }\n\n    pub fn set_dirty(&self, dirty: bool) {\n        self.inner.borrow_mut().dirty = dirty\n    }\n\n    pub fn set_phase(&self, phase: DrawPhase) {\n        self.inner.borrow_mut().draw_phase = phase\n    }\n\n    pub fn take_views(&self) -> FxHashSet<EntityId> {\n        mem::take(&mut self.inner.borrow_mut().dirty_views)\n    }\n\n    pub fn replace_views(&self, views: FxHashSet<EntityId>) {\n        self.inner.borrow_mut().dirty_views = views;\n    }\n\n    pub fn not_drawing(&self) -> bool {\n        self.inner.borrow().draw_phase == DrawPhase::None\n    }\n\n    #[track_caller]\n    pub fn debug_assert_paint(&self) {\n        debug_assert!(\n            matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),\n            \"this method can only be called during paint\"\n        );\n    }\n\n    #[track_caller]\n    pub fn debug_assert_prepaint(&self) {\n        debug_assert!(\n            matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),\n            \"this method can only be called during request_layout, or prepaint\"\n        );\n    }\n\n    #[track_caller]\n    pub fn debug_assert_paint_or_prepaint(&self) {\n        debug_assert!(\n            matches!(\n                self.inner.borrow().draw_phase,\n                DrawPhase::Paint | DrawPhase::Prepaint\n            ),\n            \"this method can only be called during request_layout, prepaint, or paint\"\n        );\n    }\n}\n\ntype AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;\n\npub(crate) type AnyWindowFocusListener =\n    Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;\n\npub(crate) struct WindowFocusEvent {\n    pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,\n    pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,\n}\n\nimpl WindowFocusEvent {\n    pub fn is_focus_in(&self, focus_id: FocusId) -> bool {\n        !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id)\n    }\n\n    pub fn is_focus_out(&self, focus_id: FocusId) -> bool {\n        self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id)\n    }\n}\n\n/// This is provided when subscribing for `Context::on_focus_out` events.\npub struct FocusOutEvent {\n    /// A weak focus handle representing what was blurred.\n    pub blurred: WeakFocusHandle,\n}\n\nslotmap::new_key_type! {\n    /// A globally unique identifier for a focusable element.\n    pub struct FocusId;\n}\n\nthread_local! {\n    /// 8MB wasn't quite enough...\n    pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(32 * 1024 * 1024));\n}\n\npub(crate) type FocusMap = RwLock<SlotMap<FocusId, AtomicUsize>>;\n\nimpl FocusId {\n    /// Obtains whether the element associated with this handle is currently focused.\n    pub fn is_focused(&self, window: &Window) -> bool {\n        window.focus == Some(*self)\n    }\n\n    /// Obtains whether the element associated with this handle contains the focused\n    /// element or is itself focused.\n    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {\n        window\n            .focused(cx)\n            .map_or(false, |focused| self.contains(focused.id, window))\n    }\n\n    /// Obtains whether the element associated with this handle is contained within the\n    /// focused element or is itself focused.\n    pub fn within_focused(&self, window: &Window, cx: &App) -> bool {\n        let focused = window.focused(cx);\n        focused.map_or(false, |focused| focused.id.contains(*self, window))\n    }\n\n    /// Obtains whether this handle contains the given handle in the most recently rendered frame.\n    pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {\n        window\n            .rendered_frame\n            .dispatch_tree\n            .focus_contains(*self, other)\n    }\n}\n\n/// A handle which can be used to track and manipulate the focused element in a window.\npub struct FocusHandle {\n    pub(crate) id: FocusId,\n    handles: Arc<FocusMap>,\n}\n\nimpl std::fmt::Debug for FocusHandle {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.write_fmt(format_args!(\"FocusHandle({:?})\", self.id))\n    }\n}\n\nimpl FocusHandle {\n    pub(crate) fn new(handles: &Arc<FocusMap>) -> Self {\n        let id = handles.write().insert(AtomicUsize::new(1));\n        Self {\n            id,\n            handles: handles.clone(),\n        }\n    }\n\n    pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {\n        let lock = handles.read();\n        let ref_count = lock.get(id)?;\n        if ref_count.load(SeqCst) == 0 {\n            None\n        } else {\n            ref_count.fetch_add(1, SeqCst);\n            Some(Self {\n                id,\n                handles: handles.clone(),\n            })\n        }\n    }\n\n    /// Converts this focus handle into a weak variant, which does not prevent it from being released.\n    pub fn downgrade(&self) -> WeakFocusHandle {\n        WeakFocusHandle {\n            id: self.id,\n            handles: Arc::downgrade(&self.handles),\n        }\n    }\n\n    /// Moves the focus to the element associated with this handle.\n    pub fn focus(&self, window: &mut Window) {\n        window.focus(self)\n    }\n\n    /// Obtains whether the element associated with this handle is currently focused.\n    pub fn is_focused(&self, window: &Window) -> bool {\n        self.id.is_focused(window)\n    }\n\n    /// Obtains whether the element associated with this handle contains the focused\n    /// element or is itself focused.\n    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {\n        self.id.contains_focused(window, cx)\n    }\n\n    /// Obtains whether the element associated with this handle is contained within the\n    /// focused element or is itself focused.\n    pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {\n        self.id.within_focused(window, cx)\n    }\n\n    /// Obtains whether this handle contains the given handle in the most recently rendered frame.\n    pub fn contains(&self, other: &Self, window: &Window) -> bool {\n        self.id.contains(other.id, window)\n    }\n\n    /// Dispatch an action on the element that rendered this focus handle\n    pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {\n        if let Some(node_id) = window\n            .rendered_frame\n            .dispatch_tree\n            .focusable_node_id(self.id)\n        {\n            window.dispatch_action_on_node(node_id, action, cx)\n        }\n    }\n}\n\nimpl Clone for FocusHandle {\n    fn clone(&self) -> Self {\n        Self::for_id(self.id, &self.handles).unwrap()\n    }\n}\n\nimpl PartialEq for FocusHandle {\n    fn eq(&self, other: &Self) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for FocusHandle {}\n\nimpl Drop for FocusHandle {\n    fn drop(&mut self) {\n        self.handles\n            .read()\n            .get(self.id)\n            .unwrap()\n            .fetch_sub(1, SeqCst);\n    }\n}\n\n/// A weak reference to a focus handle.\n#[derive(Clone, Debug)]\npub struct WeakFocusHandle {\n    pub(crate) id: FocusId,\n    pub(crate) handles: Weak<FocusMap>,\n}\n\nimpl WeakFocusHandle {\n    /// Attempts to upgrade the [WeakFocusHandle] to a [FocusHandle].\n    pub fn upgrade(&self) -> Option<FocusHandle> {\n        let handles = self.handles.upgrade()?;\n        FocusHandle::for_id(self.id, &handles)\n    }\n}\n\nimpl PartialEq for WeakFocusHandle {\n    fn eq(&self, other: &WeakFocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for WeakFocusHandle {}\n\nimpl PartialEq<FocusHandle> for WeakFocusHandle {\n    fn eq(&self, other: &FocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl PartialEq<WeakFocusHandle> for FocusHandle {\n    fn eq(&self, other: &WeakFocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\n/// Focusable allows users of your view to easily\n/// focus it (using window.focus_view(cx, view))\npub trait Focusable: 'static {\n    /// Returns the focus handle associated with this view.\n    fn focus_handle(&self, cx: &App) -> FocusHandle;\n}\n\nimpl<V: Focusable> Focusable for Entity<V> {\n    fn focus_handle(&self, cx: &App) -> FocusHandle {\n        self.read(cx).focus_handle(cx)\n    }\n}\n\n/// ManagedView is a view (like a Modal, Popover, Menu, etc.)\n/// where the lifecycle of the view is handled by another view.\npub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}\n\nimpl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}\n\n/// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal.\npub struct DismissEvent;\n\ntype FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;\n\npub(crate) type AnyMouseListener =\n    Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;\n\n#[derive(Clone)]\npub(crate) struct CursorStyleRequest {\n    pub(crate) hitbox_id: Option<HitboxId>, // None represents whole window\n    pub(crate) style: CursorStyle,\n}\n\n/// An identifier for a [Hitbox].\n#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]\npub struct HitboxId(usize);\n\nimpl HitboxId {\n    /// Checks if the hitbox with this id is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        window.mouse_hit_test.0.contains(self)\n    }\n}\n\n/// A rectangular region that potentially blocks hitboxes inserted prior.\n/// See [Window::insert_hitbox] for more details.\n#[derive(Clone, Debug, Deref)]\npub struct Hitbox {\n    /// A unique identifier for the hitbox.\n    pub id: HitboxId,\n    /// The bounds of the hitbox.\n    #[deref]\n    pub bounds: Bounds<Pixels>,\n    /// The content mask when the hitbox was inserted.\n    pub content_mask: ContentMask<Pixels>,\n    /// Whether the hitbox occludes other hitboxes inserted prior.\n    pub opaque: bool,\n}\n\nimpl Hitbox {\n    /// Checks if the hitbox is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        self.id.is_hovered(window)\n    }\n}\n\n#[derive(Default, Eq, PartialEq)]\npub(crate) struct HitTest(SmallVec<[HitboxId; 8]>);\n\n/// An identifier for a tooltip.\n#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]\npub struct TooltipId(usize);\n\nimpl TooltipId {\n    /// Checks if the tooltip is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        window\n            .tooltip_bounds\n            .as_ref()\n            .map_or(false, |tooltip_bounds| {\n                tooltip_bounds.id == *self\n                    && tooltip_bounds.bounds.contains(&window.mouse_position())\n            })\n    }\n}\n\npub(crate) struct TooltipBounds {\n    id: TooltipId,\n    bounds: Bounds<Pixels>,\n}\n\n#[derive(Clone)]\npub(crate) struct TooltipRequest {\n    id: TooltipId,\n    tooltip: AnyTooltip,\n}\n\npub(crate) struct DeferredDraw {\n    current_view: EntityId,\n    priority: usize,\n    parent_node: DispatchNodeId,\n    element_id_stack: SmallVec<[ElementId; 32]>,\n    text_style_stack: Vec<TextStyleRefinement>,\n    element: Option<AnyElement>,\n    absolute_offset: Point<Pixels>,\n    prepaint_range: Range<PrepaintStateIndex>,\n    paint_range: Range<PaintIndex>,\n}\n\npub(crate) struct Frame {\n    pub(crate) focus: Option<FocusId>,\n    pub(crate) window_active: bool,\n    pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,\n    accessed_element_states: Vec<(GlobalElementId, TypeId)>,\n    pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,\n    pub(crate) dispatch_tree: DispatchTree,\n    pub(crate) scene: Scene,\n    pub(crate) hitboxes: Vec<Hitbox>,\n    pub(crate) deferred_draws: Vec<DeferredDraw>,\n    pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,\n    pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,\n    pub(crate) cursor_styles: Vec<CursorStyleRequest>,\n    #[cfg(any(test, feature = \"test-support\"))]\n    pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,\n}\n\n#[derive(Clone, Default)]\npub(crate) struct PrepaintStateIndex {\n    hitboxes_index: usize,\n    tooltips_index: usize,\n    deferred_draws_index: usize,\n    dispatch_tree_index: usize,\n    accessed_element_states_index: usize,\n    line_layout_index: LineLayoutIndex,\n}\n\n#[derive(Clone, Default)]\npub(crate) struct PaintIndex {\n    scene_index: usize,\n    mouse_listeners_index: usize,\n    input_handlers_index: usize,\n    cursor_styles_index: usize,\n    accessed_element_states_index: usize,\n    line_layout_index: LineLayoutIndex,\n}\n\nimpl Frame {\n    pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {\n        Frame {\n            focus: None,\n            window_active: false,\n            element_states: FxHashMap::default(),\n            accessed_element_states: Vec::new(),\n            mouse_listeners: Vec::new(),\n            dispatch_tree,\n            scene: Scene::default(),\n            hitboxes: Vec::new(),\n            deferred_draws: Vec::new(),\n            input_handlers: Vec::new(),\n            tooltip_requests: Vec::new(),\n            cursor_styles: Vec::new(),\n\n            #[cfg(any(test, feature = \"test-support\"))]\n            debug_bounds: FxHashMap::default(),\n        }\n    }\n\n    pub(crate) fn clear(&mut self) {\n        self.element_states.clear();\n        self.accessed_element_states.clear();\n        self.mouse_listeners.clear();\n        self.dispatch_tree.clear();\n        self.scene.clear();\n        self.input_handlers.clear();\n        self.tooltip_requests.clear();\n        self.cursor_styles.clear();\n        self.hitboxes.clear();\n        self.deferred_draws.clear();\n        self.focus = None;\n    }\n\n    pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {\n        let mut hit_test = HitTest::default();\n        for hitbox in self.hitboxes.iter().rev() {\n            let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds);\n            if bounds.contains(&position) {\n                hit_test.0.push(hitbox.id);\n                if hitbox.opaque {\n                    break;\n                }\n            }\n        }\n        hit_test\n    }\n\n    pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {\n        self.focus\n            .map(|focus_id| self.dispatch_tree.focus_path(focus_id))\n            .unwrap_or_default()\n    }\n\n    pub(crate) fn finish(&mut self, prev_frame: &mut Self) {\n        for element_state_key in &self.accessed_element_states {\n            if let Some((element_state_key, element_state)) =\n                prev_frame.element_states.remove_entry(element_state_key)\n            {\n                self.element_states.insert(element_state_key, element_state);\n            }\n        }\n\n        self.scene.finish();\n    }\n}\n\n/// Holds the state for a specific window.\npub struct Window {\n    pub(crate) handle: AnyWindowHandle,\n    pub(crate) invalidator: WindowInvalidator,\n    pub(crate) removed: bool,\n    pub(crate) platform_window: Box<dyn PlatformWindow>,\n    display_id: Option<DisplayId>,\n    sprite_atlas: Arc<dyn PlatformAtlas>,\n    text_system: Arc<WindowTextSystem>,\n    rem_size: Pixels,\n    /// The stack of override values for the window's rem size.\n    ///\n    /// This is used by `with_rem_size` to allow rendering an element tree with\n    /// a given rem size.\n    rem_size_override_stack: SmallVec<[Pixels; 8]>,\n    pub(crate) viewport_size: Size<Pixels>,\n    layout_engine: Option<TaffyLayoutEngine>,\n    pub(crate) root: Option<AnyView>,\n    pub(crate) element_id_stack: SmallVec<[ElementId; 32]>,\n    pub(crate) text_style_stack: Vec<TextStyleRefinement>,\n    pub(crate) rendered_entity_stack: Vec<EntityId>,\n    pub(crate) element_offset_stack: Vec<Point<Pixels>>,\n    pub(crate) element_opacity: Option<f32>,\n    pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,\n    pub(crate) requested_autoscroll: Option<Bounds<Pixels>>,\n    pub(crate) image_cache_stack: Vec<AnyImageCache>,\n    pub(crate) rendered_frame: Frame,\n    pub(crate) next_frame: Frame,\n    pub(crate) next_hitbox_id: HitboxId,\n    pub(crate) next_tooltip_id: TooltipId,\n    pub(crate) tooltip_bounds: Option<TooltipBounds>,\n    next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,\n    pub(crate) dirty_views: FxHashSet<EntityId>,\n    focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,\n    pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,\n    default_prevented: bool,\n    mouse_position: Point<Pixels>,\n    mouse_hit_test: HitTest,\n    modifiers: Modifiers,\n    scale_factor: f32,\n    pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,\n    appearance: WindowAppearance,\n    pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,\n    active: Rc<Cell<bool>>,\n    hovered: Rc<Cell<bool>>,\n    pub(crate) needs_present: Rc<Cell<bool>>,\n    pub(crate) last_input_timestamp: Rc<Cell<Instant>>,\n    pub(crate) refreshing: bool,\n    pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,\n    pub(crate) focus: Option<FocusId>,\n    focus_enabled: bool,\n    pending_input: Option<PendingInput>,\n    pending_modifier: ModifierState,\n    pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,\n    prompt: Option<RenderablePromptHandle>,\n    pub(crate) client_inset: Option<Pixels>,\n}\n\n#[derive(Clone, Debug, Default)]\nstruct ModifierState {\n    modifiers: Modifiers,\n    saw_keystroke: bool,\n}\n\n#[derive(Clone, Copy, Debug, Eq, PartialEq)]\npub(crate) enum DrawPhase {\n    None,\n    Prepaint,\n    Paint,\n    Focus,\n}\n\n#[derive(Default, Debug)]\nstruct PendingInput {\n    keystrokes: SmallVec<[Keystroke; 1]>,\n    focus: Option<FocusId>,\n    timer: Option<Task<()>>,\n}\n\npub(crate) struct ElementStateBox {\n    pub(crate) inner: Box<dyn Any>,\n    #[cfg(debug_assertions)]\n    pub(crate) type_name: &'static str,\n}\n\nfn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> Bounds<Pixels> {\n    const DEFAULT_WINDOW_OFFSET: Point<Pixels> = point(px(0.), px(35.));\n\n    // TODO, BUG: if you open a window with the currently active window\n    // on the stack, this will erroneously select the 'unwrap_or_else'\n    // code path\n    cx.active_window()\n        .and_then(|w| w.update(cx, |_, window, _| window.bounds()).ok())\n        .map(|mut bounds| {\n            bounds.origin += DEFAULT_WINDOW_OFFSET;\n            bounds\n        })\n        .unwrap_or_else(|| {\n            let display = display_id\n                .map(|id| cx.find_display(id))\n                .unwrap_or_else(|| cx.primary_display());\n\n            display\n                .map(|display| display.default_bounds())\n                .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE))\n        })\n}\n\nimpl Window {\n    pub(crate) fn new(\n        handle: AnyWindowHandle,\n        options: WindowOptions,\n        cx: &mut App,\n    ) -> Result<Self> {\n        let WindowOptions {\n            window_bounds,\n            titlebar,\n            focus,\n            show,\n            kind,\n            is_movable,\n            display_id,\n            window_background,\n            app_id,\n            window_min_size,\n            window_decorations,\n        } = options;\n\n        let bounds = window_bounds\n            .map(|bounds| bounds.get_bounds())\n            .unwrap_or_else(|| default_bounds(display_id, cx));\n        let mut platform_window = cx.platform.open_window(\n            handle,\n            WindowParams {\n                bounds,\n                titlebar,\n                kind,\n                is_movable,\n                focus,\n                show,\n                display_id,\n                window_min_size,\n            },\n        )?;\n        let display_id = platform_window.display().map(|display| display.id());\n        let sprite_atlas = platform_window.sprite_atlas();\n        let mouse_position = platform_window.mouse_position();\n        let modifiers = platform_window.modifiers();\n        let content_size = platform_window.content_size();\n        let scale_factor = platform_window.scale_factor();\n        let appearance = platform_window.appearance();\n        let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));\n        let invalidator = WindowInvalidator::new();\n        let active = Rc::new(Cell::new(platform_window.is_active()));\n        let hovered = Rc::new(Cell::new(platform_window.is_hovered()));\n        let needs_present = Rc::new(Cell::new(false));\n        let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();\n        let last_input_timestamp = Rc::new(Cell::new(Instant::now()));\n\n        platform_window\n            .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server));\n        platform_window.set_background_appearance(window_background);\n\n        if let Some(ref window_open_state) = window_bounds {\n            match window_open_state {\n                WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),\n                WindowBounds::Maximized(_) => platform_window.zoom(),\n                WindowBounds::Windowed(_) => {}\n            }\n        }\n\n        platform_window.on_close(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                let _ = handle.update(&mut cx, |_, window, _| window.remove_window());\n            }\n        }));\n        platform_window.on_request_frame(Box::new({\n            let mut cx = cx.to_async();\n            let invalidator = invalidator.clone();\n            let active = active.clone();\n            let needs_present = needs_present.clone();\n            let next_frame_callbacks = next_frame_callbacks.clone();\n            let last_input_timestamp = last_input_timestamp.clone();\n            move |request_frame_options| {\n                let next_frame_callbacks = next_frame_callbacks.take();\n                if !next_frame_callbacks.is_empty() {\n                    handle\n                        .update(&mut cx, |_, window, cx| {\n                            for callback in next_frame_callbacks {\n                                callback(window, cx);\n                            }\n                        })\n                        .log_err();\n                }\n\n                // Keep presenting the current scene for 1 extra second since the\n                // last input to prevent the display from underclocking the refresh rate.\n                let needs_present = request_frame_options.require_presentation\n                    || needs_present.get()\n                    || (active.get()\n                        && last_input_timestamp.get().elapsed() < Duration::from_secs(1));\n\n                if invalidator.is_dirty() {\n                    measure(\"frame duration\", || {\n                        handle\n                            .update(&mut cx, |_, window, cx| {\n                                window.draw(cx);\n                                window.present();\n                            })\n                            .log_err();\n                    })\n                } else if needs_present {\n                    handle\n                        .update(&mut cx, |_, window, _| window.present())\n                        .log_err();\n                }\n\n                handle\n                    .update(&mut cx, |_, window, _| {\n                        window.complete_frame();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_resize(Box::new({\n            let mut cx = cx.to_async();\n            move |_, _| {\n                handle\n                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_moved(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                handle\n                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_appearance_changed(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                handle\n                    .update(&mut cx, |_, window, cx| window.appearance_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_active_status_change(Box::new({\n            let mut cx = cx.to_async();\n            move |active| {\n                handle\n                    .update(&mut cx, |_, window, cx| {\n                        window.active.set(active);\n                        window.modifiers = window.platform_window.modifiers();\n                        window\n                            .activation_observers\n                            .clone()\n                            .retain(&(), |callback| callback(window, cx));\n                        window.refresh();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_hover_status_change(Box::new({\n            let mut cx = cx.to_async();\n            move |active| {\n                handle\n                    .update(&mut cx, |_, window, _| {\n                        window.hovered.set(active);\n                        window.refresh();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_input({\n            let mut cx = cx.to_async();\n            Box::new(move |event| {\n                handle\n                    .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))\n                    .log_err()\n                    .unwrap_or(DispatchEventResult::default())\n            })\n        });\n\n        if let Some(app_id) = app_id {\n            platform_window.set_app_id(&app_id);\n        }\n\n        platform_window.map_window().unwrap();\n\n        Ok(Window {\n            handle,\n            invalidator,\n            removed: false,\n            platform_window,\n            display_id,\n            sprite_atlas,\n            text_system,\n            rem_size: px(16.),\n            rem_size_override_stack: SmallVec::new(),\n            viewport_size: content_size,\n            layout_engine: Some(TaffyLayoutEngine::new()),\n            root: None,\n            element_id_stack: SmallVec::default(),\n            text_style_stack: Vec::new(),\n            rendered_entity_stack: Vec::new(),\n            element_offset_stack: Vec::new(),\n            content_mask_stack: Vec::new(),\n            element_opacity: None,\n            requested_autoscroll: None,\n            rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),\n            next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),\n            next_frame_callbacks,\n            next_hitbox_id: HitboxId::default(),\n            next_tooltip_id: TooltipId::default(),\n            tooltip_bounds: None,\n            dirty_views: FxHashSet::default(),\n            focus_listeners: SubscriberSet::new(),\n            focus_lost_listeners: SubscriberSet::new(),\n            default_prevented: true,\n            mouse_position,\n            mouse_hit_test: HitTest::default(),\n            modifiers,\n            scale_factor,\n            bounds_observers: SubscriberSet::new(),\n            appearance,\n            appearance_observers: SubscriberSet::new(),\n            active,\n            hovered,\n            needs_present,\n            last_input_timestamp,\n            refreshing: false,\n            activation_observers: SubscriberSet::new(),\n            focus: None,\n            focus_enabled: true,\n            pending_input: None,\n            pending_modifier: ModifierState::default(),\n            pending_input_observers: SubscriberSet::new(),\n            prompt: None,\n            client_inset: None,\n            image_cache_stack: Vec::new(),\n        })\n    }\n\n    pub(crate) fn new_focus_listener(\n        &self,\n        value: AnyWindowFocusListener,\n    ) -> (Subscription, impl FnOnce() + use<>) {\n        self.focus_listeners.insert((), value)\n    }\n}\n\n#[derive(Clone, Debug, Default, PartialEq, Eq)]\npub(crate) struct DispatchEventResult {\n    pub propagate: bool,\n    pub default_prevented: bool,\n}\n\n/// Indicates which region of the window is visible. Content falling outside of this mask will not be\n/// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type\n/// to leave room to support more complex shapes in the future.\n#[derive(Clone, Debug, Default, PartialEq, Eq)]\n#[repr(C)]\npub struct ContentMask<P: Clone + Default + Debug> {\n    /// The bounds\n    pub bounds: Bounds<P>,\n}\n\nimpl ContentMask<Pixels> {\n    /// Scale the content mask's pixel units by the given scaling factor.\n    pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {\n        ContentMask {\n            bounds: self.bounds.scale(factor),\n        }\n    }\n\n    /// Intersect the content mask with the given content mask.\n    pub fn intersect(&self, other: &Self) -> Self {\n        let bounds = self.bounds.intersect(&other.bounds);\n        ContentMask { bounds }\n    }\n}\n\nimpl Window {\n    fn mark_view_dirty(&mut self, view_id: EntityId) {\n        // Mark ancestor views as dirty. If already in the `dirty_views` set, then all its ancestors\n        // should already be dirty.\n        for view_id in self\n            .rendered_frame\n            .dispatch_tree\n            .view_path(view_id)\n            .into_iter()\n            .rev()\n        {\n            if !self.dirty_views.insert(view_id) {\n                break;\n            }\n        }\n    }\n\n    /// Registers a callback to be invoked when the window appearance changes.\n    pub fn observe_window_appearance(\n        &self,\n        mut callback: impl FnMut(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let (subscription, activate) = self.appearance_observers.insert(\n            (),\n            Box::new(move |window, cx| {\n                callback(window, cx);\n                true\n            }),\n        );\n        activate();\n        subscription\n    }\n\n    /// Replaces the root entity of the window with a new one.\n    pub fn replace_root<E>(\n        &mut self,\n        cx: &mut App,\n        build_view: impl FnOnce(&mut Window, &mut Context<E>) -> E,\n    ) -> Entity<E>\n    where\n        E: 'static + Render,\n    {\n        let view = cx.new(|cx| build_view(self, cx));\n        self.root = Some(view.clone().into());\n        self.refresh();\n        view\n    }\n\n    /// Returns the root entity of the window, if it has one.\n    pub fn root<E>(&self) -> Option<Option<Entity<E>>>\n    where\n        E: 'static + Render,\n    {\n        self.root\n            .as_ref()\n            .map(|view| view.clone().downcast::<E>().ok())\n    }\n\n    /// Obtain a handle to the window that belongs to this context.\n    pub fn window_handle(&self) -> AnyWindowHandle {\n        self.handle\n    }\n\n    /// Mark the window as dirty, scheduling it to be redrawn on the next frame.\n    pub fn refresh(&mut self) {\n        if self.invalidator.not_drawing() {\n            self.refreshing = true;\n            self.invalidator.set_dirty(true);\n        }\n    }\n\n    /// Close this window.\n    pub fn remove_window(&mut self) {\n        self.removed = true;\n    }\n\n    /// Obtain the currently focused [`FocusHandle`]. If no elements are focused, returns `None`.\n    pub fn focused(&self, cx: &App) -> Option<FocusHandle> {\n        self.focus\n            .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))\n    }\n\n    /// Move focus to the element associated with the given [`FocusHandle`].\n    pub fn focus(&mut self, handle: &FocusHandle) {\n        if !self.focus_enabled || self.focus == Some(handle.id) {\n            return;\n        }\n\n        self.focus = Some(handle.id);\n        self.clear_pending_keystrokes();\n        self.refresh();\n    }\n\n    /// Remove focus from all elements within this context's window.\n    pub fn blur(&mut self) {\n        if !self.focus_enabled {\n            return;\n        }\n\n        self.focus = None;\n        self.refresh();\n    }\n\n    /// Blur the window and don't allow anything in it to be focused again.\n    pub fn disable_focus(&mut self) {\n        self.blur();\n        self.focus_enabled = false;\n    }\n\n    /// Accessor for the text system.\n    pub fn text_system(&self) -> &Arc<WindowTextSystem> {\n        &self.text_system\n    }\n\n    /// The current text style. Which is composed of all the style refinements provided to `with_text_style`.\n    pub fn text_style(&self) -> TextStyle {\n        let mut style = TextStyle::default();\n        for refinement in &self.text_style_stack {\n            style.refine(refinement);\n        }\n        style\n    }\n\n    /// Check if the platform window is maximized\n    /// On some platforms (namely Windows) this is different than the bounds being the size of the display\n    pub fn is_maximized(&self) -> bool {\n        self.platform_window.is_maximized()\n    }\n\n    /// request a certain window decoration (Wayland)\n    pub fn request_decorations(&self, decorations: WindowDecorations) {\n        self.platform_window.request_decorations(decorations);\n    }\n\n    /// Start a window resize operation (Wayland)\n    pub fn start_window_resize(&self, edge: ResizeEdge) {\n        self.platform_window.start_window_resize(edge);\n    }\n\n    /// Return the `WindowBounds` to indicate that how a window should be opened\n    /// after it has been closed\n    pub fn window_bounds(&self) -> WindowBounds {\n        self.platform_window.window_bounds()\n    }\n\n    /// Return the `WindowBounds` excluding insets (Wayland and X11)\n    pub fn inner_window_bounds(&self) -> WindowBounds {\n        self.platform_window.inner_window_bounds()\n    }\n\n    /// Dispatch the given action on the currently focused element.\n    pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {\n        let focus_handle = self.focused(cx);\n\n        let window = self.handle;\n        cx.defer(move |cx| {\n            window\n                .update(cx, |_, window, cx| {\n                    let node_id = focus_handle\n                        .and_then(|handle| {\n                            window\n                                .rendered_frame\n                                .dispatch_tree\n                                .focusable_node_id(handle.id)\n                        })\n                        .unwrap_or_else(|| window.rendered_frame.dispatch_tree.root_node_id());\n\n                    window.dispatch_action_on_node(node_id, action.as_ref(), cx);\n                })\n                .log_err();\n        })\n    }\n\n    pub(crate) fn dispatch_keystroke_observers(\n        &mut self,\n        event: &dyn Any,\n        action: Option<Box<dyn Action>>,\n        context_stack: Vec<KeyContext>,\n        cx: &mut App,\n    ) {\n        let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {\n            return;\n        };\n\n        cx.keystroke_observers.clone().retain(&(), move |callback| {\n            (callback)(\n                &KeystrokeEvent {\n                    keystroke: key_down_event.keystroke.clone(),\n                    action: action.as_ref().map(|action| action.boxed_clone()),\n                    context_stack: context_stack.clone(),\n                },\n                self,\n                cx,\n            )\n        });\n    }\n\n    /// Schedules the given function to be run at the end of the current effect cycle, allowing entities\n    /// that are currently on the stack to be returned to the app.\n    pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {\n        let handle = self.handle;\n        cx.defer(move |cx| {\n            handle.update(cx, |_, window, cx| f(window, cx)).ok();\n        });\n    }\n\n    /// Subscribe to events emitted by a entity.\n    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.\n    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.\n    pub fn observe<T: 'static>(\n        &mut self,\n        observed: &Entity<T>,\n        cx: &mut App,\n        mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let entity_id = observed.entity_id();\n        let observed = observed.downgrade();\n        let window_handle = self.handle;\n        cx.new_observer(\n            entity_id,\n            Box::new(move |cx| {\n                window_handle\n                    .update(cx, |_, window, cx| {\n                        if let Some(handle) = observed.upgrade() {\n                            on_notify(handle, window, cx);\n                            true\n                        } else {\n                            false\n                        }\n                    })\n                    .unwrap_or(false)\n            }),\n        )\n    }\n\n    /// Subscribe to events emitted by a entity.\n    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.\n    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.\n    pub fn subscribe<Emitter, Evt>(\n        &mut self,\n        entity: &Entity<Emitter>,\n        cx: &mut App,\n        mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,\n    ) -> Subscription\n    where\n        Emitter: EventEmitter<Evt>,\n        Evt: 'static,\n    {\n        let entity_id = entity.entity_id();\n        let handle = entity.downgrade();\n        let window_handle = self.handle;\n        cx.new_subscription(\n            entity_id,\n            (\n                TypeId::of::<Evt>(),\n                Box::new(move |event, cx| {\n                    window_handle\n                        .update(cx, |_, window, cx| {\n                            if let Some(entity) = handle.upgrade() {\n                                let event = event.downcast_ref().expect(\"invalid event type\");\n                                on_event(entity, event, window, cx);\n                                true\n                            } else {\n                                false\n                            }\n                        })\n                        .unwrap_or(false)\n                }),\n            ),\n        )\n    }\n\n    /// Register a callback to be invoked when the given `Entity` is released.\n    pub fn observe_release<T>(\n        &self,\n        entity: &Entity<T>,\n        cx: &mut App,\n        mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,\n    ) -> Subscription\n    where\n        T: 'static,\n    {\n        let entity_id = entity.entity_id();\n        let window_handle = self.handle;\n        let (subscription, activate) = cx.release_listeners.insert(\n            entity_id,\n            Box::new(move |entity, cx| {\n                let entity = entity.downcast_mut().expect(\"invalid entity type\");\n                let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));\n            }),\n        );\n        activate();\n        subscription\n    }\n\n    /// Creates an [`AsyncWindowContext`], which has a static lifetime and can be held across\n    /// await points in async code.\n    pub fn to_async(&self, cx: &App) -> AsyncWindowContext {\n        AsyncWindowContext::new_context(cx.to_async(), self.handle)\n    }\n\n    /// Schedule the given closure to be run directly after the current frame is rendered.\n    pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) {\n        RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback));\n    }\n\n    /// Schedule a frame to be drawn on the next animation frame.\n    ///\n    /// This is useful for elements that need to animate continuously, such as a video player or an animated GIF.\n    /// It will cause the window to redraw on the next frame, even if no other changes have occurred.\n    ///\n    /// If called from within a view, it will notify that view on the next frame. Otherwise, it will refresh the entire window.\n    pub fn request_animation_frame(&self) {\n        let entity = self.current_view();\n        self.on_next_frame(move |_, cx| cx.notify(entity));\n    }\n\n    /// Spawn the future returned by the given closure on the application thread pool.\n    /// The closure is provided a handle to the current window and an `AsyncWindowContext` for\n    /// use within your future.\n    #[track_caller]\n    pub fn spawn<AsyncFn, R>(&self, cx: &App, f: AsyncFn) -> Task<R>\n    where\n        R: 'static,\n        AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,\n    {\n        let handle = self.handle;\n        cx.spawn(async move |app| {\n            let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);\n            f(&mut async_window_cx).await\n        })\n    }\n\n    fn bounds_changed(&mut self, cx: &mut App) {\n        self.scale_factor = self.platform_window.scale_factor();\n        self.viewport_size = self.platform_window.content_size();\n        self.display_id = self.platform_window.display().map(|display| display.id());\n\n        self.refresh();\n\n        self.bounds_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    /// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays.\n    pub fn bounds(&self) -> Bounds<Pixels> {\n        self.platform_window.bounds()\n    }\n\n    /// Set the content size of the window.\n    pub fn resize(&mut self, size: Size<Pixels>) {\n        self.platform_window.resize(size);\n    }\n\n    /// Returns whether or not the window is currently fullscreen\n    pub fn is_fullscreen(&self) -> bool {\n        self.platform_window.is_fullscreen()\n    }\n\n    pub(crate) fn appearance_changed(&mut self, cx: &mut App) {\n        self.appearance = self.platform_window.appearance();\n\n        self.appearance_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    /// Returns the appearance of the current window.\n    pub fn appearance(&self) -> WindowAppearance {\n        self.appearance\n    }\n\n    /// Returns the size of the drawable area within the window.\n    pub fn viewport_size(&self) -> Size<Pixels> {\n        self.viewport_size\n    }\n\n    /// Returns whether this window is focused by the operating system (receiving key events).\n    pub fn is_window_active(&self) -> bool {\n        self.active.get()\n    }\n\n    /// Returns whether this window is considered to be the window\n    /// that currently owns the mouse cursor.\n    /// On mac, this is equivalent to `is_window_active`.\n    pub fn is_window_hovered(&self) -> bool {\n        if cfg!(any(\n            target_os = \"windows\",\n            target_os = \"linux\",\n            target_os = \"freebsd\"\n        )) {\n            self.hovered.get()\n        } else {\n            self.is_window_active()\n        }\n    }\n\n    /// Toggle zoom on the window.\n    pub fn zoom_window(&self) {\n        self.platform_window.zoom();\n    }\n\n    /// Opens the native title bar context menu, useful when implementing client side decorations (Wayland and X11)\n    pub fn show_window_menu(&self, position: Point<Pixels>) {\n        self.platform_window.show_window_menu(position)\n    }\n\n    /// Tells the compositor to take control of window movement (Wayland and X11)\n    ///\n    /// Events may not be received during a move operation.\n    pub fn start_window_move(&self) {\n        self.platform_window.start_window_move()\n    }\n\n    /// When using client side decorations, set this to the width of the invisible decorations (Wayland and X11)\n    pub fn set_client_inset(&mut self, inset: Pixels) {\n        self.client_inset = Some(inset);\n        self.platform_window.set_client_inset(inset);\n    }\n\n    /// Returns the client_inset value by [`Self::set_client_inset`].\n    pub fn client_inset(&self) -> Option<Pixels> {\n        self.client_inset\n    }\n\n    /// Returns whether the title bar window controls need to be rendered by the application (Wayland and X11)\n    pub fn window_decorations(&self) -> Decorations {\n        self.platform_window.window_decorations()\n    }\n\n    /// Returns which window controls are currently visible (Wayland)\n    pub fn window_controls(&self) -> WindowControls {\n        self.platform_window.window_controls()\n    }\n\n    /// Updates the window's title at the platform level.\n    pub fn set_window_title(&mut self, title: &str) {\n        self.platform_window.set_title(title);\n    }\n\n    /// Sets the application identifier.\n    pub fn set_app_id(&mut self, app_id: &str) {\n        self.platform_window.set_app_id(app_id);\n    }\n\n    /// Sets the window background appearance.\n    pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {\n        self.platform_window\n            .set_background_appearance(background_appearance);\n    }\n\n    /// Mark the window as dirty at the platform level.\n    pub fn set_window_edited(&mut self, edited: bool) {\n        self.platform_window.set_edited(edited);\n    }\n\n    /// Determine the display on which the window is visible.\n    pub fn display(&self, cx: &App) -> Option<Rc<dyn PlatformDisplay>> {\n        cx.platform\n            .displays()\n            .into_iter()\n            .find(|display| Some(display.id()) == self.display_id)\n    }\n\n    /// Show the platform character palette.\n    pub fn show_character_palette(&self) {\n        self.platform_window.show_character_palette();\n    }\n\n    /// The scale factor of the display associated with the window. For example, it could\n    /// return 2.0 for a \"retina\" display, indicating that each logical pixel should actually\n    /// be rendered as two pixels on screen.\n    pub fn scale_factor(&self) -> f32 {\n        self.scale_factor\n    }\n\n    /// The size of an em for the base font of the application. Adjusting this value allows the\n    /// UI to scale, just like zooming a web page.\n    pub fn rem_size(&self) -> Pixels {\n        self.rem_size_override_stack\n            .last()\n            .copied()\n            .unwrap_or(self.rem_size)\n    }\n\n    /// Sets the size of an em for the base font of the application. Adjusting this value allows the\n    /// UI to scale, just like zooming a web page.\n    pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {\n        self.rem_size = rem_size.into();\n    }\n\n    /// Acquire a globally unique identifier for the given ElementId.\n    /// Only valid for the duration of the provided closure.\n    pub fn with_global_id<R>(\n        &mut self,\n        element_id: ElementId,\n        f: impl FnOnce(&GlobalElementId, &mut Self) -> R,\n    ) -> R {\n        self.element_id_stack.push(element_id);\n        let global_id = GlobalElementId(self.element_id_stack.clone());\n        let result = f(&global_id, self);\n        self.element_id_stack.pop();\n        result\n    }\n\n    /// Executes the provided function with the specified rem size.\n    ///\n    /// This method must only be called as part of element drawing.\n    pub fn with_rem_size<F, R>(&mut self, rem_size: Option<impl Into<Pixels>>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        if let Some(rem_size) = rem_size {\n            self.rem_size_override_stack.push(rem_size.into());\n            let result = f(self);\n            self.rem_size_override_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// The line height associated with the current text style.\n    pub fn line_height(&self) -> Pixels {\n        self.text_style().line_height_in_pixels(self.rem_size())\n    }\n\n    /// Call to prevent the default action of an event. Currently only used to prevent\n    /// parent elements from becoming focused on mouse down.\n    pub fn prevent_default(&mut self) {\n        self.default_prevented = true;\n    }\n\n    /// Obtain whether default has been prevented for the event currently being dispatched.\n    pub fn default_prevented(&self) -> bool {\n        self.default_prevented\n    }\n\n    /// Determine whether the given action is available along the dispatch path to the currently focused element.\n    pub fn is_action_available(&self, action: &dyn Action, cx: &mut App) -> bool {\n        let target = self\n            .focused(cx)\n            .and_then(|focused_handle| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focused_handle.id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n        self.rendered_frame\n            .dispatch_tree\n            .is_action_available(action, target)\n    }\n\n    /// The position of the mouse relative to the window.\n    pub fn mouse_position(&self) -> Point<Pixels> {\n        self.mouse_position\n    }\n\n    /// The current state of the keyboard's modifiers\n    pub fn modifiers(&self) -> Modifiers {\n        self.modifiers\n    }\n\n    fn complete_frame(&self) {\n        self.platform_window.completed_frame();\n    }\n\n    /// Produces a new frame and assigns it to `rendered_frame`. To actually show\n    /// the contents of the new [Scene], use [present].\n    #[profiling::function]\n    pub fn draw(&mut self, cx: &mut App) {\n        self.invalidate_entities();\n        cx.entities.clear_accessed();\n        debug_assert!(self.rendered_entity_stack.is_empty());\n        self.invalidator.set_dirty(false);\n        self.requested_autoscroll = None;\n\n        // Restore the previously-used input handler.\n        if let Some(input_handler) = self.platform_window.take_input_handler() {\n            self.rendered_frame.input_handlers.push(Some(input_handler));\n        }\n        self.draw_roots(cx);\n        self.dirty_views.clear();\n        self.next_frame.window_active = self.active.get();\n\n        // Register requested input handler with the platform window.\n        if let Some(input_handler) = self.next_frame.input_handlers.pop() {\n            self.platform_window\n                .set_input_handler(input_handler.unwrap());\n        }\n\n        self.layout_engine.as_mut().unwrap().clear();\n        self.text_system().finish_frame();\n        self.next_frame.finish(&mut self.rendered_frame);\n        ELEMENT_ARENA.with_borrow_mut(|element_arena| {\n            let percentage = (element_arena.len() as f32 / element_arena.capacity() as f32) * 100.;\n            if percentage >= 80. {\n                log::warn!(\"elevated element arena occupation: {}.\", percentage);\n            }\n            element_arena.clear();\n        });\n\n        self.invalidator.set_phase(DrawPhase::Focus);\n        let previous_focus_path = self.rendered_frame.focus_path();\n        let previous_window_active = self.rendered_frame.window_active;\n        mem::swap(&mut self.rendered_frame, &mut self.next_frame);\n        self.next_frame.clear();\n        let current_focus_path = self.rendered_frame.focus_path();\n        let current_window_active = self.rendered_frame.window_active;\n\n        if previous_focus_path != current_focus_path\n            || previous_window_active != current_window_active\n        {\n            if !previous_focus_path.is_empty() && current_focus_path.is_empty() {\n                self.focus_lost_listeners\n                    .clone()\n                    .retain(&(), |listener| listener(self, cx));\n            }\n\n            let event = WindowFocusEvent {\n                previous_focus_path: if previous_window_active {\n                    previous_focus_path\n                } else {\n                    Default::default()\n                },\n                current_focus_path: if current_window_active {\n                    current_focus_path\n                } else {\n                    Default::default()\n                },\n            };\n            self.focus_listeners\n                .clone()\n                .retain(&(), |listener| listener(&event, self, cx));\n        }\n\n        debug_assert!(self.rendered_entity_stack.is_empty());\n        self.record_entities_accessed(cx);\n        self.reset_cursor_style(cx);\n        self.refreshing = false;\n        self.invalidator.set_phase(DrawPhase::None);\n        self.needs_present.set(true);\n    }\n\n    fn record_entities_accessed(&mut self, cx: &mut App) {\n        let mut entities_ref = cx.entities.accessed_entities.borrow_mut();\n        let mut entities = mem::take(entities_ref.deref_mut());\n        drop(entities_ref);\n        let handle = self.handle;\n        cx.record_entities_accessed(\n            handle,\n            // Try moving window invalidator into the Window\n            self.invalidator.clone(),\n            &entities,\n        );\n        let mut entities_ref = cx.entities.accessed_entities.borrow_mut();\n        mem::swap(&mut entities, entities_ref.deref_mut());\n    }\n\n    fn invalidate_entities(&mut self) {\n        let mut views = self.invalidator.take_views();\n        for entity in views.drain() {\n            self.mark_view_dirty(entity);\n        }\n        self.invalidator.replace_views(views);\n    }\n\n    #[profiling::function]\n    fn present(&self) {\n        self.platform_window.draw(&self.rendered_frame.scene);\n        self.needs_present.set(false);\n        profiling::finish_frame!();\n    }\n\n    fn draw_roots(&mut self, cx: &mut App) {\n        self.invalidator.set_phase(DrawPhase::Prepaint);\n        self.tooltip_bounds.take();\n\n        // Layout all root elements.\n        let mut root_element = self.root.as_ref().unwrap().clone().into_any();\n        root_element.prepaint_as_root(Point::default(), self.viewport_size.into(), self, cx);\n\n        let mut sorted_deferred_draws =\n            (0..self.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>();\n        sorted_deferred_draws.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);\n        self.prepaint_deferred_draws(&sorted_deferred_draws, cx);\n\n        let mut prompt_element = None;\n        let mut active_drag_element = None;\n        let mut tooltip_element = None;\n        if let Some(prompt) = self.prompt.take() {\n            let mut element = prompt.view.any_view().into_any();\n            element.prepaint_as_root(Point::default(), self.viewport_size.into(), self, cx);\n            prompt_element = Some(element);\n            self.prompt = Some(prompt);\n        } else if let Some(active_drag) = cx.active_drag.take() {\n            let mut element = active_drag.view.clone().into_any();\n            let offset = self.mouse_position() - active_drag.cursor_offset;\n            element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx);\n            active_drag_element = Some(element);\n            cx.active_drag = Some(active_drag);\n        } else {\n            tooltip_element = self.prepaint_tooltip(cx);\n        }\n\n        self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position);\n\n        // Now actually paint the elements.\n        self.invalidator.set_phase(DrawPhase::Paint);\n        root_element.paint(self, cx);\n\n        self.paint_deferred_draws(&sorted_deferred_draws, cx);\n\n        if let Some(mut prompt_element) = prompt_element {\n            prompt_element.paint(self, cx);\n        } else if let Some(mut drag_element) = active_drag_element {\n            drag_element.paint(self, cx);\n        } else if let Some(mut tooltip_element) = tooltip_element {\n            tooltip_element.paint(self, cx);\n        }\n    }\n\n    fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {\n        // Use indexing instead of iteration to avoid borrowing self for the duration of the loop.\n        for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() {\n            let Some(Some(tooltip_request)) = self\n                .next_frame\n                .tooltip_requests\n                .get(tooltip_request_index)\n                .cloned()\n            else {\n                log::error!(\"Unexpectedly absent TooltipRequest\");\n                continue;\n            };\n            let mut element = tooltip_request.tooltip.view.clone().into_any();\n            let mouse_position = tooltip_request.tooltip.mouse_position;\n            let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);\n\n            let mut tooltip_bounds =\n                Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);\n            let window_bounds = Bounds {\n                origin: Point::default(),\n                size: self.viewport_size(),\n            };\n\n            if tooltip_bounds.right() > window_bounds.right() {\n                let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);\n                if new_x >= Pixels::ZERO {\n                    tooltip_bounds.origin.x = new_x;\n                } else {\n                    tooltip_bounds.origin.x = cmp::max(\n                        Pixels::ZERO,\n                        tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),\n                    );\n                }\n            }\n\n            if tooltip_bounds.bottom() > window_bounds.bottom() {\n                let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);\n                if new_y >= Pixels::ZERO {\n                    tooltip_bounds.origin.y = new_y;\n                } else {\n                    tooltip_bounds.origin.y = cmp::max(\n                        Pixels::ZERO,\n                        tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),\n                    );\n                }\n            }\n\n            // It's possible for an element to have an active tooltip while not being painted (e.g.\n            // via the `visible_on_hover` method). Since mouse listeners are not active in this\n            // case, instead update the tooltip's visibility here.\n            let is_visible =\n                (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);\n            if !is_visible {\n                continue;\n            }\n\n            self.with_absolute_element_offset(tooltip_bounds.origin, |window| {\n                element.prepaint(window, cx)\n            });\n\n            self.tooltip_bounds = Some(TooltipBounds {\n                id: tooltip_request.id,\n                bounds: tooltip_bounds,\n            });\n            return Some(element);\n        }\n        None\n    }\n\n    fn prepaint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {\n        assert_eq!(self.element_id_stack.len(), 0);\n\n        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);\n        for deferred_draw_ix in deferred_draw_indices {\n            let deferred_draw = &mut deferred_draws[*deferred_draw_ix];\n            self.element_id_stack\n                .clone_from(&deferred_draw.element_id_stack);\n            self.text_style_stack\n                .clone_from(&deferred_draw.text_style_stack);\n            self.next_frame\n                .dispatch_tree\n                .set_active_node(deferred_draw.parent_node);\n\n            let prepaint_start = self.prepaint_index();\n            if let Some(element) = deferred_draw.element.as_mut() {\n                self.with_rendered_view(deferred_draw.current_view, |window| {\n                    window.with_absolute_element_offset(deferred_draw.absolute_offset, |window| {\n                        element.prepaint(window, cx)\n                    });\n                })\n            } else {\n                self.reuse_prepaint(deferred_draw.prepaint_range.clone());\n            }\n            let prepaint_end = self.prepaint_index();\n            deferred_draw.prepaint_range = prepaint_start..prepaint_end;\n        }\n        assert_eq!(\n            self.next_frame.deferred_draws.len(),\n            0,\n            \"cannot call defer_draw during deferred drawing\"\n        );\n        self.next_frame.deferred_draws = deferred_draws;\n        self.element_id_stack.clear();\n        self.text_style_stack.clear();\n    }\n\n    fn paint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {\n        assert_eq!(self.element_id_stack.len(), 0);\n\n        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);\n        for deferred_draw_ix in deferred_draw_indices {\n            let mut deferred_draw = &mut deferred_draws[*deferred_draw_ix];\n            self.element_id_stack\n                .clone_from(&deferred_draw.element_id_stack);\n            self.next_frame\n                .dispatch_tree\n                .set_active_node(deferred_draw.parent_node);\n\n            let paint_start = self.paint_index();\n            if let Some(element) = deferred_draw.element.as_mut() {\n                self.with_rendered_view(deferred_draw.current_view, |window| {\n                    element.paint(window, cx);\n                })\n            } else {\n                self.reuse_paint(deferred_draw.paint_range.clone());\n            }\n            let paint_end = self.paint_index();\n            deferred_draw.paint_range = paint_start..paint_end;\n        }\n        self.next_frame.deferred_draws = deferred_draws;\n        self.element_id_stack.clear();\n    }\n\n    pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {\n        PrepaintStateIndex {\n            hitboxes_index: self.next_frame.hitboxes.len(),\n            tooltips_index: self.next_frame.tooltip_requests.len(),\n            deferred_draws_index: self.next_frame.deferred_draws.len(),\n            dispatch_tree_index: self.next_frame.dispatch_tree.len(),\n            accessed_element_states_index: self.next_frame.accessed_element_states.len(),\n            line_layout_index: self.text_system.layout_index(),\n        }\n    }\n\n    pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {\n        self.next_frame.hitboxes.extend(\n            self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]\n                .iter()\n                .cloned(),\n        );\n        self.next_frame.tooltip_requests.extend(\n            self.rendered_frame.tooltip_requests\n                [range.start.tooltips_index..range.end.tooltips_index]\n                .iter_mut()\n                .map(|request| request.take()),\n        );\n        self.next_frame.accessed_element_states.extend(\n            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index\n                ..range.end.accessed_element_states_index]\n                .iter()\n                .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),\n        );\n        self.text_system\n            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);\n\n        let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree(\n            range.start.dispatch_tree_index..range.end.dispatch_tree_index,\n            &mut self.rendered_frame.dispatch_tree,\n            self.focus,\n        );\n\n        if reused_subtree.contains_focus() {\n            self.next_frame.focus = self.focus;\n        }\n\n        self.next_frame.deferred_draws.extend(\n            self.rendered_frame.deferred_draws\n                [range.start.deferred_draws_index..range.end.deferred_draws_index]\n                .iter()\n                .map(|deferred_draw| DeferredDraw {\n                    current_view: deferred_draw.current_view,\n                    parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),\n                    element_id_stack: deferred_draw.element_id_stack.clone(),\n                    text_style_stack: deferred_draw.text_style_stack.clone(),\n                    priority: deferred_draw.priority,\n                    element: None,\n                    absolute_offset: deferred_draw.absolute_offset,\n                    prepaint_range: deferred_draw.prepaint_range.clone(),\n                    paint_range: deferred_draw.paint_range.clone(),\n                }),\n        );\n    }\n\n    pub(crate) fn paint_index(&self) -> PaintIndex {\n        PaintIndex {\n            scene_index: self.next_frame.scene.len(),\n            mouse_listeners_index: self.next_frame.mouse_listeners.len(),\n            input_handlers_index: self.next_frame.input_handlers.len(),\n            cursor_styles_index: self.next_frame.cursor_styles.len(),\n            accessed_element_states_index: self.next_frame.accessed_element_states.len(),\n            line_layout_index: self.text_system.layout_index(),\n        }\n    }\n\n    pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {\n        self.next_frame.cursor_styles.extend(\n            self.rendered_frame.cursor_styles\n                [range.start.cursor_styles_index..range.end.cursor_styles_index]\n                .iter()\n                .cloned(),\n        );\n        self.next_frame.input_handlers.extend(\n            self.rendered_frame.input_handlers\n                [range.start.input_handlers_index..range.end.input_handlers_index]\n                .iter_mut()\n                .map(|handler| handler.take()),\n        );\n        self.next_frame.mouse_listeners.extend(\n            self.rendered_frame.mouse_listeners\n                [range.start.mouse_listeners_index..range.end.mouse_listeners_index]\n                .iter_mut()\n                .map(|listener| listener.take()),\n        );\n        self.next_frame.accessed_element_states.extend(\n            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index\n                ..range.end.accessed_element_states_index]\n                .iter()\n                .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),\n        );\n\n        self.text_system\n            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);\n        self.next_frame.scene.replay(\n            range.start.scene_index..range.end.scene_index,\n            &self.rendered_frame.scene,\n        );\n    }\n\n    /// Push a text style onto the stack, and call a function with that style active.\n    /// Use [`Window::text_style`] to get the current, combined text style. This method\n    /// should only be called as part of element drawing.\n    pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        if let Some(style) = style {\n            self.text_style_stack.push(style);\n            let result = f(self);\n            self.text_style_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Updates the cursor style at the platform level. This method should only be called\n    /// during the prepaint phase of element drawing.\n    pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: Option<&Hitbox>) {\n        self.invalidator.debug_assert_paint();\n        self.next_frame.cursor_styles.push(CursorStyleRequest {\n            hitbox_id: hitbox.map(|hitbox| hitbox.id),\n            style,\n        });\n    }\n\n    /// Sets a tooltip to be rendered for the upcoming frame. This method should only be called\n    /// during the paint phase of element drawing.\n    pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {\n        self.invalidator.debug_assert_prepaint();\n        let id = TooltipId(post_inc(&mut self.next_tooltip_id.0));\n        self.next_frame\n            .tooltip_requests\n            .push(Some(TooltipRequest { id, tooltip }));\n        id\n    }\n\n    /// Invoke the given function with the given content mask after intersecting it\n    /// with the current mask. This method should only be called during element drawing.\n    pub fn with_content_mask<R>(\n        &mut self,\n        mask: Option<ContentMask<Pixels>>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        if let Some(mask) = mask {\n            let mask = mask.intersect(&self.content_mask());\n            self.content_mask_stack.push(mask);\n            let result = f(self);\n            self.content_mask_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Updates the global element offset relative to the current offset. This is used to implement\n    /// scrolling. This method should only be called during the prepaint phase of element drawing.\n    pub fn with_element_offset<R>(\n        &mut self,\n        offset: Point<Pixels>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_prepaint();\n\n        if offset.is_zero() {\n            return f(self);\n        };\n\n        let abs_offset = self.element_offset() + offset;\n        self.with_absolute_element_offset(abs_offset, f)\n    }\n\n    /// Updates the global element offset based on the given offset. This is used to implement\n    /// drag handles and other manual painting of elements. This method should only be called during\n    /// the prepaint phase of element drawing.\n    pub fn with_absolute_element_offset<R>(\n        &mut self,\n        offset: Point<Pixels>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_prepaint();\n        self.element_offset_stack.push(offset);\n        let result = f(self);\n        self.element_offset_stack.pop();\n        result\n    }\n\n    pub(crate) fn with_element_opacity<R>(\n        &mut self,\n        opacity: Option<f32>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        if opacity.is_none() {\n            return f(self);\n        }\n\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.element_opacity = opacity;\n        let result = f(self);\n        self.element_opacity = None;\n        result\n    }\n\n    /// Perform prepaint on child elements in a \"retryable\" manner, so that any side effects\n    /// of prepaints can be discarded before prepainting again. This is used to support autoscroll\n    /// where we need to prepaint children to detect the autoscroll bounds, then adjust the\n    /// element offset and prepaint again. See [`List`] for an example. This method should only be\n    /// called during the prepaint phase of element drawing.\n    pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {\n        self.invalidator.debug_assert_prepaint();\n        let index = self.prepaint_index();\n        let result = f(self);\n        if result.is_err() {\n            self.next_frame.hitboxes.truncate(index.hitboxes_index);\n            self.next_frame\n                .tooltip_requests\n                .truncate(index.tooltips_index);\n            self.next_frame\n                .deferred_draws\n                .truncate(index.deferred_draws_index);\n            self.next_frame\n                .dispatch_tree\n                .truncate(index.dispatch_tree_index);\n            self.next_frame\n                .accessed_element_states\n                .truncate(index.accessed_element_states_index);\n            self.text_system.truncate_layouts(index.line_layout_index);\n        }\n        result\n    }\n\n    /// When you call this method during [`prepaint`], containing elements will attempt to\n    /// scroll to cause the specified bounds to become visible. When they decide to autoscroll, they will call\n    /// [`prepaint`] again with a new set of bounds. See [`List`] for an example of an element\n    /// that supports this method being called on the elements it contains. This method should only be\n    /// called during the prepaint phase of element drawing.\n    pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {\n        self.invalidator.debug_assert_prepaint();\n        self.requested_autoscroll = Some(bounds);\n    }\n\n    /// This method can be called from a containing element such as [`List`] to support the autoscroll behavior\n    /// described in [`request_autoscroll`].\n    pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {\n        self.invalidator.debug_assert_prepaint();\n        self.requested_autoscroll.take()\n    }\n\n    /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.\n    /// Your view will be re-drawn once the asset has finished loading.\n    ///\n    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a\n    /// time.\n    pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {\n        let (task, is_first) = cx.fetch_asset::<A>(source);\n        task.clone().now_or_never().or_else(|| {\n            if is_first {\n                let entity_id = self.current_view();\n                self.spawn(cx, {\n                    let task = task.clone();\n                    async move |cx| {\n                        task.await;\n\n                        cx.on_next_frame(move |_, cx| {\n                            cx.notify(entity_id);\n                        });\n                    }\n                })\n                .detach();\n            }\n\n            None\n        })\n    }\n\n    /// Asynchronously load an asset, if the asset hasn't finished loading or doesn't exist this will return None.\n    /// Your view will not be re-drawn once the asset has finished loading.\n    ///\n    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a\n    /// time.\n    pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {\n        let (task, _) = cx.fetch_asset::<A>(source);\n        task.clone().now_or_never()\n    }\n    /// Obtain the current element offset. This method should only be called during the\n    /// prepaint phase of element drawing.\n    pub fn element_offset(&self) -> Point<Pixels> {\n        self.invalidator.debug_assert_prepaint();\n        self.element_offset_stack\n            .last()\n            .copied()\n            .unwrap_or_default()\n    }\n\n    /// Obtain the current element opacity. This method should only be called during the\n    /// prepaint phase of element drawing.\n    pub(crate) fn element_opacity(&self) -> f32 {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.element_opacity.unwrap_or(1.0)\n    }\n\n    /// Obtain the current content mask. This method should only be called during element drawing.\n    pub fn content_mask(&self) -> ContentMask<Pixels> {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.content_mask_stack\n            .last()\n            .cloned()\n            .unwrap_or_else(|| ContentMask {\n                bounds: Bounds {\n                    origin: Point::default(),\n                    size: self.viewport_size,\n                },\n            })\n    }\n\n    /// Provide elements in the called function with a new namespace in which their identifiers must be unique.\n    /// This can be used within a custom element to distinguish multiple sets of child elements.\n    pub fn with_element_namespace<R>(\n        &mut self,\n        element_id: impl Into<ElementId>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.element_id_stack.push(element_id.into());\n        let result = f(self);\n        self.element_id_stack.pop();\n        result\n    }\n\n    /// Updates or initializes state for an element with the given id that lives across multiple\n    /// frames. If an element with this ID existed in the rendered frame, its state will be passed\n    /// to the given closure. The state returned by the closure will be stored so it can be referenced\n    /// when drawing the next frame. This method should only be called as part of element drawing.\n    pub fn with_element_state<S, R>(\n        &mut self,\n        global_id: &GlobalElementId,\n        f: impl FnOnce(Option<S>, &mut Self) -> (R, S),\n    ) -> R\n    where\n        S: 'static,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        let key = (GlobalElementId(global_id.0.clone()), TypeId::of::<S>());\n        self.next_frame\n            .accessed_element_states\n            .push((GlobalElementId(key.0.clone()), TypeId::of::<S>()));\n\n        if let Some(any) = self\n            .next_frame\n            .element_states\n            .remove(&key)\n            .or_else(|| self.rendered_frame.element_states.remove(&key))\n        {\n            let ElementStateBox {\n                inner,\n                #[cfg(debug_assertions)]\n                type_name,\n            } = any;\n            // Using the extra inner option to avoid needing to reallocate a new box.\n            let mut state_box = inner\n                .downcast::<Option<S>>()\n                .map_err(|_| {\n                    #[cfg(debug_assertions)]\n                    {\n                        anyhow::anyhow!(\n                            \"invalid element state type for id, requested {:?}, actual: {:?}\",\n                            std::any::type_name::<S>(),\n                            type_name\n                        )\n                    }\n\n                    #[cfg(not(debug_assertions))]\n                    {\n                        anyhow::anyhow!(\n                            \"invalid element state type for id, requested {:?}\",\n                            std::any::type_name::<S>(),\n                        )\n                    }\n                })\n                .unwrap();\n\n            let state = state_box.take().expect(\n                \"reentrant call to with_element_state for the same state type and element id\",\n            );\n            let (result, state) = f(Some(state), self);\n            state_box.replace(state);\n            self.next_frame.element_states.insert(\n                key,\n                ElementStateBox {\n                    inner: state_box,\n                    #[cfg(debug_assertions)]\n                    type_name,\n                },\n            );\n            result\n        } else {\n            let (result, state) = f(None, self);\n            self.next_frame.element_states.insert(\n                key,\n                ElementStateBox {\n                    inner: Box::new(Some(state)),\n                    #[cfg(debug_assertions)]\n                    type_name: std::any::type_name::<S>(),\n                },\n            );\n            result\n        }\n    }\n\n    /// A variant of `with_element_state` that allows the element's id to be optional. This is a convenience\n    /// method for elements where the element id may or may not be assigned. Prefer using `with_element_state`\n    /// when the element is guaranteed to have an id.\n    ///\n    /// The first option means 'no ID provided'\n    /// The second option means 'not yet initialized'\n    pub fn with_optional_element_state<S, R>(\n        &mut self,\n        global_id: Option<&GlobalElementId>,\n        f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),\n    ) -> R\n    where\n        S: 'static,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        if let Some(global_id) = global_id {\n            self.with_element_state(global_id, |state, cx| {\n                let (result, state) = f(Some(state), cx);\n                let state =\n                    state.expect(\"you must return some state when you pass some element id\");\n                (result, state)\n            })\n        } else {\n            let (result, state) = f(None, self);\n            debug_assert!(\n                state.is_none(),\n                \"you must not return an element state when passing None for the global id\"\n            );\n            result\n        }\n    }\n\n    /// Defers the drawing of the given element, scheduling it to be painted on top of the currently-drawn tree\n    /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements,\n    /// with higher values being drawn on top.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn defer_draw(\n        &mut self,\n        element: AnyElement,\n        absolute_offset: Point<Pixels>,\n        priority: usize,\n    ) {\n        self.invalidator.debug_assert_prepaint();\n        let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();\n        self.next_frame.deferred_draws.push(DeferredDraw {\n            current_view: self.current_view(),\n            parent_node,\n            element_id_stack: self.element_id_stack.clone(),\n            text_style_stack: self.text_style_stack.clone(),\n            priority,\n            element: Some(element),\n            absolute_offset,\n            prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),\n            paint_range: PaintIndex::default()..PaintIndex::default(),\n        });\n    }\n\n    /// Creates a new painting layer for the specified bounds. A \"layer\" is a batch\n    /// of geometry that are non-overlapping and have the same draw order. This is typically used\n    /// for performance reasons.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let clipped_bounds = bounds.intersect(&content_mask.bounds);\n        if !clipped_bounds.is_empty() {\n            self.next_frame\n                .scene\n                .push_layer(clipped_bounds.scale(scale_factor));\n        }\n\n        let result = f(self);\n\n        if !clipped_bounds.is_empty() {\n            self.next_frame.scene.pop_layer();\n        }\n\n        result\n    }\n\n    /// Paint one or more drop shadows into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_shadows(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        corner_radii: Corners<Pixels>,\n        shadows: &[BoxShadow],\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        for shadow in shadows {\n            let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius);\n            self.next_frame.scene.insert_primitive(Shadow {\n                order: 0,\n                blur_radius: shadow.blur_radius.scale(scale_factor),\n                bounds: shadow_bounds.scale(scale_factor),\n                content_mask: content_mask.scale(scale_factor),\n                corner_radii: corner_radii.scale(scale_factor),\n                color: shadow.color.opacity(opacity),\n            });\n        }\n    }\n\n    /// Paint one or more quads into the scene for the next frame at the current stacking context.\n    /// Quads are colored rectangular regions with an optional background, border, and corner radius.\n    /// see [`fill`](crate::fill), [`outline`](crate::outline), and [`quad`](crate::quad) to construct this type.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    ///\n    /// Note that the `quad.corner_radii` are allowed to exceed the bounds, creating sharp corners\n    /// where the circular arcs meet. This will not display well when combined with dashed borders.\n    /// Use `Corners::clamp_radii_for_quad_size` if the radii should fit within the bounds.\n    pub fn paint_quad(&mut self, quad: PaintQuad) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        self.next_frame.scene.insert_primitive(Quad {\n            order: 0,\n            bounds: quad.bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            background: quad.background.opacity(opacity),\n            border_color: quad.border_color.opacity(opacity),\n            corner_radii: quad.corner_radii.scale(scale_factor),\n            border_widths: quad.border_widths.scale(scale_factor),\n            border_style: quad.border_style,\n            transformation: quad.transformation,\n        });\n    }\n\n    /// Paint the given `Path` into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        path.content_mask = content_mask;\n        let color: Background = color.into();\n        path.color = color.opacity(opacity);\n        self.next_frame\n            .scene\n            .insert_primitive(path.scale(scale_factor));\n    }\n\n    /// Paint an underline into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_underline(\n        &mut self,\n        origin: Point<Pixels>,\n        width: Pixels,\n        style: &UnderlineStyle,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let height = if style.wavy {\n            style.thickness * 3.\n        } else {\n            style.thickness\n        };\n        let bounds = Bounds {\n            origin,\n            size: size(width, height),\n        };\n        let content_mask = self.content_mask();\n        let element_opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(Underline {\n            order: 0,\n            pad: 0,\n            bounds: bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            color: style.color.unwrap_or_default().opacity(element_opacity),\n            thickness: style.thickness.scale(scale_factor),\n            wavy: style.wavy,\n        });\n    }\n\n    /// Paint a strikethrough into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_strikethrough(\n        &mut self,\n        origin: Point<Pixels>,\n        width: Pixels,\n        style: &StrikethroughStyle,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let height = style.thickness;\n        let bounds = Bounds {\n            origin,\n            size: size(width, height),\n        };\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(Underline {\n            order: 0,\n            pad: 0,\n            bounds: bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            thickness: style.thickness.scale(scale_factor),\n            color: style.color.unwrap_or_default().opacity(opacity),\n            wavy: false,\n        });\n    }\n\n    /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.\n    ///\n    /// The y component of the origin is the baseline of the glyph.\n    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or\n    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).\n    /// This method is only useful if you need to paint a single glyph that has already been shaped.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_glyph(\n        &mut self,\n        origin: Point<Pixels>,\n        font_id: FontId,\n        glyph_id: GlyphId,\n        font_size: Pixels,\n        color: Hsla,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let element_opacity = self.element_opacity();\n        let scale_factor = self.scale_factor();\n        let glyph_origin = origin.scale(scale_factor);\n        let subpixel_variant = Point {\n            x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,\n            y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,\n        };\n        let params = RenderGlyphParams {\n            font_id,\n            glyph_id,\n            font_size,\n            subpixel_variant,\n            scale_factor,\n            is_emoji: false,\n        };\n\n        let raster_bounds = self.text_system().raster_bounds(&params)?;\n        if !raster_bounds.is_zero() {\n            let tile = self\n                .sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;\n                    Ok(Some((size, Cow::Owned(bytes))))\n                })?\n                .expect(\"Callback above only errors or returns Some\");\n            let bounds = Bounds {\n                origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),\n                size: tile.bounds.size.map(Into::into),\n            };\n            let content_mask = self.content_mask().scale(scale_factor);\n            self.next_frame.scene.insert_primitive(MonochromeSprite {\n                order: 0,\n                pad: 0,\n                bounds,\n                content_mask,\n                color: color.opacity(element_opacity),\n                tile,\n                transformation: TransformationMatrix::unit(),\n            });\n        }\n        Ok(())\n    }\n\n    /// Paints an emoji glyph into the scene for the next frame at the current z-index.\n    ///\n    /// The y component of the origin is the baseline of the glyph.\n    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or\n    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).\n    /// This method is only useful if you need to paint a single emoji that has already been shaped.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_emoji(\n        &mut self,\n        origin: Point<Pixels>,\n        font_id: FontId,\n        glyph_id: GlyphId,\n        font_size: Pixels,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let glyph_origin = origin.scale(scale_factor);\n        let params = RenderGlyphParams {\n            font_id,\n            glyph_id,\n            font_size,\n            // We don't render emojis with subpixel variants.\n            subpixel_variant: Default::default(),\n            scale_factor,\n            is_emoji: true,\n        };\n\n        let raster_bounds = self.text_system().raster_bounds(&params)?;\n        if !raster_bounds.is_zero() {\n            let tile = self\n                .sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;\n                    Ok(Some((size, Cow::Owned(bytes))))\n                })?\n                .expect(\"Callback above only errors or returns Some\");\n\n            let bounds = Bounds {\n                origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),\n                size: tile.bounds.size.map(Into::into),\n            };\n            let content_mask = self.content_mask().scale(scale_factor);\n            let opacity = self.element_opacity();\n\n            self.next_frame.scene.insert_primitive(PolychromeSprite {\n                order: 0,\n                pad: 0,\n                grayscale: false,\n                bounds,\n                corner_radii: Default::default(),\n                content_mask,\n                tile,\n                opacity,\n            });\n        }\n        Ok(())\n    }\n\n    /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_svg(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        path: SharedString,\n        transformation: TransformationMatrix,\n        color: Hsla,\n        cx: &App,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let element_opacity = self.element_opacity();\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let params = RenderSvgParams {\n            path,\n            size: bounds.size.map(|pixels| {\n                DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)\n            }),\n        };\n\n        let Some(tile) =\n            self.sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let Some(bytes) = cx.svg_renderer.render(&params)? else {\n                        return Ok(None);\n                    };\n                    Ok(Some((params.size, Cow::Owned(bytes))))\n                })?\n        else {\n            return Ok(());\n        };\n        let content_mask = self.content_mask().scale(scale_factor);\n\n        self.next_frame.scene.insert_primitive(MonochromeSprite {\n            order: 0,\n            pad: 0,\n            bounds: bounds\n                .map_origin(|origin| origin.floor())\n                .map_size(|size| size.ceil()),\n            content_mask,\n            color: color.opacity(element_opacity),\n            tile,\n            transformation,\n        });\n\n        Ok(())\n    }\n\n    /// Paint an image into the scene for the next frame at the current z-index.\n    /// This method will panic if the frame_index is not valid\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_image(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        corner_radii: Corners<Pixels>,\n        data: Arc<RenderImage>,\n        frame_index: usize,\n        grayscale: bool,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let params = RenderImageParams {\n            image_id: data.id,\n            frame_index,\n        };\n\n        let tile = self\n            .sprite_atlas\n            .get_or_insert_with(&params.clone().into(), &mut || {\n                Ok(Some((\n                    data.size(frame_index),\n                    Cow::Borrowed(\n                        data.as_bytes(frame_index)\n                            .expect(\"It's the caller's job to pass a valid frame index\"),\n                    ),\n                )))\n            })?\n            .expect(\"Callback above only returns Some\");\n        let content_mask = self.content_mask().scale(scale_factor);\n        let corner_radii = corner_radii.scale(scale_factor);\n        let opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(PolychromeSprite {\n            order: 0,\n            pad: 0,\n            grayscale,\n            bounds: bounds\n                .map_origin(|origin| origin.floor())\n                .map_size(|size| size.ceil()),\n            content_mask,\n            corner_radii,\n            tile,\n            opacity,\n        });\n        Ok(())\n    }\n\n    /// Paint a surface into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    #[cfg(target_os = \"macos\")]\n    pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVPixelBuffer) {\n        use crate::PaintSurface;\n\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let content_mask = self.content_mask().scale(scale_factor);\n        self.next_frame.scene.insert_primitive(PaintSurface {\n            order: 0,\n            bounds,\n            content_mask,\n            image_buffer,\n        });\n    }\n\n    /// Removes an image from the sprite atlas.\n    pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {\n        for frame_index in 0..data.frame_count() {\n            let params = RenderImageParams {\n                image_id: data.id,\n                frame_index,\n            };\n\n            self.sprite_atlas.remove(&params.clone().into());\n        }\n\n        Ok(())\n    }\n\n    /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which\n    /// layout is being requested, along with the layout ids of any children. This method is called during\n    /// calls to the [`Element::request_layout`] trait method and enables any element to participate in layout.\n    ///\n    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.\n    #[must_use]\n    pub fn request_layout(\n        &mut self,\n        style: Style,\n        children: impl IntoIterator<Item = LayoutId>,\n        cx: &mut App,\n    ) -> LayoutId {\n        self.invalidator.debug_assert_prepaint();\n\n        cx.layout_id_buffer.clear();\n        cx.layout_id_buffer.extend(children);\n        let rem_size = self.rem_size();\n\n        self.layout_engine\n            .as_mut()\n            .unwrap()\n            .request_layout(style, rem_size, &cx.layout_id_buffer)\n    }\n\n    /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,\n    /// this variant takes a function that is invoked during layout so you can use arbitrary logic to\n    /// determine the element's size. One place this is used internally is when measuring text.\n    ///\n    /// The given closure is invoked at layout time with the known dimensions and available space and\n    /// returns a `Size`.\n    ///\n    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.\n    pub fn request_measured_layout<\n        F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>\n            + 'static,\n    >(\n        &mut self,\n        style: Style,\n        measure: F,\n    ) -> LayoutId {\n        self.invalidator.debug_assert_prepaint();\n\n        let rem_size = self.rem_size();\n        self.layout_engine\n            .as_mut()\n            .unwrap()\n            .request_measured_layout(style, rem_size, measure)\n    }\n\n    /// Compute the layout for the given id within the given available space.\n    /// This method is called for its side effect, typically by the framework prior to painting.\n    /// After calling it, you can request the bounds of the given layout node id or any descendant.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn compute_layout(\n        &mut self,\n        layout_id: LayoutId,\n        available_space: Size<AvailableSpace>,\n        cx: &mut App,\n    ) {\n        self.invalidator.debug_assert_prepaint();\n\n        let mut layout_engine = self.layout_engine.take().unwrap();\n        layout_engine.compute_layout(layout_id, available_space, self, cx);\n        self.layout_engine = Some(layout_engine);\n    }\n\n    /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by\n    /// GPUI itself automatically in order to pass your element its `Bounds` automatically.\n    ///\n    /// This method should only be called as part of element drawing.\n    pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {\n        self.invalidator.debug_assert_prepaint();\n\n        let mut bounds = self\n            .layout_engine\n            .as_mut()\n            .unwrap()\n            .layout_bounds(layout_id)\n            .map(Into::into);\n        bounds.origin += self.element_offset();\n        bounds\n    }\n\n    /// This method should be called during `prepaint`. You can use\n    /// the returned [Hitbox] during `paint` or in an event handler\n    /// to determine whether the inserted hitbox was the topmost.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, opaque: bool) -> Hitbox {\n        self.invalidator.debug_assert_prepaint();\n\n        let content_mask = self.content_mask();\n        let id = self.next_hitbox_id;\n        self.next_hitbox_id.0 += 1;\n        let hitbox = Hitbox {\n            id,\n            bounds,\n            content_mask,\n            opaque,\n        };\n        self.next_frame.hitboxes.push(hitbox.clone());\n        hitbox\n    }\n\n    /// Sets the key context for the current element. This context will be used to translate\n    /// keybindings into actions.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn set_key_context(&mut self, context: KeyContext) {\n        self.invalidator.debug_assert_paint();\n        self.next_frame.dispatch_tree.set_key_context(context);\n    }\n\n    /// Sets the focus handle for the current element. This handle will be used to manage focus state\n    /// and keyboard event dispatch for the element.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {\n        self.invalidator.debug_assert_prepaint();\n        if focus_handle.is_focused(self) {\n            self.next_frame.focus = Some(focus_handle.id);\n        }\n        self.next_frame.dispatch_tree.set_focus_id(focus_handle.id);\n    }\n\n    /// Sets the view id for the current element, which will be used to manage view caching.\n    ///\n    /// This method should only be called as part of element prepaint. We plan on removing this\n    /// method eventually when we solve some issues that require us to construct editor elements\n    /// directly instead of always using editors via views.\n    pub fn set_view_id(&mut self, view_id: EntityId) {\n        self.invalidator.debug_assert_prepaint();\n        self.next_frame.dispatch_tree.set_view_id(view_id);\n    }\n\n    /// Get the entity ID for the currently rendering view\n    pub fn current_view(&self) -> EntityId {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.rendered_entity_stack.last().copied().unwrap()\n    }\n\n    pub(crate) fn with_rendered_view<R>(\n        &mut self,\n        id: EntityId,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.rendered_entity_stack.push(id);\n        let result = f(self);\n        self.rendered_entity_stack.pop();\n        result\n    }\n\n    /// Executes the provided function with the specified image cache.\n    pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        if let Some(image_cache) = image_cache {\n            self.image_cache_stack.push(image_cache);\n            let result = f(self);\n            self.image_cache_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the\n    /// platform to receive textual input with proper integration with concerns such\n    /// as IME interactions. This handler will be active for the upcoming frame until the following frame is\n    /// rendered.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    ///\n    /// [element_input_handler]: crate::ElementInputHandler\n    pub fn handle_input(\n        &mut self,\n        focus_handle: &FocusHandle,\n        input_handler: impl InputHandler,\n        cx: &App,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        if focus_handle.is_focused(self) {\n            let cx = self.to_async(cx);\n            self.next_frame\n                .input_handlers\n                .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));\n        }\n    }\n\n    /// Register a mouse event listener on the window for the next frame. The type of event\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_mouse_event<Event: MouseEvent>(\n        &mut self,\n        mut handler: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.mouse_listeners.push(Some(Box::new(\n            move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {\n                if let Some(event) = event.downcast_ref() {\n                    handler(event, phase, window, cx)\n                }\n            },\n        )));\n    }\n\n    /// Register a key event listener on the window for the next frame. The type of event\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have\n    /// a specific need to register a global listener.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_key_event<Event: KeyEvent>(\n        &mut self,\n        listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.dispatch_tree.on_key_event(Rc::new(\n            move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {\n                if let Some(event) = event.downcast_ref::<Event>() {\n                    listener(event, phase, window, cx)\n                }\n            },\n        ));\n    }\n\n    /// Register a modifiers changed event listener on the window for the next frame.\n    ///\n    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have\n    /// a specific need to register a global listener.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_modifiers_changed(\n        &mut self,\n        listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new(\n            move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {\n                listener(event, window, cx)\n            },\n        ));\n    }\n\n    /// Register a listener to be called when the given focus handle or one of its descendants receives focus.\n    /// This does not fire if the given focus handle - or one of its descendants - was previously focused.\n    /// Returns a subscription and persists until the subscription is dropped.\n    pub fn on_focus_in(\n        &mut self,\n        handle: &FocusHandle,\n        cx: &mut App,\n        mut listener: impl FnMut(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let focus_id = handle.id;\n        let (subscription, activate) =\n            self.new_focus_listener(Box::new(move |event, window, cx| {\n                if event.is_focus_in(focus_id) {\n                    listener(window, cx);\n                }\n                true\n            }));\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    /// Register a listener to be called when the given focus handle or one of its descendants loses focus.\n    /// Returns a subscription and persists until the subscription is dropped.\n    pub fn on_focus_out(\n        &mut self,\n        handle: &FocusHandle,\n        cx: &mut App,\n        mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let focus_id = handle.id;\n        let (subscription, activate) =\n            self.new_focus_listener(Box::new(move |event, window, cx| {\n                if let Some(blurred_id) = event.previous_focus_path.last().copied() {\n                    if event.is_focus_out(focus_id) {\n                        let event = FocusOutEvent {\n                            blurred: WeakFocusHandle {\n                                id: blurred_id,\n                                handles: Arc::downgrade(&cx.focus_handles),\n                            },\n                        };\n                        listener(event, window, cx)\n                    }\n                }\n                true\n            }));\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    fn reset_cursor_style(&self, cx: &mut App) {\n        // Set the cursor only if we're the active window.\n        if self.is_window_hovered() {\n            let style = self\n                .rendered_frame\n                .cursor_styles\n                .iter()\n                .rev()\n                .find(|request| {\n                    request\n                        .hitbox_id\n                        .map_or(true, |hitbox_id| hitbox_id.is_hovered(self))\n                })\n                .map(|request| request.style)\n                .unwrap_or(CursorStyle::Arrow);\n            cx.platform.set_cursor_style(style);\n        }\n    }\n\n    /// Dispatch a given keystroke as though the user had typed it.\n    /// You can create a keystroke with Keystroke::parse(\"\").\n    pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {\n        let keystroke = keystroke.with_simulated_ime();\n        let result = self.dispatch_event(\n            PlatformInput::KeyDown(KeyDownEvent {\n                keystroke: keystroke.clone(),\n                is_held: false,\n            }),\n            cx,\n        );\n        if !result.propagate {\n            return true;\n        }\n\n        if let Some(input) = keystroke.key_char {\n            if let Some(mut input_handler) = self.platform_window.take_input_handler() {\n                input_handler.dispatch_input(&input, self, cx);\n                self.platform_window.set_input_handler(input_handler);\n                return true;\n            }\n        }\n\n        false\n    }\n\n    /// Return a key binding string for an action, to display in the UI. Uses the highest precedence\n    /// binding for the action (last binding added to the keymap).\n    pub fn keystroke_text_for(&self, action: &dyn Action) -> String {\n        self.bindings_for_action(action)\n            .last()\n            .map(|binding| {\n                binding\n                    .keystrokes()\n                    .iter()\n                    .map(ToString::to_string)\n                    .collect::<Vec<_>>()\n                    .join(\" \")\n            })\n            .unwrap_or_else(|| action.name().to_string())\n    }\n\n    /// Dispatch a mouse or keyboard event on the window.\n    #[profiling::function]\n    pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {\n        self.last_input_timestamp.set(Instant::now());\n        // Handlers may set this to false by calling `stop_propagation`.\n        cx.propagate_event = true;\n        // Handlers may set this to true by calling `prevent_default`.\n        self.default_prevented = false;\n\n        let event = match event {\n            // Track the mouse position with our own state, since accessing the platform\n            // API for the mouse position can only occur on the main thread.\n            PlatformInput::MouseMove(mouse_move) => {\n                self.mouse_position = mouse_move.position;\n                self.modifiers = mouse_move.modifiers;\n                PlatformInput::MouseMove(mouse_move)\n            }\n            PlatformInput::MouseDown(mouse_down) => {\n                self.mouse_position = mouse_down.position;\n                self.modifiers = mouse_down.modifiers;\n                PlatformInput::MouseDown(mouse_down)\n            }\n            PlatformInput::MouseUp(mouse_up) => {\n                self.mouse_position = mouse_up.position;\n                self.modifiers = mouse_up.modifiers;\n                PlatformInput::MouseUp(mouse_up)\n            }\n            PlatformInput::MouseExited(mouse_exited) => {\n                self.modifiers = mouse_exited.modifiers;\n                PlatformInput::MouseExited(mouse_exited)\n            }\n            PlatformInput::ModifiersChanged(modifiers_changed) => {\n                self.modifiers = modifiers_changed.modifiers;\n                PlatformInput::ModifiersChanged(modifiers_changed)\n            }\n            PlatformInput::ScrollWheel(scroll_wheel) => {\n                self.mouse_position = scroll_wheel.position;\n                self.modifiers = scroll_wheel.modifiers;\n                PlatformInput::ScrollWheel(scroll_wheel)\n            }\n            // Translate dragging and dropping of external files from the operating system\n            // to internal drag and drop events.\n            PlatformInput::FileDrop(file_drop) => match file_drop {\n                FileDropEvent::Entered { position, paths } => {\n                    self.mouse_position = position;\n                    if cx.active_drag.is_none() {\n                        cx.active_drag = Some(AnyDrag {\n                            value: Arc::new(paths.clone()),\n                            view: cx.new(|_| paths).into(),\n                            cursor_offset: position,\n                            cursor_style: None,\n                        });\n                    }\n                    PlatformInput::MouseMove(MouseMoveEvent {\n                        position,\n                        pressed_button: Some(MouseButton::Left),\n                        modifiers: Modifiers::default(),\n                    })\n                }\n                FileDropEvent::Pending { position } => {\n                    self.mouse_position = position;\n                    PlatformInput::MouseMove(MouseMoveEvent {\n                        position,\n                        pressed_button: Some(MouseButton::Left),\n                        modifiers: Modifiers::default(),\n                    })\n                }\n                FileDropEvent::Submit { position } => {\n                    cx.activate(true);\n                    self.mouse_position = position;\n                    PlatformInput::MouseUp(MouseUpEvent {\n                        button: MouseButton::Left,\n                        position,\n                        modifiers: Modifiers::default(),\n                        click_count: 1,\n                    })\n                }\n                FileDropEvent::Exited => {\n                    cx.active_drag.take();\n                    PlatformInput::FileDrop(FileDropEvent::Exited)\n                }\n            },\n            PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,\n        };\n\n        if let Some(any_mouse_event) = event.mouse_event() {\n            self.dispatch_mouse_event(any_mouse_event, cx);\n        } else if let Some(any_key_event) = event.keyboard_event() {\n            self.dispatch_key_event(any_key_event, cx);\n        }\n\n        DispatchEventResult {\n            propagate: cx.propagate_event,\n            default_prevented: self.default_prevented,\n        }\n    }\n\n    fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {\n        let hit_test = self.rendered_frame.hit_test(self.mouse_position());\n        if hit_test != self.mouse_hit_test {\n            self.mouse_hit_test = hit_test;\n            self.reset_cursor_style(cx);\n        }\n\n        let mut mouse_listeners = mem::take(&mut self.rendered_frame.mouse_listeners);\n\n        // Capture phase, events bubble from back to front. Handlers for this phase are used for\n        // special purposes, such as detecting events outside of a given Bounds.\n        for listener in &mut mouse_listeners {\n            let listener = listener.as_mut().unwrap();\n            listener(event, DispatchPhase::Capture, self, cx);\n            if !cx.propagate_event {\n                break;\n            }\n        }\n\n        // Bubble phase, where most normal handlers do their work.\n        if cx.propagate_event {\n            for listener in mouse_listeners.iter_mut().rev() {\n                let listener = listener.as_mut().unwrap();\n                listener(event, DispatchPhase::Bubble, self, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n        }\n\n        self.rendered_frame.mouse_listeners = mouse_listeners;\n\n        if cx.has_active_drag() {\n            if event.is::<MouseMoveEvent>() {\n                // If this was a mouse move event, redraw the window so that the\n                // active drag can follow the mouse cursor.\n                self.refresh();\n            } else if event.is::<MouseUpEvent>() {\n                // If this was a mouse up event, cancel the active drag and redraw\n                // the window.\n                cx.active_drag = None;\n                self.refresh();\n            }\n        }\n    }\n\n    fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) {\n        if self.invalidator.is_dirty() {\n            self.draw(cx);\n        }\n\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        let mut keystroke: Option<Keystroke> = None;\n\n        if let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() {\n            if event.modifiers.number_of_modifiers() == 0\n                && self.pending_modifier.modifiers.number_of_modifiers() == 1\n                && !self.pending_modifier.saw_keystroke\n            {\n                let key = match self.pending_modifier.modifiers {\n                    modifiers if modifiers.shift => Some(\"shift\"),\n                    modifiers if modifiers.control => Some(\"control\"),\n                    modifiers if modifiers.alt => Some(\"alt\"),\n                    modifiers if modifiers.platform => Some(\"platform\"),\n                    modifiers if modifiers.function => Some(\"function\"),\n                    _ => None,\n                };\n                if let Some(key) = key {\n                    keystroke = Some(Keystroke {\n                        key: key.to_string(),\n                        key_char: None,\n                        modifiers: Modifiers::default(),\n                    });\n                }\n            }\n\n            if self.pending_modifier.modifiers.number_of_modifiers() == 0\n                && event.modifiers.number_of_modifiers() == 1\n            {\n                self.pending_modifier.saw_keystroke = false\n            }\n            self.pending_modifier.modifiers = event.modifiers\n        } else if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {\n            self.pending_modifier.saw_keystroke = true;\n            keystroke = Some(key_down_event.keystroke.clone());\n        }\n\n        let Some(keystroke) = keystroke else {\n            self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);\n            return;\n        };\n\n        let mut currently_pending = self.pending_input.take().unwrap_or_default();\n        if currently_pending.focus.is_some() && currently_pending.focus != self.focus {\n            currently_pending = PendingInput::default();\n        }\n\n        let match_result = self.rendered_frame.dispatch_tree.dispatch_key(\n            currently_pending.keystrokes,\n            keystroke,\n            &dispatch_path,\n        );\n\n        if !match_result.to_replay.is_empty() {\n            self.replay_pending_input(match_result.to_replay, cx)\n        }\n\n        if !match_result.pending.is_empty() {\n            currently_pending.keystrokes = match_result.pending;\n            currently_pending.focus = self.focus;\n            currently_pending.timer = Some(self.spawn(cx, async move |cx| {\n                cx.background_executor.timer(Duration::from_secs(1)).await;\n                cx.update(move |window, cx| {\n                    let Some(currently_pending) = window\n                        .pending_input\n                        .take()\n                        .filter(|pending| pending.focus == window.focus)\n                    else {\n                        return;\n                    };\n\n                    let dispatch_path = window.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n                    let to_replay = window\n                        .rendered_frame\n                        .dispatch_tree\n                        .flush_dispatch(currently_pending.keystrokes, &dispatch_path);\n\n                    window.replay_pending_input(to_replay, cx)\n                })\n                .log_err();\n            }));\n            self.pending_input = Some(currently_pending);\n            self.pending_input_changed(cx);\n            cx.propagate_event = false;\n            return;\n        }\n\n        cx.propagate_event = true;\n        for binding in match_result.bindings {\n            self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);\n            if !cx.propagate_event {\n                self.dispatch_keystroke_observers(\n                    event,\n                    Some(binding.action),\n                    match_result.context_stack.clone(),\n                    cx,\n                );\n                self.pending_input_changed(cx);\n                return;\n            }\n        }\n\n        self.finish_dispatch_key_event(event, dispatch_path, match_result.context_stack, cx);\n        self.pending_input_changed(cx);\n    }\n\n    fn finish_dispatch_key_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: SmallVec<[DispatchNodeId; 32]>,\n        context_stack: Vec<KeyContext>,\n        cx: &mut App,\n    ) {\n        self.dispatch_key_down_up_event(event, &dispatch_path, cx);\n        if !cx.propagate_event {\n            return;\n        }\n\n        self.dispatch_modifiers_changed_event(event, &dispatch_path, cx);\n        if !cx.propagate_event {\n            return;\n        }\n\n        self.dispatch_keystroke_observers(event, None, context_stack, cx);\n    }\n\n    fn pending_input_changed(&mut self, cx: &mut App) {\n        self.pending_input_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    fn dispatch_key_down_up_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,\n        cx: &mut App,\n    ) {\n        // Capture phase\n        for node_id in dispatch_path {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n\n            for key_listener in node.key_listeners.clone() {\n                key_listener(event, DispatchPhase::Capture, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n\n        // Bubble phase\n        for node_id in dispatch_path.iter().rev() {\n            // Handle low level key events\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for key_listener in node.key_listeners.clone() {\n                key_listener(event, DispatchPhase::Bubble, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n    }\n\n    fn dispatch_modifiers_changed_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,\n        cx: &mut App,\n    ) {\n        let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() else {\n            return;\n        };\n        for node_id in dispatch_path.iter().rev() {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for listener in node.modifiers_changed_listeners.clone() {\n                listener(event, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n    }\n\n    /// Determine whether a potential multi-stroke key binding is in progress on this window.\n    pub fn has_pending_keystrokes(&self) -> bool {\n        self.pending_input.is_some()\n    }\n\n    pub(crate) fn clear_pending_keystrokes(&mut self) {\n        self.pending_input.take();\n    }\n\n    /// Returns the currently pending input keystrokes that might result in a multi-stroke key binding.\n    pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> {\n        self.pending_input\n            .as_ref()\n            .map(|pending_input| pending_input.keystrokes.as_slice())\n    }\n\n    fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) {\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        'replay: for replay in replays {\n            let event = KeyDownEvent {\n                keystroke: replay.keystroke.clone(),\n                is_held: false,\n            };\n\n            cx.propagate_event = true;\n            for binding in replay.bindings {\n                self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);\n                if !cx.propagate_event {\n                    self.dispatch_keystroke_observers(\n                        &event,\n                        Some(binding.action),\n                        Vec::default(),\n                        cx,\n                    );\n                    continue 'replay;\n                }\n            }\n\n            self.dispatch_key_down_up_event(&event, &dispatch_path, cx);\n            if !cx.propagate_event {\n                continue 'replay;\n            }\n            if let Some(input) = replay.keystroke.key_char.as_ref().cloned() {\n                if let Some(mut input_handler) = self.platform_window.take_input_handler() {\n                    input_handler.dispatch_input(&input, self, cx);\n                    self.platform_window.set_input_handler(input_handler)\n                }\n            }\n        }\n    }\n\n    fn dispatch_action_on_node(\n        &mut self,\n        node_id: DispatchNodeId,\n        action: &dyn Action,\n        cx: &mut App,\n    ) {\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        // Capture phase for global actions.\n        cx.propagate_event = true;\n        if let Some(mut global_listeners) = cx\n            .global_action_listeners\n            .remove(&action.as_any().type_id())\n        {\n            for listener in &global_listeners {\n                listener(action.as_any(), DispatchPhase::Capture, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n\n            global_listeners.extend(\n                cx.global_action_listeners\n                    .remove(&action.as_any().type_id())\n                    .unwrap_or_default(),\n            );\n\n            cx.global_action_listeners\n                .insert(action.as_any().type_id(), global_listeners);\n        }\n\n        if !cx.propagate_event {\n            return;\n        }\n\n        // Capture phase for window actions.\n        for node_id in &dispatch_path {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for DispatchActionListener {\n                action_type,\n                listener,\n            } in node.action_listeners.clone()\n            {\n                let any_action = action.as_any();\n                if action_type == any_action.type_id() {\n                    listener(any_action, DispatchPhase::Capture, self, cx);\n\n                    if !cx.propagate_event {\n                        return;\n                    }\n                }\n            }\n        }\n\n        // Bubble phase for window actions.\n        for node_id in dispatch_path.iter().rev() {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for DispatchActionListener {\n                action_type,\n                listener,\n            } in node.action_listeners.clone()\n            {\n                let any_action = action.as_any();\n                if action_type == any_action.type_id() {\n                    cx.propagate_event = false; // Actions stop propagation by default during the bubble phase\n                    listener(any_action, DispatchPhase::Bubble, self, cx);\n\n                    if !cx.propagate_event {\n                        return;\n                    }\n                }\n            }\n        }\n\n        // Bubble phase for global actions.\n        if let Some(mut global_listeners) = cx\n            .global_action_listeners\n            .remove(&action.as_any().type_id())\n        {\n            for listener in global_listeners.iter().rev() {\n                cx.propagate_event = false; // Actions stop propagation by default during the bubble phase\n\n                listener(action.as_any(), DispatchPhase::Bubble, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n\n            global_listeners.extend(\n                cx.global_action_listeners\n                    .remove(&action.as_any().type_id())\n                    .unwrap_or_default(),\n            );\n\n            cx.global_action_listeners\n                .insert(action.as_any().type_id(), global_listeners);\n        }\n    }\n\n    /// Register the given handler to be invoked whenever the global of the given type\n    /// is updated.\n    pub fn observe_global<G: Global>(\n        &mut self,\n        cx: &mut App,\n        f: impl Fn(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let window_handle = self.handle;\n        let (subscription, activate) = cx.global_observers.insert(\n            TypeId::of::<G>(),\n            Box::new(move |cx| {\n                window_handle\n                    .update(cx, |_, window, cx| f(window, cx))\n                    .is_ok()\n            }),\n        );\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    /// Focus the current window and bring it to the foreground at the platform level.\n    pub fn activate_window(&self) {\n        self.platform_window.activate();\n    }\n\n    /// Minimize the current window at the platform level.\n    pub fn minimize_window(&self) {\n        self.platform_window.minimize();\n    }\n\n    /// Toggle full screen status on the current window at the platform level.\n    pub fn toggle_fullscreen(&self) {\n        self.platform_window.toggle_fullscreen();\n    }\n\n    /// Updates the IME panel position suggestions for languages like japanese, chinese.\n    pub fn invalidate_character_coordinates(&self) {\n        self.on_next_frame(|window, cx| {\n            if let Some(mut input_handler) = window.platform_window.take_input_handler() {\n                if let Some(bounds) = input_handler.selected_bounds(window, cx) {\n                    window\n                        .platform_window\n                        .update_ime_position(bounds.scale(window.scale_factor()));\n                }\n                window.platform_window.set_input_handler(input_handler);\n            }\n        });\n    }\n\n    /// Present a platform dialog.\n    /// The provided message will be presented, along with buttons for each answer.\n    /// When a button is clicked, the returned Receiver will receive the index of the clicked button.\n    pub fn prompt(\n        &mut self,\n        level: PromptLevel,\n        message: &str,\n        detail: Option<&str>,\n        answers: &[&str],\n        cx: &mut App,\n    ) -> oneshot::Receiver<usize> {\n        let prompt_builder = cx.prompt_builder.take();\n        let Some(prompt_builder) = prompt_builder else {\n            unreachable!(\"Re-entrant window prompting is not supported by GPUI\");\n        };\n\n        let receiver = match &prompt_builder {\n            PromptBuilder::Default => self\n                .platform_window\n                .prompt(level, message, detail, answers)\n                .unwrap_or_else(|| {\n                    self.build_custom_prompt(&prompt_builder, level, message, detail, answers, cx)\n                }),\n            PromptBuilder::Custom(_) => {\n                self.build_custom_prompt(&prompt_builder, level, message, detail, answers, cx)\n            }\n        };\n\n        cx.prompt_builder = Some(prompt_builder);\n\n        receiver\n    }\n\n    fn build_custom_prompt(\n        &mut self,\n        prompt_builder: &PromptBuilder,\n        level: PromptLevel,\n        message: &str,\n        detail: Option<&str>,\n        answers: &[&str],\n        cx: &mut App,\n    ) -> oneshot::Receiver<usize> {\n        let (sender, receiver) = oneshot::channel();\n        let handle = PromptHandle::new(sender);\n        let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx);\n        self.prompt = Some(handle);\n        receiver\n    }\n\n    /// Returns the current context stack.\n    pub fn context_stack(&self) -> Vec<KeyContext> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n        let node_id = self\n            .focus\n            .and_then(|focus_id| dispatch_tree.focusable_node_id(focus_id))\n            .unwrap_or_else(|| dispatch_tree.root_node_id());\n\n        dispatch_tree\n            .dispatch_path(node_id)\n            .iter()\n            .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone())\n            .collect()\n    }\n\n    /// Returns all available actions for the focused element.\n    pub fn available_actions(&self, cx: &App) -> Vec<Box<dyn Action>> {\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let mut actions = self.rendered_frame.dispatch_tree.available_actions(node_id);\n        for action_type in cx.global_action_listeners.keys() {\n            if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) {\n                let action = cx.actions.build_action_type(action_type).ok();\n                if let Some(action) = action {\n                    actions.insert(ix, action);\n                }\n            }\n        }\n        actions\n    }\n\n    /// Returns key bindings that invoke an action on the currently focused element. Bindings are\n    /// returned in the order they were added. For display, the last binding should take precedence.\n    pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {\n        self.rendered_frame\n            .dispatch_tree\n            .bindings_for_action(action, &self.rendered_frame.dispatch_tree.context_stack)\n    }\n\n    /// Returns any bindings that would invoke an action on the given focus handle if it were\n    /// focused. Bindings are returned in the order they were added. For display, the last binding\n    /// should take precedence.\n    pub fn bindings_for_action_in(\n        &self,\n        action: &dyn Action,\n        focus_handle: &FocusHandle,\n    ) -> Vec<KeyBinding> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n\n        let Some(node_id) = dispatch_tree.focusable_node_id(focus_handle.id) else {\n            return vec![];\n        };\n        let context_stack: Vec<_> = dispatch_tree\n            .dispatch_path(node_id)\n            .into_iter()\n            .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())\n            .collect();\n        dispatch_tree.bindings_for_action(action, &context_stack)\n    }\n\n    /// Returns the key bindings for the given action in the given context.\n    pub fn bindings_for_action_in_context(\n        &self,\n        action: &dyn Action,\n        context: KeyContext,\n    ) -> Vec<KeyBinding> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n        dispatch_tree.bindings_for_action(action, &[context])\n    }\n\n    /// Returns a generic event listener that invokes the given listener with the view and context associated with the given view handle.\n    pub fn listener_for<V: Render, E>(\n        &self,\n        view: &Entity<V>,\n        f: impl Fn(&mut V, &E, &mut Window, &mut Context<V>) + 'static,\n    ) -> impl Fn(&E, &mut Window, &mut App) + 'static {\n        let view = view.downgrade();\n        move |e: &E, window: &mut Window, cx: &mut App| {\n            view.update(cx, |view, cx| f(view, e, window, cx)).ok();\n        }\n    }\n\n    /// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle.\n    pub fn handler_for<V: Render, Callback: Fn(&mut V, &mut Window, &mut Context<V>) + 'static>(\n        &self,\n        view: &Entity<V>,\n        f: Callback,\n    ) -> impl Fn(&mut Window, &mut App) + use<V, Callback> {\n        let view = view.downgrade();\n        move |window: &mut Window, cx: &mut App| {\n            view.update(cx, |view, cx| f(view, window, cx)).ok();\n        }\n    }\n\n    /// Register a callback that can interrupt the closing of the current window based the returned boolean.\n    /// If the callback returns false, the window won't be closed.\n    pub fn on_window_should_close(\n        &self,\n        cx: &App,\n        f: impl Fn(&mut Window, &mut App) -> bool + 'static,\n    ) {\n        let mut cx = self.to_async(cx);\n        self.platform_window.on_should_close(Box::new(move || {\n            cx.update(|window, cx| f(window, cx)).unwrap_or(true)\n        }))\n    }\n\n    /// Register an action listener on the window for the next frame. The type of action\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This is a fairly low-level method, so prefer using action handlers on elements unless you have\n    /// a specific need to register a global listener.\n    pub fn on_action(\n        &mut self,\n        action_type: TypeId,\n        listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.next_frame\n            .dispatch_tree\n            .on_action(action_type, Rc::new(listener));\n    }\n\n    /// Read information about the GPU backing this window.\n    /// Currently returns None on Mac and Windows.\n    pub fn gpu_specs(&self) -> Option<GpuSpecs> {\n        self.platform_window.gpu_specs()\n    }\n}\n\n// #[derive(Clone, Copy, Eq, PartialEq, Hash)]\nslotmap::new_key_type! {\n    /// A unique identifier for a window.\n    pub struct WindowId;\n}\n\nimpl WindowId {\n    /// Converts this window ID to a `u64`.\n    pub fn as_u64(&self) -> u64 {\n        self.0.as_ffi()\n    }\n}\n\nimpl From<u64> for WindowId {\n    fn from(value: u64) -> Self {\n        WindowId(slotmap::KeyData::from_ffi(value))\n    }\n}\n\n/// A handle to a window with a specific root view type.\n/// Note that this does not keep the window alive on its own.\n#[derive(Deref, DerefMut)]\npub struct WindowHandle<V> {\n    #[deref]\n    #[deref_mut]\n    pub(crate) any_handle: AnyWindowHandle,\n    state_type: PhantomData<V>,\n}\n\nimpl<V: 'static + Render> WindowHandle<V> {\n    /// Creates a new handle from a window ID.\n    /// This does not check if the root type of the window is `V`.\n    pub fn new(id: WindowId) -> Self {\n        WindowHandle {\n            any_handle: AnyWindowHandle {\n                id,\n                state_type: TypeId::of::<V>(),\n            },\n            state_type: PhantomData,\n        }\n    }\n\n    /// Get the root view out of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    #[cfg(any(test, feature = \"test-support\"))]\n    pub fn root<C>(&self, cx: &mut C) -> Result<Entity<V>>\n    where\n        C: AppContext,\n    {\n        crate::Flatten::flatten(cx.update_window(self.any_handle, |root_view, _, _| {\n            root_view\n                .downcast::<V>()\n                .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))\n        }))\n    }\n\n    /// Updates the root view of this window.\n    ///\n    /// This will fail if the window has been closed or if the root view's type does not match\n    pub fn update<C, R>(\n        &self,\n        cx: &mut C,\n        update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,\n    ) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.update_window(self.any_handle, |root_view, window, cx| {\n            let view = root_view\n                .downcast::<V>()\n                .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))?;\n\n            Ok(view.update(cx, |view, cx| update(view, window, cx)))\n        })?\n    }\n\n    /// Read the root view out of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> {\n        let x = cx\n            .windows\n            .get(self.id)\n            .and_then(|window| {\n                window\n                    .as_ref()\n                    .and_then(|window| window.root.clone())\n                    .map(|root_view| root_view.downcast::<V>())\n            })\n            .ok_or_else(|| anyhow!(\"window not found\"))?\n            .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))?;\n\n        Ok(x.read(cx))\n    }\n\n    /// Read the root view out of this window, with a callback\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))\n    }\n\n    /// Read the root view pointer off of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn entity<C>(&self, cx: &C) -> Result<Entity<V>>\n    where\n        C: AppContext,\n    {\n        cx.read_window(self, |root_view, _cx| root_view.clone())\n    }\n\n    /// Check if this window is 'active'.\n    ///\n    /// Will return `None` if the window is closed or currently\n    /// borrowed.\n    pub fn is_active(&self, cx: &mut App) -> Option<bool> {\n        cx.update_window(self.any_handle, |_, window, _| window.is_window_active())\n            .ok()\n    }\n}\n\nimpl<V> Copy for WindowHandle<V> {}\n\nimpl<V> Clone for WindowHandle<V> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<V> PartialEq for WindowHandle<V> {\n    fn eq(&self, other: &Self) -> bool {\n        self.any_handle == other.any_handle\n    }\n}\n\nimpl<V> Eq for WindowHandle<V> {}\n\nimpl<V> Hash for WindowHandle<V> {\n    fn hash<H: Hasher>(&self, state: &mut H) {\n        self.any_handle.hash(state);\n    }\n}\n\nimpl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {\n    fn from(val: WindowHandle<V>) -> Self {\n        val.any_handle\n    }\n}\n\nunsafe impl<V> Send for WindowHandle<V> {}\nunsafe impl<V> Sync for WindowHandle<V> {}\n\n/// A handle to a window with any root view type, which can be downcast to a window with a specific root view type.\n#[derive(Copy, Clone, PartialEq, Eq, Hash)]\npub struct AnyWindowHandle {\n    pub(crate) id: WindowId,\n    state_type: TypeId,\n}\n\nimpl AnyWindowHandle {\n    /// Get the ID of this window.\n    pub fn window_id(&self) -> WindowId {\n        self.id\n    }\n\n    /// Attempt to convert this handle to a window handle with a specific root view type.\n    /// If the types do not match, this will return `None`.\n    pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {\n        if TypeId::of::<T>() == self.state_type {\n            Some(WindowHandle {\n                any_handle: *self,\n                state_type: PhantomData,\n            })\n        } else {\n            None\n        }\n    }\n\n    /// Updates the state of the root view of this window.\n    ///\n    /// This will fail if the window has been closed.\n    pub fn update<C, R>(\n        self,\n        cx: &mut C,\n        update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,\n    ) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.update_window(self, update)\n    }\n\n    /// Read the state of the root view of this window.\n    ///\n    /// This will fail if the window has been closed.\n    pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(Entity<T>, &App) -> R) -> Result<R>\n    where\n        C: AppContext,\n        T: 'static,\n    {\n        let view = self\n            .downcast::<T>()\n            .context(\"the type of the window's root view has changed\")?;\n\n        cx.read_window(&view, read)\n    }\n}\n\nimpl HasWindowHandle for Window {\n    fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, HandleError> {\n        self.platform_window.window_handle()\n    }\n}\n\n/// An identifier for an [`Element`](crate::Element).\n///\n/// Can be constructed with a string, a number, or both, as well\n/// as other internal representations.\n#[derive(Clone, Debug, Eq, PartialEq, Hash)]\npub enum ElementId {\n    /// The ID of a View element\n    View(EntityId),\n    /// An integer ID.\n    Integer(u64),\n    /// A string based ID.\n    Name(SharedString),\n    /// A UUID.\n    Uuid(Uuid),\n    /// An ID that's equated with a focus handle.\n    FocusHandle(FocusId),\n    /// A combination of a name and an integer.\n    NamedInteger(SharedString, u64),\n    /// A path\n    Path(Arc<std::path::Path>),\n}\n\nimpl ElementId {\n    /// Constructs an `ElementId::NamedInteger` from a name and `usize`.\n    pub fn named_usize(name: impl Into<SharedString>, integer: usize) -> ElementId {\n        Self::NamedInteger(name.into(), integer as u64)\n    }\n}\n\nimpl Display for ElementId {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            ElementId::View(entity_id) => write!(f, \"view-{}\", entity_id)?,\n            ElementId::Integer(ix) => write!(f, \"{}\", ix)?,\n            ElementId::Name(name) => write!(f, \"{}\", name)?,\n            ElementId::FocusHandle(_) => write!(f, \"FocusHandle\")?,\n            ElementId::NamedInteger(s, i) => write!(f, \"{}-{}\", s, i)?,\n            ElementId::Uuid(uuid) => write!(f, \"{}\", uuid)?,\n            ElementId::Path(path) => write!(f, \"{}\", path.display())?,\n        }\n\n        Ok(())\n    }\n}\n\nimpl TryInto<SharedString> for ElementId {\n    type Error = anyhow::Error;\n\n    fn try_into(self) -> anyhow::Result<SharedString> {\n        if let ElementId::Name(name) = self {\n            Ok(name)\n        } else {\n            Err(anyhow!(\"element id is not string\"))\n        }\n    }\n}\n\nimpl From<usize> for ElementId {\n    fn from(id: usize) -> Self {\n        ElementId::Integer(id as u64)\n    }\n}\n\nimpl From<i32> for ElementId {\n    fn from(id: i32) -> Self {\n        Self::Integer(id as u64)\n    }\n}\n\nimpl From<SharedString> for ElementId {\n    fn from(name: SharedString) -> Self {\n        ElementId::Name(name)\n    }\n}\n\nimpl From<Arc<std::path::Path>> for ElementId {\n    fn from(path: Arc<std::path::Path>) -> Self {\n        ElementId::Path(path)\n    }\n}\n\nimpl From<&'static str> for ElementId {\n    fn from(name: &'static str) -> Self {\n        ElementId::Name(name.into())\n    }\n}\n\nimpl<'a> From<&'a FocusHandle> for ElementId {\n    fn from(handle: &'a FocusHandle) -> Self {\n        ElementId::FocusHandle(handle.id)\n    }\n}\n\nimpl From<(&'static str, EntityId)> for ElementId {\n    fn from((name, id): (&'static str, EntityId)) -> Self {\n        ElementId::NamedInteger(name.into(), id.as_u64())\n    }\n}\n\nimpl From<(&'static str, usize)> for ElementId {\n    fn from((name, id): (&'static str, usize)) -> Self {\n        ElementId::NamedInteger(name.into(), id as u64)\n    }\n}\n\nimpl From<(SharedString, usize)> for ElementId {\n    fn from((name, id): (SharedString, usize)) -> Self {\n        ElementId::NamedInteger(name, id as u64)\n    }\n}\n\nimpl From<(&'static str, u64)> for ElementId {\n    fn from((name, id): (&'static str, u64)) -> Self {\n        ElementId::NamedInteger(name.into(), id)\n    }\n}\n\nimpl From<Uuid> for ElementId {\n    fn from(value: Uuid) -> Self {\n        Self::Uuid(value)\n    }\n}\n\nimpl From<(&'static str, u32)> for ElementId {\n    fn from((name, id): (&'static str, u32)) -> Self {\n        ElementId::NamedInteger(name.into(), id.into())\n    }\n}\n\n/// A rectangle to be rendered in the window at the given position and size.\n/// Passed as an argument [`Window::paint_quad`].\n#[derive(Clone)]\npub struct PaintQuad {\n    /// The bounds of the quad within the window.\n    pub bounds: Bounds<Pixels>,\n    /// The radii of the quad's corners.\n    pub corner_radii: Corners<Pixels>,\n    /// The background color of the quad.\n    pub background: Background,\n    /// The widths of the quad's borders.\n    pub border_widths: Edges<Pixels>,\n    /// The color of the quad's borders.\n    pub border_color: Hsla,\n    /// The style of the quad's borders.\n    pub border_style: BorderStyle,\n    /// The transformation to apply to the quad.\n    pub transformation: TransformationMatrix,\n}\n\nimpl PaintQuad {\n    /// Sets the corner radii of the quad.\n    pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {\n        PaintQuad {\n            corner_radii: corner_radii.into(),\n            ..self\n        }\n    }\n\n    /// Sets the border widths of the quad.\n    pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {\n        PaintQuad {\n            border_widths: border_widths.into(),\n            ..self\n        }\n    }\n\n    /// Sets the border color of the quad.\n    pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {\n        PaintQuad {\n            border_color: border_color.into(),\n            ..self\n        }\n    }\n\n    /// Sets the background color of the quad.\n    pub fn background(self, background: impl Into<Background>) -> Self {\n        PaintQuad {\n            background: background.into(),\n            ..self\n        }\n    }\n}\n\n/// Creates a quad with the given parameters.\npub fn quad(\n    bounds: Bounds<Pixels>,\n    corner_radii: impl Into<Corners<Pixels>>,\n    background: impl Into<Background>,\n    border_widths: impl Into<Edges<Pixels>>,\n    border_color: impl Into<Hsla>,\n    border_style: BorderStyle,\n) -> PaintQuad {\n    PaintQuad {\n        bounds,\n        corner_radii: corner_radii.into(),\n        background: background.into(),\n        border_widths: border_widths.into(),\n        border_color: border_color.into(),\n        border_style,\n        transformation: TransformationMatrix::default(),\n    }\n}\n\npub(crate) fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad {\n    PaintQuad {\n        transformation,\n        ..quad\n    }\n}\n\n/// Creates a filled quad with the given bounds and background color.\npub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {\n    PaintQuad {\n        bounds: bounds.into(),\n        corner_radii: (0.).into(),\n        background: background.into(),\n        border_widths: (0.).into(),\n        border_color: transparent_black(),\n        border_style: BorderStyle::default(),\n        transformation: TransformationMatrix::default(),\n    }\n}\n\n/// Creates a rectangle outline with the given bounds, border color, and a 1px border width\npub fn outline(\n    bounds: impl Into<Bounds<Pixels>>,\n    border_color: impl Into<Hsla>,\n    border_style: BorderStyle,\n) -> PaintQuad {\n    PaintQuad {\n        bounds: bounds.into(),\n        corner_radii: (0.).into(),\n        background: transparent_black().into(),\n        border_widths: (1.).into(),\n        border_color: border_color.into(),\n        border_style,\n        transformation: TransformationMatrix::default(),\n    }\n}\n",
  "raw_output": {
    "raw_edits": "<edits>\n\n<old_text>\n    /// Sets the background color of the quad.\n    pub fn background(self, background: impl Into<Background>) -> Self {\n        PaintQuad {\n            background: background.into(),\n            ..self\n        }\n    }\n}\n</old_text>\n<new_text>\n    /// Sets the background color of the quad.\n    pub fn background(self, background: impl Into<Background>) -> Self {\n        PaintQuad {\n            background: background.into(),\n            ..self\n        }\n    }\n\n    /// Sets the transformation matrix to apply to the quad.\n    pub fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {\n        PaintQuad {\n            transformation: transformation.into(),\n            ..self\n        }\n    }\n}\n</new_text>\n\n</edits>",
    "parser_metrics": {
      "tags": 2,
      "mismatched_tags": 0
    }
  }
}

Agent

Now that we have implemented all the needed changes, let's summarize what we've done:

  1. We've made sure the Quad struct in Rust (scene.rs) has a transformation field - it was already there
  2. We've made sure the PaintQuad struct also includes a transformation field - it was already there
  3. We've added a transformation() method to PaintQuad to make it easy to set the transformation
  4. We've updated the Metal shader to use the transformation matrix by changing:
    float4 device_position = to_device_position(unit_vertex, quad.bounds, viewport_size);
    to
    float4 device_position = to_device_position_transformed(unit_vertex, quad.bounds, quad.transformation, viewport_size);

This implementation provides complete support for transformations (scale, rotation, translation) on Quads in the UI framework. The transformations are applied in the Metal shader during rendering, using the same mechanism that was already in place for MonochromeSprites.

User

This can't be all, I don't see anything about rotation or scaling

Agent

You're absolutely right - I might have missed some important considerations. Let's look more deeply into how transformations are applied in this codebase, especially for rotation and scaling.

The TransformationMatrix struct has methods for rotation and scaling, but we need to make sure that:

  1. The Metal shader correctly applies these transformations
  2. The Rust API makes it easy to set up rotations and scaling for quads

Let's look more closely at the transformation code in the Metal shader:

You're right - I've only made it possible to use transformations, but I haven't fully analyzed how rotations and scaling are properly applied. Let's look deeper into how the transformation pipeline works:

Use Tool: read_file (toolu_013ksNPvYzTG6Xky4QHmvRYQ)

{
  "path": "zed/crates/gpui/src/scene.rs",
  "start_line": 532,
  "end_line": 614
}

Tool Results: toolu_013ksNPvYzTG6Xky4QHmvRYQ

impl TransformationMatrix { /// The unit matrix, has no effect. pub fn unit() -> Self { Self { rotation_scale: [[1.0, 0.0], [0.0, 1.0]], translation: [0.0, 0.0], } }

/// Move the origin by a given point
pub fn translate(mut self, point: Point<ScaledPixels>) -> Self {
    self.compose(Self {
        rotation_scale: [[1.0, 0.0], [0.0, 1.0]],
        translation: [point.x.0, point.y.0],
    })
}

/// Clockwise rotation in radians around the origin
pub fn rotate(self, angle: Radians) -> Self {
    self.compose(Self {
        rotation_scale: [
            [angle.0.cos(), -angle.0.sin()],
            [angle.0.sin(), angle.0.cos()],
        ],
        translation: [0.0, 0.0],
    })
}

/// Scale around the origin
pub fn scale(self, size: Size<f32>) -> Self {
    self.compose(Self {
        rotation_scale: [[size.width, 0.0], [0.0, size.height]],
        translation: [0.0, 0.0],
    })
}

/// Perform matrix multiplication with another transformation
/// to produce a new transformation that is the result of
/// applying both transformations: first, `other`, then `self`.
#[inline]
pub fn compose(self, other: TransformationMatrix) -> TransformationMatrix {
    if other == Self::unit() {
        return self;
    }
    // Perform matrix multiplication
    TransformationMatrix {
        rotation_scale: [
            [
                self.rotation_scale[0][0] * other.rotation_scale[0][0]
                    + self.rotation_scale[0][1] * other.rotation_scale[1][0],
                self.rotation_scale[0][0] * other.rotation_scale[0][1]
                    + self.rotation_scale[0][1] * other.rotation_scale[1][1],
            ],
            [
                self.rotation_scale[1][0] * other.rotation_scale[0][0]
                    + self.rotation_scale[1][1] * other.rotation_scale[1][0],
                self.rotation_scale[1][0] * other.rotation_scale[0][1]
                    + self.rotation_scale[1][1] * other.rotation_scale[1][1],
            ],
        ],
        translation: [
            self.translation[0]
                + self.rotation_scale[0][0] * other.translation[0]
                + self.rotation_scale[0][1] * other.translation[1],
            self.translation[1]
                + self.rotation_scale[1][0] * other.translation[0]
                + self.rotation_scale[1][1] * other.translation[1],
        ],
    }
}

/// Apply transformation to a point, mainly useful for debugging
pub fn apply(&self, point: Point<Pixels>) -> Point<Pixels> {
    let input = [point.x.0, point.y.0];
    let mut output = self.translation;
    for (i, output_cell) in output.iter_mut().enumerate() {
        for (k, input_cell) in input.iter().enumerate() {
            *output_cell += self.rotation_scale[i][k] * *input_cell;
        }
    }
    Point::new(output[0].into(), output[1].into())
}

Agent

Let me check the updated version of `window.rs` to understand what has changed since our last analysis. This will help me understand what might be missing in our implementation.

I'll examine the updated window.rs file to see what changes were made:

Use Tool: read_file (toolu_01NVbejgBq1LqBVPWcZJuAwW)

{
  "path": "zed/crates/gpui/src/window.rs",
  "start_line": 4200,
  "end_line": 4250
}

Tool Results: toolu_01NVbejgBq1LqBVPWcZJuAwW

/// The transformation to apply to the quad.
pub transformation: TransformationMatrix,

}

impl PaintQuad { /// Sets the corner radii of the quad. pub fn corner_radii(self, corner_radii: impl Into<Corners>) -> Self { PaintQuad { corner_radii: corner_radii.into(), ..self } }

/// Sets the border widths of the quad.
pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {
    PaintQuad {
        border_widths: border_widths.into(),
        ..self
    }
}

/// Sets the border color of the quad.
pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {
    PaintQuad {
        border_color: border_color.into(),
        ..self
    }
}

/// Sets the background color of the quad.
pub fn background(self, background: impl Into<Background>) -> Self {
    PaintQuad {
        background: background.into(),
        ..self
    }
}

/// Sets the transformation matrix to apply to the quad.
pub(crate) fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {
    PaintQuad {
        transformation: transformation.into(),
        ..self
    }
}

}

/// Creates a quad with the given parameters. pub fn quad( bounds: Bounds, corner_radii: impl Into<Corners>, background: impl Into,

Agent

Use Tool: read_file (toolu_01NwJDL4TjPZeywtVnc4T2c4)

{
  "end_line": 4285,
  "path": "zed/crates/gpui/src/window.rs",
  "start_line": 4249
}

Tool Results: toolu_01NwJDL4TjPZeywtVnc4T2c4

corner_radii: impl Into<Corners<Pixels>>,
background: impl Into<Background>,
border_widths: impl Into<Edges<Pixels>>,
border_color: impl Into<Hsla>,
border_style: BorderStyle,

) -> PaintQuad { PaintQuad { bounds, corner_radii: corner_radii.into(), background: background.into(), border_widths: border_widths.into(), border_color: border_color.into(), border_style, transformation: TransformationMatrix::default(), } }

pub(crate) fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad { PaintQuad { transformation, ..quad } }

/// Creates a filled quad with the given bounds and background color. pub fn fill(bounds: impl Into<Bounds>, background: impl Into) -> PaintQuad { PaintQuad { bounds: bounds.into(), corner_radii: (0.).into(), background: background.into(), border_widths: (0.).into(), border_color: transparent_black(), border_style: BorderStyle::default(), transformation: TransformationMatrix::default(), } }

Agent

Now let's examine how the Metal shader applies transformations to ensure it correctly handles rotation and scaling:

Use Tool: read_file (toolu_01LrzfwdtricdGjRztfJGQDe)

{
  "end_line": 990,
  "path": "zed/crates/gpui/src/platform/mac/shaders.metal",
  "start_line": 967
}

Tool Results: toolu_01LrzfwdtricdGjRztfJGQDe

}

float4 to_device_position_transformed(float2 unit_vertex, Bounds_ScaledPixels bounds, TransformationMatrix transformation, constant Size_DevicePixels *input_viewport_size) { float2 position = unit_vertex * float2(bounds.size.width, bounds.size.height) + float2(bounds.origin.x, bounds.origin.y);

// Apply the transformation matrix to the position via matrix multiplication. float2 transformed_position = float2(0, 0); transformed_position[0] = position[0] * transformation.rotation_scale[0][0] + position[1] * transformation.rotation_scale[0][1]; transformed_position[1] = position[0] * transformation.rotation_scale[1][0] + position[1] * transformation.rotation_scale[1][1];

// Add in the translation component of the transformation matrix. transformed_position[0] += transformation.translation[0]; transformed_position[1] += transformation.translation[1];

float2 viewport_size = float2((float)input_viewport_size->width, (float)input_viewport_size->height); float2 device_position = transformed_position / viewport_size * float2(2., -2.) + float2(-1., 1.); return float4(device_position, 0., 1.); }

Agent

I need to look at the original error you mentioned. Let me examine my earlier implementation where I added the transformation method to PaintQuad:

Use Tool: terminal (toolu_01JSudBcWz1YXfbJAuCfVrp1)

{
  "cd": "zed",
  "command": "git diff crates/gpui/src/window.rs"
}

Tool Results: toolu_01JSudBcWz1YXfbJAuCfVrp1

diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs
index 14c12693df..a7d92dc60e 100644
--- a/crates/gpui/src/window.rs
+++ b/crates/gpui/src/window.rs
@@ -2388,6 +2388,7 @@ impl Window {
             corner_radii: quad.corner_radii.scale(scale_factor),
             border_widths: quad.border_widths.scale(scale_factor),
             border_style: quad.border_style,
+            transformation: quad.transformation,
         });
     }

@@ -4196,6 +4197,8 @@ pub struct PaintQuad {
     pub border_color: Hsla,
     /// The style of the quad's borders.
     pub border_style: BorderStyle,
+    /// The transformation to apply to the quad.
+    pub transformation: TransformationMatrix,
 }

 impl PaintQuad {
@@ -4230,6 +4233,14 @@ impl PaintQuad {
             ..self
         }
     }
+
+    /// Sets the transformation matrix to apply to the quad.
+    pub(crate) fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {
+        PaintQuad {
+            transformation: transformation.into(),
+            ..self
+        }
+    }
 }

 /// Creates a quad with the given parameters.
@@ -4248,6 +4259,14 @@ pub fn quad(
         border_widths: border_widths.into(),
         border_color: border_color.into(),
         border_style,
+        transformation: TransformationMatrix::default(),
+    }
+}
+
+pub(crate) fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad {
+    PaintQuad {
+        transformation,
+        ..quad
     }
 }

@@ -4260,6 +4279,7 @@ pub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>
         border_widths: (0.).into(),
         border_color: transparent_black(),
         border_style: BorderStyle::default(),
+        transformation: TransformationMatrix::default(),
     }
 }

@@ -4276,5 +4296,6 @@ pub fn outline(
         border_widths: (1.).into(),
         border_color: border_color.into(),
         border_style,
+        transformation: TransformationMatrix::default(),
     }
 }

Agent

I missed several important things:

  1. I made the transformation method on PaintQuad use pub(crate) accessibility - it should be pub to be usable from outside the crate.

  2. We need helper functions to make it easier to apply rotation and scaling to quads.

  3. The Metal shader does apply transformations correctly, but we need to make the API more user-friendly.

Let's address these issues:

Use Tool: edit_file (toolu_01QkfvT2X43rpw1Pw4gRzToT)

{
  "create_or_overwrite": false,
  "display_description": "Update PaintQuad to provide user-friendly rotation and scaling APIs",
  "path": "zed/crates/gpui/src/window.rs"
}

Tool Results: toolu_01QkfvT2X43rpw1Pw4gRzToT

Edited zed/crates/gpui/src/window.rs:

@@ -4235,9 +4235,33 @@
     }
 
     /// Sets the transformation matrix to apply to the quad.
-    pub(crate) fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {
+    pub fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {
         PaintQuad {
             transformation: transformation.into(),
+            ..self
+        }
+    }
+    
+    /// Rotates the quad around its origin by the given angle (in radians, clockwise).
+    pub fn rotate(self, angle: impl Into<Radians>) -> Self {
+        PaintQuad {
+            transformation: self.transformation.rotate(angle.into()),
+            ..self
+        }
+    }
+    
+    /// Scales the quad around its origin by the given factor.
+    pub fn scale(self, scale: impl Into<Size<f32>>) -> Self {
+        PaintQuad {
+            transformation: self.transformation.scale(scale.into()),
+            ..self
+        }
+    }
+    
+    /// Translates the quad by the given offset.
+    pub fn translate(self, offset: impl Into<Point<ScaledPixels>>) -> Self {
+        PaintQuad {
+            transformation: self.transformation.translate(offset.into()),
             ..self
         }
     }
@@ -4263,7 +4287,8 @@
     }
 }
 
-pub(crate) fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad {
+/// Applies a transformation matrix to a quad.
+pub fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad {
     PaintQuad {
         transformation,
         ..quad

Debug Output:

{
  "original_path": "crates/gpui/src/window.rs",
  "new_text": "use crate::{\n    Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,\n    AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Context,\n    Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId,\n    DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, FontId,\n    Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero, KeyBinding, KeyContext,\n    KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers,\n    ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent,\n    Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler,\n    PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams,\n    RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR,\n    SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style,\n    SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement,\n    TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance,\n    WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem,\n    point, prelude::*, px, size, transparent_black,\n};\nuse anyhow::{Context as _, Result, anyhow};\nuse collections::{FxHashMap, FxHashSet};\n#[cfg(target_os = \"macos\")]\nuse core_video::pixel_buffer::CVPixelBuffer;\nuse derive_more::{Deref, DerefMut};\nuse futures::FutureExt;\nuse futures::channel::oneshot;\nuse parking_lot::RwLock;\nuse raw_window_handle::{HandleError, HasWindowHandle};\nuse refineable::Refineable;\nuse slotmap::SlotMap;\nuse smallvec::SmallVec;\nuse std::{\n    any::{Any, TypeId},\n    borrow::Cow,\n    cell::{Cell, RefCell},\n    cmp,\n    fmt::{Debug, Display},\n    hash::{Hash, Hasher},\n    marker::PhantomData,\n    mem,\n    ops::{DerefMut, Range},\n    rc::Rc,\n    sync::{\n        Arc, Weak,\n        atomic::{AtomicUsize, Ordering::SeqCst},\n    },\n    time::{Duration, Instant},\n};\nuse util::post_inc;\nuse util::{ResultExt, measure};\nuse uuid::Uuid;\n\nmod prompts;\n\npub use prompts::*;\n\npub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1024.), px(700.));\n\n/// Represents the two different phases when dispatching events.\n#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]\npub enum DispatchPhase {\n    /// After the capture phase comes the bubble phase, in which mouse event listeners are\n    /// invoked front to back and keyboard event listeners are invoked from the focused element\n    /// to the root of the element tree. This is the phase you'll most commonly want to use when\n    /// registering event listeners.\n    #[default]\n    Bubble,\n    /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard\n    /// listeners are invoked from the root of the tree downward toward the focused element. This phase\n    /// is used for special purposes such as clearing the \"pressed\" state for click events. If\n    /// you stop event propagation during this phase, you need to know what you're doing. Handlers\n    /// outside of the immediate region may rely on detecting non-local events during this phase.\n    Capture,\n}\n\nimpl DispatchPhase {\n    /// Returns true if this represents the \"bubble\" phase.\n    pub fn bubble(self) -> bool {\n        self == DispatchPhase::Bubble\n    }\n\n    /// Returns true if this represents the \"capture\" phase.\n    pub fn capture(self) -> bool {\n        self == DispatchPhase::Capture\n    }\n}\n\nstruct WindowInvalidatorInner {\n    pub dirty: bool,\n    pub draw_phase: DrawPhase,\n    pub dirty_views: FxHashSet<EntityId>,\n}\n\n#[derive(Clone)]\npub(crate) struct WindowInvalidator {\n    inner: Rc<RefCell<WindowInvalidatorInner>>,\n}\n\nimpl WindowInvalidator {\n    pub fn new() -> Self {\n        WindowInvalidator {\n            inner: Rc::new(RefCell::new(WindowInvalidatorInner {\n                dirty: true,\n                draw_phase: DrawPhase::None,\n                dirty_views: FxHashSet::default(),\n            })),\n        }\n    }\n\n    pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {\n        let mut inner = self.inner.borrow_mut();\n        inner.dirty_views.insert(entity);\n        if inner.draw_phase == DrawPhase::None {\n            inner.dirty = true;\n            cx.push_effect(Effect::Notify { emitter: entity });\n            true\n        } else {\n            false\n        }\n    }\n\n    pub fn is_dirty(&self) -> bool {\n        self.inner.borrow().dirty\n    }\n\n    pub fn set_dirty(&self, dirty: bool) {\n        self.inner.borrow_mut().dirty = dirty\n    }\n\n    pub fn set_phase(&self, phase: DrawPhase) {\n        self.inner.borrow_mut().draw_phase = phase\n    }\n\n    pub fn take_views(&self) -> FxHashSet<EntityId> {\n        mem::take(&mut self.inner.borrow_mut().dirty_views)\n    }\n\n    pub fn replace_views(&self, views: FxHashSet<EntityId>) {\n        self.inner.borrow_mut().dirty_views = views;\n    }\n\n    pub fn not_drawing(&self) -> bool {\n        self.inner.borrow().draw_phase == DrawPhase::None\n    }\n\n    #[track_caller]\n    pub fn debug_assert_paint(&self) {\n        debug_assert!(\n            matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),\n            \"this method can only be called during paint\"\n        );\n    }\n\n    #[track_caller]\n    pub fn debug_assert_prepaint(&self) {\n        debug_assert!(\n            matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),\n            \"this method can only be called during request_layout, or prepaint\"\n        );\n    }\n\n    #[track_caller]\n    pub fn debug_assert_paint_or_prepaint(&self) {\n        debug_assert!(\n            matches!(\n                self.inner.borrow().draw_phase,\n                DrawPhase::Paint | DrawPhase::Prepaint\n            ),\n            \"this method can only be called during request_layout, prepaint, or paint\"\n        );\n    }\n}\n\ntype AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;\n\npub(crate) type AnyWindowFocusListener =\n    Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;\n\npub(crate) struct WindowFocusEvent {\n    pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,\n    pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,\n}\n\nimpl WindowFocusEvent {\n    pub fn is_focus_in(&self, focus_id: FocusId) -> bool {\n        !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id)\n    }\n\n    pub fn is_focus_out(&self, focus_id: FocusId) -> bool {\n        self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id)\n    }\n}\n\n/// This is provided when subscribing for `Context::on_focus_out` events.\npub struct FocusOutEvent {\n    /// A weak focus handle representing what was blurred.\n    pub blurred: WeakFocusHandle,\n}\n\nslotmap::new_key_type! {\n    /// A globally unique identifier for a focusable element.\n    pub struct FocusId;\n}\n\nthread_local! {\n    /// 8MB wasn't quite enough...\n    pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(32 * 1024 * 1024));\n}\n\npub(crate) type FocusMap = RwLock<SlotMap<FocusId, AtomicUsize>>;\n\nimpl FocusId {\n    /// Obtains whether the element associated with this handle is currently focused.\n    pub fn is_focused(&self, window: &Window) -> bool {\n        window.focus == Some(*self)\n    }\n\n    /// Obtains whether the element associated with this handle contains the focused\n    /// element or is itself focused.\n    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {\n        window\n            .focused(cx)\n            .map_or(false, |focused| self.contains(focused.id, window))\n    }\n\n    /// Obtains whether the element associated with this handle is contained within the\n    /// focused element or is itself focused.\n    pub fn within_focused(&self, window: &Window, cx: &App) -> bool {\n        let focused = window.focused(cx);\n        focused.map_or(false, |focused| focused.id.contains(*self, window))\n    }\n\n    /// Obtains whether this handle contains the given handle in the most recently rendered frame.\n    pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {\n        window\n            .rendered_frame\n            .dispatch_tree\n            .focus_contains(*self, other)\n    }\n}\n\n/// A handle which can be used to track and manipulate the focused element in a window.\npub struct FocusHandle {\n    pub(crate) id: FocusId,\n    handles: Arc<FocusMap>,\n}\n\nimpl std::fmt::Debug for FocusHandle {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.write_fmt(format_args!(\"FocusHandle({:?})\", self.id))\n    }\n}\n\nimpl FocusHandle {\n    pub(crate) fn new(handles: &Arc<FocusMap>) -> Self {\n        let id = handles.write().insert(AtomicUsize::new(1));\n        Self {\n            id,\n            handles: handles.clone(),\n        }\n    }\n\n    pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {\n        let lock = handles.read();\n        let ref_count = lock.get(id)?;\n        if ref_count.load(SeqCst) == 0 {\n            None\n        } else {\n            ref_count.fetch_add(1, SeqCst);\n            Some(Self {\n                id,\n                handles: handles.clone(),\n            })\n        }\n    }\n\n    /// Converts this focus handle into a weak variant, which does not prevent it from being released.\n    pub fn downgrade(&self) -> WeakFocusHandle {\n        WeakFocusHandle {\n            id: self.id,\n            handles: Arc::downgrade(&self.handles),\n        }\n    }\n\n    /// Moves the focus to the element associated with this handle.\n    pub fn focus(&self, window: &mut Window) {\n        window.focus(self)\n    }\n\n    /// Obtains whether the element associated with this handle is currently focused.\n    pub fn is_focused(&self, window: &Window) -> bool {\n        self.id.is_focused(window)\n    }\n\n    /// Obtains whether the element associated with this handle contains the focused\n    /// element or is itself focused.\n    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {\n        self.id.contains_focused(window, cx)\n    }\n\n    /// Obtains whether the element associated with this handle is contained within the\n    /// focused element or is itself focused.\n    pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {\n        self.id.within_focused(window, cx)\n    }\n\n    /// Obtains whether this handle contains the given handle in the most recently rendered frame.\n    pub fn contains(&self, other: &Self, window: &Window) -> bool {\n        self.id.contains(other.id, window)\n    }\n\n    /// Dispatch an action on the element that rendered this focus handle\n    pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {\n        if let Some(node_id) = window\n            .rendered_frame\n            .dispatch_tree\n            .focusable_node_id(self.id)\n        {\n            window.dispatch_action_on_node(node_id, action, cx)\n        }\n    }\n}\n\nimpl Clone for FocusHandle {\n    fn clone(&self) -> Self {\n        Self::for_id(self.id, &self.handles).unwrap()\n    }\n}\n\nimpl PartialEq for FocusHandle {\n    fn eq(&self, other: &Self) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for FocusHandle {}\n\nimpl Drop for FocusHandle {\n    fn drop(&mut self) {\n        self.handles\n            .read()\n            .get(self.id)\n            .unwrap()\n            .fetch_sub(1, SeqCst);\n    }\n}\n\n/// A weak reference to a focus handle.\n#[derive(Clone, Debug)]\npub struct WeakFocusHandle {\n    pub(crate) id: FocusId,\n    pub(crate) handles: Weak<FocusMap>,\n}\n\nimpl WeakFocusHandle {\n    /// Attempts to upgrade the [WeakFocusHandle] to a [FocusHandle].\n    pub fn upgrade(&self) -> Option<FocusHandle> {\n        let handles = self.handles.upgrade()?;\n        FocusHandle::for_id(self.id, &handles)\n    }\n}\n\nimpl PartialEq for WeakFocusHandle {\n    fn eq(&self, other: &WeakFocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for WeakFocusHandle {}\n\nimpl PartialEq<FocusHandle> for WeakFocusHandle {\n    fn eq(&self, other: &FocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl PartialEq<WeakFocusHandle> for FocusHandle {\n    fn eq(&self, other: &WeakFocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\n/// Focusable allows users of your view to easily\n/// focus it (using window.focus_view(cx, view))\npub trait Focusable: 'static {\n    /// Returns the focus handle associated with this view.\n    fn focus_handle(&self, cx: &App) -> FocusHandle;\n}\n\nimpl<V: Focusable> Focusable for Entity<V> {\n    fn focus_handle(&self, cx: &App) -> FocusHandle {\n        self.read(cx).focus_handle(cx)\n    }\n}\n\n/// ManagedView is a view (like a Modal, Popover, Menu, etc.)\n/// where the lifecycle of the view is handled by another view.\npub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}\n\nimpl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}\n\n/// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal.\npub struct DismissEvent;\n\ntype FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;\n\npub(crate) type AnyMouseListener =\n    Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;\n\n#[derive(Clone)]\npub(crate) struct CursorStyleRequest {\n    pub(crate) hitbox_id: Option<HitboxId>, // None represents whole window\n    pub(crate) style: CursorStyle,\n}\n\n/// An identifier for a [Hitbox].\n#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]\npub struct HitboxId(usize);\n\nimpl HitboxId {\n    /// Checks if the hitbox with this id is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        window.mouse_hit_test.0.contains(self)\n    }\n}\n\n/// A rectangular region that potentially blocks hitboxes inserted prior.\n/// See [Window::insert_hitbox] for more details.\n#[derive(Clone, Debug, Deref)]\npub struct Hitbox {\n    /// A unique identifier for the hitbox.\n    pub id: HitboxId,\n    /// The bounds of the hitbox.\n    #[deref]\n    pub bounds: Bounds<Pixels>,\n    /// The content mask when the hitbox was inserted.\n    pub content_mask: ContentMask<Pixels>,\n    /// Whether the hitbox occludes other hitboxes inserted prior.\n    pub opaque: bool,\n}\n\nimpl Hitbox {\n    /// Checks if the hitbox is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        self.id.is_hovered(window)\n    }\n}\n\n#[derive(Default, Eq, PartialEq)]\npub(crate) struct HitTest(SmallVec<[HitboxId; 8]>);\n\n/// An identifier for a tooltip.\n#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]\npub struct TooltipId(usize);\n\nimpl TooltipId {\n    /// Checks if the tooltip is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        window\n            .tooltip_bounds\n            .as_ref()\n            .map_or(false, |tooltip_bounds| {\n                tooltip_bounds.id == *self\n                    && tooltip_bounds.bounds.contains(&window.mouse_position())\n            })\n    }\n}\n\npub(crate) struct TooltipBounds {\n    id: TooltipId,\n    bounds: Bounds<Pixels>,\n}\n\n#[derive(Clone)]\npub(crate) struct TooltipRequest {\n    id: TooltipId,\n    tooltip: AnyTooltip,\n}\n\npub(crate) struct DeferredDraw {\n    current_view: EntityId,\n    priority: usize,\n    parent_node: DispatchNodeId,\n    element_id_stack: SmallVec<[ElementId; 32]>,\n    text_style_stack: Vec<TextStyleRefinement>,\n    element: Option<AnyElement>,\n    absolute_offset: Point<Pixels>,\n    prepaint_range: Range<PrepaintStateIndex>,\n    paint_range: Range<PaintIndex>,\n}\n\npub(crate) struct Frame {\n    pub(crate) focus: Option<FocusId>,\n    pub(crate) window_active: bool,\n    pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,\n    accessed_element_states: Vec<(GlobalElementId, TypeId)>,\n    pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,\n    pub(crate) dispatch_tree: DispatchTree,\n    pub(crate) scene: Scene,\n    pub(crate) hitboxes: Vec<Hitbox>,\n    pub(crate) deferred_draws: Vec<DeferredDraw>,\n    pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,\n    pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,\n    pub(crate) cursor_styles: Vec<CursorStyleRequest>,\n    #[cfg(any(test, feature = \"test-support\"))]\n    pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,\n}\n\n#[derive(Clone, Default)]\npub(crate) struct PrepaintStateIndex {\n    hitboxes_index: usize,\n    tooltips_index: usize,\n    deferred_draws_index: usize,\n    dispatch_tree_index: usize,\n    accessed_element_states_index: usize,\n    line_layout_index: LineLayoutIndex,\n}\n\n#[derive(Clone, Default)]\npub(crate) struct PaintIndex {\n    scene_index: usize,\n    mouse_listeners_index: usize,\n    input_handlers_index: usize,\n    cursor_styles_index: usize,\n    accessed_element_states_index: usize,\n    line_layout_index: LineLayoutIndex,\n}\n\nimpl Frame {\n    pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {\n        Frame {\n            focus: None,\n            window_active: false,\n            element_states: FxHashMap::default(),\n            accessed_element_states: Vec::new(),\n            mouse_listeners: Vec::new(),\n            dispatch_tree,\n            scene: Scene::default(),\n            hitboxes: Vec::new(),\n            deferred_draws: Vec::new(),\n            input_handlers: Vec::new(),\n            tooltip_requests: Vec::new(),\n            cursor_styles: Vec::new(),\n\n            #[cfg(any(test, feature = \"test-support\"))]\n            debug_bounds: FxHashMap::default(),\n        }\n    }\n\n    pub(crate) fn clear(&mut self) {\n        self.element_states.clear();\n        self.accessed_element_states.clear();\n        self.mouse_listeners.clear();\n        self.dispatch_tree.clear();\n        self.scene.clear();\n        self.input_handlers.clear();\n        self.tooltip_requests.clear();\n        self.cursor_styles.clear();\n        self.hitboxes.clear();\n        self.deferred_draws.clear();\n        self.focus = None;\n    }\n\n    pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {\n        let mut hit_test = HitTest::default();\n        for hitbox in self.hitboxes.iter().rev() {\n            let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds);\n            if bounds.contains(&position) {\n                hit_test.0.push(hitbox.id);\n                if hitbox.opaque {\n                    break;\n                }\n            }\n        }\n        hit_test\n    }\n\n    pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {\n        self.focus\n            .map(|focus_id| self.dispatch_tree.focus_path(focus_id))\n            .unwrap_or_default()\n    }\n\n    pub(crate) fn finish(&mut self, prev_frame: &mut Self) {\n        for element_state_key in &self.accessed_element_states {\n            if let Some((element_state_key, element_state)) =\n                prev_frame.element_states.remove_entry(element_state_key)\n            {\n                self.element_states.insert(element_state_key, element_state);\n            }\n        }\n\n        self.scene.finish();\n    }\n}\n\n/// Holds the state for a specific window.\npub struct Window {\n    pub(crate) handle: AnyWindowHandle,\n    pub(crate) invalidator: WindowInvalidator,\n    pub(crate) removed: bool,\n    pub(crate) platform_window: Box<dyn PlatformWindow>,\n    display_id: Option<DisplayId>,\n    sprite_atlas: Arc<dyn PlatformAtlas>,\n    text_system: Arc<WindowTextSystem>,\n    rem_size: Pixels,\n    /// The stack of override values for the window's rem size.\n    ///\n    /// This is used by `with_rem_size` to allow rendering an element tree with\n    /// a given rem size.\n    rem_size_override_stack: SmallVec<[Pixels; 8]>,\n    pub(crate) viewport_size: Size<Pixels>,\n    layout_engine: Option<TaffyLayoutEngine>,\n    pub(crate) root: Option<AnyView>,\n    pub(crate) element_id_stack: SmallVec<[ElementId; 32]>,\n    pub(crate) text_style_stack: Vec<TextStyleRefinement>,\n    pub(crate) rendered_entity_stack: Vec<EntityId>,\n    pub(crate) element_offset_stack: Vec<Point<Pixels>>,\n    pub(crate) element_opacity: Option<f32>,\n    pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,\n    pub(crate) requested_autoscroll: Option<Bounds<Pixels>>,\n    pub(crate) image_cache_stack: Vec<AnyImageCache>,\n    pub(crate) rendered_frame: Frame,\n    pub(crate) next_frame: Frame,\n    pub(crate) next_hitbox_id: HitboxId,\n    pub(crate) next_tooltip_id: TooltipId,\n    pub(crate) tooltip_bounds: Option<TooltipBounds>,\n    next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,\n    pub(crate) dirty_views: FxHashSet<EntityId>,\n    focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,\n    pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,\n    default_prevented: bool,\n    mouse_position: Point<Pixels>,\n    mouse_hit_test: HitTest,\n    modifiers: Modifiers,\n    scale_factor: f32,\n    pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,\n    appearance: WindowAppearance,\n    pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,\n    active: Rc<Cell<bool>>,\n    hovered: Rc<Cell<bool>>,\n    pub(crate) needs_present: Rc<Cell<bool>>,\n    pub(crate) last_input_timestamp: Rc<Cell<Instant>>,\n    pub(crate) refreshing: bool,\n    pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,\n    pub(crate) focus: Option<FocusId>,\n    focus_enabled: bool,\n    pending_input: Option<PendingInput>,\n    pending_modifier: ModifierState,\n    pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,\n    prompt: Option<RenderablePromptHandle>,\n    pub(crate) client_inset: Option<Pixels>,\n}\n\n#[derive(Clone, Debug, Default)]\nstruct ModifierState {\n    modifiers: Modifiers,\n    saw_keystroke: bool,\n}\n\n#[derive(Clone, Copy, Debug, Eq, PartialEq)]\npub(crate) enum DrawPhase {\n    None,\n    Prepaint,\n    Paint,\n    Focus,\n}\n\n#[derive(Default, Debug)]\nstruct PendingInput {\n    keystrokes: SmallVec<[Keystroke; 1]>,\n    focus: Option<FocusId>,\n    timer: Option<Task<()>>,\n}\n\npub(crate) struct ElementStateBox {\n    pub(crate) inner: Box<dyn Any>,\n    #[cfg(debug_assertions)]\n    pub(crate) type_name: &'static str,\n}\n\nfn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> Bounds<Pixels> {\n    const DEFAULT_WINDOW_OFFSET: Point<Pixels> = point(px(0.), px(35.));\n\n    // TODO, BUG: if you open a window with the currently active window\n    // on the stack, this will erroneously select the 'unwrap_or_else'\n    // code path\n    cx.active_window()\n        .and_then(|w| w.update(cx, |_, window, _| window.bounds()).ok())\n        .map(|mut bounds| {\n            bounds.origin += DEFAULT_WINDOW_OFFSET;\n            bounds\n        })\n        .unwrap_or_else(|| {\n            let display = display_id\n                .map(|id| cx.find_display(id))\n                .unwrap_or_else(|| cx.primary_display());\n\n            display\n                .map(|display| display.default_bounds())\n                .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE))\n        })\n}\n\nimpl Window {\n    pub(crate) fn new(\n        handle: AnyWindowHandle,\n        options: WindowOptions,\n        cx: &mut App,\n    ) -> Result<Self> {\n        let WindowOptions {\n            window_bounds,\n            titlebar,\n            focus,\n            show,\n            kind,\n            is_movable,\n            display_id,\n            window_background,\n            app_id,\n            window_min_size,\n            window_decorations,\n        } = options;\n\n        let bounds = window_bounds\n            .map(|bounds| bounds.get_bounds())\n            .unwrap_or_else(|| default_bounds(display_id, cx));\n        let mut platform_window = cx.platform.open_window(\n            handle,\n            WindowParams {\n                bounds,\n                titlebar,\n                kind,\n                is_movable,\n                focus,\n                show,\n                display_id,\n                window_min_size,\n            },\n        )?;\n        let display_id = platform_window.display().map(|display| display.id());\n        let sprite_atlas = platform_window.sprite_atlas();\n        let mouse_position = platform_window.mouse_position();\n        let modifiers = platform_window.modifiers();\n        let content_size = platform_window.content_size();\n        let scale_factor = platform_window.scale_factor();\n        let appearance = platform_window.appearance();\n        let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));\n        let invalidator = WindowInvalidator::new();\n        let active = Rc::new(Cell::new(platform_window.is_active()));\n        let hovered = Rc::new(Cell::new(platform_window.is_hovered()));\n        let needs_present = Rc::new(Cell::new(false));\n        let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();\n        let last_input_timestamp = Rc::new(Cell::new(Instant::now()));\n\n        platform_window\n            .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server));\n        platform_window.set_background_appearance(window_background);\n\n        if let Some(ref window_open_state) = window_bounds {\n            match window_open_state {\n                WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),\n                WindowBounds::Maximized(_) => platform_window.zoom(),\n                WindowBounds::Windowed(_) => {}\n            }\n        }\n\n        platform_window.on_close(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                let _ = handle.update(&mut cx, |_, window, _| window.remove_window());\n            }\n        }));\n        platform_window.on_request_frame(Box::new({\n            let mut cx = cx.to_async();\n            let invalidator = invalidator.clone();\n            let active = active.clone();\n            let needs_present = needs_present.clone();\n            let next_frame_callbacks = next_frame_callbacks.clone();\n            let last_input_timestamp = last_input_timestamp.clone();\n            move |request_frame_options| {\n                let next_frame_callbacks = next_frame_callbacks.take();\n                if !next_frame_callbacks.is_empty() {\n                    handle\n                        .update(&mut cx, |_, window, cx| {\n                            for callback in next_frame_callbacks {\n                                callback(window, cx);\n                            }\n                        })\n                        .log_err();\n                }\n\n                // Keep presenting the current scene for 1 extra second since the\n                // last input to prevent the display from underclocking the refresh rate.\n                let needs_present = request_frame_options.require_presentation\n                    || needs_present.get()\n                    || (active.get()\n                        && last_input_timestamp.get().elapsed() < Duration::from_secs(1));\n\n                if invalidator.is_dirty() {\n                    measure(\"frame duration\", || {\n                        handle\n                            .update(&mut cx, |_, window, cx| {\n                                window.draw(cx);\n                                window.present();\n                            })\n                            .log_err();\n                    })\n                } else if needs_present {\n                    handle\n                        .update(&mut cx, |_, window, _| window.present())\n                        .log_err();\n                }\n\n                handle\n                    .update(&mut cx, |_, window, _| {\n                        window.complete_frame();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_resize(Box::new({\n            let mut cx = cx.to_async();\n            move |_, _| {\n                handle\n                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_moved(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                handle\n                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_appearance_changed(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                handle\n                    .update(&mut cx, |_, window, cx| window.appearance_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_active_status_change(Box::new({\n            let mut cx = cx.to_async();\n            move |active| {\n                handle\n                    .update(&mut cx, |_, window, cx| {\n                        window.active.set(active);\n                        window.modifiers = window.platform_window.modifiers();\n                        window\n                            .activation_observers\n                            .clone()\n                            .retain(&(), |callback| callback(window, cx));\n                        window.refresh();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_hover_status_change(Box::new({\n            let mut cx = cx.to_async();\n            move |active| {\n                handle\n                    .update(&mut cx, |_, window, _| {\n                        window.hovered.set(active);\n                        window.refresh();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_input({\n            let mut cx = cx.to_async();\n            Box::new(move |event| {\n                handle\n                    .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))\n                    .log_err()\n                    .unwrap_or(DispatchEventResult::default())\n            })\n        });\n\n        if let Some(app_id) = app_id {\n            platform_window.set_app_id(&app_id);\n        }\n\n        platform_window.map_window().unwrap();\n\n        Ok(Window {\n            handle,\n            invalidator,\n            removed: false,\n            platform_window,\n            display_id,\n            sprite_atlas,\n            text_system,\n            rem_size: px(16.),\n            rem_size_override_stack: SmallVec::new(),\n            viewport_size: content_size,\n            layout_engine: Some(TaffyLayoutEngine::new()),\n            root: None,\n            element_id_stack: SmallVec::default(),\n            text_style_stack: Vec::new(),\n            rendered_entity_stack: Vec::new(),\n            element_offset_stack: Vec::new(),\n            content_mask_stack: Vec::new(),\n            element_opacity: None,\n            requested_autoscroll: None,\n            rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),\n            next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),\n            next_frame_callbacks,\n            next_hitbox_id: HitboxId::default(),\n            next_tooltip_id: TooltipId::default(),\n            tooltip_bounds: None,\n            dirty_views: FxHashSet::default(),\n            focus_listeners: SubscriberSet::new(),\n            focus_lost_listeners: SubscriberSet::new(),\n            default_prevented: true,\n            mouse_position,\n            mouse_hit_test: HitTest::default(),\n            modifiers,\n            scale_factor,\n            bounds_observers: SubscriberSet::new(),\n            appearance,\n            appearance_observers: SubscriberSet::new(),\n            active,\n            hovered,\n            needs_present,\n            last_input_timestamp,\n            refreshing: false,\n            activation_observers: SubscriberSet::new(),\n            focus: None,\n            focus_enabled: true,\n            pending_input: None,\n            pending_modifier: ModifierState::default(),\n            pending_input_observers: SubscriberSet::new(),\n            prompt: None,\n            client_inset: None,\n            image_cache_stack: Vec::new(),\n        })\n    }\n\n    pub(crate) fn new_focus_listener(\n        &self,\n        value: AnyWindowFocusListener,\n    ) -> (Subscription, impl FnOnce() + use<>) {\n        self.focus_listeners.insert((), value)\n    }\n}\n\n#[derive(Clone, Debug, Default, PartialEq, Eq)]\npub(crate) struct DispatchEventResult {\n    pub propagate: bool,\n    pub default_prevented: bool,\n}\n\n/// Indicates which region of the window is visible. Content falling outside of this mask will not be\n/// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type\n/// to leave room to support more complex shapes in the future.\n#[derive(Clone, Debug, Default, PartialEq, Eq)]\n#[repr(C)]\npub struct ContentMask<P: Clone + Default + Debug> {\n    /// The bounds\n    pub bounds: Bounds<P>,\n}\n\nimpl ContentMask<Pixels> {\n    /// Scale the content mask's pixel units by the given scaling factor.\n    pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {\n        ContentMask {\n            bounds: self.bounds.scale(factor),\n        }\n    }\n\n    /// Intersect the content mask with the given content mask.\n    pub fn intersect(&self, other: &Self) -> Self {\n        let bounds = self.bounds.intersect(&other.bounds);\n        ContentMask { bounds }\n    }\n}\n\nimpl Window {\n    fn mark_view_dirty(&mut self, view_id: EntityId) {\n        // Mark ancestor views as dirty. If already in the `dirty_views` set, then all its ancestors\n        // should already be dirty.\n        for view_id in self\n            .rendered_frame\n            .dispatch_tree\n            .view_path(view_id)\n            .into_iter()\n            .rev()\n        {\n            if !self.dirty_views.insert(view_id) {\n                break;\n            }\n        }\n    }\n\n    /// Registers a callback to be invoked when the window appearance changes.\n    pub fn observe_window_appearance(\n        &self,\n        mut callback: impl FnMut(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let (subscription, activate) = self.appearance_observers.insert(\n            (),\n            Box::new(move |window, cx| {\n                callback(window, cx);\n                true\n            }),\n        );\n        activate();\n        subscription\n    }\n\n    /// Replaces the root entity of the window with a new one.\n    pub fn replace_root<E>(\n        &mut self,\n        cx: &mut App,\n        build_view: impl FnOnce(&mut Window, &mut Context<E>) -> E,\n    ) -> Entity<E>\n    where\n        E: 'static + Render,\n    {\n        let view = cx.new(|cx| build_view(self, cx));\n        self.root = Some(view.clone().into());\n        self.refresh();\n        view\n    }\n\n    /// Returns the root entity of the window, if it has one.\n    pub fn root<E>(&self) -> Option<Option<Entity<E>>>\n    where\n        E: 'static + Render,\n    {\n        self.root\n            .as_ref()\n            .map(|view| view.clone().downcast::<E>().ok())\n    }\n\n    /// Obtain a handle to the window that belongs to this context.\n    pub fn window_handle(&self) -> AnyWindowHandle {\n        self.handle\n    }\n\n    /// Mark the window as dirty, scheduling it to be redrawn on the next frame.\n    pub fn refresh(&mut self) {\n        if self.invalidator.not_drawing() {\n            self.refreshing = true;\n            self.invalidator.set_dirty(true);\n        }\n    }\n\n    /// Close this window.\n    pub fn remove_window(&mut self) {\n        self.removed = true;\n    }\n\n    /// Obtain the currently focused [`FocusHandle`]. If no elements are focused, returns `None`.\n    pub fn focused(&self, cx: &App) -> Option<FocusHandle> {\n        self.focus\n            .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))\n    }\n\n    /// Move focus to the element associated with the given [`FocusHandle`].\n    pub fn focus(&mut self, handle: &FocusHandle) {\n        if !self.focus_enabled || self.focus == Some(handle.id) {\n            return;\n        }\n\n        self.focus = Some(handle.id);\n        self.clear_pending_keystrokes();\n        self.refresh();\n    }\n\n    /// Remove focus from all elements within this context's window.\n    pub fn blur(&mut self) {\n        if !self.focus_enabled {\n            return;\n        }\n\n        self.focus = None;\n        self.refresh();\n    }\n\n    /// Blur the window and don't allow anything in it to be focused again.\n    pub fn disable_focus(&mut self) {\n        self.blur();\n        self.focus_enabled = false;\n    }\n\n    /// Accessor for the text system.\n    pub fn text_system(&self) -> &Arc<WindowTextSystem> {\n        &self.text_system\n    }\n\n    /// The current text style. Which is composed of all the style refinements provided to `with_text_style`.\n    pub fn text_style(&self) -> TextStyle {\n        let mut style = TextStyle::default();\n        for refinement in &self.text_style_stack {\n            style.refine(refinement);\n        }\n        style\n    }\n\n    /// Check if the platform window is maximized\n    /// On some platforms (namely Windows) this is different than the bounds being the size of the display\n    pub fn is_maximized(&self) -> bool {\n        self.platform_window.is_maximized()\n    }\n\n    /// request a certain window decoration (Wayland)\n    pub fn request_decorations(&self, decorations: WindowDecorations) {\n        self.platform_window.request_decorations(decorations);\n    }\n\n    /// Start a window resize operation (Wayland)\n    pub fn start_window_resize(&self, edge: ResizeEdge) {\n        self.platform_window.start_window_resize(edge);\n    }\n\n    /// Return the `WindowBounds` to indicate that how a window should be opened\n    /// after it has been closed\n    pub fn window_bounds(&self) -> WindowBounds {\n        self.platform_window.window_bounds()\n    }\n\n    /// Return the `WindowBounds` excluding insets (Wayland and X11)\n    pub fn inner_window_bounds(&self) -> WindowBounds {\n        self.platform_window.inner_window_bounds()\n    }\n\n    /// Dispatch the given action on the currently focused element.\n    pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {\n        let focus_handle = self.focused(cx);\n\n        let window = self.handle;\n        cx.defer(move |cx| {\n            window\n                .update(cx, |_, window, cx| {\n                    let node_id = focus_handle\n                        .and_then(|handle| {\n                            window\n                                .rendered_frame\n                                .dispatch_tree\n                                .focusable_node_id(handle.id)\n                        })\n                        .unwrap_or_else(|| window.rendered_frame.dispatch_tree.root_node_id());\n\n                    window.dispatch_action_on_node(node_id, action.as_ref(), cx);\n                })\n                .log_err();\n        })\n    }\n\n    pub(crate) fn dispatch_keystroke_observers(\n        &mut self,\n        event: &dyn Any,\n        action: Option<Box<dyn Action>>,\n        context_stack: Vec<KeyContext>,\n        cx: &mut App,\n    ) {\n        let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {\n            return;\n        };\n\n        cx.keystroke_observers.clone().retain(&(), move |callback| {\n            (callback)(\n                &KeystrokeEvent {\n                    keystroke: key_down_event.keystroke.clone(),\n                    action: action.as_ref().map(|action| action.boxed_clone()),\n                    context_stack: context_stack.clone(),\n                },\n                self,\n                cx,\n            )\n        });\n    }\n\n    /// Schedules the given function to be run at the end of the current effect cycle, allowing entities\n    /// that are currently on the stack to be returned to the app.\n    pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {\n        let handle = self.handle;\n        cx.defer(move |cx| {\n            handle.update(cx, |_, window, cx| f(window, cx)).ok();\n        });\n    }\n\n    /// Subscribe to events emitted by a entity.\n    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.\n    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.\n    pub fn observe<T: 'static>(\n        &mut self,\n        observed: &Entity<T>,\n        cx: &mut App,\n        mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let entity_id = observed.entity_id();\n        let observed = observed.downgrade();\n        let window_handle = self.handle;\n        cx.new_observer(\n            entity_id,\n            Box::new(move |cx| {\n                window_handle\n                    .update(cx, |_, window, cx| {\n                        if let Some(handle) = observed.upgrade() {\n                            on_notify(handle, window, cx);\n                            true\n                        } else {\n                            false\n                        }\n                    })\n                    .unwrap_or(false)\n            }),\n        )\n    }\n\n    /// Subscribe to events emitted by a entity.\n    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.\n    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.\n    pub fn subscribe<Emitter, Evt>(\n        &mut self,\n        entity: &Entity<Emitter>,\n        cx: &mut App,\n        mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,\n    ) -> Subscription\n    where\n        Emitter: EventEmitter<Evt>,\n        Evt: 'static,\n    {\n        let entity_id = entity.entity_id();\n        let handle = entity.downgrade();\n        let window_handle = self.handle;\n        cx.new_subscription(\n            entity_id,\n            (\n                TypeId::of::<Evt>(),\n                Box::new(move |event, cx| {\n                    window_handle\n                        .update(cx, |_, window, cx| {\n                            if let Some(entity) = handle.upgrade() {\n                                let event = event.downcast_ref().expect(\"invalid event type\");\n                                on_event(entity, event, window, cx);\n                                true\n                            } else {\n                                false\n                            }\n                        })\n                        .unwrap_or(false)\n                }),\n            ),\n        )\n    }\n\n    /// Register a callback to be invoked when the given `Entity` is released.\n    pub fn observe_release<T>(\n        &self,\n        entity: &Entity<T>,\n        cx: &mut App,\n        mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,\n    ) -> Subscription\n    where\n        T: 'static,\n    {\n        let entity_id = entity.entity_id();\n        let window_handle = self.handle;\n        let (subscription, activate) = cx.release_listeners.insert(\n            entity_id,\n            Box::new(move |entity, cx| {\n                let entity = entity.downcast_mut().expect(\"invalid entity type\");\n                let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));\n            }),\n        );\n        activate();\n        subscription\n    }\n\n    /// Creates an [`AsyncWindowContext`], which has a static lifetime and can be held across\n    /// await points in async code.\n    pub fn to_async(&self, cx: &App) -> AsyncWindowContext {\n        AsyncWindowContext::new_context(cx.to_async(), self.handle)\n    }\n\n    /// Schedule the given closure to be run directly after the current frame is rendered.\n    pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) {\n        RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback));\n    }\n\n    /// Schedule a frame to be drawn on the next animation frame.\n    ///\n    /// This is useful for elements that need to animate continuously, such as a video player or an animated GIF.\n    /// It will cause the window to redraw on the next frame, even if no other changes have occurred.\n    ///\n    /// If called from within a view, it will notify that view on the next frame. Otherwise, it will refresh the entire window.\n    pub fn request_animation_frame(&self) {\n        let entity = self.current_view();\n        self.on_next_frame(move |_, cx| cx.notify(entity));\n    }\n\n    /// Spawn the future returned by the given closure on the application thread pool.\n    /// The closure is provided a handle to the current window and an `AsyncWindowContext` for\n    /// use within your future.\n    #[track_caller]\n    pub fn spawn<AsyncFn, R>(&self, cx: &App, f: AsyncFn) -> Task<R>\n    where\n        R: 'static,\n        AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,\n    {\n        let handle = self.handle;\n        cx.spawn(async move |app| {\n            let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);\n            f(&mut async_window_cx).await\n        })\n    }\n\n    fn bounds_changed(&mut self, cx: &mut App) {\n        self.scale_factor = self.platform_window.scale_factor();\n        self.viewport_size = self.platform_window.content_size();\n        self.display_id = self.platform_window.display().map(|display| display.id());\n\n        self.refresh();\n\n        self.bounds_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    /// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays.\n    pub fn bounds(&self) -> Bounds<Pixels> {\n        self.platform_window.bounds()\n    }\n\n    /// Set the content size of the window.\n    pub fn resize(&mut self, size: Size<Pixels>) {\n        self.platform_window.resize(size);\n    }\n\n    /// Returns whether or not the window is currently fullscreen\n    pub fn is_fullscreen(&self) -> bool {\n        self.platform_window.is_fullscreen()\n    }\n\n    pub(crate) fn appearance_changed(&mut self, cx: &mut App) {\n        self.appearance = self.platform_window.appearance();\n\n        self.appearance_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    /// Returns the appearance of the current window.\n    pub fn appearance(&self) -> WindowAppearance {\n        self.appearance\n    }\n\n    /// Returns the size of the drawable area within the window.\n    pub fn viewport_size(&self) -> Size<Pixels> {\n        self.viewport_size\n    }\n\n    /// Returns whether this window is focused by the operating system (receiving key events).\n    pub fn is_window_active(&self) -> bool {\n        self.active.get()\n    }\n\n    /// Returns whether this window is considered to be the window\n    /// that currently owns the mouse cursor.\n    /// On mac, this is equivalent to `is_window_active`.\n    pub fn is_window_hovered(&self) -> bool {\n        if cfg!(any(\n            target_os = \"windows\",\n            target_os = \"linux\",\n            target_os = \"freebsd\"\n        )) {\n            self.hovered.get()\n        } else {\n            self.is_window_active()\n        }\n    }\n\n    /// Toggle zoom on the window.\n    pub fn zoom_window(&self) {\n        self.platform_window.zoom();\n    }\n\n    /// Opens the native title bar context menu, useful when implementing client side decorations (Wayland and X11)\n    pub fn show_window_menu(&self, position: Point<Pixels>) {\n        self.platform_window.show_window_menu(position)\n    }\n\n    /// Tells the compositor to take control of window movement (Wayland and X11)\n    ///\n    /// Events may not be received during a move operation.\n    pub fn start_window_move(&self) {\n        self.platform_window.start_window_move()\n    }\n\n    /// When using client side decorations, set this to the width of the invisible decorations (Wayland and X11)\n    pub fn set_client_inset(&mut self, inset: Pixels) {\n        self.client_inset = Some(inset);\n        self.platform_window.set_client_inset(inset);\n    }\n\n    /// Returns the client_inset value by [`Self::set_client_inset`].\n    pub fn client_inset(&self) -> Option<Pixels> {\n        self.client_inset\n    }\n\n    /// Returns whether the title bar window controls need to be rendered by the application (Wayland and X11)\n    pub fn window_decorations(&self) -> Decorations {\n        self.platform_window.window_decorations()\n    }\n\n    /// Returns which window controls are currently visible (Wayland)\n    pub fn window_controls(&self) -> WindowControls {\n        self.platform_window.window_controls()\n    }\n\n    /// Updates the window's title at the platform level.\n    pub fn set_window_title(&mut self, title: &str) {\n        self.platform_window.set_title(title);\n    }\n\n    /// Sets the application identifier.\n    pub fn set_app_id(&mut self, app_id: &str) {\n        self.platform_window.set_app_id(app_id);\n    }\n\n    /// Sets the window background appearance.\n    pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {\n        self.platform_window\n            .set_background_appearance(background_appearance);\n    }\n\n    /// Mark the window as dirty at the platform level.\n    pub fn set_window_edited(&mut self, edited: bool) {\n        self.platform_window.set_edited(edited);\n    }\n\n    /// Determine the display on which the window is visible.\n    pub fn display(&self, cx: &App) -> Option<Rc<dyn PlatformDisplay>> {\n        cx.platform\n            .displays()\n            .into_iter()\n            .find(|display| Some(display.id()) == self.display_id)\n    }\n\n    /// Show the platform character palette.\n    pub fn show_character_palette(&self) {\n        self.platform_window.show_character_palette();\n    }\n\n    /// The scale factor of the display associated with the window. For example, it could\n    /// return 2.0 for a \"retina\" display, indicating that each logical pixel should actually\n    /// be rendered as two pixels on screen.\n    pub fn scale_factor(&self) -> f32 {\n        self.scale_factor\n    }\n\n    /// The size of an em for the base font of the application. Adjusting this value allows the\n    /// UI to scale, just like zooming a web page.\n    pub fn rem_size(&self) -> Pixels {\n        self.rem_size_override_stack\n            .last()\n            .copied()\n            .unwrap_or(self.rem_size)\n    }\n\n    /// Sets the size of an em for the base font of the application. Adjusting this value allows the\n    /// UI to scale, just like zooming a web page.\n    pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {\n        self.rem_size = rem_size.into();\n    }\n\n    /// Acquire a globally unique identifier for the given ElementId.\n    /// Only valid for the duration of the provided closure.\n    pub fn with_global_id<R>(\n        &mut self,\n        element_id: ElementId,\n        f: impl FnOnce(&GlobalElementId, &mut Self) -> R,\n    ) -> R {\n        self.element_id_stack.push(element_id);\n        let global_id = GlobalElementId(self.element_id_stack.clone());\n        let result = f(&global_id, self);\n        self.element_id_stack.pop();\n        result\n    }\n\n    /// Executes the provided function with the specified rem size.\n    ///\n    /// This method must only be called as part of element drawing.\n    pub fn with_rem_size<F, R>(&mut self, rem_size: Option<impl Into<Pixels>>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        if let Some(rem_size) = rem_size {\n            self.rem_size_override_stack.push(rem_size.into());\n            let result = f(self);\n            self.rem_size_override_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// The line height associated with the current text style.\n    pub fn line_height(&self) -> Pixels {\n        self.text_style().line_height_in_pixels(self.rem_size())\n    }\n\n    /// Call to prevent the default action of an event. Currently only used to prevent\n    /// parent elements from becoming focused on mouse down.\n    pub fn prevent_default(&mut self) {\n        self.default_prevented = true;\n    }\n\n    /// Obtain whether default has been prevented for the event currently being dispatched.\n    pub fn default_prevented(&self) -> bool {\n        self.default_prevented\n    }\n\n    /// Determine whether the given action is available along the dispatch path to the currently focused element.\n    pub fn is_action_available(&self, action: &dyn Action, cx: &mut App) -> bool {\n        let target = self\n            .focused(cx)\n            .and_then(|focused_handle| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focused_handle.id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n        self.rendered_frame\n            .dispatch_tree\n            .is_action_available(action, target)\n    }\n\n    /// The position of the mouse relative to the window.\n    pub fn mouse_position(&self) -> Point<Pixels> {\n        self.mouse_position\n    }\n\n    /// The current state of the keyboard's modifiers\n    pub fn modifiers(&self) -> Modifiers {\n        self.modifiers\n    }\n\n    fn complete_frame(&self) {\n        self.platform_window.completed_frame();\n    }\n\n    /// Produces a new frame and assigns it to `rendered_frame`. To actually show\n    /// the contents of the new [Scene], use [present].\n    #[profiling::function]\n    pub fn draw(&mut self, cx: &mut App) {\n        self.invalidate_entities();\n        cx.entities.clear_accessed();\n        debug_assert!(self.rendered_entity_stack.is_empty());\n        self.invalidator.set_dirty(false);\n        self.requested_autoscroll = None;\n\n        // Restore the previously-used input handler.\n        if let Some(input_handler) = self.platform_window.take_input_handler() {\n            self.rendered_frame.input_handlers.push(Some(input_handler));\n        }\n        self.draw_roots(cx);\n        self.dirty_views.clear();\n        self.next_frame.window_active = self.active.get();\n\n        // Register requested input handler with the platform window.\n        if let Some(input_handler) = self.next_frame.input_handlers.pop() {\n            self.platform_window\n                .set_input_handler(input_handler.unwrap());\n        }\n\n        self.layout_engine.as_mut().unwrap().clear();\n        self.text_system().finish_frame();\n        self.next_frame.finish(&mut self.rendered_frame);\n        ELEMENT_ARENA.with_borrow_mut(|element_arena| {\n            let percentage = (element_arena.len() as f32 / element_arena.capacity() as f32) * 100.;\n            if percentage >= 80. {\n                log::warn!(\"elevated element arena occupation: {}.\", percentage);\n            }\n            element_arena.clear();\n        });\n\n        self.invalidator.set_phase(DrawPhase::Focus);\n        let previous_focus_path = self.rendered_frame.focus_path();\n        let previous_window_active = self.rendered_frame.window_active;\n        mem::swap(&mut self.rendered_frame, &mut self.next_frame);\n        self.next_frame.clear();\n        let current_focus_path = self.rendered_frame.focus_path();\n        let current_window_active = self.rendered_frame.window_active;\n\n        if previous_focus_path != current_focus_path\n            || previous_window_active != current_window_active\n        {\n            if !previous_focus_path.is_empty() && current_focus_path.is_empty() {\n                self.focus_lost_listeners\n                    .clone()\n                    .retain(&(), |listener| listener(self, cx));\n            }\n\n            let event = WindowFocusEvent {\n                previous_focus_path: if previous_window_active {\n                    previous_focus_path\n                } else {\n                    Default::default()\n                },\n                current_focus_path: if current_window_active {\n                    current_focus_path\n                } else {\n                    Default::default()\n                },\n            };\n            self.focus_listeners\n                .clone()\n                .retain(&(), |listener| listener(&event, self, cx));\n        }\n\n        debug_assert!(self.rendered_entity_stack.is_empty());\n        self.record_entities_accessed(cx);\n        self.reset_cursor_style(cx);\n        self.refreshing = false;\n        self.invalidator.set_phase(DrawPhase::None);\n        self.needs_present.set(true);\n    }\n\n    fn record_entities_accessed(&mut self, cx: &mut App) {\n        let mut entities_ref = cx.entities.accessed_entities.borrow_mut();\n        let mut entities = mem::take(entities_ref.deref_mut());\n        drop(entities_ref);\n        let handle = self.handle;\n        cx.record_entities_accessed(\n            handle,\n            // Try moving window invalidator into the Window\n            self.invalidator.clone(),\n            &entities,\n        );\n        let mut entities_ref = cx.entities.accessed_entities.borrow_mut();\n        mem::swap(&mut entities, entities_ref.deref_mut());\n    }\n\n    fn invalidate_entities(&mut self) {\n        let mut views = self.invalidator.take_views();\n        for entity in views.drain() {\n            self.mark_view_dirty(entity);\n        }\n        self.invalidator.replace_views(views);\n    }\n\n    #[profiling::function]\n    fn present(&self) {\n        self.platform_window.draw(&self.rendered_frame.scene);\n        self.needs_present.set(false);\n        profiling::finish_frame!();\n    }\n\n    fn draw_roots(&mut self, cx: &mut App) {\n        self.invalidator.set_phase(DrawPhase::Prepaint);\n        self.tooltip_bounds.take();\n\n        // Layout all root elements.\n        let mut root_element = self.root.as_ref().unwrap().clone().into_any();\n        root_element.prepaint_as_root(Point::default(), self.viewport_size.into(), self, cx);\n\n        let mut sorted_deferred_draws =\n            (0..self.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>();\n        sorted_deferred_draws.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);\n        self.prepaint_deferred_draws(&sorted_deferred_draws, cx);\n\n        let mut prompt_element = None;\n        let mut active_drag_element = None;\n        let mut tooltip_element = None;\n        if let Some(prompt) = self.prompt.take() {\n            let mut element = prompt.view.any_view().into_any();\n            element.prepaint_as_root(Point::default(), self.viewport_size.into(), self, cx);\n            prompt_element = Some(element);\n            self.prompt = Some(prompt);\n        } else if let Some(active_drag) = cx.active_drag.take() {\n            let mut element = active_drag.view.clone().into_any();\n            let offset = self.mouse_position() - active_drag.cursor_offset;\n            element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx);\n            active_drag_element = Some(element);\n            cx.active_drag = Some(active_drag);\n        } else {\n            tooltip_element = self.prepaint_tooltip(cx);\n        }\n\n        self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position);\n\n        // Now actually paint the elements.\n        self.invalidator.set_phase(DrawPhase::Paint);\n        root_element.paint(self, cx);\n\n        self.paint_deferred_draws(&sorted_deferred_draws, cx);\n\n        if let Some(mut prompt_element) = prompt_element {\n            prompt_element.paint(self, cx);\n        } else if let Some(mut drag_element) = active_drag_element {\n            drag_element.paint(self, cx);\n        } else if let Some(mut tooltip_element) = tooltip_element {\n            tooltip_element.paint(self, cx);\n        }\n    }\n\n    fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {\n        // Use indexing instead of iteration to avoid borrowing self for the duration of the loop.\n        for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() {\n            let Some(Some(tooltip_request)) = self\n                .next_frame\n                .tooltip_requests\n                .get(tooltip_request_index)\n                .cloned()\n            else {\n                log::error!(\"Unexpectedly absent TooltipRequest\");\n                continue;\n            };\n            let mut element = tooltip_request.tooltip.view.clone().into_any();\n            let mouse_position = tooltip_request.tooltip.mouse_position;\n            let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);\n\n            let mut tooltip_bounds =\n                Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);\n            let window_bounds = Bounds {\n                origin: Point::default(),\n                size: self.viewport_size(),\n            };\n\n            if tooltip_bounds.right() > window_bounds.right() {\n                let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);\n                if new_x >= Pixels::ZERO {\n                    tooltip_bounds.origin.x = new_x;\n                } else {\n                    tooltip_bounds.origin.x = cmp::max(\n                        Pixels::ZERO,\n                        tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),\n                    );\n                }\n            }\n\n            if tooltip_bounds.bottom() > window_bounds.bottom() {\n                let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);\n                if new_y >= Pixels::ZERO {\n                    tooltip_bounds.origin.y = new_y;\n                } else {\n                    tooltip_bounds.origin.y = cmp::max(\n                        Pixels::ZERO,\n                        tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),\n                    );\n                }\n            }\n\n            // It's possible for an element to have an active tooltip while not being painted (e.g.\n            // via the `visible_on_hover` method). Since mouse listeners are not active in this\n            // case, instead update the tooltip's visibility here.\n            let is_visible =\n                (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);\n            if !is_visible {\n                continue;\n            }\n\n            self.with_absolute_element_offset(tooltip_bounds.origin, |window| {\n                element.prepaint(window, cx)\n            });\n\n            self.tooltip_bounds = Some(TooltipBounds {\n                id: tooltip_request.id,\n                bounds: tooltip_bounds,\n            });\n            return Some(element);\n        }\n        None\n    }\n\n    fn prepaint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {\n        assert_eq!(self.element_id_stack.len(), 0);\n\n        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);\n        for deferred_draw_ix in deferred_draw_indices {\n            let deferred_draw = &mut deferred_draws[*deferred_draw_ix];\n            self.element_id_stack\n                .clone_from(&deferred_draw.element_id_stack);\n            self.text_style_stack\n                .clone_from(&deferred_draw.text_style_stack);\n            self.next_frame\n                .dispatch_tree\n                .set_active_node(deferred_draw.parent_node);\n\n            let prepaint_start = self.prepaint_index();\n            if let Some(element) = deferred_draw.element.as_mut() {\n                self.with_rendered_view(deferred_draw.current_view, |window| {\n                    window.with_absolute_element_offset(deferred_draw.absolute_offset, |window| {\n                        element.prepaint(window, cx)\n                    });\n                })\n            } else {\n                self.reuse_prepaint(deferred_draw.prepaint_range.clone());\n            }\n            let prepaint_end = self.prepaint_index();\n            deferred_draw.prepaint_range = prepaint_start..prepaint_end;\n        }\n        assert_eq!(\n            self.next_frame.deferred_draws.len(),\n            0,\n            \"cannot call defer_draw during deferred drawing\"\n        );\n        self.next_frame.deferred_draws = deferred_draws;\n        self.element_id_stack.clear();\n        self.text_style_stack.clear();\n    }\n\n    fn paint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {\n        assert_eq!(self.element_id_stack.len(), 0);\n\n        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);\n        for deferred_draw_ix in deferred_draw_indices {\n            let mut deferred_draw = &mut deferred_draws[*deferred_draw_ix];\n            self.element_id_stack\n                .clone_from(&deferred_draw.element_id_stack);\n            self.next_frame\n                .dispatch_tree\n                .set_active_node(deferred_draw.parent_node);\n\n            let paint_start = self.paint_index();\n            if let Some(element) = deferred_draw.element.as_mut() {\n                self.with_rendered_view(deferred_draw.current_view, |window| {\n                    element.paint(window, cx);\n                })\n            } else {\n                self.reuse_paint(deferred_draw.paint_range.clone());\n            }\n            let paint_end = self.paint_index();\n            deferred_draw.paint_range = paint_start..paint_end;\n        }\n        self.next_frame.deferred_draws = deferred_draws;\n        self.element_id_stack.clear();\n    }\n\n    pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {\n        PrepaintStateIndex {\n            hitboxes_index: self.next_frame.hitboxes.len(),\n            tooltips_index: self.next_frame.tooltip_requests.len(),\n            deferred_draws_index: self.next_frame.deferred_draws.len(),\n            dispatch_tree_index: self.next_frame.dispatch_tree.len(),\n            accessed_element_states_index: self.next_frame.accessed_element_states.len(),\n            line_layout_index: self.text_system.layout_index(),\n        }\n    }\n\n    pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {\n        self.next_frame.hitboxes.extend(\n            self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]\n                .iter()\n                .cloned(),\n        );\n        self.next_frame.tooltip_requests.extend(\n            self.rendered_frame.tooltip_requests\n                [range.start.tooltips_index..range.end.tooltips_index]\n                .iter_mut()\n                .map(|request| request.take()),\n        );\n        self.next_frame.accessed_element_states.extend(\n            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index\n                ..range.end.accessed_element_states_index]\n                .iter()\n                .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),\n        );\n        self.text_system\n            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);\n\n        let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree(\n            range.start.dispatch_tree_index..range.end.dispatch_tree_index,\n            &mut self.rendered_frame.dispatch_tree,\n            self.focus,\n        );\n\n        if reused_subtree.contains_focus() {\n            self.next_frame.focus = self.focus;\n        }\n\n        self.next_frame.deferred_draws.extend(\n            self.rendered_frame.deferred_draws\n                [range.start.deferred_draws_index..range.end.deferred_draws_index]\n                .iter()\n                .map(|deferred_draw| DeferredDraw {\n                    current_view: deferred_draw.current_view,\n                    parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),\n                    element_id_stack: deferred_draw.element_id_stack.clone(),\n                    text_style_stack: deferred_draw.text_style_stack.clone(),\n                    priority: deferred_draw.priority,\n                    element: None,\n                    absolute_offset: deferred_draw.absolute_offset,\n                    prepaint_range: deferred_draw.prepaint_range.clone(),\n                    paint_range: deferred_draw.paint_range.clone(),\n                }),\n        );\n    }\n\n    pub(crate) fn paint_index(&self) -> PaintIndex {\n        PaintIndex {\n            scene_index: self.next_frame.scene.len(),\n            mouse_listeners_index: self.next_frame.mouse_listeners.len(),\n            input_handlers_index: self.next_frame.input_handlers.len(),\n            cursor_styles_index: self.next_frame.cursor_styles.len(),\n            accessed_element_states_index: self.next_frame.accessed_element_states.len(),\n            line_layout_index: self.text_system.layout_index(),\n        }\n    }\n\n    pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {\n        self.next_frame.cursor_styles.extend(\n            self.rendered_frame.cursor_styles\n                [range.start.cursor_styles_index..range.end.cursor_styles_index]\n                .iter()\n                .cloned(),\n        );\n        self.next_frame.input_handlers.extend(\n            self.rendered_frame.input_handlers\n                [range.start.input_handlers_index..range.end.input_handlers_index]\n                .iter_mut()\n                .map(|handler| handler.take()),\n        );\n        self.next_frame.mouse_listeners.extend(\n            self.rendered_frame.mouse_listeners\n                [range.start.mouse_listeners_index..range.end.mouse_listeners_index]\n                .iter_mut()\n                .map(|listener| listener.take()),\n        );\n        self.next_frame.accessed_element_states.extend(\n            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index\n                ..range.end.accessed_element_states_index]\n                .iter()\n                .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),\n        );\n\n        self.text_system\n            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);\n        self.next_frame.scene.replay(\n            range.start.scene_index..range.end.scene_index,\n            &self.rendered_frame.scene,\n        );\n    }\n\n    /// Push a text style onto the stack, and call a function with that style active.\n    /// Use [`Window::text_style`] to get the current, combined text style. This method\n    /// should only be called as part of element drawing.\n    pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        if let Some(style) = style {\n            self.text_style_stack.push(style);\n            let result = f(self);\n            self.text_style_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Updates the cursor style at the platform level. This method should only be called\n    /// during the prepaint phase of element drawing.\n    pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: Option<&Hitbox>) {\n        self.invalidator.debug_assert_paint();\n        self.next_frame.cursor_styles.push(CursorStyleRequest {\n            hitbox_id: hitbox.map(|hitbox| hitbox.id),\n            style,\n        });\n    }\n\n    /// Sets a tooltip to be rendered for the upcoming frame. This method should only be called\n    /// during the paint phase of element drawing.\n    pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {\n        self.invalidator.debug_assert_prepaint();\n        let id = TooltipId(post_inc(&mut self.next_tooltip_id.0));\n        self.next_frame\n            .tooltip_requests\n            .push(Some(TooltipRequest { id, tooltip }));\n        id\n    }\n\n    /// Invoke the given function with the given content mask after intersecting it\n    /// with the current mask. This method should only be called during element drawing.\n    pub fn with_content_mask<R>(\n        &mut self,\n        mask: Option<ContentMask<Pixels>>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        if let Some(mask) = mask {\n            let mask = mask.intersect(&self.content_mask());\n            self.content_mask_stack.push(mask);\n            let result = f(self);\n            self.content_mask_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Updates the global element offset relative to the current offset. This is used to implement\n    /// scrolling. This method should only be called during the prepaint phase of element drawing.\n    pub fn with_element_offset<R>(\n        &mut self,\n        offset: Point<Pixels>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_prepaint();\n\n        if offset.is_zero() {\n            return f(self);\n        };\n\n        let abs_offset = self.element_offset() + offset;\n        self.with_absolute_element_offset(abs_offset, f)\n    }\n\n    /// Updates the global element offset based on the given offset. This is used to implement\n    /// drag handles and other manual painting of elements. This method should only be called during\n    /// the prepaint phase of element drawing.\n    pub fn with_absolute_element_offset<R>(\n        &mut self,\n        offset: Point<Pixels>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_prepaint();\n        self.element_offset_stack.push(offset);\n        let result = f(self);\n        self.element_offset_stack.pop();\n        result\n    }\n\n    pub(crate) fn with_element_opacity<R>(\n        &mut self,\n        opacity: Option<f32>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        if opacity.is_none() {\n            return f(self);\n        }\n\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.element_opacity = opacity;\n        let result = f(self);\n        self.element_opacity = None;\n        result\n    }\n\n    /// Perform prepaint on child elements in a \"retryable\" manner, so that any side effects\n    /// of prepaints can be discarded before prepainting again. This is used to support autoscroll\n    /// where we need to prepaint children to detect the autoscroll bounds, then adjust the\n    /// element offset and prepaint again. See [`List`] for an example. This method should only be\n    /// called during the prepaint phase of element drawing.\n    pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {\n        self.invalidator.debug_assert_prepaint();\n        let index = self.prepaint_index();\n        let result = f(self);\n        if result.is_err() {\n            self.next_frame.hitboxes.truncate(index.hitboxes_index);\n            self.next_frame\n                .tooltip_requests\n                .truncate(index.tooltips_index);\n            self.next_frame\n                .deferred_draws\n                .truncate(index.deferred_draws_index);\n            self.next_frame\n                .dispatch_tree\n                .truncate(index.dispatch_tree_index);\n            self.next_frame\n                .accessed_element_states\n                .truncate(index.accessed_element_states_index);\n            self.text_system.truncate_layouts(index.line_layout_index);\n        }\n        result\n    }\n\n    /// When you call this method during [`prepaint`], containing elements will attempt to\n    /// scroll to cause the specified bounds to become visible. When they decide to autoscroll, they will call\n    /// [`prepaint`] again with a new set of bounds. See [`List`] for an example of an element\n    /// that supports this method being called on the elements it contains. This method should only be\n    /// called during the prepaint phase of element drawing.\n    pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {\n        self.invalidator.debug_assert_prepaint();\n        self.requested_autoscroll = Some(bounds);\n    }\n\n    /// This method can be called from a containing element such as [`List`] to support the autoscroll behavior\n    /// described in [`request_autoscroll`].\n    pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {\n        self.invalidator.debug_assert_prepaint();\n        self.requested_autoscroll.take()\n    }\n\n    /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.\n    /// Your view will be re-drawn once the asset has finished loading.\n    ///\n    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a\n    /// time.\n    pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {\n        let (task, is_first) = cx.fetch_asset::<A>(source);\n        task.clone().now_or_never().or_else(|| {\n            if is_first {\n                let entity_id = self.current_view();\n                self.spawn(cx, {\n                    let task = task.clone();\n                    async move |cx| {\n                        task.await;\n\n                        cx.on_next_frame(move |_, cx| {\n                            cx.notify(entity_id);\n                        });\n                    }\n                })\n                .detach();\n            }\n\n            None\n        })\n    }\n\n    /// Asynchronously load an asset, if the asset hasn't finished loading or doesn't exist this will return None.\n    /// Your view will not be re-drawn once the asset has finished loading.\n    ///\n    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a\n    /// time.\n    pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {\n        let (task, _) = cx.fetch_asset::<A>(source);\n        task.clone().now_or_never()\n    }\n    /// Obtain the current element offset. This method should only be called during the\n    /// prepaint phase of element drawing.\n    pub fn element_offset(&self) -> Point<Pixels> {\n        self.invalidator.debug_assert_prepaint();\n        self.element_offset_stack\n            .last()\n            .copied()\n            .unwrap_or_default()\n    }\n\n    /// Obtain the current element opacity. This method should only be called during the\n    /// prepaint phase of element drawing.\n    pub(crate) fn element_opacity(&self) -> f32 {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.element_opacity.unwrap_or(1.0)\n    }\n\n    /// Obtain the current content mask. This method should only be called during element drawing.\n    pub fn content_mask(&self) -> ContentMask<Pixels> {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.content_mask_stack\n            .last()\n            .cloned()\n            .unwrap_or_else(|| ContentMask {\n                bounds: Bounds {\n                    origin: Point::default(),\n                    size: self.viewport_size,\n                },\n            })\n    }\n\n    /// Provide elements in the called function with a new namespace in which their identifiers must be unique.\n    /// This can be used within a custom element to distinguish multiple sets of child elements.\n    pub fn with_element_namespace<R>(\n        &mut self,\n        element_id: impl Into<ElementId>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.element_id_stack.push(element_id.into());\n        let result = f(self);\n        self.element_id_stack.pop();\n        result\n    }\n\n    /// Updates or initializes state for an element with the given id that lives across multiple\n    /// frames. If an element with this ID existed in the rendered frame, its state will be passed\n    /// to the given closure. The state returned by the closure will be stored so it can be referenced\n    /// when drawing the next frame. This method should only be called as part of element drawing.\n    pub fn with_element_state<S, R>(\n        &mut self,\n        global_id: &GlobalElementId,\n        f: impl FnOnce(Option<S>, &mut Self) -> (R, S),\n    ) -> R\n    where\n        S: 'static,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        let key = (GlobalElementId(global_id.0.clone()), TypeId::of::<S>());\n        self.next_frame\n            .accessed_element_states\n            .push((GlobalElementId(key.0.clone()), TypeId::of::<S>()));\n\n        if let Some(any) = self\n            .next_frame\n            .element_states\n            .remove(&key)\n            .or_else(|| self.rendered_frame.element_states.remove(&key))\n        {\n            let ElementStateBox {\n                inner,\n                #[cfg(debug_assertions)]\n                type_name,\n            } = any;\n            // Using the extra inner option to avoid needing to reallocate a new box.\n            let mut state_box = inner\n                .downcast::<Option<S>>()\n                .map_err(|_| {\n                    #[cfg(debug_assertions)]\n                    {\n                        anyhow::anyhow!(\n                            \"invalid element state type for id, requested {:?}, actual: {:?}\",\n                            std::any::type_name::<S>(),\n                            type_name\n                        )\n                    }\n\n                    #[cfg(not(debug_assertions))]\n                    {\n                        anyhow::anyhow!(\n                            \"invalid element state type for id, requested {:?}\",\n                            std::any::type_name::<S>(),\n                        )\n                    }\n                })\n                .unwrap();\n\n            let state = state_box.take().expect(\n                \"reentrant call to with_element_state for the same state type and element id\",\n            );\n            let (result, state) = f(Some(state), self);\n            state_box.replace(state);\n            self.next_frame.element_states.insert(\n                key,\n                ElementStateBox {\n                    inner: state_box,\n                    #[cfg(debug_assertions)]\n                    type_name,\n                },\n            );\n            result\n        } else {\n            let (result, state) = f(None, self);\n            self.next_frame.element_states.insert(\n                key,\n                ElementStateBox {\n                    inner: Box::new(Some(state)),\n                    #[cfg(debug_assertions)]\n                    type_name: std::any::type_name::<S>(),\n                },\n            );\n            result\n        }\n    }\n\n    /// A variant of `with_element_state` that allows the element's id to be optional. This is a convenience\n    /// method for elements where the element id may or may not be assigned. Prefer using `with_element_state`\n    /// when the element is guaranteed to have an id.\n    ///\n    /// The first option means 'no ID provided'\n    /// The second option means 'not yet initialized'\n    pub fn with_optional_element_state<S, R>(\n        &mut self,\n        global_id: Option<&GlobalElementId>,\n        f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),\n    ) -> R\n    where\n        S: 'static,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        if let Some(global_id) = global_id {\n            self.with_element_state(global_id, |state, cx| {\n                let (result, state) = f(Some(state), cx);\n                let state =\n                    state.expect(\"you must return some state when you pass some element id\");\n                (result, state)\n            })\n        } else {\n            let (result, state) = f(None, self);\n            debug_assert!(\n                state.is_none(),\n                \"you must not return an element state when passing None for the global id\"\n            );\n            result\n        }\n    }\n\n    /// Defers the drawing of the given element, scheduling it to be painted on top of the currently-drawn tree\n    /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements,\n    /// with higher values being drawn on top.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn defer_draw(\n        &mut self,\n        element: AnyElement,\n        absolute_offset: Point<Pixels>,\n        priority: usize,\n    ) {\n        self.invalidator.debug_assert_prepaint();\n        let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();\n        self.next_frame.deferred_draws.push(DeferredDraw {\n            current_view: self.current_view(),\n            parent_node,\n            element_id_stack: self.element_id_stack.clone(),\n            text_style_stack: self.text_style_stack.clone(),\n            priority,\n            element: Some(element),\n            absolute_offset,\n            prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),\n            paint_range: PaintIndex::default()..PaintIndex::default(),\n        });\n    }\n\n    /// Creates a new painting layer for the specified bounds. A \"layer\" is a batch\n    /// of geometry that are non-overlapping and have the same draw order. This is typically used\n    /// for performance reasons.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let clipped_bounds = bounds.intersect(&content_mask.bounds);\n        if !clipped_bounds.is_empty() {\n            self.next_frame\n                .scene\n                .push_layer(clipped_bounds.scale(scale_factor));\n        }\n\n        let result = f(self);\n\n        if !clipped_bounds.is_empty() {\n            self.next_frame.scene.pop_layer();\n        }\n\n        result\n    }\n\n    /// Paint one or more drop shadows into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_shadows(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        corner_radii: Corners<Pixels>,\n        shadows: &[BoxShadow],\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        for shadow in shadows {\n            let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius);\n            self.next_frame.scene.insert_primitive(Shadow {\n                order: 0,\n                blur_radius: shadow.blur_radius.scale(scale_factor),\n                bounds: shadow_bounds.scale(scale_factor),\n                content_mask: content_mask.scale(scale_factor),\n                corner_radii: corner_radii.scale(scale_factor),\n                color: shadow.color.opacity(opacity),\n            });\n        }\n    }\n\n    /// Paint one or more quads into the scene for the next frame at the current stacking context.\n    /// Quads are colored rectangular regions with an optional background, border, and corner radius.\n    /// see [`fill`](crate::fill), [`outline`](crate::outline), and [`quad`](crate::quad) to construct this type.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    ///\n    /// Note that the `quad.corner_radii` are allowed to exceed the bounds, creating sharp corners\n    /// where the circular arcs meet. This will not display well when combined with dashed borders.\n    /// Use `Corners::clamp_radii_for_quad_size` if the radii should fit within the bounds.\n    pub fn paint_quad(&mut self, quad: PaintQuad) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        self.next_frame.scene.insert_primitive(Quad {\n            order: 0,\n            bounds: quad.bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            background: quad.background.opacity(opacity),\n            border_color: quad.border_color.opacity(opacity),\n            corner_radii: quad.corner_radii.scale(scale_factor),\n            border_widths: quad.border_widths.scale(scale_factor),\n            border_style: quad.border_style,\n            transformation: quad.transformation,\n        });\n    }\n\n    /// Paint the given `Path` into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        path.content_mask = content_mask;\n        let color: Background = color.into();\n        path.color = color.opacity(opacity);\n        self.next_frame\n            .scene\n            .insert_primitive(path.scale(scale_factor));\n    }\n\n    /// Paint an underline into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_underline(\n        &mut self,\n        origin: Point<Pixels>,\n        width: Pixels,\n        style: &UnderlineStyle,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let height = if style.wavy {\n            style.thickness * 3.\n        } else {\n            style.thickness\n        };\n        let bounds = Bounds {\n            origin,\n            size: size(width, height),\n        };\n        let content_mask = self.content_mask();\n        let element_opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(Underline {\n            order: 0,\n            pad: 0,\n            bounds: bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            color: style.color.unwrap_or_default().opacity(element_opacity),\n            thickness: style.thickness.scale(scale_factor),\n            wavy: style.wavy,\n        });\n    }\n\n    /// Paint a strikethrough into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_strikethrough(\n        &mut self,\n        origin: Point<Pixels>,\n        width: Pixels,\n        style: &StrikethroughStyle,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let height = style.thickness;\n        let bounds = Bounds {\n            origin,\n            size: size(width, height),\n        };\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(Underline {\n            order: 0,\n            pad: 0,\n            bounds: bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            thickness: style.thickness.scale(scale_factor),\n            color: style.color.unwrap_or_default().opacity(opacity),\n            wavy: false,\n        });\n    }\n\n    /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.\n    ///\n    /// The y component of the origin is the baseline of the glyph.\n    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or\n    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).\n    /// This method is only useful if you need to paint a single glyph that has already been shaped.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_glyph(\n        &mut self,\n        origin: Point<Pixels>,\n        font_id: FontId,\n        glyph_id: GlyphId,\n        font_size: Pixels,\n        color: Hsla,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let element_opacity = self.element_opacity();\n        let scale_factor = self.scale_factor();\n        let glyph_origin = origin.scale(scale_factor);\n        let subpixel_variant = Point {\n            x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,\n            y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,\n        };\n        let params = RenderGlyphParams {\n            font_id,\n            glyph_id,\n            font_size,\n            subpixel_variant,\n            scale_factor,\n            is_emoji: false,\n        };\n\n        let raster_bounds = self.text_system().raster_bounds(&params)?;\n        if !raster_bounds.is_zero() {\n            let tile = self\n                .sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;\n                    Ok(Some((size, Cow::Owned(bytes))))\n                })?\n                .expect(\"Callback above only errors or returns Some\");\n            let bounds = Bounds {\n                origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),\n                size: tile.bounds.size.map(Into::into),\n            };\n            let content_mask = self.content_mask().scale(scale_factor);\n            self.next_frame.scene.insert_primitive(MonochromeSprite {\n                order: 0,\n                pad: 0,\n                bounds,\n                content_mask,\n                color: color.opacity(element_opacity),\n                tile,\n                transformation: TransformationMatrix::unit(),\n            });\n        }\n        Ok(())\n    }\n\n    /// Paints an emoji glyph into the scene for the next frame at the current z-index.\n    ///\n    /// The y component of the origin is the baseline of the glyph.\n    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or\n    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).\n    /// This method is only useful if you need to paint a single emoji that has already been shaped.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_emoji(\n        &mut self,\n        origin: Point<Pixels>,\n        font_id: FontId,\n        glyph_id: GlyphId,\n        font_size: Pixels,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let glyph_origin = origin.scale(scale_factor);\n        let params = RenderGlyphParams {\n            font_id,\n            glyph_id,\n            font_size,\n            // We don't render emojis with subpixel variants.\n            subpixel_variant: Default::default(),\n            scale_factor,\n            is_emoji: true,\n        };\n\n        let raster_bounds = self.text_system().raster_bounds(&params)?;\n        if !raster_bounds.is_zero() {\n            let tile = self\n                .sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;\n                    Ok(Some((size, Cow::Owned(bytes))))\n                })?\n                .expect(\"Callback above only errors or returns Some\");\n\n            let bounds = Bounds {\n                origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),\n                size: tile.bounds.size.map(Into::into),\n            };\n            let content_mask = self.content_mask().scale(scale_factor);\n            let opacity = self.element_opacity();\n\n            self.next_frame.scene.insert_primitive(PolychromeSprite {\n                order: 0,\n                pad: 0,\n                grayscale: false,\n                bounds,\n                corner_radii: Default::default(),\n                content_mask,\n                tile,\n                opacity,\n            });\n        }\n        Ok(())\n    }\n\n    /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_svg(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        path: SharedString,\n        transformation: TransformationMatrix,\n        color: Hsla,\n        cx: &App,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let element_opacity = self.element_opacity();\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let params = RenderSvgParams {\n            path,\n            size: bounds.size.map(|pixels| {\n                DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)\n            }),\n        };\n\n        let Some(tile) =\n            self.sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let Some(bytes) = cx.svg_renderer.render(&params)? else {\n                        return Ok(None);\n                    };\n                    Ok(Some((params.size, Cow::Owned(bytes))))\n                })?\n        else {\n            return Ok(());\n        };\n        let content_mask = self.content_mask().scale(scale_factor);\n\n        self.next_frame.scene.insert_primitive(MonochromeSprite {\n            order: 0,\n            pad: 0,\n            bounds: bounds\n                .map_origin(|origin| origin.floor())\n                .map_size(|size| size.ceil()),\n            content_mask,\n            color: color.opacity(element_opacity),\n            tile,\n            transformation,\n        });\n\n        Ok(())\n    }\n\n    /// Paint an image into the scene for the next frame at the current z-index.\n    /// This method will panic if the frame_index is not valid\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_image(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        corner_radii: Corners<Pixels>,\n        data: Arc<RenderImage>,\n        frame_index: usize,\n        grayscale: bool,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let params = RenderImageParams {\n            image_id: data.id,\n            frame_index,\n        };\n\n        let tile = self\n            .sprite_atlas\n            .get_or_insert_with(&params.clone().into(), &mut || {\n                Ok(Some((\n                    data.size(frame_index),\n                    Cow::Borrowed(\n                        data.as_bytes(frame_index)\n                            .expect(\"It's the caller's job to pass a valid frame index\"),\n                    ),\n                )))\n            })?\n            .expect(\"Callback above only returns Some\");\n        let content_mask = self.content_mask().scale(scale_factor);\n        let corner_radii = corner_radii.scale(scale_factor);\n        let opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(PolychromeSprite {\n            order: 0,\n            pad: 0,\n            grayscale,\n            bounds: bounds\n                .map_origin(|origin| origin.floor())\n                .map_size(|size| size.ceil()),\n            content_mask,\n            corner_radii,\n            tile,\n            opacity,\n        });\n        Ok(())\n    }\n\n    /// Paint a surface into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    #[cfg(target_os = \"macos\")]\n    pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVPixelBuffer) {\n        use crate::PaintSurface;\n\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let content_mask = self.content_mask().scale(scale_factor);\n        self.next_frame.scene.insert_primitive(PaintSurface {\n            order: 0,\n            bounds,\n            content_mask,\n            image_buffer,\n        });\n    }\n\n    /// Removes an image from the sprite atlas.\n    pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {\n        for frame_index in 0..data.frame_count() {\n            let params = RenderImageParams {\n                image_id: data.id,\n                frame_index,\n            };\n\n            self.sprite_atlas.remove(&params.clone().into());\n        }\n\n        Ok(())\n    }\n\n    /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which\n    /// layout is being requested, along with the layout ids of any children. This method is called during\n    /// calls to the [`Element::request_layout`] trait method and enables any element to participate in layout.\n    ///\n    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.\n    #[must_use]\n    pub fn request_layout(\n        &mut self,\n        style: Style,\n        children: impl IntoIterator<Item = LayoutId>,\n        cx: &mut App,\n    ) -> LayoutId {\n        self.invalidator.debug_assert_prepaint();\n\n        cx.layout_id_buffer.clear();\n        cx.layout_id_buffer.extend(children);\n        let rem_size = self.rem_size();\n\n        self.layout_engine\n            .as_mut()\n            .unwrap()\n            .request_layout(style, rem_size, &cx.layout_id_buffer)\n    }\n\n    /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,\n    /// this variant takes a function that is invoked during layout so you can use arbitrary logic to\n    /// determine the element's size. One place this is used internally is when measuring text.\n    ///\n    /// The given closure is invoked at layout time with the known dimensions and available space and\n    /// returns a `Size`.\n    ///\n    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.\n    pub fn request_measured_layout<\n        F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>\n            + 'static,\n    >(\n        &mut self,\n        style: Style,\n        measure: F,\n    ) -> LayoutId {\n        self.invalidator.debug_assert_prepaint();\n\n        let rem_size = self.rem_size();\n        self.layout_engine\n            .as_mut()\n            .unwrap()\n            .request_measured_layout(style, rem_size, measure)\n    }\n\n    /// Compute the layout for the given id within the given available space.\n    /// This method is called for its side effect, typically by the framework prior to painting.\n    /// After calling it, you can request the bounds of the given layout node id or any descendant.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn compute_layout(\n        &mut self,\n        layout_id: LayoutId,\n        available_space: Size<AvailableSpace>,\n        cx: &mut App,\n    ) {\n        self.invalidator.debug_assert_prepaint();\n\n        let mut layout_engine = self.layout_engine.take().unwrap();\n        layout_engine.compute_layout(layout_id, available_space, self, cx);\n        self.layout_engine = Some(layout_engine);\n    }\n\n    /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by\n    /// GPUI itself automatically in order to pass your element its `Bounds` automatically.\n    ///\n    /// This method should only be called as part of element drawing.\n    pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {\n        self.invalidator.debug_assert_prepaint();\n\n        let mut bounds = self\n            .layout_engine\n            .as_mut()\n            .unwrap()\n            .layout_bounds(layout_id)\n            .map(Into::into);\n        bounds.origin += self.element_offset();\n        bounds\n    }\n\n    /// This method should be called during `prepaint`. You can use\n    /// the returned [Hitbox] during `paint` or in an event handler\n    /// to determine whether the inserted hitbox was the topmost.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, opaque: bool) -> Hitbox {\n        self.invalidator.debug_assert_prepaint();\n\n        let content_mask = self.content_mask();\n        let id = self.next_hitbox_id;\n        self.next_hitbox_id.0 += 1;\n        let hitbox = Hitbox {\n            id,\n            bounds,\n            content_mask,\n            opaque,\n        };\n        self.next_frame.hitboxes.push(hitbox.clone());\n        hitbox\n    }\n\n    /// Sets the key context for the current element. This context will be used to translate\n    /// keybindings into actions.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn set_key_context(&mut self, context: KeyContext) {\n        self.invalidator.debug_assert_paint();\n        self.next_frame.dispatch_tree.set_key_context(context);\n    }\n\n    /// Sets the focus handle for the current element. This handle will be used to manage focus state\n    /// and keyboard event dispatch for the element.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {\n        self.invalidator.debug_assert_prepaint();\n        if focus_handle.is_focused(self) {\n            self.next_frame.focus = Some(focus_handle.id);\n        }\n        self.next_frame.dispatch_tree.set_focus_id(focus_handle.id);\n    }\n\n    /// Sets the view id for the current element, which will be used to manage view caching.\n    ///\n    /// This method should only be called as part of element prepaint. We plan on removing this\n    /// method eventually when we solve some issues that require us to construct editor elements\n    /// directly instead of always using editors via views.\n    pub fn set_view_id(&mut self, view_id: EntityId) {\n        self.invalidator.debug_assert_prepaint();\n        self.next_frame.dispatch_tree.set_view_id(view_id);\n    }\n\n    /// Get the entity ID for the currently rendering view\n    pub fn current_view(&self) -> EntityId {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.rendered_entity_stack.last().copied().unwrap()\n    }\n\n    pub(crate) fn with_rendered_view<R>(\n        &mut self,\n        id: EntityId,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.rendered_entity_stack.push(id);\n        let result = f(self);\n        self.rendered_entity_stack.pop();\n        result\n    }\n\n    /// Executes the provided function with the specified image cache.\n    pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        if let Some(image_cache) = image_cache {\n            self.image_cache_stack.push(image_cache);\n            let result = f(self);\n            self.image_cache_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the\n    /// platform to receive textual input with proper integration with concerns such\n    /// as IME interactions. This handler will be active for the upcoming frame until the following frame is\n    /// rendered.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    ///\n    /// [element_input_handler]: crate::ElementInputHandler\n    pub fn handle_input(\n        &mut self,\n        focus_handle: &FocusHandle,\n        input_handler: impl InputHandler,\n        cx: &App,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        if focus_handle.is_focused(self) {\n            let cx = self.to_async(cx);\n            self.next_frame\n                .input_handlers\n                .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));\n        }\n    }\n\n    /// Register a mouse event listener on the window for the next frame. The type of event\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_mouse_event<Event: MouseEvent>(\n        &mut self,\n        mut handler: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.mouse_listeners.push(Some(Box::new(\n            move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {\n                if let Some(event) = event.downcast_ref() {\n                    handler(event, phase, window, cx)\n                }\n            },\n        )));\n    }\n\n    /// Register a key event listener on the window for the next frame. The type of event\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have\n    /// a specific need to register a global listener.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_key_event<Event: KeyEvent>(\n        &mut self,\n        listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.dispatch_tree.on_key_event(Rc::new(\n            move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {\n                if let Some(event) = event.downcast_ref::<Event>() {\n                    listener(event, phase, window, cx)\n                }\n            },\n        ));\n    }\n\n    /// Register a modifiers changed event listener on the window for the next frame.\n    ///\n    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have\n    /// a specific need to register a global listener.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_modifiers_changed(\n        &mut self,\n        listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new(\n            move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {\n                listener(event, window, cx)\n            },\n        ));\n    }\n\n    /// Register a listener to be called when the given focus handle or one of its descendants receives focus.\n    /// This does not fire if the given focus handle - or one of its descendants - was previously focused.\n    /// Returns a subscription and persists until the subscription is dropped.\n    pub fn on_focus_in(\n        &mut self,\n        handle: &FocusHandle,\n        cx: &mut App,\n        mut listener: impl FnMut(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let focus_id = handle.id;\n        let (subscription, activate) =\n            self.new_focus_listener(Box::new(move |event, window, cx| {\n                if event.is_focus_in(focus_id) {\n                    listener(window, cx);\n                }\n                true\n            }));\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    /// Register a listener to be called when the given focus handle or one of its descendants loses focus.\n    /// Returns a subscription and persists until the subscription is dropped.\n    pub fn on_focus_out(\n        &mut self,\n        handle: &FocusHandle,\n        cx: &mut App,\n        mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let focus_id = handle.id;\n        let (subscription, activate) =\n            self.new_focus_listener(Box::new(move |event, window, cx| {\n                if let Some(blurred_id) = event.previous_focus_path.last().copied() {\n                    if event.is_focus_out(focus_id) {\n                        let event = FocusOutEvent {\n                            blurred: WeakFocusHandle {\n                                id: blurred_id,\n                                handles: Arc::downgrade(&cx.focus_handles),\n                            },\n                        };\n                        listener(event, window, cx)\n                    }\n                }\n                true\n            }));\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    fn reset_cursor_style(&self, cx: &mut App) {\n        // Set the cursor only if we're the active window.\n        if self.is_window_hovered() {\n            let style = self\n                .rendered_frame\n                .cursor_styles\n                .iter()\n                .rev()\n                .find(|request| {\n                    request\n                        .hitbox_id\n                        .map_or(true, |hitbox_id| hitbox_id.is_hovered(self))\n                })\n                .map(|request| request.style)\n                .unwrap_or(CursorStyle::Arrow);\n            cx.platform.set_cursor_style(style);\n        }\n    }\n\n    /// Dispatch a given keystroke as though the user had typed it.\n    /// You can create a keystroke with Keystroke::parse(\"\").\n    pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {\n        let keystroke = keystroke.with_simulated_ime();\n        let result = self.dispatch_event(\n            PlatformInput::KeyDown(KeyDownEvent {\n                keystroke: keystroke.clone(),\n                is_held: false,\n            }),\n            cx,\n        );\n        if !result.propagate {\n            return true;\n        }\n\n        if let Some(input) = keystroke.key_char {\n            if let Some(mut input_handler) = self.platform_window.take_input_handler() {\n                input_handler.dispatch_input(&input, self, cx);\n                self.platform_window.set_input_handler(input_handler);\n                return true;\n            }\n        }\n\n        false\n    }\n\n    /// Return a key binding string for an action, to display in the UI. Uses the highest precedence\n    /// binding for the action (last binding added to the keymap).\n    pub fn keystroke_text_for(&self, action: &dyn Action) -> String {\n        self.bindings_for_action(action)\n            .last()\n            .map(|binding| {\n                binding\n                    .keystrokes()\n                    .iter()\n                    .map(ToString::to_string)\n                    .collect::<Vec<_>>()\n                    .join(\" \")\n            })\n            .unwrap_or_else(|| action.name().to_string())\n    }\n\n    /// Dispatch a mouse or keyboard event on the window.\n    #[profiling::function]\n    pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {\n        self.last_input_timestamp.set(Instant::now());\n        // Handlers may set this to false by calling `stop_propagation`.\n        cx.propagate_event = true;\n        // Handlers may set this to true by calling `prevent_default`.\n        self.default_prevented = false;\n\n        let event = match event {\n            // Track the mouse position with our own state, since accessing the platform\n            // API for the mouse position can only occur on the main thread.\n            PlatformInput::MouseMove(mouse_move) => {\n                self.mouse_position = mouse_move.position;\n                self.modifiers = mouse_move.modifiers;\n                PlatformInput::MouseMove(mouse_move)\n            }\n            PlatformInput::MouseDown(mouse_down) => {\n                self.mouse_position = mouse_down.position;\n                self.modifiers = mouse_down.modifiers;\n                PlatformInput::MouseDown(mouse_down)\n            }\n            PlatformInput::MouseUp(mouse_up) => {\n                self.mouse_position = mouse_up.position;\n                self.modifiers = mouse_up.modifiers;\n                PlatformInput::MouseUp(mouse_up)\n            }\n            PlatformInput::MouseExited(mouse_exited) => {\n                self.modifiers = mouse_exited.modifiers;\n                PlatformInput::MouseExited(mouse_exited)\n            }\n            PlatformInput::ModifiersChanged(modifiers_changed) => {\n                self.modifiers = modifiers_changed.modifiers;\n                PlatformInput::ModifiersChanged(modifiers_changed)\n            }\n            PlatformInput::ScrollWheel(scroll_wheel) => {\n                self.mouse_position = scroll_wheel.position;\n                self.modifiers = scroll_wheel.modifiers;\n                PlatformInput::ScrollWheel(scroll_wheel)\n            }\n            // Translate dragging and dropping of external files from the operating system\n            // to internal drag and drop events.\n            PlatformInput::FileDrop(file_drop) => match file_drop {\n                FileDropEvent::Entered { position, paths } => {\n                    self.mouse_position = position;\n                    if cx.active_drag.is_none() {\n                        cx.active_drag = Some(AnyDrag {\n                            value: Arc::new(paths.clone()),\n                            view: cx.new(|_| paths).into(),\n                            cursor_offset: position,\n                            cursor_style: None,\n                        });\n                    }\n                    PlatformInput::MouseMove(MouseMoveEvent {\n                        position,\n                        pressed_button: Some(MouseButton::Left),\n                        modifiers: Modifiers::default(),\n                    })\n                }\n                FileDropEvent::Pending { position } => {\n                    self.mouse_position = position;\n                    PlatformInput::MouseMove(MouseMoveEvent {\n                        position,\n                        pressed_button: Some(MouseButton::Left),\n                        modifiers: Modifiers::default(),\n                    })\n                }\n                FileDropEvent::Submit { position } => {\n                    cx.activate(true);\n                    self.mouse_position = position;\n                    PlatformInput::MouseUp(MouseUpEvent {\n                        button: MouseButton::Left,\n                        position,\n                        modifiers: Modifiers::default(),\n                        click_count: 1,\n                    })\n                }\n                FileDropEvent::Exited => {\n                    cx.active_drag.take();\n                    PlatformInput::FileDrop(FileDropEvent::Exited)\n                }\n            },\n            PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,\n        };\n\n        if let Some(any_mouse_event) = event.mouse_event() {\n            self.dispatch_mouse_event(any_mouse_event, cx);\n        } else if let Some(any_key_event) = event.keyboard_event() {\n            self.dispatch_key_event(any_key_event, cx);\n        }\n\n        DispatchEventResult {\n            propagate: cx.propagate_event,\n            default_prevented: self.default_prevented,\n        }\n    }\n\n    fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {\n        let hit_test = self.rendered_frame.hit_test(self.mouse_position());\n        if hit_test != self.mouse_hit_test {\n            self.mouse_hit_test = hit_test;\n            self.reset_cursor_style(cx);\n        }\n\n        let mut mouse_listeners = mem::take(&mut self.rendered_frame.mouse_listeners);\n\n        // Capture phase, events bubble from back to front. Handlers for this phase are used for\n        // special purposes, such as detecting events outside of a given Bounds.\n        for listener in &mut mouse_listeners {\n            let listener = listener.as_mut().unwrap();\n            listener(event, DispatchPhase::Capture, self, cx);\n            if !cx.propagate_event {\n                break;\n            }\n        }\n\n        // Bubble phase, where most normal handlers do their work.\n        if cx.propagate_event {\n            for listener in mouse_listeners.iter_mut().rev() {\n                let listener = listener.as_mut().unwrap();\n                listener(event, DispatchPhase::Bubble, self, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n        }\n\n        self.rendered_frame.mouse_listeners = mouse_listeners;\n\n        if cx.has_active_drag() {\n            if event.is::<MouseMoveEvent>() {\n                // If this was a mouse move event, redraw the window so that the\n                // active drag can follow the mouse cursor.\n                self.refresh();\n            } else if event.is::<MouseUpEvent>() {\n                // If this was a mouse up event, cancel the active drag and redraw\n                // the window.\n                cx.active_drag = None;\n                self.refresh();\n            }\n        }\n    }\n\n    fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) {\n        if self.invalidator.is_dirty() {\n            self.draw(cx);\n        }\n\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        let mut keystroke: Option<Keystroke> = None;\n\n        if let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() {\n            if event.modifiers.number_of_modifiers() == 0\n                && self.pending_modifier.modifiers.number_of_modifiers() == 1\n                && !self.pending_modifier.saw_keystroke\n            {\n                let key = match self.pending_modifier.modifiers {\n                    modifiers if modifiers.shift => Some(\"shift\"),\n                    modifiers if modifiers.control => Some(\"control\"),\n                    modifiers if modifiers.alt => Some(\"alt\"),\n                    modifiers if modifiers.platform => Some(\"platform\"),\n                    modifiers if modifiers.function => Some(\"function\"),\n                    _ => None,\n                };\n                if let Some(key) = key {\n                    keystroke = Some(Keystroke {\n                        key: key.to_string(),\n                        key_char: None,\n                        modifiers: Modifiers::default(),\n                    });\n                }\n            }\n\n            if self.pending_modifier.modifiers.number_of_modifiers() == 0\n                && event.modifiers.number_of_modifiers() == 1\n            {\n                self.pending_modifier.saw_keystroke = false\n            }\n            self.pending_modifier.modifiers = event.modifiers\n        } else if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {\n            self.pending_modifier.saw_keystroke = true;\n            keystroke = Some(key_down_event.keystroke.clone());\n        }\n\n        let Some(keystroke) = keystroke else {\n            self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);\n            return;\n        };\n\n        let mut currently_pending = self.pending_input.take().unwrap_or_default();\n        if currently_pending.focus.is_some() && currently_pending.focus != self.focus {\n            currently_pending = PendingInput::default();\n        }\n\n        let match_result = self.rendered_frame.dispatch_tree.dispatch_key(\n            currently_pending.keystrokes,\n            keystroke,\n            &dispatch_path,\n        );\n\n        if !match_result.to_replay.is_empty() {\n            self.replay_pending_input(match_result.to_replay, cx)\n        }\n\n        if !match_result.pending.is_empty() {\n            currently_pending.keystrokes = match_result.pending;\n            currently_pending.focus = self.focus;\n            currently_pending.timer = Some(self.spawn(cx, async move |cx| {\n                cx.background_executor.timer(Duration::from_secs(1)).await;\n                cx.update(move |window, cx| {\n                    let Some(currently_pending) = window\n                        .pending_input\n                        .take()\n                        .filter(|pending| pending.focus == window.focus)\n                    else {\n                        return;\n                    };\n\n                    let dispatch_path = window.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n                    let to_replay = window\n                        .rendered_frame\n                        .dispatch_tree\n                        .flush_dispatch(currently_pending.keystrokes, &dispatch_path);\n\n                    window.replay_pending_input(to_replay, cx)\n                })\n                .log_err();\n            }));\n            self.pending_input = Some(currently_pending);\n            self.pending_input_changed(cx);\n            cx.propagate_event = false;\n            return;\n        }\n\n        cx.propagate_event = true;\n        for binding in match_result.bindings {\n            self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);\n            if !cx.propagate_event {\n                self.dispatch_keystroke_observers(\n                    event,\n                    Some(binding.action),\n                    match_result.context_stack.clone(),\n                    cx,\n                );\n                self.pending_input_changed(cx);\n                return;\n            }\n        }\n\n        self.finish_dispatch_key_event(event, dispatch_path, match_result.context_stack, cx);\n        self.pending_input_changed(cx);\n    }\n\n    fn finish_dispatch_key_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: SmallVec<[DispatchNodeId; 32]>,\n        context_stack: Vec<KeyContext>,\n        cx: &mut App,\n    ) {\n        self.dispatch_key_down_up_event(event, &dispatch_path, cx);\n        if !cx.propagate_event {\n            return;\n        }\n\n        self.dispatch_modifiers_changed_event(event, &dispatch_path, cx);\n        if !cx.propagate_event {\n            return;\n        }\n\n        self.dispatch_keystroke_observers(event, None, context_stack, cx);\n    }\n\n    fn pending_input_changed(&mut self, cx: &mut App) {\n        self.pending_input_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    fn dispatch_key_down_up_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,\n        cx: &mut App,\n    ) {\n        // Capture phase\n        for node_id in dispatch_path {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n\n            for key_listener in node.key_listeners.clone() {\n                key_listener(event, DispatchPhase::Capture, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n\n        // Bubble phase\n        for node_id in dispatch_path.iter().rev() {\n            // Handle low level key events\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for key_listener in node.key_listeners.clone() {\n                key_listener(event, DispatchPhase::Bubble, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n    }\n\n    fn dispatch_modifiers_changed_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,\n        cx: &mut App,\n    ) {\n        let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() else {\n            return;\n        };\n        for node_id in dispatch_path.iter().rev() {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for listener in node.modifiers_changed_listeners.clone() {\n                listener(event, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n    }\n\n    /// Determine whether a potential multi-stroke key binding is in progress on this window.\n    pub fn has_pending_keystrokes(&self) -> bool {\n        self.pending_input.is_some()\n    }\n\n    pub(crate) fn clear_pending_keystrokes(&mut self) {\n        self.pending_input.take();\n    }\n\n    /// Returns the currently pending input keystrokes that might result in a multi-stroke key binding.\n    pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> {\n        self.pending_input\n            .as_ref()\n            .map(|pending_input| pending_input.keystrokes.as_slice())\n    }\n\n    fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) {\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        'replay: for replay in replays {\n            let event = KeyDownEvent {\n                keystroke: replay.keystroke.clone(),\n                is_held: false,\n            };\n\n            cx.propagate_event = true;\n            for binding in replay.bindings {\n                self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);\n                if !cx.propagate_event {\n                    self.dispatch_keystroke_observers(\n                        &event,\n                        Some(binding.action),\n                        Vec::default(),\n                        cx,\n                    );\n                    continue 'replay;\n                }\n            }\n\n            self.dispatch_key_down_up_event(&event, &dispatch_path, cx);\n            if !cx.propagate_event {\n                continue 'replay;\n            }\n            if let Some(input) = replay.keystroke.key_char.as_ref().cloned() {\n                if let Some(mut input_handler) = self.platform_window.take_input_handler() {\n                    input_handler.dispatch_input(&input, self, cx);\n                    self.platform_window.set_input_handler(input_handler)\n                }\n            }\n        }\n    }\n\n    fn dispatch_action_on_node(\n        &mut self,\n        node_id: DispatchNodeId,\n        action: &dyn Action,\n        cx: &mut App,\n    ) {\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        // Capture phase for global actions.\n        cx.propagate_event = true;\n        if let Some(mut global_listeners) = cx\n            .global_action_listeners\n            .remove(&action.as_any().type_id())\n        {\n            for listener in &global_listeners {\n                listener(action.as_any(), DispatchPhase::Capture, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n\n            global_listeners.extend(\n                cx.global_action_listeners\n                    .remove(&action.as_any().type_id())\n                    .unwrap_or_default(),\n            );\n\n            cx.global_action_listeners\n                .insert(action.as_any().type_id(), global_listeners);\n        }\n\n        if !cx.propagate_event {\n            return;\n        }\n\n        // Capture phase for window actions.\n        for node_id in &dispatch_path {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for DispatchActionListener {\n                action_type,\n                listener,\n            } in node.action_listeners.clone()\n            {\n                let any_action = action.as_any();\n                if action_type == any_action.type_id() {\n                    listener(any_action, DispatchPhase::Capture, self, cx);\n\n                    if !cx.propagate_event {\n                        return;\n                    }\n                }\n            }\n        }\n\n        // Bubble phase for window actions.\n        for node_id in dispatch_path.iter().rev() {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for DispatchActionListener {\n                action_type,\n                listener,\n            } in node.action_listeners.clone()\n            {\n                let any_action = action.as_any();\n                if action_type == any_action.type_id() {\n                    cx.propagate_event = false; // Actions stop propagation by default during the bubble phase\n                    listener(any_action, DispatchPhase::Bubble, self, cx);\n\n                    if !cx.propagate_event {\n                        return;\n                    }\n                }\n            }\n        }\n\n        // Bubble phase for global actions.\n        if let Some(mut global_listeners) = cx\n            .global_action_listeners\n            .remove(&action.as_any().type_id())\n        {\n            for listener in global_listeners.iter().rev() {\n                cx.propagate_event = false; // Actions stop propagation by default during the bubble phase\n\n                listener(action.as_any(), DispatchPhase::Bubble, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n\n            global_listeners.extend(\n                cx.global_action_listeners\n                    .remove(&action.as_any().type_id())\n                    .unwrap_or_default(),\n            );\n\n            cx.global_action_listeners\n                .insert(action.as_any().type_id(), global_listeners);\n        }\n    }\n\n    /// Register the given handler to be invoked whenever the global of the given type\n    /// is updated.\n    pub fn observe_global<G: Global>(\n        &mut self,\n        cx: &mut App,\n        f: impl Fn(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let window_handle = self.handle;\n        let (subscription, activate) = cx.global_observers.insert(\n            TypeId::of::<G>(),\n            Box::new(move |cx| {\n                window_handle\n                    .update(cx, |_, window, cx| f(window, cx))\n                    .is_ok()\n            }),\n        );\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    /// Focus the current window and bring it to the foreground at the platform level.\n    pub fn activate_window(&self) {\n        self.platform_window.activate();\n    }\n\n    /// Minimize the current window at the platform level.\n    pub fn minimize_window(&self) {\n        self.platform_window.minimize();\n    }\n\n    /// Toggle full screen status on the current window at the platform level.\n    pub fn toggle_fullscreen(&self) {\n        self.platform_window.toggle_fullscreen();\n    }\n\n    /// Updates the IME panel position suggestions for languages like japanese, chinese.\n    pub fn invalidate_character_coordinates(&self) {\n        self.on_next_frame(|window, cx| {\n            if let Some(mut input_handler) = window.platform_window.take_input_handler() {\n                if let Some(bounds) = input_handler.selected_bounds(window, cx) {\n                    window\n                        .platform_window\n                        .update_ime_position(bounds.scale(window.scale_factor()));\n                }\n                window.platform_window.set_input_handler(input_handler);\n            }\n        });\n    }\n\n    /// Present a platform dialog.\n    /// The provided message will be presented, along with buttons for each answer.\n    /// When a button is clicked, the returned Receiver will receive the index of the clicked button.\n    pub fn prompt(\n        &mut self,\n        level: PromptLevel,\n        message: &str,\n        detail: Option<&str>,\n        answers: &[&str],\n        cx: &mut App,\n    ) -> oneshot::Receiver<usize> {\n        let prompt_builder = cx.prompt_builder.take();\n        let Some(prompt_builder) = prompt_builder else {\n            unreachable!(\"Re-entrant window prompting is not supported by GPUI\");\n        };\n\n        let receiver = match &prompt_builder {\n            PromptBuilder::Default => self\n                .platform_window\n                .prompt(level, message, detail, answers)\n                .unwrap_or_else(|| {\n                    self.build_custom_prompt(&prompt_builder, level, message, detail, answers, cx)\n                }),\n            PromptBuilder::Custom(_) => {\n                self.build_custom_prompt(&prompt_builder, level, message, detail, answers, cx)\n            }\n        };\n\n        cx.prompt_builder = Some(prompt_builder);\n\n        receiver\n    }\n\n    fn build_custom_prompt(\n        &mut self,\n        prompt_builder: &PromptBuilder,\n        level: PromptLevel,\n        message: &str,\n        detail: Option<&str>,\n        answers: &[&str],\n        cx: &mut App,\n    ) -> oneshot::Receiver<usize> {\n        let (sender, receiver) = oneshot::channel();\n        let handle = PromptHandle::new(sender);\n        let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx);\n        self.prompt = Some(handle);\n        receiver\n    }\n\n    /// Returns the current context stack.\n    pub fn context_stack(&self) -> Vec<KeyContext> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n        let node_id = self\n            .focus\n            .and_then(|focus_id| dispatch_tree.focusable_node_id(focus_id))\n            .unwrap_or_else(|| dispatch_tree.root_node_id());\n\n        dispatch_tree\n            .dispatch_path(node_id)\n            .iter()\n            .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone())\n            .collect()\n    }\n\n    /// Returns all available actions for the focused element.\n    pub fn available_actions(&self, cx: &App) -> Vec<Box<dyn Action>> {\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let mut actions = self.rendered_frame.dispatch_tree.available_actions(node_id);\n        for action_type in cx.global_action_listeners.keys() {\n            if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) {\n                let action = cx.actions.build_action_type(action_type).ok();\n                if let Some(action) = action {\n                    actions.insert(ix, action);\n                }\n            }\n        }\n        actions\n    }\n\n    /// Returns key bindings that invoke an action on the currently focused element. Bindings are\n    /// returned in the order they were added. For display, the last binding should take precedence.\n    pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {\n        self.rendered_frame\n            .dispatch_tree\n            .bindings_for_action(action, &self.rendered_frame.dispatch_tree.context_stack)\n    }\n\n    /// Returns any bindings that would invoke an action on the given focus handle if it were\n    /// focused. Bindings are returned in the order they were added. For display, the last binding\n    /// should take precedence.\n    pub fn bindings_for_action_in(\n        &self,\n        action: &dyn Action,\n        focus_handle: &FocusHandle,\n    ) -> Vec<KeyBinding> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n\n        let Some(node_id) = dispatch_tree.focusable_node_id(focus_handle.id) else {\n            return vec![];\n        };\n        let context_stack: Vec<_> = dispatch_tree\n            .dispatch_path(node_id)\n            .into_iter()\n            .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())\n            .collect();\n        dispatch_tree.bindings_for_action(action, &context_stack)\n    }\n\n    /// Returns the key bindings for the given action in the given context.\n    pub fn bindings_for_action_in_context(\n        &self,\n        action: &dyn Action,\n        context: KeyContext,\n    ) -> Vec<KeyBinding> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n        dispatch_tree.bindings_for_action(action, &[context])\n    }\n\n    /// Returns a generic event listener that invokes the given listener with the view and context associated with the given view handle.\n    pub fn listener_for<V: Render, E>(\n        &self,\n        view: &Entity<V>,\n        f: impl Fn(&mut V, &E, &mut Window, &mut Context<V>) + 'static,\n    ) -> impl Fn(&E, &mut Window, &mut App) + 'static {\n        let view = view.downgrade();\n        move |e: &E, window: &mut Window, cx: &mut App| {\n            view.update(cx, |view, cx| f(view, e, window, cx)).ok();\n        }\n    }\n\n    /// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle.\n    pub fn handler_for<V: Render, Callback: Fn(&mut V, &mut Window, &mut Context<V>) + 'static>(\n        &self,\n        view: &Entity<V>,\n        f: Callback,\n    ) -> impl Fn(&mut Window, &mut App) + use<V, Callback> {\n        let view = view.downgrade();\n        move |window: &mut Window, cx: &mut App| {\n            view.update(cx, |view, cx| f(view, window, cx)).ok();\n        }\n    }\n\n    /// Register a callback that can interrupt the closing of the current window based the returned boolean.\n    /// If the callback returns false, the window won't be closed.\n    pub fn on_window_should_close(\n        &self,\n        cx: &App,\n        f: impl Fn(&mut Window, &mut App) -> bool + 'static,\n    ) {\n        let mut cx = self.to_async(cx);\n        self.platform_window.on_should_close(Box::new(move || {\n            cx.update(|window, cx| f(window, cx)).unwrap_or(true)\n        }))\n    }\n\n    /// Register an action listener on the window for the next frame. The type of action\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This is a fairly low-level method, so prefer using action handlers on elements unless you have\n    /// a specific need to register a global listener.\n    pub fn on_action(\n        &mut self,\n        action_type: TypeId,\n        listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.next_frame\n            .dispatch_tree\n            .on_action(action_type, Rc::new(listener));\n    }\n\n    /// Read information about the GPU backing this window.\n    /// Currently returns None on Mac and Windows.\n    pub fn gpu_specs(&self) -> Option<GpuSpecs> {\n        self.platform_window.gpu_specs()\n    }\n}\n\n// #[derive(Clone, Copy, Eq, PartialEq, Hash)]\nslotmap::new_key_type! {\n    /// A unique identifier for a window.\n    pub struct WindowId;\n}\n\nimpl WindowId {\n    /// Converts this window ID to a `u64`.\n    pub fn as_u64(&self) -> u64 {\n        self.0.as_ffi()\n    }\n}\n\nimpl From<u64> for WindowId {\n    fn from(value: u64) -> Self {\n        WindowId(slotmap::KeyData::from_ffi(value))\n    }\n}\n\n/// A handle to a window with a specific root view type.\n/// Note that this does not keep the window alive on its own.\n#[derive(Deref, DerefMut)]\npub struct WindowHandle<V> {\n    #[deref]\n    #[deref_mut]\n    pub(crate) any_handle: AnyWindowHandle,\n    state_type: PhantomData<V>,\n}\n\nimpl<V: 'static + Render> WindowHandle<V> {\n    /// Creates a new handle from a window ID.\n    /// This does not check if the root type of the window is `V`.\n    pub fn new(id: WindowId) -> Self {\n        WindowHandle {\n            any_handle: AnyWindowHandle {\n                id,\n                state_type: TypeId::of::<V>(),\n            },\n            state_type: PhantomData,\n        }\n    }\n\n    /// Get the root view out of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    #[cfg(any(test, feature = \"test-support\"))]\n    pub fn root<C>(&self, cx: &mut C) -> Result<Entity<V>>\n    where\n        C: AppContext,\n    {\n        crate::Flatten::flatten(cx.update_window(self.any_handle, |root_view, _, _| {\n            root_view\n                .downcast::<V>()\n                .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))\n        }))\n    }\n\n    /// Updates the root view of this window.\n    ///\n    /// This will fail if the window has been closed or if the root view's type does not match\n    pub fn update<C, R>(\n        &self,\n        cx: &mut C,\n        update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,\n    ) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.update_window(self.any_handle, |root_view, window, cx| {\n            let view = root_view\n                .downcast::<V>()\n                .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))?;\n\n            Ok(view.update(cx, |view, cx| update(view, window, cx)))\n        })?\n    }\n\n    /// Read the root view out of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> {\n        let x = cx\n            .windows\n            .get(self.id)\n            .and_then(|window| {\n                window\n                    .as_ref()\n                    .and_then(|window| window.root.clone())\n                    .map(|root_view| root_view.downcast::<V>())\n            })\n            .ok_or_else(|| anyhow!(\"window not found\"))?\n            .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))?;\n\n        Ok(x.read(cx))\n    }\n\n    /// Read the root view out of this window, with a callback\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))\n    }\n\n    /// Read the root view pointer off of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn entity<C>(&self, cx: &C) -> Result<Entity<V>>\n    where\n        C: AppContext,\n    {\n        cx.read_window(self, |root_view, _cx| root_view.clone())\n    }\n\n    /// Check if this window is 'active'.\n    ///\n    /// Will return `None` if the window is closed or currently\n    /// borrowed.\n    pub fn is_active(&self, cx: &mut App) -> Option<bool> {\n        cx.update_window(self.any_handle, |_, window, _| window.is_window_active())\n            .ok()\n    }\n}\n\nimpl<V> Copy for WindowHandle<V> {}\n\nimpl<V> Clone for WindowHandle<V> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<V> PartialEq for WindowHandle<V> {\n    fn eq(&self, other: &Self) -> bool {\n        self.any_handle == other.any_handle\n    }\n}\n\nimpl<V> Eq for WindowHandle<V> {}\n\nimpl<V> Hash for WindowHandle<V> {\n    fn hash<H: Hasher>(&self, state: &mut H) {\n        self.any_handle.hash(state);\n    }\n}\n\nimpl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {\n    fn from(val: WindowHandle<V>) -> Self {\n        val.any_handle\n    }\n}\n\nunsafe impl<V> Send for WindowHandle<V> {}\nunsafe impl<V> Sync for WindowHandle<V> {}\n\n/// A handle to a window with any root view type, which can be downcast to a window with a specific root view type.\n#[derive(Copy, Clone, PartialEq, Eq, Hash)]\npub struct AnyWindowHandle {\n    pub(crate) id: WindowId,\n    state_type: TypeId,\n}\n\nimpl AnyWindowHandle {\n    /// Get the ID of this window.\n    pub fn window_id(&self) -> WindowId {\n        self.id\n    }\n\n    /// Attempt to convert this handle to a window handle with a specific root view type.\n    /// If the types do not match, this will return `None`.\n    pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {\n        if TypeId::of::<T>() == self.state_type {\n            Some(WindowHandle {\n                any_handle: *self,\n                state_type: PhantomData,\n            })\n        } else {\n            None\n        }\n    }\n\n    /// Updates the state of the root view of this window.\n    ///\n    /// This will fail if the window has been closed.\n    pub fn update<C, R>(\n        self,\n        cx: &mut C,\n        update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,\n    ) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.update_window(self, update)\n    }\n\n    /// Read the state of the root view of this window.\n    ///\n    /// This will fail if the window has been closed.\n    pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(Entity<T>, &App) -> R) -> Result<R>\n    where\n        C: AppContext,\n        T: 'static,\n    {\n        let view = self\n            .downcast::<T>()\n            .context(\"the type of the window's root view has changed\")?;\n\n        cx.read_window(&view, read)\n    }\n}\n\nimpl HasWindowHandle for Window {\n    fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, HandleError> {\n        self.platform_window.window_handle()\n    }\n}\n\n/// An identifier for an [`Element`](crate::Element).\n///\n/// Can be constructed with a string, a number, or both, as well\n/// as other internal representations.\n#[derive(Clone, Debug, Eq, PartialEq, Hash)]\npub enum ElementId {\n    /// The ID of a View element\n    View(EntityId),\n    /// An integer ID.\n    Integer(u64),\n    /// A string based ID.\n    Name(SharedString),\n    /// A UUID.\n    Uuid(Uuid),\n    /// An ID that's equated with a focus handle.\n    FocusHandle(FocusId),\n    /// A combination of a name and an integer.\n    NamedInteger(SharedString, u64),\n    /// A path\n    Path(Arc<std::path::Path>),\n}\n\nimpl ElementId {\n    /// Constructs an `ElementId::NamedInteger` from a name and `usize`.\n    pub fn named_usize(name: impl Into<SharedString>, integer: usize) -> ElementId {\n        Self::NamedInteger(name.into(), integer as u64)\n    }\n}\n\nimpl Display for ElementId {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            ElementId::View(entity_id) => write!(f, \"view-{}\", entity_id)?,\n            ElementId::Integer(ix) => write!(f, \"{}\", ix)?,\n            ElementId::Name(name) => write!(f, \"{}\", name)?,\n            ElementId::FocusHandle(_) => write!(f, \"FocusHandle\")?,\n            ElementId::NamedInteger(s, i) => write!(f, \"{}-{}\", s, i)?,\n            ElementId::Uuid(uuid) => write!(f, \"{}\", uuid)?,\n            ElementId::Path(path) => write!(f, \"{}\", path.display())?,\n        }\n\n        Ok(())\n    }\n}\n\nimpl TryInto<SharedString> for ElementId {\n    type Error = anyhow::Error;\n\n    fn try_into(self) -> anyhow::Result<SharedString> {\n        if let ElementId::Name(name) = self {\n            Ok(name)\n        } else {\n            Err(anyhow!(\"element id is not string\"))\n        }\n    }\n}\n\nimpl From<usize> for ElementId {\n    fn from(id: usize) -> Self {\n        ElementId::Integer(id as u64)\n    }\n}\n\nimpl From<i32> for ElementId {\n    fn from(id: i32) -> Self {\n        Self::Integer(id as u64)\n    }\n}\n\nimpl From<SharedString> for ElementId {\n    fn from(name: SharedString) -> Self {\n        ElementId::Name(name)\n    }\n}\n\nimpl From<Arc<std::path::Path>> for ElementId {\n    fn from(path: Arc<std::path::Path>) -> Self {\n        ElementId::Path(path)\n    }\n}\n\nimpl From<&'static str> for ElementId {\n    fn from(name: &'static str) -> Self {\n        ElementId::Name(name.into())\n    }\n}\n\nimpl<'a> From<&'a FocusHandle> for ElementId {\n    fn from(handle: &'a FocusHandle) -> Self {\n        ElementId::FocusHandle(handle.id)\n    }\n}\n\nimpl From<(&'static str, EntityId)> for ElementId {\n    fn from((name, id): (&'static str, EntityId)) -> Self {\n        ElementId::NamedInteger(name.into(), id.as_u64())\n    }\n}\n\nimpl From<(&'static str, usize)> for ElementId {\n    fn from((name, id): (&'static str, usize)) -> Self {\n        ElementId::NamedInteger(name.into(), id as u64)\n    }\n}\n\nimpl From<(SharedString, usize)> for ElementId {\n    fn from((name, id): (SharedString, usize)) -> Self {\n        ElementId::NamedInteger(name, id as u64)\n    }\n}\n\nimpl From<(&'static str, u64)> for ElementId {\n    fn from((name, id): (&'static str, u64)) -> Self {\n        ElementId::NamedInteger(name.into(), id)\n    }\n}\n\nimpl From<Uuid> for ElementId {\n    fn from(value: Uuid) -> Self {\n        Self::Uuid(value)\n    }\n}\n\nimpl From<(&'static str, u32)> for ElementId {\n    fn from((name, id): (&'static str, u32)) -> Self {\n        ElementId::NamedInteger(name.into(), id.into())\n    }\n}\n\n/// A rectangle to be rendered in the window at the given position and size.\n/// Passed as an argument [`Window::paint_quad`].\n#[derive(Clone)]\npub struct PaintQuad {\n    /// The bounds of the quad within the window.\n    pub bounds: Bounds<Pixels>,\n    /// The radii of the quad's corners.\n    pub corner_radii: Corners<Pixels>,\n    /// The background color of the quad.\n    pub background: Background,\n    /// The widths of the quad's borders.\n    pub border_widths: Edges<Pixels>,\n    /// The color of the quad's borders.\n    pub border_color: Hsla,\n    /// The style of the quad's borders.\n    pub border_style: BorderStyle,\n    /// The transformation to apply to the quad.\n    pub transformation: TransformationMatrix,\n}\n\nimpl PaintQuad {\n    /// Sets the corner radii of the quad.\n    pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {\n        PaintQuad {\n            corner_radii: corner_radii.into(),\n            ..self\n        }\n    }\n\n    /// Sets the border widths of the quad.\n    pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {\n        PaintQuad {\n            border_widths: border_widths.into(),\n            ..self\n        }\n    }\n\n    /// Sets the border color of the quad.\n    pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {\n        PaintQuad {\n            border_color: border_color.into(),\n            ..self\n        }\n    }\n\n    /// Sets the background color of the quad.\n    pub fn background(self, background: impl Into<Background>) -> Self {\n        PaintQuad {\n            background: background.into(),\n            ..self\n        }\n    }\n\n    /// Sets the transformation matrix to apply to the quad.\n    pub fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {\n        PaintQuad {\n            transformation: transformation.into(),\n            ..self\n        }\n    }\n    \n    /// Rotates the quad around its origin by the given angle (in radians, clockwise).\n    pub fn rotate(self, angle: impl Into<Radians>) -> Self {\n        PaintQuad {\n            transformation: self.transformation.rotate(angle.into()),\n            ..self\n        }\n    }\n    \n    /// Scales the quad around its origin by the given factor.\n    pub fn scale(self, scale: impl Into<Size<f32>>) -> Self {\n        PaintQuad {\n            transformation: self.transformation.scale(scale.into()),\n            ..self\n        }\n    }\n    \n    /// Translates the quad by the given offset.\n    pub fn translate(self, offset: impl Into<Point<ScaledPixels>>) -> Self {\n        PaintQuad {\n            transformation: self.transformation.translate(offset.into()),\n            ..self\n        }\n    }\n}\n\n/// Creates a quad with the given parameters.\npub fn quad(\n    bounds: Bounds<Pixels>,\n    corner_radii: impl Into<Corners<Pixels>>,\n    background: impl Into<Background>,\n    border_widths: impl Into<Edges<Pixels>>,\n    border_color: impl Into<Hsla>,\n    border_style: BorderStyle,\n) -> PaintQuad {\n    PaintQuad {\n        bounds,\n        corner_radii: corner_radii.into(),\n        background: background.into(),\n        border_widths: border_widths.into(),\n        border_color: border_color.into(),\n        border_style,\n        transformation: TransformationMatrix::default(),\n    }\n}\n\n/// Applies a transformation matrix to a quad.\npub fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad {\n    PaintQuad {\n        transformation,\n        ..quad\n    }\n}\n\n/// Creates a filled quad with the given bounds and background color.\npub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {\n    PaintQuad {\n        bounds: bounds.into(),\n        corner_radii: (0.).into(),\n        background: background.into(),\n        border_widths: (0.).into(),\n        border_color: transparent_black(),\n        border_style: BorderStyle::default(),\n        transformation: TransformationMatrix::default(),\n    }\n}\n\n/// Creates a rectangle outline with the given bounds, border color, and a 1px border width\npub fn outline(\n    bounds: impl Into<Bounds<Pixels>>,\n    border_color: impl Into<Hsla>,\n    border_style: BorderStyle,\n) -> PaintQuad {\n    PaintQuad {\n        bounds: bounds.into(),\n        corner_radii: (0.).into(),\n        background: transparent_black().into(),\n        border_widths: (1.).into(),\n        border_color: border_color.into(),\n        border_style,\n        transformation: TransformationMatrix::default(),\n    }\n}\n",
  "old_text": "use crate::{\n    Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,\n    AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Context,\n    Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId,\n    DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, FontId,\n    Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero, KeyBinding, KeyContext,\n    KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers,\n    ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent,\n    Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler,\n    PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams,\n    RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR,\n    SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style,\n    SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement,\n    TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance,\n    WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem,\n    point, prelude::*, px, size, transparent_black,\n};\nuse anyhow::{Context as _, Result, anyhow};\nuse collections::{FxHashMap, FxHashSet};\n#[cfg(target_os = \"macos\")]\nuse core_video::pixel_buffer::CVPixelBuffer;\nuse derive_more::{Deref, DerefMut};\nuse futures::FutureExt;\nuse futures::channel::oneshot;\nuse parking_lot::RwLock;\nuse raw_window_handle::{HandleError, HasWindowHandle};\nuse refineable::Refineable;\nuse slotmap::SlotMap;\nuse smallvec::SmallVec;\nuse std::{\n    any::{Any, TypeId},\n    borrow::Cow,\n    cell::{Cell, RefCell},\n    cmp,\n    fmt::{Debug, Display},\n    hash::{Hash, Hasher},\n    marker::PhantomData,\n    mem,\n    ops::{DerefMut, Range},\n    rc::Rc,\n    sync::{\n        Arc, Weak,\n        atomic::{AtomicUsize, Ordering::SeqCst},\n    },\n    time::{Duration, Instant},\n};\nuse util::post_inc;\nuse util::{ResultExt, measure};\nuse uuid::Uuid;\n\nmod prompts;\n\npub use prompts::*;\n\npub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1024.), px(700.));\n\n/// Represents the two different phases when dispatching events.\n#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]\npub enum DispatchPhase {\n    /// After the capture phase comes the bubble phase, in which mouse event listeners are\n    /// invoked front to back and keyboard event listeners are invoked from the focused element\n    /// to the root of the element tree. This is the phase you'll most commonly want to use when\n    /// registering event listeners.\n    #[default]\n    Bubble,\n    /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard\n    /// listeners are invoked from the root of the tree downward toward the focused element. This phase\n    /// is used for special purposes such as clearing the \"pressed\" state for click events. If\n    /// you stop event propagation during this phase, you need to know what you're doing. Handlers\n    /// outside of the immediate region may rely on detecting non-local events during this phase.\n    Capture,\n}\n\nimpl DispatchPhase {\n    /// Returns true if this represents the \"bubble\" phase.\n    pub fn bubble(self) -> bool {\n        self == DispatchPhase::Bubble\n    }\n\n    /// Returns true if this represents the \"capture\" phase.\n    pub fn capture(self) -> bool {\n        self == DispatchPhase::Capture\n    }\n}\n\nstruct WindowInvalidatorInner {\n    pub dirty: bool,\n    pub draw_phase: DrawPhase,\n    pub dirty_views: FxHashSet<EntityId>,\n}\n\n#[derive(Clone)]\npub(crate) struct WindowInvalidator {\n    inner: Rc<RefCell<WindowInvalidatorInner>>,\n}\n\nimpl WindowInvalidator {\n    pub fn new() -> Self {\n        WindowInvalidator {\n            inner: Rc::new(RefCell::new(WindowInvalidatorInner {\n                dirty: true,\n                draw_phase: DrawPhase::None,\n                dirty_views: FxHashSet::default(),\n            })),\n        }\n    }\n\n    pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {\n        let mut inner = self.inner.borrow_mut();\n        inner.dirty_views.insert(entity);\n        if inner.draw_phase == DrawPhase::None {\n            inner.dirty = true;\n            cx.push_effect(Effect::Notify { emitter: entity });\n            true\n        } else {\n            false\n        }\n    }\n\n    pub fn is_dirty(&self) -> bool {\n        self.inner.borrow().dirty\n    }\n\n    pub fn set_dirty(&self, dirty: bool) {\n        self.inner.borrow_mut().dirty = dirty\n    }\n\n    pub fn set_phase(&self, phase: DrawPhase) {\n        self.inner.borrow_mut().draw_phase = phase\n    }\n\n    pub fn take_views(&self) -> FxHashSet<EntityId> {\n        mem::take(&mut self.inner.borrow_mut().dirty_views)\n    }\n\n    pub fn replace_views(&self, views: FxHashSet<EntityId>) {\n        self.inner.borrow_mut().dirty_views = views;\n    }\n\n    pub fn not_drawing(&self) -> bool {\n        self.inner.borrow().draw_phase == DrawPhase::None\n    }\n\n    #[track_caller]\n    pub fn debug_assert_paint(&self) {\n        debug_assert!(\n            matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),\n            \"this method can only be called during paint\"\n        );\n    }\n\n    #[track_caller]\n    pub fn debug_assert_prepaint(&self) {\n        debug_assert!(\n            matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),\n            \"this method can only be called during request_layout, or prepaint\"\n        );\n    }\n\n    #[track_caller]\n    pub fn debug_assert_paint_or_prepaint(&self) {\n        debug_assert!(\n            matches!(\n                self.inner.borrow().draw_phase,\n                DrawPhase::Paint | DrawPhase::Prepaint\n            ),\n            \"this method can only be called during request_layout, prepaint, or paint\"\n        );\n    }\n}\n\ntype AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;\n\npub(crate) type AnyWindowFocusListener =\n    Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;\n\npub(crate) struct WindowFocusEvent {\n    pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,\n    pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,\n}\n\nimpl WindowFocusEvent {\n    pub fn is_focus_in(&self, focus_id: FocusId) -> bool {\n        !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id)\n    }\n\n    pub fn is_focus_out(&self, focus_id: FocusId) -> bool {\n        self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id)\n    }\n}\n\n/// This is provided when subscribing for `Context::on_focus_out` events.\npub struct FocusOutEvent {\n    /// A weak focus handle representing what was blurred.\n    pub blurred: WeakFocusHandle,\n}\n\nslotmap::new_key_type! {\n    /// A globally unique identifier for a focusable element.\n    pub struct FocusId;\n}\n\nthread_local! {\n    /// 8MB wasn't quite enough...\n    pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(32 * 1024 * 1024));\n}\n\npub(crate) type FocusMap = RwLock<SlotMap<FocusId, AtomicUsize>>;\n\nimpl FocusId {\n    /// Obtains whether the element associated with this handle is currently focused.\n    pub fn is_focused(&self, window: &Window) -> bool {\n        window.focus == Some(*self)\n    }\n\n    /// Obtains whether the element associated with this handle contains the focused\n    /// element or is itself focused.\n    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {\n        window\n            .focused(cx)\n            .map_or(false, |focused| self.contains(focused.id, window))\n    }\n\n    /// Obtains whether the element associated with this handle is contained within the\n    /// focused element or is itself focused.\n    pub fn within_focused(&self, window: &Window, cx: &App) -> bool {\n        let focused = window.focused(cx);\n        focused.map_or(false, |focused| focused.id.contains(*self, window))\n    }\n\n    /// Obtains whether this handle contains the given handle in the most recently rendered frame.\n    pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {\n        window\n            .rendered_frame\n            .dispatch_tree\n            .focus_contains(*self, other)\n    }\n}\n\n/// A handle which can be used to track and manipulate the focused element in a window.\npub struct FocusHandle {\n    pub(crate) id: FocusId,\n    handles: Arc<FocusMap>,\n}\n\nimpl std::fmt::Debug for FocusHandle {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.write_fmt(format_args!(\"FocusHandle({:?})\", self.id))\n    }\n}\n\nimpl FocusHandle {\n    pub(crate) fn new(handles: &Arc<FocusMap>) -> Self {\n        let id = handles.write().insert(AtomicUsize::new(1));\n        Self {\n            id,\n            handles: handles.clone(),\n        }\n    }\n\n    pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {\n        let lock = handles.read();\n        let ref_count = lock.get(id)?;\n        if ref_count.load(SeqCst) == 0 {\n            None\n        } else {\n            ref_count.fetch_add(1, SeqCst);\n            Some(Self {\n                id,\n                handles: handles.clone(),\n            })\n        }\n    }\n\n    /// Converts this focus handle into a weak variant, which does not prevent it from being released.\n    pub fn downgrade(&self) -> WeakFocusHandle {\n        WeakFocusHandle {\n            id: self.id,\n            handles: Arc::downgrade(&self.handles),\n        }\n    }\n\n    /// Moves the focus to the element associated with this handle.\n    pub fn focus(&self, window: &mut Window) {\n        window.focus(self)\n    }\n\n    /// Obtains whether the element associated with this handle is currently focused.\n    pub fn is_focused(&self, window: &Window) -> bool {\n        self.id.is_focused(window)\n    }\n\n    /// Obtains whether the element associated with this handle contains the focused\n    /// element or is itself focused.\n    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {\n        self.id.contains_focused(window, cx)\n    }\n\n    /// Obtains whether the element associated with this handle is contained within the\n    /// focused element or is itself focused.\n    pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {\n        self.id.within_focused(window, cx)\n    }\n\n    /// Obtains whether this handle contains the given handle in the most recently rendered frame.\n    pub fn contains(&self, other: &Self, window: &Window) -> bool {\n        self.id.contains(other.id, window)\n    }\n\n    /// Dispatch an action on the element that rendered this focus handle\n    pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {\n        if let Some(node_id) = window\n            .rendered_frame\n            .dispatch_tree\n            .focusable_node_id(self.id)\n        {\n            window.dispatch_action_on_node(node_id, action, cx)\n        }\n    }\n}\n\nimpl Clone for FocusHandle {\n    fn clone(&self) -> Self {\n        Self::for_id(self.id, &self.handles).unwrap()\n    }\n}\n\nimpl PartialEq for FocusHandle {\n    fn eq(&self, other: &Self) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for FocusHandle {}\n\nimpl Drop for FocusHandle {\n    fn drop(&mut self) {\n        self.handles\n            .read()\n            .get(self.id)\n            .unwrap()\n            .fetch_sub(1, SeqCst);\n    }\n}\n\n/// A weak reference to a focus handle.\n#[derive(Clone, Debug)]\npub struct WeakFocusHandle {\n    pub(crate) id: FocusId,\n    pub(crate) handles: Weak<FocusMap>,\n}\n\nimpl WeakFocusHandle {\n    /// Attempts to upgrade the [WeakFocusHandle] to a [FocusHandle].\n    pub fn upgrade(&self) -> Option<FocusHandle> {\n        let handles = self.handles.upgrade()?;\n        FocusHandle::for_id(self.id, &handles)\n    }\n}\n\nimpl PartialEq for WeakFocusHandle {\n    fn eq(&self, other: &WeakFocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for WeakFocusHandle {}\n\nimpl PartialEq<FocusHandle> for WeakFocusHandle {\n    fn eq(&self, other: &FocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl PartialEq<WeakFocusHandle> for FocusHandle {\n    fn eq(&self, other: &WeakFocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\n/// Focusable allows users of your view to easily\n/// focus it (using window.focus_view(cx, view))\npub trait Focusable: 'static {\n    /// Returns the focus handle associated with this view.\n    fn focus_handle(&self, cx: &App) -> FocusHandle;\n}\n\nimpl<V: Focusable> Focusable for Entity<V> {\n    fn focus_handle(&self, cx: &App) -> FocusHandle {\n        self.read(cx).focus_handle(cx)\n    }\n}\n\n/// ManagedView is a view (like a Modal, Popover, Menu, etc.)\n/// where the lifecycle of the view is handled by another view.\npub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}\n\nimpl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}\n\n/// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal.\npub struct DismissEvent;\n\ntype FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;\n\npub(crate) type AnyMouseListener =\n    Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;\n\n#[derive(Clone)]\npub(crate) struct CursorStyleRequest {\n    pub(crate) hitbox_id: Option<HitboxId>, // None represents whole window\n    pub(crate) style: CursorStyle,\n}\n\n/// An identifier for a [Hitbox].\n#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]\npub struct HitboxId(usize);\n\nimpl HitboxId {\n    /// Checks if the hitbox with this id is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        window.mouse_hit_test.0.contains(self)\n    }\n}\n\n/// A rectangular region that potentially blocks hitboxes inserted prior.\n/// See [Window::insert_hitbox] for more details.\n#[derive(Clone, Debug, Deref)]\npub struct Hitbox {\n    /// A unique identifier for the hitbox.\n    pub id: HitboxId,\n    /// The bounds of the hitbox.\n    #[deref]\n    pub bounds: Bounds<Pixels>,\n    /// The content mask when the hitbox was inserted.\n    pub content_mask: ContentMask<Pixels>,\n    /// Whether the hitbox occludes other hitboxes inserted prior.\n    pub opaque: bool,\n}\n\nimpl Hitbox {\n    /// Checks if the hitbox is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        self.id.is_hovered(window)\n    }\n}\n\n#[derive(Default, Eq, PartialEq)]\npub(crate) struct HitTest(SmallVec<[HitboxId; 8]>);\n\n/// An identifier for a tooltip.\n#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]\npub struct TooltipId(usize);\n\nimpl TooltipId {\n    /// Checks if the tooltip is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        window\n            .tooltip_bounds\n            .as_ref()\n            .map_or(false, |tooltip_bounds| {\n                tooltip_bounds.id == *self\n                    && tooltip_bounds.bounds.contains(&window.mouse_position())\n            })\n    }\n}\n\npub(crate) struct TooltipBounds {\n    id: TooltipId,\n    bounds: Bounds<Pixels>,\n}\n\n#[derive(Clone)]\npub(crate) struct TooltipRequest {\n    id: TooltipId,\n    tooltip: AnyTooltip,\n}\n\npub(crate) struct DeferredDraw {\n    current_view: EntityId,\n    priority: usize,\n    parent_node: DispatchNodeId,\n    element_id_stack: SmallVec<[ElementId; 32]>,\n    text_style_stack: Vec<TextStyleRefinement>,\n    element: Option<AnyElement>,\n    absolute_offset: Point<Pixels>,\n    prepaint_range: Range<PrepaintStateIndex>,\n    paint_range: Range<PaintIndex>,\n}\n\npub(crate) struct Frame {\n    pub(crate) focus: Option<FocusId>,\n    pub(crate) window_active: bool,\n    pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,\n    accessed_element_states: Vec<(GlobalElementId, TypeId)>,\n    pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,\n    pub(crate) dispatch_tree: DispatchTree,\n    pub(crate) scene: Scene,\n    pub(crate) hitboxes: Vec<Hitbox>,\n    pub(crate) deferred_draws: Vec<DeferredDraw>,\n    pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,\n    pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,\n    pub(crate) cursor_styles: Vec<CursorStyleRequest>,\n    #[cfg(any(test, feature = \"test-support\"))]\n    pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,\n}\n\n#[derive(Clone, Default)]\npub(crate) struct PrepaintStateIndex {\n    hitboxes_index: usize,\n    tooltips_index: usize,\n    deferred_draws_index: usize,\n    dispatch_tree_index: usize,\n    accessed_element_states_index: usize,\n    line_layout_index: LineLayoutIndex,\n}\n\n#[derive(Clone, Default)]\npub(crate) struct PaintIndex {\n    scene_index: usize,\n    mouse_listeners_index: usize,\n    input_handlers_index: usize,\n    cursor_styles_index: usize,\n    accessed_element_states_index: usize,\n    line_layout_index: LineLayoutIndex,\n}\n\nimpl Frame {\n    pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {\n        Frame {\n            focus: None,\n            window_active: false,\n            element_states: FxHashMap::default(),\n            accessed_element_states: Vec::new(),\n            mouse_listeners: Vec::new(),\n            dispatch_tree,\n            scene: Scene::default(),\n            hitboxes: Vec::new(),\n            deferred_draws: Vec::new(),\n            input_handlers: Vec::new(),\n            tooltip_requests: Vec::new(),\n            cursor_styles: Vec::new(),\n\n            #[cfg(any(test, feature = \"test-support\"))]\n            debug_bounds: FxHashMap::default(),\n        }\n    }\n\n    pub(crate) fn clear(&mut self) {\n        self.element_states.clear();\n        self.accessed_element_states.clear();\n        self.mouse_listeners.clear();\n        self.dispatch_tree.clear();\n        self.scene.clear();\n        self.input_handlers.clear();\n        self.tooltip_requests.clear();\n        self.cursor_styles.clear();\n        self.hitboxes.clear();\n        self.deferred_draws.clear();\n        self.focus = None;\n    }\n\n    pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {\n        let mut hit_test = HitTest::default();\n        for hitbox in self.hitboxes.iter().rev() {\n            let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds);\n            if bounds.contains(&position) {\n                hit_test.0.push(hitbox.id);\n                if hitbox.opaque {\n                    break;\n                }\n            }\n        }\n        hit_test\n    }\n\n    pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {\n        self.focus\n            .map(|focus_id| self.dispatch_tree.focus_path(focus_id))\n            .unwrap_or_default()\n    }\n\n    pub(crate) fn finish(&mut self, prev_frame: &mut Self) {\n        for element_state_key in &self.accessed_element_states {\n            if let Some((element_state_key, element_state)) =\n                prev_frame.element_states.remove_entry(element_state_key)\n            {\n                self.element_states.insert(element_state_key, element_state);\n            }\n        }\n\n        self.scene.finish();\n    }\n}\n\n/// Holds the state for a specific window.\npub struct Window {\n    pub(crate) handle: AnyWindowHandle,\n    pub(crate) invalidator: WindowInvalidator,\n    pub(crate) removed: bool,\n    pub(crate) platform_window: Box<dyn PlatformWindow>,\n    display_id: Option<DisplayId>,\n    sprite_atlas: Arc<dyn PlatformAtlas>,\n    text_system: Arc<WindowTextSystem>,\n    rem_size: Pixels,\n    /// The stack of override values for the window's rem size.\n    ///\n    /// This is used by `with_rem_size` to allow rendering an element tree with\n    /// a given rem size.\n    rem_size_override_stack: SmallVec<[Pixels; 8]>,\n    pub(crate) viewport_size: Size<Pixels>,\n    layout_engine: Option<TaffyLayoutEngine>,\n    pub(crate) root: Option<AnyView>,\n    pub(crate) element_id_stack: SmallVec<[ElementId; 32]>,\n    pub(crate) text_style_stack: Vec<TextStyleRefinement>,\n    pub(crate) rendered_entity_stack: Vec<EntityId>,\n    pub(crate) element_offset_stack: Vec<Point<Pixels>>,\n    pub(crate) element_opacity: Option<f32>,\n    pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,\n    pub(crate) requested_autoscroll: Option<Bounds<Pixels>>,\n    pub(crate) image_cache_stack: Vec<AnyImageCache>,\n    pub(crate) rendered_frame: Frame,\n    pub(crate) next_frame: Frame,\n    pub(crate) next_hitbox_id: HitboxId,\n    pub(crate) next_tooltip_id: TooltipId,\n    pub(crate) tooltip_bounds: Option<TooltipBounds>,\n    next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,\n    pub(crate) dirty_views: FxHashSet<EntityId>,\n    focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,\n    pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,\n    default_prevented: bool,\n    mouse_position: Point<Pixels>,\n    mouse_hit_test: HitTest,\n    modifiers: Modifiers,\n    scale_factor: f32,\n    pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,\n    appearance: WindowAppearance,\n    pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,\n    active: Rc<Cell<bool>>,\n    hovered: Rc<Cell<bool>>,\n    pub(crate) needs_present: Rc<Cell<bool>>,\n    pub(crate) last_input_timestamp: Rc<Cell<Instant>>,\n    pub(crate) refreshing: bool,\n    pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,\n    pub(crate) focus: Option<FocusId>,\n    focus_enabled: bool,\n    pending_input: Option<PendingInput>,\n    pending_modifier: ModifierState,\n    pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,\n    prompt: Option<RenderablePromptHandle>,\n    pub(crate) client_inset: Option<Pixels>,\n}\n\n#[derive(Clone, Debug, Default)]\nstruct ModifierState {\n    modifiers: Modifiers,\n    saw_keystroke: bool,\n}\n\n#[derive(Clone, Copy, Debug, Eq, PartialEq)]\npub(crate) enum DrawPhase {\n    None,\n    Prepaint,\n    Paint,\n    Focus,\n}\n\n#[derive(Default, Debug)]\nstruct PendingInput {\n    keystrokes: SmallVec<[Keystroke; 1]>,\n    focus: Option<FocusId>,\n    timer: Option<Task<()>>,\n}\n\npub(crate) struct ElementStateBox {\n    pub(crate) inner: Box<dyn Any>,\n    #[cfg(debug_assertions)]\n    pub(crate) type_name: &'static str,\n}\n\nfn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> Bounds<Pixels> {\n    const DEFAULT_WINDOW_OFFSET: Point<Pixels> = point(px(0.), px(35.));\n\n    // TODO, BUG: if you open a window with the currently active window\n    // on the stack, this will erroneously select the 'unwrap_or_else'\n    // code path\n    cx.active_window()\n        .and_then(|w| w.update(cx, |_, window, _| window.bounds()).ok())\n        .map(|mut bounds| {\n            bounds.origin += DEFAULT_WINDOW_OFFSET;\n            bounds\n        })\n        .unwrap_or_else(|| {\n            let display = display_id\n                .map(|id| cx.find_display(id))\n                .unwrap_or_else(|| cx.primary_display());\n\n            display\n                .map(|display| display.default_bounds())\n                .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE))\n        })\n}\n\nimpl Window {\n    pub(crate) fn new(\n        handle: AnyWindowHandle,\n        options: WindowOptions,\n        cx: &mut App,\n    ) -> Result<Self> {\n        let WindowOptions {\n            window_bounds,\n            titlebar,\n            focus,\n            show,\n            kind,\n            is_movable,\n            display_id,\n            window_background,\n            app_id,\n            window_min_size,\n            window_decorations,\n        } = options;\n\n        let bounds = window_bounds\n            .map(|bounds| bounds.get_bounds())\n            .unwrap_or_else(|| default_bounds(display_id, cx));\n        let mut platform_window = cx.platform.open_window(\n            handle,\n            WindowParams {\n                bounds,\n                titlebar,\n                kind,\n                is_movable,\n                focus,\n                show,\n                display_id,\n                window_min_size,\n            },\n        )?;\n        let display_id = platform_window.display().map(|display| display.id());\n        let sprite_atlas = platform_window.sprite_atlas();\n        let mouse_position = platform_window.mouse_position();\n        let modifiers = platform_window.modifiers();\n        let content_size = platform_window.content_size();\n        let scale_factor = platform_window.scale_factor();\n        let appearance = platform_window.appearance();\n        let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));\n        let invalidator = WindowInvalidator::new();\n        let active = Rc::new(Cell::new(platform_window.is_active()));\n        let hovered = Rc::new(Cell::new(platform_window.is_hovered()));\n        let needs_present = Rc::new(Cell::new(false));\n        let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();\n        let last_input_timestamp = Rc::new(Cell::new(Instant::now()));\n\n        platform_window\n            .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server));\n        platform_window.set_background_appearance(window_background);\n\n        if let Some(ref window_open_state) = window_bounds {\n            match window_open_state {\n                WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),\n                WindowBounds::Maximized(_) => platform_window.zoom(),\n                WindowBounds::Windowed(_) => {}\n            }\n        }\n\n        platform_window.on_close(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                let _ = handle.update(&mut cx, |_, window, _| window.remove_window());\n            }\n        }));\n        platform_window.on_request_frame(Box::new({\n            let mut cx = cx.to_async();\n            let invalidator = invalidator.clone();\n            let active = active.clone();\n            let needs_present = needs_present.clone();\n            let next_frame_callbacks = next_frame_callbacks.clone();\n            let last_input_timestamp = last_input_timestamp.clone();\n            move |request_frame_options| {\n                let next_frame_callbacks = next_frame_callbacks.take();\n                if !next_frame_callbacks.is_empty() {\n                    handle\n                        .update(&mut cx, |_, window, cx| {\n                            for callback in next_frame_callbacks {\n                                callback(window, cx);\n                            }\n                        })\n                        .log_err();\n                }\n\n                // Keep presenting the current scene for 1 extra second since the\n                // last input to prevent the display from underclocking the refresh rate.\n                let needs_present = request_frame_options.require_presentation\n                    || needs_present.get()\n                    || (active.get()\n                        && last_input_timestamp.get().elapsed() < Duration::from_secs(1));\n\n                if invalidator.is_dirty() {\n                    measure(\"frame duration\", || {\n                        handle\n                            .update(&mut cx, |_, window, cx| {\n                                window.draw(cx);\n                                window.present();\n                            })\n                            .log_err();\n                    })\n                } else if needs_present {\n                    handle\n                        .update(&mut cx, |_, window, _| window.present())\n                        .log_err();\n                }\n\n                handle\n                    .update(&mut cx, |_, window, _| {\n                        window.complete_frame();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_resize(Box::new({\n            let mut cx = cx.to_async();\n            move |_, _| {\n                handle\n                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_moved(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                handle\n                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_appearance_changed(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                handle\n                    .update(&mut cx, |_, window, cx| window.appearance_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_active_status_change(Box::new({\n            let mut cx = cx.to_async();\n            move |active| {\n                handle\n                    .update(&mut cx, |_, window, cx| {\n                        window.active.set(active);\n                        window.modifiers = window.platform_window.modifiers();\n                        window\n                            .activation_observers\n                            .clone()\n                            .retain(&(), |callback| callback(window, cx));\n                        window.refresh();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_hover_status_change(Box::new({\n            let mut cx = cx.to_async();\n            move |active| {\n                handle\n                    .update(&mut cx, |_, window, _| {\n                        window.hovered.set(active);\n                        window.refresh();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_input({\n            let mut cx = cx.to_async();\n            Box::new(move |event| {\n                handle\n                    .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))\n                    .log_err()\n                    .unwrap_or(DispatchEventResult::default())\n            })\n        });\n\n        if let Some(app_id) = app_id {\n            platform_window.set_app_id(&app_id);\n        }\n\n        platform_window.map_window().unwrap();\n\n        Ok(Window {\n            handle,\n            invalidator,\n            removed: false,\n            platform_window,\n            display_id,\n            sprite_atlas,\n            text_system,\n            rem_size: px(16.),\n            rem_size_override_stack: SmallVec::new(),\n            viewport_size: content_size,\n            layout_engine: Some(TaffyLayoutEngine::new()),\n            root: None,\n            element_id_stack: SmallVec::default(),\n            text_style_stack: Vec::new(),\n            rendered_entity_stack: Vec::new(),\n            element_offset_stack: Vec::new(),\n            content_mask_stack: Vec::new(),\n            element_opacity: None,\n            requested_autoscroll: None,\n            rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),\n            next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),\n            next_frame_callbacks,\n            next_hitbox_id: HitboxId::default(),\n            next_tooltip_id: TooltipId::default(),\n            tooltip_bounds: None,\n            dirty_views: FxHashSet::default(),\n            focus_listeners: SubscriberSet::new(),\n            focus_lost_listeners: SubscriberSet::new(),\n            default_prevented: true,\n            mouse_position,\n            mouse_hit_test: HitTest::default(),\n            modifiers,\n            scale_factor,\n            bounds_observers: SubscriberSet::new(),\n            appearance,\n            appearance_observers: SubscriberSet::new(),\n            active,\n            hovered,\n            needs_present,\n            last_input_timestamp,\n            refreshing: false,\n            activation_observers: SubscriberSet::new(),\n            focus: None,\n            focus_enabled: true,\n            pending_input: None,\n            pending_modifier: ModifierState::default(),\n            pending_input_observers: SubscriberSet::new(),\n            prompt: None,\n            client_inset: None,\n            image_cache_stack: Vec::new(),\n        })\n    }\n\n    pub(crate) fn new_focus_listener(\n        &self,\n        value: AnyWindowFocusListener,\n    ) -> (Subscription, impl FnOnce() + use<>) {\n        self.focus_listeners.insert((), value)\n    }\n}\n\n#[derive(Clone, Debug, Default, PartialEq, Eq)]\npub(crate) struct DispatchEventResult {\n    pub propagate: bool,\n    pub default_prevented: bool,\n}\n\n/// Indicates which region of the window is visible. Content falling outside of this mask will not be\n/// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type\n/// to leave room to support more complex shapes in the future.\n#[derive(Clone, Debug, Default, PartialEq, Eq)]\n#[repr(C)]\npub struct ContentMask<P: Clone + Default + Debug> {\n    /// The bounds\n    pub bounds: Bounds<P>,\n}\n\nimpl ContentMask<Pixels> {\n    /// Scale the content mask's pixel units by the given scaling factor.\n    pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {\n        ContentMask {\n            bounds: self.bounds.scale(factor),\n        }\n    }\n\n    /// Intersect the content mask with the given content mask.\n    pub fn intersect(&self, other: &Self) -> Self {\n        let bounds = self.bounds.intersect(&other.bounds);\n        ContentMask { bounds }\n    }\n}\n\nimpl Window {\n    fn mark_view_dirty(&mut self, view_id: EntityId) {\n        // Mark ancestor views as dirty. If already in the `dirty_views` set, then all its ancestors\n        // should already be dirty.\n        for view_id in self\n            .rendered_frame\n            .dispatch_tree\n            .view_path(view_id)\n            .into_iter()\n            .rev()\n        {\n            if !self.dirty_views.insert(view_id) {\n                break;\n            }\n        }\n    }\n\n    /// Registers a callback to be invoked when the window appearance changes.\n    pub fn observe_window_appearance(\n        &self,\n        mut callback: impl FnMut(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let (subscription, activate) = self.appearance_observers.insert(\n            (),\n            Box::new(move |window, cx| {\n                callback(window, cx);\n                true\n            }),\n        );\n        activate();\n        subscription\n    }\n\n    /// Replaces the root entity of the window with a new one.\n    pub fn replace_root<E>(\n        &mut self,\n        cx: &mut App,\n        build_view: impl FnOnce(&mut Window, &mut Context<E>) -> E,\n    ) -> Entity<E>\n    where\n        E: 'static + Render,\n    {\n        let view = cx.new(|cx| build_view(self, cx));\n        self.root = Some(view.clone().into());\n        self.refresh();\n        view\n    }\n\n    /// Returns the root entity of the window, if it has one.\n    pub fn root<E>(&self) -> Option<Option<Entity<E>>>\n    where\n        E: 'static + Render,\n    {\n        self.root\n            .as_ref()\n            .map(|view| view.clone().downcast::<E>().ok())\n    }\n\n    /// Obtain a handle to the window that belongs to this context.\n    pub fn window_handle(&self) -> AnyWindowHandle {\n        self.handle\n    }\n\n    /// Mark the window as dirty, scheduling it to be redrawn on the next frame.\n    pub fn refresh(&mut self) {\n        if self.invalidator.not_drawing() {\n            self.refreshing = true;\n            self.invalidator.set_dirty(true);\n        }\n    }\n\n    /// Close this window.\n    pub fn remove_window(&mut self) {\n        self.removed = true;\n    }\n\n    /// Obtain the currently focused [`FocusHandle`]. If no elements are focused, returns `None`.\n    pub fn focused(&self, cx: &App) -> Option<FocusHandle> {\n        self.focus\n            .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))\n    }\n\n    /// Move focus to the element associated with the given [`FocusHandle`].\n    pub fn focus(&mut self, handle: &FocusHandle) {\n        if !self.focus_enabled || self.focus == Some(handle.id) {\n            return;\n        }\n\n        self.focus = Some(handle.id);\n        self.clear_pending_keystrokes();\n        self.refresh();\n    }\n\n    /// Remove focus from all elements within this context's window.\n    pub fn blur(&mut self) {\n        if !self.focus_enabled {\n            return;\n        }\n\n        self.focus = None;\n        self.refresh();\n    }\n\n    /// Blur the window and don't allow anything in it to be focused again.\n    pub fn disable_focus(&mut self) {\n        self.blur();\n        self.focus_enabled = false;\n    }\n\n    /// Accessor for the text system.\n    pub fn text_system(&self) -> &Arc<WindowTextSystem> {\n        &self.text_system\n    }\n\n    /// The current text style. Which is composed of all the style refinements provided to `with_text_style`.\n    pub fn text_style(&self) -> TextStyle {\n        let mut style = TextStyle::default();\n        for refinement in &self.text_style_stack {\n            style.refine(refinement);\n        }\n        style\n    }\n\n    /// Check if the platform window is maximized\n    /// On some platforms (namely Windows) this is different than the bounds being the size of the display\n    pub fn is_maximized(&self) -> bool {\n        self.platform_window.is_maximized()\n    }\n\n    /// request a certain window decoration (Wayland)\n    pub fn request_decorations(&self, decorations: WindowDecorations) {\n        self.platform_window.request_decorations(decorations);\n    }\n\n    /// Start a window resize operation (Wayland)\n    pub fn start_window_resize(&self, edge: ResizeEdge) {\n        self.platform_window.start_window_resize(edge);\n    }\n\n    /// Return the `WindowBounds` to indicate that how a window should be opened\n    /// after it has been closed\n    pub fn window_bounds(&self) -> WindowBounds {\n        self.platform_window.window_bounds()\n    }\n\n    /// Return the `WindowBounds` excluding insets (Wayland and X11)\n    pub fn inner_window_bounds(&self) -> WindowBounds {\n        self.platform_window.inner_window_bounds()\n    }\n\n    /// Dispatch the given action on the currently focused element.\n    pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {\n        let focus_handle = self.focused(cx);\n\n        let window = self.handle;\n        cx.defer(move |cx| {\n            window\n                .update(cx, |_, window, cx| {\n                    let node_id = focus_handle\n                        .and_then(|handle| {\n                            window\n                                .rendered_frame\n                                .dispatch_tree\n                                .focusable_node_id(handle.id)\n                        })\n                        .unwrap_or_else(|| window.rendered_frame.dispatch_tree.root_node_id());\n\n                    window.dispatch_action_on_node(node_id, action.as_ref(), cx);\n                })\n                .log_err();\n        })\n    }\n\n    pub(crate) fn dispatch_keystroke_observers(\n        &mut self,\n        event: &dyn Any,\n        action: Option<Box<dyn Action>>,\n        context_stack: Vec<KeyContext>,\n        cx: &mut App,\n    ) {\n        let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {\n            return;\n        };\n\n        cx.keystroke_observers.clone().retain(&(), move |callback| {\n            (callback)(\n                &KeystrokeEvent {\n                    keystroke: key_down_event.keystroke.clone(),\n                    action: action.as_ref().map(|action| action.boxed_clone()),\n                    context_stack: context_stack.clone(),\n                },\n                self,\n                cx,\n            )\n        });\n    }\n\n    /// Schedules the given function to be run at the end of the current effect cycle, allowing entities\n    /// that are currently on the stack to be returned to the app.\n    pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {\n        let handle = self.handle;\n        cx.defer(move |cx| {\n            handle.update(cx, |_, window, cx| f(window, cx)).ok();\n        });\n    }\n\n    /// Subscribe to events emitted by a entity.\n    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.\n    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.\n    pub fn observe<T: 'static>(\n        &mut self,\n        observed: &Entity<T>,\n        cx: &mut App,\n        mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let entity_id = observed.entity_id();\n        let observed = observed.downgrade();\n        let window_handle = self.handle;\n        cx.new_observer(\n            entity_id,\n            Box::new(move |cx| {\n                window_handle\n                    .update(cx, |_, window, cx| {\n                        if let Some(handle) = observed.upgrade() {\n                            on_notify(handle, window, cx);\n                            true\n                        } else {\n                            false\n                        }\n                    })\n                    .unwrap_or(false)\n            }),\n        )\n    }\n\n    /// Subscribe to events emitted by a entity.\n    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.\n    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.\n    pub fn subscribe<Emitter, Evt>(\n        &mut self,\n        entity: &Entity<Emitter>,\n        cx: &mut App,\n        mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,\n    ) -> Subscription\n    where\n        Emitter: EventEmitter<Evt>,\n        Evt: 'static,\n    {\n        let entity_id = entity.entity_id();\n        let handle = entity.downgrade();\n        let window_handle = self.handle;\n        cx.new_subscription(\n            entity_id,\n            (\n                TypeId::of::<Evt>(),\n                Box::new(move |event, cx| {\n                    window_handle\n                        .update(cx, |_, window, cx| {\n                            if let Some(entity) = handle.upgrade() {\n                                let event = event.downcast_ref().expect(\"invalid event type\");\n                                on_event(entity, event, window, cx);\n                                true\n                            } else {\n                                false\n                            }\n                        })\n                        .unwrap_or(false)\n                }),\n            ),\n        )\n    }\n\n    /// Register a callback to be invoked when the given `Entity` is released.\n    pub fn observe_release<T>(\n        &self,\n        entity: &Entity<T>,\n        cx: &mut App,\n        mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,\n    ) -> Subscription\n    where\n        T: 'static,\n    {\n        let entity_id = entity.entity_id();\n        let window_handle = self.handle;\n        let (subscription, activate) = cx.release_listeners.insert(\n            entity_id,\n            Box::new(move |entity, cx| {\n                let entity = entity.downcast_mut().expect(\"invalid entity type\");\n                let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));\n            }),\n        );\n        activate();\n        subscription\n    }\n\n    /// Creates an [`AsyncWindowContext`], which has a static lifetime and can be held across\n    /// await points in async code.\n    pub fn to_async(&self, cx: &App) -> AsyncWindowContext {\n        AsyncWindowContext::new_context(cx.to_async(), self.handle)\n    }\n\n    /// Schedule the given closure to be run directly after the current frame is rendered.\n    pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) {\n        RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback));\n    }\n\n    /// Schedule a frame to be drawn on the next animation frame.\n    ///\n    /// This is useful for elements that need to animate continuously, such as a video player or an animated GIF.\n    /// It will cause the window to redraw on the next frame, even if no other changes have occurred.\n    ///\n    /// If called from within a view, it will notify that view on the next frame. Otherwise, it will refresh the entire window.\n    pub fn request_animation_frame(&self) {\n        let entity = self.current_view();\n        self.on_next_frame(move |_, cx| cx.notify(entity));\n    }\n\n    /// Spawn the future returned by the given closure on the application thread pool.\n    /// The closure is provided a handle to the current window and an `AsyncWindowContext` for\n    /// use within your future.\n    #[track_caller]\n    pub fn spawn<AsyncFn, R>(&self, cx: &App, f: AsyncFn) -> Task<R>\n    where\n        R: 'static,\n        AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,\n    {\n        let handle = self.handle;\n        cx.spawn(async move |app| {\n            let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);\n            f(&mut async_window_cx).await\n        })\n    }\n\n    fn bounds_changed(&mut self, cx: &mut App) {\n        self.scale_factor = self.platform_window.scale_factor();\n        self.viewport_size = self.platform_window.content_size();\n        self.display_id = self.platform_window.display().map(|display| display.id());\n\n        self.refresh();\n\n        self.bounds_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    /// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays.\n    pub fn bounds(&self) -> Bounds<Pixels> {\n        self.platform_window.bounds()\n    }\n\n    /// Set the content size of the window.\n    pub fn resize(&mut self, size: Size<Pixels>) {\n        self.platform_window.resize(size);\n    }\n\n    /// Returns whether or not the window is currently fullscreen\n    pub fn is_fullscreen(&self) -> bool {\n        self.platform_window.is_fullscreen()\n    }\n\n    pub(crate) fn appearance_changed(&mut self, cx: &mut App) {\n        self.appearance = self.platform_window.appearance();\n\n        self.appearance_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    /// Returns the appearance of the current window.\n    pub fn appearance(&self) -> WindowAppearance {\n        self.appearance\n    }\n\n    /// Returns the size of the drawable area within the window.\n    pub fn viewport_size(&self) -> Size<Pixels> {\n        self.viewport_size\n    }\n\n    /// Returns whether this window is focused by the operating system (receiving key events).\n    pub fn is_window_active(&self) -> bool {\n        self.active.get()\n    }\n\n    /// Returns whether this window is considered to be the window\n    /// that currently owns the mouse cursor.\n    /// On mac, this is equivalent to `is_window_active`.\n    pub fn is_window_hovered(&self) -> bool {\n        if cfg!(any(\n            target_os = \"windows\",\n            target_os = \"linux\",\n            target_os = \"freebsd\"\n        )) {\n            self.hovered.get()\n        } else {\n            self.is_window_active()\n        }\n    }\n\n    /// Toggle zoom on the window.\n    pub fn zoom_window(&self) {\n        self.platform_window.zoom();\n    }\n\n    /// Opens the native title bar context menu, useful when implementing client side decorations (Wayland and X11)\n    pub fn show_window_menu(&self, position: Point<Pixels>) {\n        self.platform_window.show_window_menu(position)\n    }\n\n    /// Tells the compositor to take control of window movement (Wayland and X11)\n    ///\n    /// Events may not be received during a move operation.\n    pub fn start_window_move(&self) {\n        self.platform_window.start_window_move()\n    }\n\n    /// When using client side decorations, set this to the width of the invisible decorations (Wayland and X11)\n    pub fn set_client_inset(&mut self, inset: Pixels) {\n        self.client_inset = Some(inset);\n        self.platform_window.set_client_inset(inset);\n    }\n\n    /// Returns the client_inset value by [`Self::set_client_inset`].\n    pub fn client_inset(&self) -> Option<Pixels> {\n        self.client_inset\n    }\n\n    /// Returns whether the title bar window controls need to be rendered by the application (Wayland and X11)\n    pub fn window_decorations(&self) -> Decorations {\n        self.platform_window.window_decorations()\n    }\n\n    /// Returns which window controls are currently visible (Wayland)\n    pub fn window_controls(&self) -> WindowControls {\n        self.platform_window.window_controls()\n    }\n\n    /// Updates the window's title at the platform level.\n    pub fn set_window_title(&mut self, title: &str) {\n        self.platform_window.set_title(title);\n    }\n\n    /// Sets the application identifier.\n    pub fn set_app_id(&mut self, app_id: &str) {\n        self.platform_window.set_app_id(app_id);\n    }\n\n    /// Sets the window background appearance.\n    pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {\n        self.platform_window\n            .set_background_appearance(background_appearance);\n    }\n\n    /// Mark the window as dirty at the platform level.\n    pub fn set_window_edited(&mut self, edited: bool) {\n        self.platform_window.set_edited(edited);\n    }\n\n    /// Determine the display on which the window is visible.\n    pub fn display(&self, cx: &App) -> Option<Rc<dyn PlatformDisplay>> {\n        cx.platform\n            .displays()\n            .into_iter()\n            .find(|display| Some(display.id()) == self.display_id)\n    }\n\n    /// Show the platform character palette.\n    pub fn show_character_palette(&self) {\n        self.platform_window.show_character_palette();\n    }\n\n    /// The scale factor of the display associated with the window. For example, it could\n    /// return 2.0 for a \"retina\" display, indicating that each logical pixel should actually\n    /// be rendered as two pixels on screen.\n    pub fn scale_factor(&self) -> f32 {\n        self.scale_factor\n    }\n\n    /// The size of an em for the base font of the application. Adjusting this value allows the\n    /// UI to scale, just like zooming a web page.\n    pub fn rem_size(&self) -> Pixels {\n        self.rem_size_override_stack\n            .last()\n            .copied()\n            .unwrap_or(self.rem_size)\n    }\n\n    /// Sets the size of an em for the base font of the application. Adjusting this value allows the\n    /// UI to scale, just like zooming a web page.\n    pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {\n        self.rem_size = rem_size.into();\n    }\n\n    /// Acquire a globally unique identifier for the given ElementId.\n    /// Only valid for the duration of the provided closure.\n    pub fn with_global_id<R>(\n        &mut self,\n        element_id: ElementId,\n        f: impl FnOnce(&GlobalElementId, &mut Self) -> R,\n    ) -> R {\n        self.element_id_stack.push(element_id);\n        let global_id = GlobalElementId(self.element_id_stack.clone());\n        let result = f(&global_id, self);\n        self.element_id_stack.pop();\n        result\n    }\n\n    /// Executes the provided function with the specified rem size.\n    ///\n    /// This method must only be called as part of element drawing.\n    pub fn with_rem_size<F, R>(&mut self, rem_size: Option<impl Into<Pixels>>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        if let Some(rem_size) = rem_size {\n            self.rem_size_override_stack.push(rem_size.into());\n            let result = f(self);\n            self.rem_size_override_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// The line height associated with the current text style.\n    pub fn line_height(&self) -> Pixels {\n        self.text_style().line_height_in_pixels(self.rem_size())\n    }\n\n    /// Call to prevent the default action of an event. Currently only used to prevent\n    /// parent elements from becoming focused on mouse down.\n    pub fn prevent_default(&mut self) {\n        self.default_prevented = true;\n    }\n\n    /// Obtain whether default has been prevented for the event currently being dispatched.\n    pub fn default_prevented(&self) -> bool {\n        self.default_prevented\n    }\n\n    /// Determine whether the given action is available along the dispatch path to the currently focused element.\n    pub fn is_action_available(&self, action: &dyn Action, cx: &mut App) -> bool {\n        let target = self\n            .focused(cx)\n            .and_then(|focused_handle| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focused_handle.id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n        self.rendered_frame\n            .dispatch_tree\n            .is_action_available(action, target)\n    }\n\n    /// The position of the mouse relative to the window.\n    pub fn mouse_position(&self) -> Point<Pixels> {\n        self.mouse_position\n    }\n\n    /// The current state of the keyboard's modifiers\n    pub fn modifiers(&self) -> Modifiers {\n        self.modifiers\n    }\n\n    fn complete_frame(&self) {\n        self.platform_window.completed_frame();\n    }\n\n    /// Produces a new frame and assigns it to `rendered_frame`. To actually show\n    /// the contents of the new [Scene], use [present].\n    #[profiling::function]\n    pub fn draw(&mut self, cx: &mut App) {\n        self.invalidate_entities();\n        cx.entities.clear_accessed();\n        debug_assert!(self.rendered_entity_stack.is_empty());\n        self.invalidator.set_dirty(false);\n        self.requested_autoscroll = None;\n\n        // Restore the previously-used input handler.\n        if let Some(input_handler) = self.platform_window.take_input_handler() {\n            self.rendered_frame.input_handlers.push(Some(input_handler));\n        }\n        self.draw_roots(cx);\n        self.dirty_views.clear();\n        self.next_frame.window_active = self.active.get();\n\n        // Register requested input handler with the platform window.\n        if let Some(input_handler) = self.next_frame.input_handlers.pop() {\n            self.platform_window\n                .set_input_handler(input_handler.unwrap());\n        }\n\n        self.layout_engine.as_mut().unwrap().clear();\n        self.text_system().finish_frame();\n        self.next_frame.finish(&mut self.rendered_frame);\n        ELEMENT_ARENA.with_borrow_mut(|element_arena| {\n            let percentage = (element_arena.len() as f32 / element_arena.capacity() as f32) * 100.;\n            if percentage >= 80. {\n                log::warn!(\"elevated element arena occupation: {}.\", percentage);\n            }\n            element_arena.clear();\n        });\n\n        self.invalidator.set_phase(DrawPhase::Focus);\n        let previous_focus_path = self.rendered_frame.focus_path();\n        let previous_window_active = self.rendered_frame.window_active;\n        mem::swap(&mut self.rendered_frame, &mut self.next_frame);\n        self.next_frame.clear();\n        let current_focus_path = self.rendered_frame.focus_path();\n        let current_window_active = self.rendered_frame.window_active;\n\n        if previous_focus_path != current_focus_path\n            || previous_window_active != current_window_active\n        {\n            if !previous_focus_path.is_empty() && current_focus_path.is_empty() {\n                self.focus_lost_listeners\n                    .clone()\n                    .retain(&(), |listener| listener(self, cx));\n            }\n\n            let event = WindowFocusEvent {\n                previous_focus_path: if previous_window_active {\n                    previous_focus_path\n                } else {\n                    Default::default()\n                },\n                current_focus_path: if current_window_active {\n                    current_focus_path\n                } else {\n                    Default::default()\n                },\n            };\n            self.focus_listeners\n                .clone()\n                .retain(&(), |listener| listener(&event, self, cx));\n        }\n\n        debug_assert!(self.rendered_entity_stack.is_empty());\n        self.record_entities_accessed(cx);\n        self.reset_cursor_style(cx);\n        self.refreshing = false;\n        self.invalidator.set_phase(DrawPhase::None);\n        self.needs_present.set(true);\n    }\n\n    fn record_entities_accessed(&mut self, cx: &mut App) {\n        let mut entities_ref = cx.entities.accessed_entities.borrow_mut();\n        let mut entities = mem::take(entities_ref.deref_mut());\n        drop(entities_ref);\n        let handle = self.handle;\n        cx.record_entities_accessed(\n            handle,\n            // Try moving window invalidator into the Window\n            self.invalidator.clone(),\n            &entities,\n        );\n        let mut entities_ref = cx.entities.accessed_entities.borrow_mut();\n        mem::swap(&mut entities, entities_ref.deref_mut());\n    }\n\n    fn invalidate_entities(&mut self) {\n        let mut views = self.invalidator.take_views();\n        for entity in views.drain() {\n            self.mark_view_dirty(entity);\n        }\n        self.invalidator.replace_views(views);\n    }\n\n    #[profiling::function]\n    fn present(&self) {\n        self.platform_window.draw(&self.rendered_frame.scene);\n        self.needs_present.set(false);\n        profiling::finish_frame!();\n    }\n\n    fn draw_roots(&mut self, cx: &mut App) {\n        self.invalidator.set_phase(DrawPhase::Prepaint);\n        self.tooltip_bounds.take();\n\n        // Layout all root elements.\n        let mut root_element = self.root.as_ref().unwrap().clone().into_any();\n        root_element.prepaint_as_root(Point::default(), self.viewport_size.into(), self, cx);\n\n        let mut sorted_deferred_draws =\n            (0..self.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>();\n        sorted_deferred_draws.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);\n        self.prepaint_deferred_draws(&sorted_deferred_draws, cx);\n\n        let mut prompt_element = None;\n        let mut active_drag_element = None;\n        let mut tooltip_element = None;\n        if let Some(prompt) = self.prompt.take() {\n            let mut element = prompt.view.any_view().into_any();\n            element.prepaint_as_root(Point::default(), self.viewport_size.into(), self, cx);\n            prompt_element = Some(element);\n            self.prompt = Some(prompt);\n        } else if let Some(active_drag) = cx.active_drag.take() {\n            let mut element = active_drag.view.clone().into_any();\n            let offset = self.mouse_position() - active_drag.cursor_offset;\n            element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx);\n            active_drag_element = Some(element);\n            cx.active_drag = Some(active_drag);\n        } else {\n            tooltip_element = self.prepaint_tooltip(cx);\n        }\n\n        self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position);\n\n        // Now actually paint the elements.\n        self.invalidator.set_phase(DrawPhase::Paint);\n        root_element.paint(self, cx);\n\n        self.paint_deferred_draws(&sorted_deferred_draws, cx);\n\n        if let Some(mut prompt_element) = prompt_element {\n            prompt_element.paint(self, cx);\n        } else if let Some(mut drag_element) = active_drag_element {\n            drag_element.paint(self, cx);\n        } else if let Some(mut tooltip_element) = tooltip_element {\n            tooltip_element.paint(self, cx);\n        }\n    }\n\n    fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {\n        // Use indexing instead of iteration to avoid borrowing self for the duration of the loop.\n        for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() {\n            let Some(Some(tooltip_request)) = self\n                .next_frame\n                .tooltip_requests\n                .get(tooltip_request_index)\n                .cloned()\n            else {\n                log::error!(\"Unexpectedly absent TooltipRequest\");\n                continue;\n            };\n            let mut element = tooltip_request.tooltip.view.clone().into_any();\n            let mouse_position = tooltip_request.tooltip.mouse_position;\n            let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);\n\n            let mut tooltip_bounds =\n                Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);\n            let window_bounds = Bounds {\n                origin: Point::default(),\n                size: self.viewport_size(),\n            };\n\n            if tooltip_bounds.right() > window_bounds.right() {\n                let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);\n                if new_x >= Pixels::ZERO {\n                    tooltip_bounds.origin.x = new_x;\n                } else {\n                    tooltip_bounds.origin.x = cmp::max(\n                        Pixels::ZERO,\n                        tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),\n                    );\n                }\n            }\n\n            if tooltip_bounds.bottom() > window_bounds.bottom() {\n                let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);\n                if new_y >= Pixels::ZERO {\n                    tooltip_bounds.origin.y = new_y;\n                } else {\n                    tooltip_bounds.origin.y = cmp::max(\n                        Pixels::ZERO,\n                        tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),\n                    );\n                }\n            }\n\n            // It's possible for an element to have an active tooltip while not being painted (e.g.\n            // via the `visible_on_hover` method). Since mouse listeners are not active in this\n            // case, instead update the tooltip's visibility here.\n            let is_visible =\n                (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);\n            if !is_visible {\n                continue;\n            }\n\n            self.with_absolute_element_offset(tooltip_bounds.origin, |window| {\n                element.prepaint(window, cx)\n            });\n\n            self.tooltip_bounds = Some(TooltipBounds {\n                id: tooltip_request.id,\n                bounds: tooltip_bounds,\n            });\n            return Some(element);\n        }\n        None\n    }\n\n    fn prepaint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {\n        assert_eq!(self.element_id_stack.len(), 0);\n\n        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);\n        for deferred_draw_ix in deferred_draw_indices {\n            let deferred_draw = &mut deferred_draws[*deferred_draw_ix];\n            self.element_id_stack\n                .clone_from(&deferred_draw.element_id_stack);\n            self.text_style_stack\n                .clone_from(&deferred_draw.text_style_stack);\n            self.next_frame\n                .dispatch_tree\n                .set_active_node(deferred_draw.parent_node);\n\n            let prepaint_start = self.prepaint_index();\n            if let Some(element) = deferred_draw.element.as_mut() {\n                self.with_rendered_view(deferred_draw.current_view, |window| {\n                    window.with_absolute_element_offset(deferred_draw.absolute_offset, |window| {\n                        element.prepaint(window, cx)\n                    });\n                })\n            } else {\n                self.reuse_prepaint(deferred_draw.prepaint_range.clone());\n            }\n            let prepaint_end = self.prepaint_index();\n            deferred_draw.prepaint_range = prepaint_start..prepaint_end;\n        }\n        assert_eq!(\n            self.next_frame.deferred_draws.len(),\n            0,\n            \"cannot call defer_draw during deferred drawing\"\n        );\n        self.next_frame.deferred_draws = deferred_draws;\n        self.element_id_stack.clear();\n        self.text_style_stack.clear();\n    }\n\n    fn paint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {\n        assert_eq!(self.element_id_stack.len(), 0);\n\n        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);\n        for deferred_draw_ix in deferred_draw_indices {\n            let mut deferred_draw = &mut deferred_draws[*deferred_draw_ix];\n            self.element_id_stack\n                .clone_from(&deferred_draw.element_id_stack);\n            self.next_frame\n                .dispatch_tree\n                .set_active_node(deferred_draw.parent_node);\n\n            let paint_start = self.paint_index();\n            if let Some(element) = deferred_draw.element.as_mut() {\n                self.with_rendered_view(deferred_draw.current_view, |window| {\n                    element.paint(window, cx);\n                })\n            } else {\n                self.reuse_paint(deferred_draw.paint_range.clone());\n            }\n            let paint_end = self.paint_index();\n            deferred_draw.paint_range = paint_start..paint_end;\n        }\n        self.next_frame.deferred_draws = deferred_draws;\n        self.element_id_stack.clear();\n    }\n\n    pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {\n        PrepaintStateIndex {\n            hitboxes_index: self.next_frame.hitboxes.len(),\n            tooltips_index: self.next_frame.tooltip_requests.len(),\n            deferred_draws_index: self.next_frame.deferred_draws.len(),\n            dispatch_tree_index: self.next_frame.dispatch_tree.len(),\n            accessed_element_states_index: self.next_frame.accessed_element_states.len(),\n            line_layout_index: self.text_system.layout_index(),\n        }\n    }\n\n    pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {\n        self.next_frame.hitboxes.extend(\n            self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]\n                .iter()\n                .cloned(),\n        );\n        self.next_frame.tooltip_requests.extend(\n            self.rendered_frame.tooltip_requests\n                [range.start.tooltips_index..range.end.tooltips_index]\n                .iter_mut()\n                .map(|request| request.take()),\n        );\n        self.next_frame.accessed_element_states.extend(\n            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index\n                ..range.end.accessed_element_states_index]\n                .iter()\n                .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),\n        );\n        self.text_system\n            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);\n\n        let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree(\n            range.start.dispatch_tree_index..range.end.dispatch_tree_index,\n            &mut self.rendered_frame.dispatch_tree,\n            self.focus,\n        );\n\n        if reused_subtree.contains_focus() {\n            self.next_frame.focus = self.focus;\n        }\n\n        self.next_frame.deferred_draws.extend(\n            self.rendered_frame.deferred_draws\n                [range.start.deferred_draws_index..range.end.deferred_draws_index]\n                .iter()\n                .map(|deferred_draw| DeferredDraw {\n                    current_view: deferred_draw.current_view,\n                    parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),\n                    element_id_stack: deferred_draw.element_id_stack.clone(),\n                    text_style_stack: deferred_draw.text_style_stack.clone(),\n                    priority: deferred_draw.priority,\n                    element: None,\n                    absolute_offset: deferred_draw.absolute_offset,\n                    prepaint_range: deferred_draw.prepaint_range.clone(),\n                    paint_range: deferred_draw.paint_range.clone(),\n                }),\n        );\n    }\n\n    pub(crate) fn paint_index(&self) -> PaintIndex {\n        PaintIndex {\n            scene_index: self.next_frame.scene.len(),\n            mouse_listeners_index: self.next_frame.mouse_listeners.len(),\n            input_handlers_index: self.next_frame.input_handlers.len(),\n            cursor_styles_index: self.next_frame.cursor_styles.len(),\n            accessed_element_states_index: self.next_frame.accessed_element_states.len(),\n            line_layout_index: self.text_system.layout_index(),\n        }\n    }\n\n    pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {\n        self.next_frame.cursor_styles.extend(\n            self.rendered_frame.cursor_styles\n                [range.start.cursor_styles_index..range.end.cursor_styles_index]\n                .iter()\n                .cloned(),\n        );\n        self.next_frame.input_handlers.extend(\n            self.rendered_frame.input_handlers\n                [range.start.input_handlers_index..range.end.input_handlers_index]\n                .iter_mut()\n                .map(|handler| handler.take()),\n        );\n        self.next_frame.mouse_listeners.extend(\n            self.rendered_frame.mouse_listeners\n                [range.start.mouse_listeners_index..range.end.mouse_listeners_index]\n                .iter_mut()\n                .map(|listener| listener.take()),\n        );\n        self.next_frame.accessed_element_states.extend(\n            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index\n                ..range.end.accessed_element_states_index]\n                .iter()\n                .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),\n        );\n\n        self.text_system\n            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);\n        self.next_frame.scene.replay(\n            range.start.scene_index..range.end.scene_index,\n            &self.rendered_frame.scene,\n        );\n    }\n\n    /// Push a text style onto the stack, and call a function with that style active.\n    /// Use [`Window::text_style`] to get the current, combined text style. This method\n    /// should only be called as part of element drawing.\n    pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        if let Some(style) = style {\n            self.text_style_stack.push(style);\n            let result = f(self);\n            self.text_style_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Updates the cursor style at the platform level. This method should only be called\n    /// during the prepaint phase of element drawing.\n    pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: Option<&Hitbox>) {\n        self.invalidator.debug_assert_paint();\n        self.next_frame.cursor_styles.push(CursorStyleRequest {\n            hitbox_id: hitbox.map(|hitbox| hitbox.id),\n            style,\n        });\n    }\n\n    /// Sets a tooltip to be rendered for the upcoming frame. This method should only be called\n    /// during the paint phase of element drawing.\n    pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {\n        self.invalidator.debug_assert_prepaint();\n        let id = TooltipId(post_inc(&mut self.next_tooltip_id.0));\n        self.next_frame\n            .tooltip_requests\n            .push(Some(TooltipRequest { id, tooltip }));\n        id\n    }\n\n    /// Invoke the given function with the given content mask after intersecting it\n    /// with the current mask. This method should only be called during element drawing.\n    pub fn with_content_mask<R>(\n        &mut self,\n        mask: Option<ContentMask<Pixels>>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        if let Some(mask) = mask {\n            let mask = mask.intersect(&self.content_mask());\n            self.content_mask_stack.push(mask);\n            let result = f(self);\n            self.content_mask_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Updates the global element offset relative to the current offset. This is used to implement\n    /// scrolling. This method should only be called during the prepaint phase of element drawing.\n    pub fn with_element_offset<R>(\n        &mut self,\n        offset: Point<Pixels>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_prepaint();\n\n        if offset.is_zero() {\n            return f(self);\n        };\n\n        let abs_offset = self.element_offset() + offset;\n        self.with_absolute_element_offset(abs_offset, f)\n    }\n\n    /// Updates the global element offset based on the given offset. This is used to implement\n    /// drag handles and other manual painting of elements. This method should only be called during\n    /// the prepaint phase of element drawing.\n    pub fn with_absolute_element_offset<R>(\n        &mut self,\n        offset: Point<Pixels>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_prepaint();\n        self.element_offset_stack.push(offset);\n        let result = f(self);\n        self.element_offset_stack.pop();\n        result\n    }\n\n    pub(crate) fn with_element_opacity<R>(\n        &mut self,\n        opacity: Option<f32>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        if opacity.is_none() {\n            return f(self);\n        }\n\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.element_opacity = opacity;\n        let result = f(self);\n        self.element_opacity = None;\n        result\n    }\n\n    /// Perform prepaint on child elements in a \"retryable\" manner, so that any side effects\n    /// of prepaints can be discarded before prepainting again. This is used to support autoscroll\n    /// where we need to prepaint children to detect the autoscroll bounds, then adjust the\n    /// element offset and prepaint again. See [`List`] for an example. This method should only be\n    /// called during the prepaint phase of element drawing.\n    pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {\n        self.invalidator.debug_assert_prepaint();\n        let index = self.prepaint_index();\n        let result = f(self);\n        if result.is_err() {\n            self.next_frame.hitboxes.truncate(index.hitboxes_index);\n            self.next_frame\n                .tooltip_requests\n                .truncate(index.tooltips_index);\n            self.next_frame\n                .deferred_draws\n                .truncate(index.deferred_draws_index);\n            self.next_frame\n                .dispatch_tree\n                .truncate(index.dispatch_tree_index);\n            self.next_frame\n                .accessed_element_states\n                .truncate(index.accessed_element_states_index);\n            self.text_system.truncate_layouts(index.line_layout_index);\n        }\n        result\n    }\n\n    /// When you call this method during [`prepaint`], containing elements will attempt to\n    /// scroll to cause the specified bounds to become visible. When they decide to autoscroll, they will call\n    /// [`prepaint`] again with a new set of bounds. See [`List`] for an example of an element\n    /// that supports this method being called on the elements it contains. This method should only be\n    /// called during the prepaint phase of element drawing.\n    pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {\n        self.invalidator.debug_assert_prepaint();\n        self.requested_autoscroll = Some(bounds);\n    }\n\n    /// This method can be called from a containing element such as [`List`] to support the autoscroll behavior\n    /// described in [`request_autoscroll`].\n    pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {\n        self.invalidator.debug_assert_prepaint();\n        self.requested_autoscroll.take()\n    }\n\n    /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.\n    /// Your view will be re-drawn once the asset has finished loading.\n    ///\n    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a\n    /// time.\n    pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {\n        let (task, is_first) = cx.fetch_asset::<A>(source);\n        task.clone().now_or_never().or_else(|| {\n            if is_first {\n                let entity_id = self.current_view();\n                self.spawn(cx, {\n                    let task = task.clone();\n                    async move |cx| {\n                        task.await;\n\n                        cx.on_next_frame(move |_, cx| {\n                            cx.notify(entity_id);\n                        });\n                    }\n                })\n                .detach();\n            }\n\n            None\n        })\n    }\n\n    /// Asynchronously load an asset, if the asset hasn't finished loading or doesn't exist this will return None.\n    /// Your view will not be re-drawn once the asset has finished loading.\n    ///\n    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a\n    /// time.\n    pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {\n        let (task, _) = cx.fetch_asset::<A>(source);\n        task.clone().now_or_never()\n    }\n    /// Obtain the current element offset. This method should only be called during the\n    /// prepaint phase of element drawing.\n    pub fn element_offset(&self) -> Point<Pixels> {\n        self.invalidator.debug_assert_prepaint();\n        self.element_offset_stack\n            .last()\n            .copied()\n            .unwrap_or_default()\n    }\n\n    /// Obtain the current element opacity. This method should only be called during the\n    /// prepaint phase of element drawing.\n    pub(crate) fn element_opacity(&self) -> f32 {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.element_opacity.unwrap_or(1.0)\n    }\n\n    /// Obtain the current content mask. This method should only be called during element drawing.\n    pub fn content_mask(&self) -> ContentMask<Pixels> {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.content_mask_stack\n            .last()\n            .cloned()\n            .unwrap_or_else(|| ContentMask {\n                bounds: Bounds {\n                    origin: Point::default(),\n                    size: self.viewport_size,\n                },\n            })\n    }\n\n    /// Provide elements in the called function with a new namespace in which their identifiers must be unique.\n    /// This can be used within a custom element to distinguish multiple sets of child elements.\n    pub fn with_element_namespace<R>(\n        &mut self,\n        element_id: impl Into<ElementId>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.element_id_stack.push(element_id.into());\n        let result = f(self);\n        self.element_id_stack.pop();\n        result\n    }\n\n    /// Updates or initializes state for an element with the given id that lives across multiple\n    /// frames. If an element with this ID existed in the rendered frame, its state will be passed\n    /// to the given closure. The state returned by the closure will be stored so it can be referenced\n    /// when drawing the next frame. This method should only be called as part of element drawing.\n    pub fn with_element_state<S, R>(\n        &mut self,\n        global_id: &GlobalElementId,\n        f: impl FnOnce(Option<S>, &mut Self) -> (R, S),\n    ) -> R\n    where\n        S: 'static,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        let key = (GlobalElementId(global_id.0.clone()), TypeId::of::<S>());\n        self.next_frame\n            .accessed_element_states\n            .push((GlobalElementId(key.0.clone()), TypeId::of::<S>()));\n\n        if let Some(any) = self\n            .next_frame\n            .element_states\n            .remove(&key)\n            .or_else(|| self.rendered_frame.element_states.remove(&key))\n        {\n            let ElementStateBox {\n                inner,\n                #[cfg(debug_assertions)]\n                type_name,\n            } = any;\n            // Using the extra inner option to avoid needing to reallocate a new box.\n            let mut state_box = inner\n                .downcast::<Option<S>>()\n                .map_err(|_| {\n                    #[cfg(debug_assertions)]\n                    {\n                        anyhow::anyhow!(\n                            \"invalid element state type for id, requested {:?}, actual: {:?}\",\n                            std::any::type_name::<S>(),\n                            type_name\n                        )\n                    }\n\n                    #[cfg(not(debug_assertions))]\n                    {\n                        anyhow::anyhow!(\n                            \"invalid element state type for id, requested {:?}\",\n                            std::any::type_name::<S>(),\n                        )\n                    }\n                })\n                .unwrap();\n\n            let state = state_box.take().expect(\n                \"reentrant call to with_element_state for the same state type and element id\",\n            );\n            let (result, state) = f(Some(state), self);\n            state_box.replace(state);\n            self.next_frame.element_states.insert(\n                key,\n                ElementStateBox {\n                    inner: state_box,\n                    #[cfg(debug_assertions)]\n                    type_name,\n                },\n            );\n            result\n        } else {\n            let (result, state) = f(None, self);\n            self.next_frame.element_states.insert(\n                key,\n                ElementStateBox {\n                    inner: Box::new(Some(state)),\n                    #[cfg(debug_assertions)]\n                    type_name: std::any::type_name::<S>(),\n                },\n            );\n            result\n        }\n    }\n\n    /// A variant of `with_element_state` that allows the element's id to be optional. This is a convenience\n    /// method for elements where the element id may or may not be assigned. Prefer using `with_element_state`\n    /// when the element is guaranteed to have an id.\n    ///\n    /// The first option means 'no ID provided'\n    /// The second option means 'not yet initialized'\n    pub fn with_optional_element_state<S, R>(\n        &mut self,\n        global_id: Option<&GlobalElementId>,\n        f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),\n    ) -> R\n    where\n        S: 'static,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        if let Some(global_id) = global_id {\n            self.with_element_state(global_id, |state, cx| {\n                let (result, state) = f(Some(state), cx);\n                let state =\n                    state.expect(\"you must return some state when you pass some element id\");\n                (result, state)\n            })\n        } else {\n            let (result, state) = f(None, self);\n            debug_assert!(\n                state.is_none(),\n                \"you must not return an element state when passing None for the global id\"\n            );\n            result\n        }\n    }\n\n    /// Defers the drawing of the given element, scheduling it to be painted on top of the currently-drawn tree\n    /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements,\n    /// with higher values being drawn on top.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn defer_draw(\n        &mut self,\n        element: AnyElement,\n        absolute_offset: Point<Pixels>,\n        priority: usize,\n    ) {\n        self.invalidator.debug_assert_prepaint();\n        let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();\n        self.next_frame.deferred_draws.push(DeferredDraw {\n            current_view: self.current_view(),\n            parent_node,\n            element_id_stack: self.element_id_stack.clone(),\n            text_style_stack: self.text_style_stack.clone(),\n            priority,\n            element: Some(element),\n            absolute_offset,\n            prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),\n            paint_range: PaintIndex::default()..PaintIndex::default(),\n        });\n    }\n\n    /// Creates a new painting layer for the specified bounds. A \"layer\" is a batch\n    /// of geometry that are non-overlapping and have the same draw order. This is typically used\n    /// for performance reasons.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let clipped_bounds = bounds.intersect(&content_mask.bounds);\n        if !clipped_bounds.is_empty() {\n            self.next_frame\n                .scene\n                .push_layer(clipped_bounds.scale(scale_factor));\n        }\n\n        let result = f(self);\n\n        if !clipped_bounds.is_empty() {\n            self.next_frame.scene.pop_layer();\n        }\n\n        result\n    }\n\n    /// Paint one or more drop shadows into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_shadows(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        corner_radii: Corners<Pixels>,\n        shadows: &[BoxShadow],\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        for shadow in shadows {\n            let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius);\n            self.next_frame.scene.insert_primitive(Shadow {\n                order: 0,\n                blur_radius: shadow.blur_radius.scale(scale_factor),\n                bounds: shadow_bounds.scale(scale_factor),\n                content_mask: content_mask.scale(scale_factor),\n                corner_radii: corner_radii.scale(scale_factor),\n                color: shadow.color.opacity(opacity),\n            });\n        }\n    }\n\n    /// Paint one or more quads into the scene for the next frame at the current stacking context.\n    /// Quads are colored rectangular regions with an optional background, border, and corner radius.\n    /// see [`fill`](crate::fill), [`outline`](crate::outline), and [`quad`](crate::quad) to construct this type.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    ///\n    /// Note that the `quad.corner_radii` are allowed to exceed the bounds, creating sharp corners\n    /// where the circular arcs meet. This will not display well when combined with dashed borders.\n    /// Use `Corners::clamp_radii_for_quad_size` if the radii should fit within the bounds.\n    pub fn paint_quad(&mut self, quad: PaintQuad) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        self.next_frame.scene.insert_primitive(Quad {\n            order: 0,\n            bounds: quad.bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            background: quad.background.opacity(opacity),\n            border_color: quad.border_color.opacity(opacity),\n            corner_radii: quad.corner_radii.scale(scale_factor),\n            border_widths: quad.border_widths.scale(scale_factor),\n            border_style: quad.border_style,\n            transformation: quad.transformation,\n        });\n    }\n\n    /// Paint the given `Path` into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        path.content_mask = content_mask;\n        let color: Background = color.into();\n        path.color = color.opacity(opacity);\n        self.next_frame\n            .scene\n            .insert_primitive(path.scale(scale_factor));\n    }\n\n    /// Paint an underline into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_underline(\n        &mut self,\n        origin: Point<Pixels>,\n        width: Pixels,\n        style: &UnderlineStyle,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let height = if style.wavy {\n            style.thickness * 3.\n        } else {\n            style.thickness\n        };\n        let bounds = Bounds {\n            origin,\n            size: size(width, height),\n        };\n        let content_mask = self.content_mask();\n        let element_opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(Underline {\n            order: 0,\n            pad: 0,\n            bounds: bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            color: style.color.unwrap_or_default().opacity(element_opacity),\n            thickness: style.thickness.scale(scale_factor),\n            wavy: style.wavy,\n        });\n    }\n\n    /// Paint a strikethrough into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_strikethrough(\n        &mut self,\n        origin: Point<Pixels>,\n        width: Pixels,\n        style: &StrikethroughStyle,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let height = style.thickness;\n        let bounds = Bounds {\n            origin,\n            size: size(width, height),\n        };\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(Underline {\n            order: 0,\n            pad: 0,\n            bounds: bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            thickness: style.thickness.scale(scale_factor),\n            color: style.color.unwrap_or_default().opacity(opacity),\n            wavy: false,\n        });\n    }\n\n    /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.\n    ///\n    /// The y component of the origin is the baseline of the glyph.\n    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or\n    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).\n    /// This method is only useful if you need to paint a single glyph that has already been shaped.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_glyph(\n        &mut self,\n        origin: Point<Pixels>,\n        font_id: FontId,\n        glyph_id: GlyphId,\n        font_size: Pixels,\n        color: Hsla,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let element_opacity = self.element_opacity();\n        let scale_factor = self.scale_factor();\n        let glyph_origin = origin.scale(scale_factor);\n        let subpixel_variant = Point {\n            x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,\n            y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,\n        };\n        let params = RenderGlyphParams {\n            font_id,\n            glyph_id,\n            font_size,\n            subpixel_variant,\n            scale_factor,\n            is_emoji: false,\n        };\n\n        let raster_bounds = self.text_system().raster_bounds(&params)?;\n        if !raster_bounds.is_zero() {\n            let tile = self\n                .sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;\n                    Ok(Some((size, Cow::Owned(bytes))))\n                })?\n                .expect(\"Callback above only errors or returns Some\");\n            let bounds = Bounds {\n                origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),\n                size: tile.bounds.size.map(Into::into),\n            };\n            let content_mask = self.content_mask().scale(scale_factor);\n            self.next_frame.scene.insert_primitive(MonochromeSprite {\n                order: 0,\n                pad: 0,\n                bounds,\n                content_mask,\n                color: color.opacity(element_opacity),\n                tile,\n                transformation: TransformationMatrix::unit(),\n            });\n        }\n        Ok(())\n    }\n\n    /// Paints an emoji glyph into the scene for the next frame at the current z-index.\n    ///\n    /// The y component of the origin is the baseline of the glyph.\n    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or\n    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).\n    /// This method is only useful if you need to paint a single emoji that has already been shaped.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_emoji(\n        &mut self,\n        origin: Point<Pixels>,\n        font_id: FontId,\n        glyph_id: GlyphId,\n        font_size: Pixels,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let glyph_origin = origin.scale(scale_factor);\n        let params = RenderGlyphParams {\n            font_id,\n            glyph_id,\n            font_size,\n            // We don't render emojis with subpixel variants.\n            subpixel_variant: Default::default(),\n            scale_factor,\n            is_emoji: true,\n        };\n\n        let raster_bounds = self.text_system().raster_bounds(&params)?;\n        if !raster_bounds.is_zero() {\n            let tile = self\n                .sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;\n                    Ok(Some((size, Cow::Owned(bytes))))\n                })?\n                .expect(\"Callback above only errors or returns Some\");\n\n            let bounds = Bounds {\n                origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),\n                size: tile.bounds.size.map(Into::into),\n            };\n            let content_mask = self.content_mask().scale(scale_factor);\n            let opacity = self.element_opacity();\n\n            self.next_frame.scene.insert_primitive(PolychromeSprite {\n                order: 0,\n                pad: 0,\n                grayscale: false,\n                bounds,\n                corner_radii: Default::default(),\n                content_mask,\n                tile,\n                opacity,\n            });\n        }\n        Ok(())\n    }\n\n    /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_svg(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        path: SharedString,\n        transformation: TransformationMatrix,\n        color: Hsla,\n        cx: &App,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let element_opacity = self.element_opacity();\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let params = RenderSvgParams {\n            path,\n            size: bounds.size.map(|pixels| {\n                DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)\n            }),\n        };\n\n        let Some(tile) =\n            self.sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let Some(bytes) = cx.svg_renderer.render(&params)? else {\n                        return Ok(None);\n                    };\n                    Ok(Some((params.size, Cow::Owned(bytes))))\n                })?\n        else {\n            return Ok(());\n        };\n        let content_mask = self.content_mask().scale(scale_factor);\n\n        self.next_frame.scene.insert_primitive(MonochromeSprite {\n            order: 0,\n            pad: 0,\n            bounds: bounds\n                .map_origin(|origin| origin.floor())\n                .map_size(|size| size.ceil()),\n            content_mask,\n            color: color.opacity(element_opacity),\n            tile,\n            transformation,\n        });\n\n        Ok(())\n    }\n\n    /// Paint an image into the scene for the next frame at the current z-index.\n    /// This method will panic if the frame_index is not valid\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_image(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        corner_radii: Corners<Pixels>,\n        data: Arc<RenderImage>,\n        frame_index: usize,\n        grayscale: bool,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let params = RenderImageParams {\n            image_id: data.id,\n            frame_index,\n        };\n\n        let tile = self\n            .sprite_atlas\n            .get_or_insert_with(&params.clone().into(), &mut || {\n                Ok(Some((\n                    data.size(frame_index),\n                    Cow::Borrowed(\n                        data.as_bytes(frame_index)\n                            .expect(\"It's the caller's job to pass a valid frame index\"),\n                    ),\n                )))\n            })?\n            .expect(\"Callback above only returns Some\");\n        let content_mask = self.content_mask().scale(scale_factor);\n        let corner_radii = corner_radii.scale(scale_factor);\n        let opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(PolychromeSprite {\n            order: 0,\n            pad: 0,\n            grayscale,\n            bounds: bounds\n                .map_origin(|origin| origin.floor())\n                .map_size(|size| size.ceil()),\n            content_mask,\n            corner_radii,\n            tile,\n            opacity,\n        });\n        Ok(())\n    }\n\n    /// Paint a surface into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    #[cfg(target_os = \"macos\")]\n    pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVPixelBuffer) {\n        use crate::PaintSurface;\n\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let content_mask = self.content_mask().scale(scale_factor);\n        self.next_frame.scene.insert_primitive(PaintSurface {\n            order: 0,\n            bounds,\n            content_mask,\n            image_buffer,\n        });\n    }\n\n    /// Removes an image from the sprite atlas.\n    pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {\n        for frame_index in 0..data.frame_count() {\n            let params = RenderImageParams {\n                image_id: data.id,\n                frame_index,\n            };\n\n            self.sprite_atlas.remove(&params.clone().into());\n        }\n\n        Ok(())\n    }\n\n    /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which\n    /// layout is being requested, along with the layout ids of any children. This method is called during\n    /// calls to the [`Element::request_layout`] trait method and enables any element to participate in layout.\n    ///\n    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.\n    #[must_use]\n    pub fn request_layout(\n        &mut self,\n        style: Style,\n        children: impl IntoIterator<Item = LayoutId>,\n        cx: &mut App,\n    ) -> LayoutId {\n        self.invalidator.debug_assert_prepaint();\n\n        cx.layout_id_buffer.clear();\n        cx.layout_id_buffer.extend(children);\n        let rem_size = self.rem_size();\n\n        self.layout_engine\n            .as_mut()\n            .unwrap()\n            .request_layout(style, rem_size, &cx.layout_id_buffer)\n    }\n\n    /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,\n    /// this variant takes a function that is invoked during layout so you can use arbitrary logic to\n    /// determine the element's size. One place this is used internally is when measuring text.\n    ///\n    /// The given closure is invoked at layout time with the known dimensions and available space and\n    /// returns a `Size`.\n    ///\n    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.\n    pub fn request_measured_layout<\n        F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>\n            + 'static,\n    >(\n        &mut self,\n        style: Style,\n        measure: F,\n    ) -> LayoutId {\n        self.invalidator.debug_assert_prepaint();\n\n        let rem_size = self.rem_size();\n        self.layout_engine\n            .as_mut()\n            .unwrap()\n            .request_measured_layout(style, rem_size, measure)\n    }\n\n    /// Compute the layout for the given id within the given available space.\n    /// This method is called for its side effect, typically by the framework prior to painting.\n    /// After calling it, you can request the bounds of the given layout node id or any descendant.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn compute_layout(\n        &mut self,\n        layout_id: LayoutId,\n        available_space: Size<AvailableSpace>,\n        cx: &mut App,\n    ) {\n        self.invalidator.debug_assert_prepaint();\n\n        let mut layout_engine = self.layout_engine.take().unwrap();\n        layout_engine.compute_layout(layout_id, available_space, self, cx);\n        self.layout_engine = Some(layout_engine);\n    }\n\n    /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by\n    /// GPUI itself automatically in order to pass your element its `Bounds` automatically.\n    ///\n    /// This method should only be called as part of element drawing.\n    pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {\n        self.invalidator.debug_assert_prepaint();\n\n        let mut bounds = self\n            .layout_engine\n            .as_mut()\n            .unwrap()\n            .layout_bounds(layout_id)\n            .map(Into::into);\n        bounds.origin += self.element_offset();\n        bounds\n    }\n\n    /// This method should be called during `prepaint`. You can use\n    /// the returned [Hitbox] during `paint` or in an event handler\n    /// to determine whether the inserted hitbox was the topmost.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, opaque: bool) -> Hitbox {\n        self.invalidator.debug_assert_prepaint();\n\n        let content_mask = self.content_mask();\n        let id = self.next_hitbox_id;\n        self.next_hitbox_id.0 += 1;\n        let hitbox = Hitbox {\n            id,\n            bounds,\n            content_mask,\n            opaque,\n        };\n        self.next_frame.hitboxes.push(hitbox.clone());\n        hitbox\n    }\n\n    /// Sets the key context for the current element. This context will be used to translate\n    /// keybindings into actions.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn set_key_context(&mut self, context: KeyContext) {\n        self.invalidator.debug_assert_paint();\n        self.next_frame.dispatch_tree.set_key_context(context);\n    }\n\n    /// Sets the focus handle for the current element. This handle will be used to manage focus state\n    /// and keyboard event dispatch for the element.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {\n        self.invalidator.debug_assert_prepaint();\n        if focus_handle.is_focused(self) {\n            self.next_frame.focus = Some(focus_handle.id);\n        }\n        self.next_frame.dispatch_tree.set_focus_id(focus_handle.id);\n    }\n\n    /// Sets the view id for the current element, which will be used to manage view caching.\n    ///\n    /// This method should only be called as part of element prepaint. We plan on removing this\n    /// method eventually when we solve some issues that require us to construct editor elements\n    /// directly instead of always using editors via views.\n    pub fn set_view_id(&mut self, view_id: EntityId) {\n        self.invalidator.debug_assert_prepaint();\n        self.next_frame.dispatch_tree.set_view_id(view_id);\n    }\n\n    /// Get the entity ID for the currently rendering view\n    pub fn current_view(&self) -> EntityId {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.rendered_entity_stack.last().copied().unwrap()\n    }\n\n    pub(crate) fn with_rendered_view<R>(\n        &mut self,\n        id: EntityId,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.rendered_entity_stack.push(id);\n        let result = f(self);\n        self.rendered_entity_stack.pop();\n        result\n    }\n\n    /// Executes the provided function with the specified image cache.\n    pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        if let Some(image_cache) = image_cache {\n            self.image_cache_stack.push(image_cache);\n            let result = f(self);\n            self.image_cache_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the\n    /// platform to receive textual input with proper integration with concerns such\n    /// as IME interactions. This handler will be active for the upcoming frame until the following frame is\n    /// rendered.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    ///\n    /// [element_input_handler]: crate::ElementInputHandler\n    pub fn handle_input(\n        &mut self,\n        focus_handle: &FocusHandle,\n        input_handler: impl InputHandler,\n        cx: &App,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        if focus_handle.is_focused(self) {\n            let cx = self.to_async(cx);\n            self.next_frame\n                .input_handlers\n                .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));\n        }\n    }\n\n    /// Register a mouse event listener on the window for the next frame. The type of event\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_mouse_event<Event: MouseEvent>(\n        &mut self,\n        mut handler: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.mouse_listeners.push(Some(Box::new(\n            move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {\n                if let Some(event) = event.downcast_ref() {\n                    handler(event, phase, window, cx)\n                }\n            },\n        )));\n    }\n\n    /// Register a key event listener on the window for the next frame. The type of event\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have\n    /// a specific need to register a global listener.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_key_event<Event: KeyEvent>(\n        &mut self,\n        listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.dispatch_tree.on_key_event(Rc::new(\n            move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {\n                if let Some(event) = event.downcast_ref::<Event>() {\n                    listener(event, phase, window, cx)\n                }\n            },\n        ));\n    }\n\n    /// Register a modifiers changed event listener on the window for the next frame.\n    ///\n    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have\n    /// a specific need to register a global listener.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_modifiers_changed(\n        &mut self,\n        listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new(\n            move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {\n                listener(event, window, cx)\n            },\n        ));\n    }\n\n    /// Register a listener to be called when the given focus handle or one of its descendants receives focus.\n    /// This does not fire if the given focus handle - or one of its descendants - was previously focused.\n    /// Returns a subscription and persists until the subscription is dropped.\n    pub fn on_focus_in(\n        &mut self,\n        handle: &FocusHandle,\n        cx: &mut App,\n        mut listener: impl FnMut(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let focus_id = handle.id;\n        let (subscription, activate) =\n            self.new_focus_listener(Box::new(move |event, window, cx| {\n                if event.is_focus_in(focus_id) {\n                    listener(window, cx);\n                }\n                true\n            }));\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    /// Register a listener to be called when the given focus handle or one of its descendants loses focus.\n    /// Returns a subscription and persists until the subscription is dropped.\n    pub fn on_focus_out(\n        &mut self,\n        handle: &FocusHandle,\n        cx: &mut App,\n        mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let focus_id = handle.id;\n        let (subscription, activate) =\n            self.new_focus_listener(Box::new(move |event, window, cx| {\n                if let Some(blurred_id) = event.previous_focus_path.last().copied() {\n                    if event.is_focus_out(focus_id) {\n                        let event = FocusOutEvent {\n                            blurred: WeakFocusHandle {\n                                id: blurred_id,\n                                handles: Arc::downgrade(&cx.focus_handles),\n                            },\n                        };\n                        listener(event, window, cx)\n                    }\n                }\n                true\n            }));\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    fn reset_cursor_style(&self, cx: &mut App) {\n        // Set the cursor only if we're the active window.\n        if self.is_window_hovered() {\n            let style = self\n                .rendered_frame\n                .cursor_styles\n                .iter()\n                .rev()\n                .find(|request| {\n                    request\n                        .hitbox_id\n                        .map_or(true, |hitbox_id| hitbox_id.is_hovered(self))\n                })\n                .map(|request| request.style)\n                .unwrap_or(CursorStyle::Arrow);\n            cx.platform.set_cursor_style(style);\n        }\n    }\n\n    /// Dispatch a given keystroke as though the user had typed it.\n    /// You can create a keystroke with Keystroke::parse(\"\").\n    pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {\n        let keystroke = keystroke.with_simulated_ime();\n        let result = self.dispatch_event(\n            PlatformInput::KeyDown(KeyDownEvent {\n                keystroke: keystroke.clone(),\n                is_held: false,\n            }),\n            cx,\n        );\n        if !result.propagate {\n            return true;\n        }\n\n        if let Some(input) = keystroke.key_char {\n            if let Some(mut input_handler) = self.platform_window.take_input_handler() {\n                input_handler.dispatch_input(&input, self, cx);\n                self.platform_window.set_input_handler(input_handler);\n                return true;\n            }\n        }\n\n        false\n    }\n\n    /// Return a key binding string for an action, to display in the UI. Uses the highest precedence\n    /// binding for the action (last binding added to the keymap).\n    pub fn keystroke_text_for(&self, action: &dyn Action) -> String {\n        self.bindings_for_action(action)\n            .last()\n            .map(|binding| {\n                binding\n                    .keystrokes()\n                    .iter()\n                    .map(ToString::to_string)\n                    .collect::<Vec<_>>()\n                    .join(\" \")\n            })\n            .unwrap_or_else(|| action.name().to_string())\n    }\n\n    /// Dispatch a mouse or keyboard event on the window.\n    #[profiling::function]\n    pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {\n        self.last_input_timestamp.set(Instant::now());\n        // Handlers may set this to false by calling `stop_propagation`.\n        cx.propagate_event = true;\n        // Handlers may set this to true by calling `prevent_default`.\n        self.default_prevented = false;\n\n        let event = match event {\n            // Track the mouse position with our own state, since accessing the platform\n            // API for the mouse position can only occur on the main thread.\n            PlatformInput::MouseMove(mouse_move) => {\n                self.mouse_position = mouse_move.position;\n                self.modifiers = mouse_move.modifiers;\n                PlatformInput::MouseMove(mouse_move)\n            }\n            PlatformInput::MouseDown(mouse_down) => {\n                self.mouse_position = mouse_down.position;\n                self.modifiers = mouse_down.modifiers;\n                PlatformInput::MouseDown(mouse_down)\n            }\n            PlatformInput::MouseUp(mouse_up) => {\n                self.mouse_position = mouse_up.position;\n                self.modifiers = mouse_up.modifiers;\n                PlatformInput::MouseUp(mouse_up)\n            }\n            PlatformInput::MouseExited(mouse_exited) => {\n                self.modifiers = mouse_exited.modifiers;\n                PlatformInput::MouseExited(mouse_exited)\n            }\n            PlatformInput::ModifiersChanged(modifiers_changed) => {\n                self.modifiers = modifiers_changed.modifiers;\n                PlatformInput::ModifiersChanged(modifiers_changed)\n            }\n            PlatformInput::ScrollWheel(scroll_wheel) => {\n                self.mouse_position = scroll_wheel.position;\n                self.modifiers = scroll_wheel.modifiers;\n                PlatformInput::ScrollWheel(scroll_wheel)\n            }\n            // Translate dragging and dropping of external files from the operating system\n            // to internal drag and drop events.\n            PlatformInput::FileDrop(file_drop) => match file_drop {\n                FileDropEvent::Entered { position, paths } => {\n                    self.mouse_position = position;\n                    if cx.active_drag.is_none() {\n                        cx.active_drag = Some(AnyDrag {\n                            value: Arc::new(paths.clone()),\n                            view: cx.new(|_| paths).into(),\n                            cursor_offset: position,\n                            cursor_style: None,\n                        });\n                    }\n                    PlatformInput::MouseMove(MouseMoveEvent {\n                        position,\n                        pressed_button: Some(MouseButton::Left),\n                        modifiers: Modifiers::default(),\n                    })\n                }\n                FileDropEvent::Pending { position } => {\n                    self.mouse_position = position;\n                    PlatformInput::MouseMove(MouseMoveEvent {\n                        position,\n                        pressed_button: Some(MouseButton::Left),\n                        modifiers: Modifiers::default(),\n                    })\n                }\n                FileDropEvent::Submit { position } => {\n                    cx.activate(true);\n                    self.mouse_position = position;\n                    PlatformInput::MouseUp(MouseUpEvent {\n                        button: MouseButton::Left,\n                        position,\n                        modifiers: Modifiers::default(),\n                        click_count: 1,\n                    })\n                }\n                FileDropEvent::Exited => {\n                    cx.active_drag.take();\n                    PlatformInput::FileDrop(FileDropEvent::Exited)\n                }\n            },\n            PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,\n        };\n\n        if let Some(any_mouse_event) = event.mouse_event() {\n            self.dispatch_mouse_event(any_mouse_event, cx);\n        } else if let Some(any_key_event) = event.keyboard_event() {\n            self.dispatch_key_event(any_key_event, cx);\n        }\n\n        DispatchEventResult {\n            propagate: cx.propagate_event,\n            default_prevented: self.default_prevented,\n        }\n    }\n\n    fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {\n        let hit_test = self.rendered_frame.hit_test(self.mouse_position());\n        if hit_test != self.mouse_hit_test {\n            self.mouse_hit_test = hit_test;\n            self.reset_cursor_style(cx);\n        }\n\n        let mut mouse_listeners = mem::take(&mut self.rendered_frame.mouse_listeners);\n\n        // Capture phase, events bubble from back to front. Handlers for this phase are used for\n        // special purposes, such as detecting events outside of a given Bounds.\n        for listener in &mut mouse_listeners {\n            let listener = listener.as_mut().unwrap();\n            listener(event, DispatchPhase::Capture, self, cx);\n            if !cx.propagate_event {\n                break;\n            }\n        }\n\n        // Bubble phase, where most normal handlers do their work.\n        if cx.propagate_event {\n            for listener in mouse_listeners.iter_mut().rev() {\n                let listener = listener.as_mut().unwrap();\n                listener(event, DispatchPhase::Bubble, self, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n        }\n\n        self.rendered_frame.mouse_listeners = mouse_listeners;\n\n        if cx.has_active_drag() {\n            if event.is::<MouseMoveEvent>() {\n                // If this was a mouse move event, redraw the window so that the\n                // active drag can follow the mouse cursor.\n                self.refresh();\n            } else if event.is::<MouseUpEvent>() {\n                // If this was a mouse up event, cancel the active drag and redraw\n                // the window.\n                cx.active_drag = None;\n                self.refresh();\n            }\n        }\n    }\n\n    fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) {\n        if self.invalidator.is_dirty() {\n            self.draw(cx);\n        }\n\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        let mut keystroke: Option<Keystroke> = None;\n\n        if let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() {\n            if event.modifiers.number_of_modifiers() == 0\n                && self.pending_modifier.modifiers.number_of_modifiers() == 1\n                && !self.pending_modifier.saw_keystroke\n            {\n                let key = match self.pending_modifier.modifiers {\n                    modifiers if modifiers.shift => Some(\"shift\"),\n                    modifiers if modifiers.control => Some(\"control\"),\n                    modifiers if modifiers.alt => Some(\"alt\"),\n                    modifiers if modifiers.platform => Some(\"platform\"),\n                    modifiers if modifiers.function => Some(\"function\"),\n                    _ => None,\n                };\n                if let Some(key) = key {\n                    keystroke = Some(Keystroke {\n                        key: key.to_string(),\n                        key_char: None,\n                        modifiers: Modifiers::default(),\n                    });\n                }\n            }\n\n            if self.pending_modifier.modifiers.number_of_modifiers() == 0\n                && event.modifiers.number_of_modifiers() == 1\n            {\n                self.pending_modifier.saw_keystroke = false\n            }\n            self.pending_modifier.modifiers = event.modifiers\n        } else if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {\n            self.pending_modifier.saw_keystroke = true;\n            keystroke = Some(key_down_event.keystroke.clone());\n        }\n\n        let Some(keystroke) = keystroke else {\n            self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);\n            return;\n        };\n\n        let mut currently_pending = self.pending_input.take().unwrap_or_default();\n        if currently_pending.focus.is_some() && currently_pending.focus != self.focus {\n            currently_pending = PendingInput::default();\n        }\n\n        let match_result = self.rendered_frame.dispatch_tree.dispatch_key(\n            currently_pending.keystrokes,\n            keystroke,\n            &dispatch_path,\n        );\n\n        if !match_result.to_replay.is_empty() {\n            self.replay_pending_input(match_result.to_replay, cx)\n        }\n\n        if !match_result.pending.is_empty() {\n            currently_pending.keystrokes = match_result.pending;\n            currently_pending.focus = self.focus;\n            currently_pending.timer = Some(self.spawn(cx, async move |cx| {\n                cx.background_executor.timer(Duration::from_secs(1)).await;\n                cx.update(move |window, cx| {\n                    let Some(currently_pending) = window\n                        .pending_input\n                        .take()\n                        .filter(|pending| pending.focus == window.focus)\n                    else {\n                        return;\n                    };\n\n                    let dispatch_path = window.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n                    let to_replay = window\n                        .rendered_frame\n                        .dispatch_tree\n                        .flush_dispatch(currently_pending.keystrokes, &dispatch_path);\n\n                    window.replay_pending_input(to_replay, cx)\n                })\n                .log_err();\n            }));\n            self.pending_input = Some(currently_pending);\n            self.pending_input_changed(cx);\n            cx.propagate_event = false;\n            return;\n        }\n\n        cx.propagate_event = true;\n        for binding in match_result.bindings {\n            self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);\n            if !cx.propagate_event {\n                self.dispatch_keystroke_observers(\n                    event,\n                    Some(binding.action),\n                    match_result.context_stack.clone(),\n                    cx,\n                );\n                self.pending_input_changed(cx);\n                return;\n            }\n        }\n\n        self.finish_dispatch_key_event(event, dispatch_path, match_result.context_stack, cx);\n        self.pending_input_changed(cx);\n    }\n\n    fn finish_dispatch_key_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: SmallVec<[DispatchNodeId; 32]>,\n        context_stack: Vec<KeyContext>,\n        cx: &mut App,\n    ) {\n        self.dispatch_key_down_up_event(event, &dispatch_path, cx);\n        if !cx.propagate_event {\n            return;\n        }\n\n        self.dispatch_modifiers_changed_event(event, &dispatch_path, cx);\n        if !cx.propagate_event {\n            return;\n        }\n\n        self.dispatch_keystroke_observers(event, None, context_stack, cx);\n    }\n\n    fn pending_input_changed(&mut self, cx: &mut App) {\n        self.pending_input_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    fn dispatch_key_down_up_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,\n        cx: &mut App,\n    ) {\n        // Capture phase\n        for node_id in dispatch_path {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n\n            for key_listener in node.key_listeners.clone() {\n                key_listener(event, DispatchPhase::Capture, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n\n        // Bubble phase\n        for node_id in dispatch_path.iter().rev() {\n            // Handle low level key events\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for key_listener in node.key_listeners.clone() {\n                key_listener(event, DispatchPhase::Bubble, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n    }\n\n    fn dispatch_modifiers_changed_event(\n        &mut self,\n        event: &dyn Any,\n        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,\n        cx: &mut App,\n    ) {\n        let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() else {\n            return;\n        };\n        for node_id in dispatch_path.iter().rev() {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for listener in node.modifiers_changed_listeners.clone() {\n                listener(event, self, cx);\n                if !cx.propagate_event {\n                    return;\n                }\n            }\n        }\n    }\n\n    /// Determine whether a potential multi-stroke key binding is in progress on this window.\n    pub fn has_pending_keystrokes(&self) -> bool {\n        self.pending_input.is_some()\n    }\n\n    pub(crate) fn clear_pending_keystrokes(&mut self) {\n        self.pending_input.take();\n    }\n\n    /// Returns the currently pending input keystrokes that might result in a multi-stroke key binding.\n    pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> {\n        self.pending_input\n            .as_ref()\n            .map(|pending_input| pending_input.keystrokes.as_slice())\n    }\n\n    fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) {\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        'replay: for replay in replays {\n            let event = KeyDownEvent {\n                keystroke: replay.keystroke.clone(),\n                is_held: false,\n            };\n\n            cx.propagate_event = true;\n            for binding in replay.bindings {\n                self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);\n                if !cx.propagate_event {\n                    self.dispatch_keystroke_observers(\n                        &event,\n                        Some(binding.action),\n                        Vec::default(),\n                        cx,\n                    );\n                    continue 'replay;\n                }\n            }\n\n            self.dispatch_key_down_up_event(&event, &dispatch_path, cx);\n            if !cx.propagate_event {\n                continue 'replay;\n            }\n            if let Some(input) = replay.keystroke.key_char.as_ref().cloned() {\n                if let Some(mut input_handler) = self.platform_window.take_input_handler() {\n                    input_handler.dispatch_input(&input, self, cx);\n                    self.platform_window.set_input_handler(input_handler)\n                }\n            }\n        }\n    }\n\n    fn dispatch_action_on_node(\n        &mut self,\n        node_id: DispatchNodeId,\n        action: &dyn Action,\n        cx: &mut App,\n    ) {\n        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);\n\n        // Capture phase for global actions.\n        cx.propagate_event = true;\n        if let Some(mut global_listeners) = cx\n            .global_action_listeners\n            .remove(&action.as_any().type_id())\n        {\n            for listener in &global_listeners {\n                listener(action.as_any(), DispatchPhase::Capture, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n\n            global_listeners.extend(\n                cx.global_action_listeners\n                    .remove(&action.as_any().type_id())\n                    .unwrap_or_default(),\n            );\n\n            cx.global_action_listeners\n                .insert(action.as_any().type_id(), global_listeners);\n        }\n\n        if !cx.propagate_event {\n            return;\n        }\n\n        // Capture phase for window actions.\n        for node_id in &dispatch_path {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for DispatchActionListener {\n                action_type,\n                listener,\n            } in node.action_listeners.clone()\n            {\n                let any_action = action.as_any();\n                if action_type == any_action.type_id() {\n                    listener(any_action, DispatchPhase::Capture, self, cx);\n\n                    if !cx.propagate_event {\n                        return;\n                    }\n                }\n            }\n        }\n\n        // Bubble phase for window actions.\n        for node_id in dispatch_path.iter().rev() {\n            let node = self.rendered_frame.dispatch_tree.node(*node_id);\n            for DispatchActionListener {\n                action_type,\n                listener,\n            } in node.action_listeners.clone()\n            {\n                let any_action = action.as_any();\n                if action_type == any_action.type_id() {\n                    cx.propagate_event = false; // Actions stop propagation by default during the bubble phase\n                    listener(any_action, DispatchPhase::Bubble, self, cx);\n\n                    if !cx.propagate_event {\n                        return;\n                    }\n                }\n            }\n        }\n\n        // Bubble phase for global actions.\n        if let Some(mut global_listeners) = cx\n            .global_action_listeners\n            .remove(&action.as_any().type_id())\n        {\n            for listener in global_listeners.iter().rev() {\n                cx.propagate_event = false; // Actions stop propagation by default during the bubble phase\n\n                listener(action.as_any(), DispatchPhase::Bubble, cx);\n                if !cx.propagate_event {\n                    break;\n                }\n            }\n\n            global_listeners.extend(\n                cx.global_action_listeners\n                    .remove(&action.as_any().type_id())\n                    .unwrap_or_default(),\n            );\n\n            cx.global_action_listeners\n                .insert(action.as_any().type_id(), global_listeners);\n        }\n    }\n\n    /// Register the given handler to be invoked whenever the global of the given type\n    /// is updated.\n    pub fn observe_global<G: Global>(\n        &mut self,\n        cx: &mut App,\n        f: impl Fn(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let window_handle = self.handle;\n        let (subscription, activate) = cx.global_observers.insert(\n            TypeId::of::<G>(),\n            Box::new(move |cx| {\n                window_handle\n                    .update(cx, |_, window, cx| f(window, cx))\n                    .is_ok()\n            }),\n        );\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    /// Focus the current window and bring it to the foreground at the platform level.\n    pub fn activate_window(&self) {\n        self.platform_window.activate();\n    }\n\n    /// Minimize the current window at the platform level.\n    pub fn minimize_window(&self) {\n        self.platform_window.minimize();\n    }\n\n    /// Toggle full screen status on the current window at the platform level.\n    pub fn toggle_fullscreen(&self) {\n        self.platform_window.toggle_fullscreen();\n    }\n\n    /// Updates the IME panel position suggestions for languages like japanese, chinese.\n    pub fn invalidate_character_coordinates(&self) {\n        self.on_next_frame(|window, cx| {\n            if let Some(mut input_handler) = window.platform_window.take_input_handler() {\n                if let Some(bounds) = input_handler.selected_bounds(window, cx) {\n                    window\n                        .platform_window\n                        .update_ime_position(bounds.scale(window.scale_factor()));\n                }\n                window.platform_window.set_input_handler(input_handler);\n            }\n        });\n    }\n\n    /// Present a platform dialog.\n    /// The provided message will be presented, along with buttons for each answer.\n    /// When a button is clicked, the returned Receiver will receive the index of the clicked button.\n    pub fn prompt(\n        &mut self,\n        level: PromptLevel,\n        message: &str,\n        detail: Option<&str>,\n        answers: &[&str],\n        cx: &mut App,\n    ) -> oneshot::Receiver<usize> {\n        let prompt_builder = cx.prompt_builder.take();\n        let Some(prompt_builder) = prompt_builder else {\n            unreachable!(\"Re-entrant window prompting is not supported by GPUI\");\n        };\n\n        let receiver = match &prompt_builder {\n            PromptBuilder::Default => self\n                .platform_window\n                .prompt(level, message, detail, answers)\n                .unwrap_or_else(|| {\n                    self.build_custom_prompt(&prompt_builder, level, message, detail, answers, cx)\n                }),\n            PromptBuilder::Custom(_) => {\n                self.build_custom_prompt(&prompt_builder, level, message, detail, answers, cx)\n            }\n        };\n\n        cx.prompt_builder = Some(prompt_builder);\n\n        receiver\n    }\n\n    fn build_custom_prompt(\n        &mut self,\n        prompt_builder: &PromptBuilder,\n        level: PromptLevel,\n        message: &str,\n        detail: Option<&str>,\n        answers: &[&str],\n        cx: &mut App,\n    ) -> oneshot::Receiver<usize> {\n        let (sender, receiver) = oneshot::channel();\n        let handle = PromptHandle::new(sender);\n        let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx);\n        self.prompt = Some(handle);\n        receiver\n    }\n\n    /// Returns the current context stack.\n    pub fn context_stack(&self) -> Vec<KeyContext> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n        let node_id = self\n            .focus\n            .and_then(|focus_id| dispatch_tree.focusable_node_id(focus_id))\n            .unwrap_or_else(|| dispatch_tree.root_node_id());\n\n        dispatch_tree\n            .dispatch_path(node_id)\n            .iter()\n            .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone())\n            .collect()\n    }\n\n    /// Returns all available actions for the focused element.\n    pub fn available_actions(&self, cx: &App) -> Vec<Box<dyn Action>> {\n        let node_id = self\n            .focus\n            .and_then(|focus_id| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focus_id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n\n        let mut actions = self.rendered_frame.dispatch_tree.available_actions(node_id);\n        for action_type in cx.global_action_listeners.keys() {\n            if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) {\n                let action = cx.actions.build_action_type(action_type).ok();\n                if let Some(action) = action {\n                    actions.insert(ix, action);\n                }\n            }\n        }\n        actions\n    }\n\n    /// Returns key bindings that invoke an action on the currently focused element. Bindings are\n    /// returned in the order they were added. For display, the last binding should take precedence.\n    pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {\n        self.rendered_frame\n            .dispatch_tree\n            .bindings_for_action(action, &self.rendered_frame.dispatch_tree.context_stack)\n    }\n\n    /// Returns any bindings that would invoke an action on the given focus handle if it were\n    /// focused. Bindings are returned in the order they were added. For display, the last binding\n    /// should take precedence.\n    pub fn bindings_for_action_in(\n        &self,\n        action: &dyn Action,\n        focus_handle: &FocusHandle,\n    ) -> Vec<KeyBinding> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n\n        let Some(node_id) = dispatch_tree.focusable_node_id(focus_handle.id) else {\n            return vec![];\n        };\n        let context_stack: Vec<_> = dispatch_tree\n            .dispatch_path(node_id)\n            .into_iter()\n            .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())\n            .collect();\n        dispatch_tree.bindings_for_action(action, &context_stack)\n    }\n\n    /// Returns the key bindings for the given action in the given context.\n    pub fn bindings_for_action_in_context(\n        &self,\n        action: &dyn Action,\n        context: KeyContext,\n    ) -> Vec<KeyBinding> {\n        let dispatch_tree = &self.rendered_frame.dispatch_tree;\n        dispatch_tree.bindings_for_action(action, &[context])\n    }\n\n    /// Returns a generic event listener that invokes the given listener with the view and context associated with the given view handle.\n    pub fn listener_for<V: Render, E>(\n        &self,\n        view: &Entity<V>,\n        f: impl Fn(&mut V, &E, &mut Window, &mut Context<V>) + 'static,\n    ) -> impl Fn(&E, &mut Window, &mut App) + 'static {\n        let view = view.downgrade();\n        move |e: &E, window: &mut Window, cx: &mut App| {\n            view.update(cx, |view, cx| f(view, e, window, cx)).ok();\n        }\n    }\n\n    /// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle.\n    pub fn handler_for<V: Render, Callback: Fn(&mut V, &mut Window, &mut Context<V>) + 'static>(\n        &self,\n        view: &Entity<V>,\n        f: Callback,\n    ) -> impl Fn(&mut Window, &mut App) + use<V, Callback> {\n        let view = view.downgrade();\n        move |window: &mut Window, cx: &mut App| {\n            view.update(cx, |view, cx| f(view, window, cx)).ok();\n        }\n    }\n\n    /// Register a callback that can interrupt the closing of the current window based the returned boolean.\n    /// If the callback returns false, the window won't be closed.\n    pub fn on_window_should_close(\n        &self,\n        cx: &App,\n        f: impl Fn(&mut Window, &mut App) -> bool + 'static,\n    ) {\n        let mut cx = self.to_async(cx);\n        self.platform_window.on_should_close(Box::new(move || {\n            cx.update(|window, cx| f(window, cx)).unwrap_or(true)\n        }))\n    }\n\n    /// Register an action listener on the window for the next frame. The type of action\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This is a fairly low-level method, so prefer using action handlers on elements unless you have\n    /// a specific need to register a global listener.\n    pub fn on_action(\n        &mut self,\n        action_type: TypeId,\n        listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.next_frame\n            .dispatch_tree\n            .on_action(action_type, Rc::new(listener));\n    }\n\n    /// Read information about the GPU backing this window.\n    /// Currently returns None on Mac and Windows.\n    pub fn gpu_specs(&self) -> Option<GpuSpecs> {\n        self.platform_window.gpu_specs()\n    }\n}\n\n// #[derive(Clone, Copy, Eq, PartialEq, Hash)]\nslotmap::new_key_type! {\n    /// A unique identifier for a window.\n    pub struct WindowId;\n}\n\nimpl WindowId {\n    /// Converts this window ID to a `u64`.\n    pub fn as_u64(&self) -> u64 {\n        self.0.as_ffi()\n    }\n}\n\nimpl From<u64> for WindowId {\n    fn from(value: u64) -> Self {\n        WindowId(slotmap::KeyData::from_ffi(value))\n    }\n}\n\n/// A handle to a window with a specific root view type.\n/// Note that this does not keep the window alive on its own.\n#[derive(Deref, DerefMut)]\npub struct WindowHandle<V> {\n    #[deref]\n    #[deref_mut]\n    pub(crate) any_handle: AnyWindowHandle,\n    state_type: PhantomData<V>,\n}\n\nimpl<V: 'static + Render> WindowHandle<V> {\n    /// Creates a new handle from a window ID.\n    /// This does not check if the root type of the window is `V`.\n    pub fn new(id: WindowId) -> Self {\n        WindowHandle {\n            any_handle: AnyWindowHandle {\n                id,\n                state_type: TypeId::of::<V>(),\n            },\n            state_type: PhantomData,\n        }\n    }\n\n    /// Get the root view out of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    #[cfg(any(test, feature = \"test-support\"))]\n    pub fn root<C>(&self, cx: &mut C) -> Result<Entity<V>>\n    where\n        C: AppContext,\n    {\n        crate::Flatten::flatten(cx.update_window(self.any_handle, |root_view, _, _| {\n            root_view\n                .downcast::<V>()\n                .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))\n        }))\n    }\n\n    /// Updates the root view of this window.\n    ///\n    /// This will fail if the window has been closed or if the root view's type does not match\n    pub fn update<C, R>(\n        &self,\n        cx: &mut C,\n        update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,\n    ) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.update_window(self.any_handle, |root_view, window, cx| {\n            let view = root_view\n                .downcast::<V>()\n                .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))?;\n\n            Ok(view.update(cx, |view, cx| update(view, window, cx)))\n        })?\n    }\n\n    /// Read the root view out of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> {\n        let x = cx\n            .windows\n            .get(self.id)\n            .and_then(|window| {\n                window\n                    .as_ref()\n                    .and_then(|window| window.root.clone())\n                    .map(|root_view| root_view.downcast::<V>())\n            })\n            .ok_or_else(|| anyhow!(\"window not found\"))?\n            .map_err(|_| anyhow!(\"the type of the window's root view has changed\"))?;\n\n        Ok(x.read(cx))\n    }\n\n    /// Read the root view out of this window, with a callback\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))\n    }\n\n    /// Read the root view pointer off of this window.\n    ///\n    /// This will fail if the window is closed or if the root view's type does not match `V`.\n    pub fn entity<C>(&self, cx: &C) -> Result<Entity<V>>\n    where\n        C: AppContext,\n    {\n        cx.read_window(self, |root_view, _cx| root_view.clone())\n    }\n\n    /// Check if this window is 'active'.\n    ///\n    /// Will return `None` if the window is closed or currently\n    /// borrowed.\n    pub fn is_active(&self, cx: &mut App) -> Option<bool> {\n        cx.update_window(self.any_handle, |_, window, _| window.is_window_active())\n            .ok()\n    }\n}\n\nimpl<V> Copy for WindowHandle<V> {}\n\nimpl<V> Clone for WindowHandle<V> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<V> PartialEq for WindowHandle<V> {\n    fn eq(&self, other: &Self) -> bool {\n        self.any_handle == other.any_handle\n    }\n}\n\nimpl<V> Eq for WindowHandle<V> {}\n\nimpl<V> Hash for WindowHandle<V> {\n    fn hash<H: Hasher>(&self, state: &mut H) {\n        self.any_handle.hash(state);\n    }\n}\n\nimpl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {\n    fn from(val: WindowHandle<V>) -> Self {\n        val.any_handle\n    }\n}\n\nunsafe impl<V> Send for WindowHandle<V> {}\nunsafe impl<V> Sync for WindowHandle<V> {}\n\n/// A handle to a window with any root view type, which can be downcast to a window with a specific root view type.\n#[derive(Copy, Clone, PartialEq, Eq, Hash)]\npub struct AnyWindowHandle {\n    pub(crate) id: WindowId,\n    state_type: TypeId,\n}\n\nimpl AnyWindowHandle {\n    /// Get the ID of this window.\n    pub fn window_id(&self) -> WindowId {\n        self.id\n    }\n\n    /// Attempt to convert this handle to a window handle with a specific root view type.\n    /// If the types do not match, this will return `None`.\n    pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {\n        if TypeId::of::<T>() == self.state_type {\n            Some(WindowHandle {\n                any_handle: *self,\n                state_type: PhantomData,\n            })\n        } else {\n            None\n        }\n    }\n\n    /// Updates the state of the root view of this window.\n    ///\n    /// This will fail if the window has been closed.\n    pub fn update<C, R>(\n        self,\n        cx: &mut C,\n        update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,\n    ) -> Result<R>\n    where\n        C: AppContext,\n    {\n        cx.update_window(self, update)\n    }\n\n    /// Read the state of the root view of this window.\n    ///\n    /// This will fail if the window has been closed.\n    pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(Entity<T>, &App) -> R) -> Result<R>\n    where\n        C: AppContext,\n        T: 'static,\n    {\n        let view = self\n            .downcast::<T>()\n            .context(\"the type of the window's root view has changed\")?;\n\n        cx.read_window(&view, read)\n    }\n}\n\nimpl HasWindowHandle for Window {\n    fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, HandleError> {\n        self.platform_window.window_handle()\n    }\n}\n\n/// An identifier for an [`Element`](crate::Element).\n///\n/// Can be constructed with a string, a number, or both, as well\n/// as other internal representations.\n#[derive(Clone, Debug, Eq, PartialEq, Hash)]\npub enum ElementId {\n    /// The ID of a View element\n    View(EntityId),\n    /// An integer ID.\n    Integer(u64),\n    /// A string based ID.\n    Name(SharedString),\n    /// A UUID.\n    Uuid(Uuid),\n    /// An ID that's equated with a focus handle.\n    FocusHandle(FocusId),\n    /// A combination of a name and an integer.\n    NamedInteger(SharedString, u64),\n    /// A path\n    Path(Arc<std::path::Path>),\n}\n\nimpl ElementId {\n    /// Constructs an `ElementId::NamedInteger` from a name and `usize`.\n    pub fn named_usize(name: impl Into<SharedString>, integer: usize) -> ElementId {\n        Self::NamedInteger(name.into(), integer as u64)\n    }\n}\n\nimpl Display for ElementId {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            ElementId::View(entity_id) => write!(f, \"view-{}\", entity_id)?,\n            ElementId::Integer(ix) => write!(f, \"{}\", ix)?,\n            ElementId::Name(name) => write!(f, \"{}\", name)?,\n            ElementId::FocusHandle(_) => write!(f, \"FocusHandle\")?,\n            ElementId::NamedInteger(s, i) => write!(f, \"{}-{}\", s, i)?,\n            ElementId::Uuid(uuid) => write!(f, \"{}\", uuid)?,\n            ElementId::Path(path) => write!(f, \"{}\", path.display())?,\n        }\n\n        Ok(())\n    }\n}\n\nimpl TryInto<SharedString> for ElementId {\n    type Error = anyhow::Error;\n\n    fn try_into(self) -> anyhow::Result<SharedString> {\n        if let ElementId::Name(name) = self {\n            Ok(name)\n        } else {\n            Err(anyhow!(\"element id is not string\"))\n        }\n    }\n}\n\nimpl From<usize> for ElementId {\n    fn from(id: usize) -> Self {\n        ElementId::Integer(id as u64)\n    }\n}\n\nimpl From<i32> for ElementId {\n    fn from(id: i32) -> Self {\n        Self::Integer(id as u64)\n    }\n}\n\nimpl From<SharedString> for ElementId {\n    fn from(name: SharedString) -> Self {\n        ElementId::Name(name)\n    }\n}\n\nimpl From<Arc<std::path::Path>> for ElementId {\n    fn from(path: Arc<std::path::Path>) -> Self {\n        ElementId::Path(path)\n    }\n}\n\nimpl From<&'static str> for ElementId {\n    fn from(name: &'static str) -> Self {\n        ElementId::Name(name.into())\n    }\n}\n\nimpl<'a> From<&'a FocusHandle> for ElementId {\n    fn from(handle: &'a FocusHandle) -> Self {\n        ElementId::FocusHandle(handle.id)\n    }\n}\n\nimpl From<(&'static str, EntityId)> for ElementId {\n    fn from((name, id): (&'static str, EntityId)) -> Self {\n        ElementId::NamedInteger(name.into(), id.as_u64())\n    }\n}\n\nimpl From<(&'static str, usize)> for ElementId {\n    fn from((name, id): (&'static str, usize)) -> Self {\n        ElementId::NamedInteger(name.into(), id as u64)\n    }\n}\n\nimpl From<(SharedString, usize)> for ElementId {\n    fn from((name, id): (SharedString, usize)) -> Self {\n        ElementId::NamedInteger(name, id as u64)\n    }\n}\n\nimpl From<(&'static str, u64)> for ElementId {\n    fn from((name, id): (&'static str, u64)) -> Self {\n        ElementId::NamedInteger(name.into(), id)\n    }\n}\n\nimpl From<Uuid> for ElementId {\n    fn from(value: Uuid) -> Self {\n        Self::Uuid(value)\n    }\n}\n\nimpl From<(&'static str, u32)> for ElementId {\n    fn from((name, id): (&'static str, u32)) -> Self {\n        ElementId::NamedInteger(name.into(), id.into())\n    }\n}\n\n/// A rectangle to be rendered in the window at the given position and size.\n/// Passed as an argument [`Window::paint_quad`].\n#[derive(Clone)]\npub struct PaintQuad {\n    /// The bounds of the quad within the window.\n    pub bounds: Bounds<Pixels>,\n    /// The radii of the quad's corners.\n    pub corner_radii: Corners<Pixels>,\n    /// The background color of the quad.\n    pub background: Background,\n    /// The widths of the quad's borders.\n    pub border_widths: Edges<Pixels>,\n    /// The color of the quad's borders.\n    pub border_color: Hsla,\n    /// The style of the quad's borders.\n    pub border_style: BorderStyle,\n    /// The transformation to apply to the quad.\n    pub transformation: TransformationMatrix,\n}\n\nimpl PaintQuad {\n    /// Sets the corner radii of the quad.\n    pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {\n        PaintQuad {\n            corner_radii: corner_radii.into(),\n            ..self\n        }\n    }\n\n    /// Sets the border widths of the quad.\n    pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {\n        PaintQuad {\n            border_widths: border_widths.into(),\n            ..self\n        }\n    }\n\n    /// Sets the border color of the quad.\n    pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {\n        PaintQuad {\n            border_color: border_color.into(),\n            ..self\n        }\n    }\n\n    /// Sets the background color of the quad.\n    pub fn background(self, background: impl Into<Background>) -> Self {\n        PaintQuad {\n            background: background.into(),\n            ..self\n        }\n    }\n\n    /// Sets the transformation matrix to apply to the quad.\n    pub(crate) fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {\n        PaintQuad {\n            transformation: transformation.into(),\n            ..self\n        }\n    }\n}\n\n/// Creates a quad with the given parameters.\npub fn quad(\n    bounds: Bounds<Pixels>,\n    corner_radii: impl Into<Corners<Pixels>>,\n    background: impl Into<Background>,\n    border_widths: impl Into<Edges<Pixels>>,\n    border_color: impl Into<Hsla>,\n    border_style: BorderStyle,\n) -> PaintQuad {\n    PaintQuad {\n        bounds,\n        corner_radii: corner_radii.into(),\n        background: background.into(),\n        border_widths: border_widths.into(),\n        border_color: border_color.into(),\n        border_style,\n        transformation: TransformationMatrix::default(),\n    }\n}\n\npub(crate) fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad {\n    PaintQuad {\n        transformation,\n        ..quad\n    }\n}\n\n/// Creates a filled quad with the given bounds and background color.\npub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {\n    PaintQuad {\n        bounds: bounds.into(),\n        corner_radii: (0.).into(),\n        background: background.into(),\n        border_widths: (0.).into(),\n        border_color: transparent_black(),\n        border_style: BorderStyle::default(),\n        transformation: TransformationMatrix::default(),\n    }\n}\n\n/// Creates a rectangle outline with the given bounds, border color, and a 1px border width\npub fn outline(\n    bounds: impl Into<Bounds<Pixels>>,\n    border_color: impl Into<Hsla>,\n    border_style: BorderStyle,\n) -> PaintQuad {\n    PaintQuad {\n        bounds: bounds.into(),\n        corner_radii: (0.).into(),\n        background: transparent_black().into(),\n        border_widths: (1.).into(),\n        border_color: border_color.into(),\n        border_style,\n        transformation: TransformationMatrix::default(),\n    }\n}\n",
  "raw_output": {
    "raw_edits": "<edits>\n\n<old_text>\n    /// Sets the transformation matrix to apply to the quad.\n    pub(crate) fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {\n        PaintQuad {\n            transformation: transformation.into(),\n            ..self\n        }\n    }\n</old_text>\n<new_text>\n    /// Sets the transformation matrix to apply to the quad.\n    pub fn transformation(self, transformation: impl Into<TransformationMatrix>) -> Self {\n        PaintQuad {\n            transformation: transformation.into(),\n            ..self\n        }\n    }\n    \n    /// Rotates the quad around its origin by the given angle (in radians, clockwise).\n    pub fn rotate(self, angle: impl Into<Radians>) -> Self {\n        PaintQuad {\n            transformation: self.transformation.rotate(angle.into()),\n            ..self\n        }\n    }\n    \n    /// Scales the quad around its origin by the given factor.\n    pub fn scale(self, scale: impl Into<Size<f32>>) -> Self {\n        PaintQuad {\n            transformation: self.transformation.scale(scale.into()),\n            ..self\n        }\n    }\n    \n    /// Translates the quad by the given offset.\n    pub fn translate(self, offset: impl Into<Point<ScaledPixels>>) -> Self {\n        PaintQuad {\n            transformation: self.transformation.translate(offset.into()),\n            ..self\n        }\n    }\n</new_text>\n\n<old_text>\npub(crate) fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad {\n    PaintQuad {\n        transformation,\n        ..quad\n    }\n}\n</old_text>\n<new_text>\n/// Applies a transformation matrix to a quad.\npub fn transform_quad(quad: PaintQuad, transformation: TransformationMatrix) -> PaintQuad {\n    PaintQuad {\n        transformation,\n        ..quad\n    }\n}\n</new_text>\n\n</edits>",
    "parser_metrics": {
      "tags": 4,
      "mismatched_tags": 0
    }
  }
}

Agent

Now, let's also add some additional helper functions to create quads with transformations more easily:

Use Tool: edit_file (toolu_01QsUQvZAbGdatfVFMrovVLq)

{
  "create_or_overwrite": false,
  "display_description": "Add helper functions for creating transformed quads",
  "path": "zed/crates/gpui/src/window.rs"
}

Tool Results: toolu_01QsUQvZAbGdatfVFMrovVLq

Edited zed/crates/gpui/src/window.rs:

@@ -4265,6 +4265,16 @@
             ..self
         }
     }
+    
+    /// Applies multiple transformations in sequence: first rotation, then scaling, then translation.
+    pub fn transform(
+        self, 
+        angle: impl Into<Radians>, 
+        scale: impl Into<Size<f32>>,
+        offset: impl Into<Point<ScaledPixels>>
+    ) -> Self {
+        self.rotate(angle).scale(scale).translate(offset)
+    }
 }
 
 /// Creates a quad with the given parameters.
@@ -4293,6 +4303,33 @@
         transformation,
         ..quad
     }
+}
+
+/// Creates a filled quad that is rotated by the given angle.
+pub fn rotated_fill(
+    bounds: impl Into<Bounds<Pixels>>,
+    background: impl Into<Background>,
+    angle: impl Into<Radians>,
+) -> PaintQuad {
+    fill(bounds, background).rotate(angle)
+}
+
+/// Creates a filled quad that is scaled by the given factor.
+pub fn scaled_fill(
+    bounds: impl Into<Bounds<Pixels>>,
+    background: impl Into<Background>,
+    scale: impl Into<Size<f32>>,
+) -> PaintQuad {
+    fill(bounds, background).scale(scale)
+}
+
+/// Creates a filled quad that is translated by the given offset.
+pub fn translated_fill(
+    bounds: impl Into<Bounds<Pixels>>,
+    background: impl Into<Background>,
+    offset: impl Into<Point<ScaledPixels>>,
+) -> PaintQuad {
+    fill(bounds, background).translate(offset)
 }
 
 /// Creates a filled quad with the given bounds and background color.

Debug Output:

{
  "original_path": "crates/gpui/src/window.rs",
  "new_text": "use crate::{\n    Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,\n    AsyncWindowContext, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Context,\n    Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener, DispatchNodeId,\n    DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, FontId,\n    Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero, KeyBinding, KeyContext,\n    KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers,\n    ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent,\n    Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler,\n    PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams,\n    RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR,\n    SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style,\n    SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement,\n    TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance,\n    WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem,\n    point, prelude::*, px, size, transparent_black,\n};\nuse anyhow::{Context as _, Result, anyhow};\nuse collections::{FxHashMap, FxHashSet};\n#[cfg(target_os = \"macos\")]\nuse core_video::pixel_buffer::CVPixelBuffer;\nuse derive_more::{Deref, DerefMut};\nuse futures::FutureExt;\nuse futures::channel::oneshot;\nuse parking_lot::RwLock;\nuse raw_window_handle::{HandleError, HasWindowHandle};\nuse refineable::Refineable;\nuse slotmap::SlotMap;\nuse smallvec::SmallVec;\nuse std::{\n    any::{Any, TypeId},\n    borrow::Cow,\n    cell::{Cell, RefCell},\n    cmp,\n    fmt::{Debug, Display},\n    hash::{Hash, Hasher},\n    marker::PhantomData,\n    mem,\n    ops::{DerefMut, Range},\n    rc::Rc,\n    sync::{\n        Arc, Weak,\n        atomic::{AtomicUsize, Ordering::SeqCst},\n    },\n    time::{Duration, Instant},\n};\nuse util::post_inc;\nuse util::{ResultExt, measure};\nuse uuid::Uuid;\n\nmod prompts;\n\npub use prompts::*;\n\npub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1024.), px(700.));\n\n/// Represents the two different phases when dispatching events.\n#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]\npub enum DispatchPhase {\n    /// After the capture phase comes the bubble phase, in which mouse event listeners are\n    /// invoked front to back and keyboard event listeners are invoked from the focused element\n    /// to the root of the element tree. This is the phase you'll most commonly want to use when\n    /// registering event listeners.\n    #[default]\n    Bubble,\n    /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard\n    /// listeners are invoked from the root of the tree downward toward the focused element. This phase\n    /// is used for special purposes such as clearing the \"pressed\" state for click events. If\n    /// you stop event propagation during this phase, you need to know what you're doing. Handlers\n    /// outside of the immediate region may rely on detecting non-local events during this phase.\n    Capture,\n}\n\nimpl DispatchPhase {\n    /// Returns true if this represents the \"bubble\" phase.\n    pub fn bubble(self) -> bool {\n        self == DispatchPhase::Bubble\n    }\n\n    /// Returns true if this represents the \"capture\" phase.\n    pub fn capture(self) -> bool {\n        self == DispatchPhase::Capture\n    }\n}\n\nstruct WindowInvalidatorInner {\n    pub dirty: bool,\n    pub draw_phase: DrawPhase,\n    pub dirty_views: FxHashSet<EntityId>,\n}\n\n#[derive(Clone)]\npub(crate) struct WindowInvalidator {\n    inner: Rc<RefCell<WindowInvalidatorInner>>,\n}\n\nimpl WindowInvalidator {\n    pub fn new() -> Self {\n        WindowInvalidator {\n            inner: Rc::new(RefCell::new(WindowInvalidatorInner {\n                dirty: true,\n                draw_phase: DrawPhase::None,\n                dirty_views: FxHashSet::default(),\n            })),\n        }\n    }\n\n    pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {\n        let mut inner = self.inner.borrow_mut();\n        inner.dirty_views.insert(entity);\n        if inner.draw_phase == DrawPhase::None {\n            inner.dirty = true;\n            cx.push_effect(Effect::Notify { emitter: entity });\n            true\n        } else {\n            false\n        }\n    }\n\n    pub fn is_dirty(&self) -> bool {\n        self.inner.borrow().dirty\n    }\n\n    pub fn set_dirty(&self, dirty: bool) {\n        self.inner.borrow_mut().dirty = dirty\n    }\n\n    pub fn set_phase(&self, phase: DrawPhase) {\n        self.inner.borrow_mut().draw_phase = phase\n    }\n\n    pub fn take_views(&self) -> FxHashSet<EntityId> {\n        mem::take(&mut self.inner.borrow_mut().dirty_views)\n    }\n\n    pub fn replace_views(&self, views: FxHashSet<EntityId>) {\n        self.inner.borrow_mut().dirty_views = views;\n    }\n\n    pub fn not_drawing(&self) -> bool {\n        self.inner.borrow().draw_phase == DrawPhase::None\n    }\n\n    #[track_caller]\n    pub fn debug_assert_paint(&self) {\n        debug_assert!(\n            matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),\n            \"this method can only be called during paint\"\n        );\n    }\n\n    #[track_caller]\n    pub fn debug_assert_prepaint(&self) {\n        debug_assert!(\n            matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),\n            \"this method can only be called during request_layout, or prepaint\"\n        );\n    }\n\n    #[track_caller]\n    pub fn debug_assert_paint_or_prepaint(&self) {\n        debug_assert!(\n            matches!(\n                self.inner.borrow().draw_phase,\n                DrawPhase::Paint | DrawPhase::Prepaint\n            ),\n            \"this method can only be called during request_layout, prepaint, or paint\"\n        );\n    }\n}\n\ntype AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;\n\npub(crate) type AnyWindowFocusListener =\n    Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;\n\npub(crate) struct WindowFocusEvent {\n    pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,\n    pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,\n}\n\nimpl WindowFocusEvent {\n    pub fn is_focus_in(&self, focus_id: FocusId) -> bool {\n        !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id)\n    }\n\n    pub fn is_focus_out(&self, focus_id: FocusId) -> bool {\n        self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id)\n    }\n}\n\n/// This is provided when subscribing for `Context::on_focus_out` events.\npub struct FocusOutEvent {\n    /// A weak focus handle representing what was blurred.\n    pub blurred: WeakFocusHandle,\n}\n\nslotmap::new_key_type! {\n    /// A globally unique identifier for a focusable element.\n    pub struct FocusId;\n}\n\nthread_local! {\n    /// 8MB wasn't quite enough...\n    pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(32 * 1024 * 1024));\n}\n\npub(crate) type FocusMap = RwLock<SlotMap<FocusId, AtomicUsize>>;\n\nimpl FocusId {\n    /// Obtains whether the element associated with this handle is currently focused.\n    pub fn is_focused(&self, window: &Window) -> bool {\n        window.focus == Some(*self)\n    }\n\n    /// Obtains whether the element associated with this handle contains the focused\n    /// element or is itself focused.\n    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {\n        window\n            .focused(cx)\n            .map_or(false, |focused| self.contains(focused.id, window))\n    }\n\n    /// Obtains whether the element associated with this handle is contained within the\n    /// focused element or is itself focused.\n    pub fn within_focused(&self, window: &Window, cx: &App) -> bool {\n        let focused = window.focused(cx);\n        focused.map_or(false, |focused| focused.id.contains(*self, window))\n    }\n\n    /// Obtains whether this handle contains the given handle in the most recently rendered frame.\n    pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {\n        window\n            .rendered_frame\n            .dispatch_tree\n            .focus_contains(*self, other)\n    }\n}\n\n/// A handle which can be used to track and manipulate the focused element in a window.\npub struct FocusHandle {\n    pub(crate) id: FocusId,\n    handles: Arc<FocusMap>,\n}\n\nimpl std::fmt::Debug for FocusHandle {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.write_fmt(format_args!(\"FocusHandle({:?})\", self.id))\n    }\n}\n\nimpl FocusHandle {\n    pub(crate) fn new(handles: &Arc<FocusMap>) -> Self {\n        let id = handles.write().insert(AtomicUsize::new(1));\n        Self {\n            id,\n            handles: handles.clone(),\n        }\n    }\n\n    pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {\n        let lock = handles.read();\n        let ref_count = lock.get(id)?;\n        if ref_count.load(SeqCst) == 0 {\n            None\n        } else {\n            ref_count.fetch_add(1, SeqCst);\n            Some(Self {\n                id,\n                handles: handles.clone(),\n            })\n        }\n    }\n\n    /// Converts this focus handle into a weak variant, which does not prevent it from being released.\n    pub fn downgrade(&self) -> WeakFocusHandle {\n        WeakFocusHandle {\n            id: self.id,\n            handles: Arc::downgrade(&self.handles),\n        }\n    }\n\n    /// Moves the focus to the element associated with this handle.\n    pub fn focus(&self, window: &mut Window) {\n        window.focus(self)\n    }\n\n    /// Obtains whether the element associated with this handle is currently focused.\n    pub fn is_focused(&self, window: &Window) -> bool {\n        self.id.is_focused(window)\n    }\n\n    /// Obtains whether the element associated with this handle contains the focused\n    /// element or is itself focused.\n    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {\n        self.id.contains_focused(window, cx)\n    }\n\n    /// Obtains whether the element associated with this handle is contained within the\n    /// focused element or is itself focused.\n    pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {\n        self.id.within_focused(window, cx)\n    }\n\n    /// Obtains whether this handle contains the given handle in the most recently rendered frame.\n    pub fn contains(&self, other: &Self, window: &Window) -> bool {\n        self.id.contains(other.id, window)\n    }\n\n    /// Dispatch an action on the element that rendered this focus handle\n    pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {\n        if let Some(node_id) = window\n            .rendered_frame\n            .dispatch_tree\n            .focusable_node_id(self.id)\n        {\n            window.dispatch_action_on_node(node_id, action, cx)\n        }\n    }\n}\n\nimpl Clone for FocusHandle {\n    fn clone(&self) -> Self {\n        Self::for_id(self.id, &self.handles).unwrap()\n    }\n}\n\nimpl PartialEq for FocusHandle {\n    fn eq(&self, other: &Self) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for FocusHandle {}\n\nimpl Drop for FocusHandle {\n    fn drop(&mut self) {\n        self.handles\n            .read()\n            .get(self.id)\n            .unwrap()\n            .fetch_sub(1, SeqCst);\n    }\n}\n\n/// A weak reference to a focus handle.\n#[derive(Clone, Debug)]\npub struct WeakFocusHandle {\n    pub(crate) id: FocusId,\n    pub(crate) handles: Weak<FocusMap>,\n}\n\nimpl WeakFocusHandle {\n    /// Attempts to upgrade the [WeakFocusHandle] to a [FocusHandle].\n    pub fn upgrade(&self) -> Option<FocusHandle> {\n        let handles = self.handles.upgrade()?;\n        FocusHandle::for_id(self.id, &handles)\n    }\n}\n\nimpl PartialEq for WeakFocusHandle {\n    fn eq(&self, other: &WeakFocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for WeakFocusHandle {}\n\nimpl PartialEq<FocusHandle> for WeakFocusHandle {\n    fn eq(&self, other: &FocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl PartialEq<WeakFocusHandle> for FocusHandle {\n    fn eq(&self, other: &WeakFocusHandle) -> bool {\n        self.id == other.id\n    }\n}\n\n/// Focusable allows users of your view to easily\n/// focus it (using window.focus_view(cx, view))\npub trait Focusable: 'static {\n    /// Returns the focus handle associated with this view.\n    fn focus_handle(&self, cx: &App) -> FocusHandle;\n}\n\nimpl<V: Focusable> Focusable for Entity<V> {\n    fn focus_handle(&self, cx: &App) -> FocusHandle {\n        self.read(cx).focus_handle(cx)\n    }\n}\n\n/// ManagedView is a view (like a Modal, Popover, Menu, etc.)\n/// where the lifecycle of the view is handled by another view.\npub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}\n\nimpl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}\n\n/// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal.\npub struct DismissEvent;\n\ntype FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;\n\npub(crate) type AnyMouseListener =\n    Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;\n\n#[derive(Clone)]\npub(crate) struct CursorStyleRequest {\n    pub(crate) hitbox_id: Option<HitboxId>, // None represents whole window\n    pub(crate) style: CursorStyle,\n}\n\n/// An identifier for a [Hitbox].\n#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]\npub struct HitboxId(usize);\n\nimpl HitboxId {\n    /// Checks if the hitbox with this id is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        window.mouse_hit_test.0.contains(self)\n    }\n}\n\n/// A rectangular region that potentially blocks hitboxes inserted prior.\n/// See [Window::insert_hitbox] for more details.\n#[derive(Clone, Debug, Deref)]\npub struct Hitbox {\n    /// A unique identifier for the hitbox.\n    pub id: HitboxId,\n    /// The bounds of the hitbox.\n    #[deref]\n    pub bounds: Bounds<Pixels>,\n    /// The content mask when the hitbox was inserted.\n    pub content_mask: ContentMask<Pixels>,\n    /// Whether the hitbox occludes other hitboxes inserted prior.\n    pub opaque: bool,\n}\n\nimpl Hitbox {\n    /// Checks if the hitbox is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        self.id.is_hovered(window)\n    }\n}\n\n#[derive(Default, Eq, PartialEq)]\npub(crate) struct HitTest(SmallVec<[HitboxId; 8]>);\n\n/// An identifier for a tooltip.\n#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]\npub struct TooltipId(usize);\n\nimpl TooltipId {\n    /// Checks if the tooltip is currently hovered.\n    pub fn is_hovered(&self, window: &Window) -> bool {\n        window\n            .tooltip_bounds\n            .as_ref()\n            .map_or(false, |tooltip_bounds| {\n                tooltip_bounds.id == *self\n                    && tooltip_bounds.bounds.contains(&window.mouse_position())\n            })\n    }\n}\n\npub(crate) struct TooltipBounds {\n    id: TooltipId,\n    bounds: Bounds<Pixels>,\n}\n\n#[derive(Clone)]\npub(crate) struct TooltipRequest {\n    id: TooltipId,\n    tooltip: AnyTooltip,\n}\n\npub(crate) struct DeferredDraw {\n    current_view: EntityId,\n    priority: usize,\n    parent_node: DispatchNodeId,\n    element_id_stack: SmallVec<[ElementId; 32]>,\n    text_style_stack: Vec<TextStyleRefinement>,\n    element: Option<AnyElement>,\n    absolute_offset: Point<Pixels>,\n    prepaint_range: Range<PrepaintStateIndex>,\n    paint_range: Range<PaintIndex>,\n}\n\npub(crate) struct Frame {\n    pub(crate) focus: Option<FocusId>,\n    pub(crate) window_active: bool,\n    pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,\n    accessed_element_states: Vec<(GlobalElementId, TypeId)>,\n    pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,\n    pub(crate) dispatch_tree: DispatchTree,\n    pub(crate) scene: Scene,\n    pub(crate) hitboxes: Vec<Hitbox>,\n    pub(crate) deferred_draws: Vec<DeferredDraw>,\n    pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,\n    pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,\n    pub(crate) cursor_styles: Vec<CursorStyleRequest>,\n    #[cfg(any(test, feature = \"test-support\"))]\n    pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,\n}\n\n#[derive(Clone, Default)]\npub(crate) struct PrepaintStateIndex {\n    hitboxes_index: usize,\n    tooltips_index: usize,\n    deferred_draws_index: usize,\n    dispatch_tree_index: usize,\n    accessed_element_states_index: usize,\n    line_layout_index: LineLayoutIndex,\n}\n\n#[derive(Clone, Default)]\npub(crate) struct PaintIndex {\n    scene_index: usize,\n    mouse_listeners_index: usize,\n    input_handlers_index: usize,\n    cursor_styles_index: usize,\n    accessed_element_states_index: usize,\n    line_layout_index: LineLayoutIndex,\n}\n\nimpl Frame {\n    pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {\n        Frame {\n            focus: None,\n            window_active: false,\n            element_states: FxHashMap::default(),\n            accessed_element_states: Vec::new(),\n            mouse_listeners: Vec::new(),\n            dispatch_tree,\n            scene: Scene::default(),\n            hitboxes: Vec::new(),\n            deferred_draws: Vec::new(),\n            input_handlers: Vec::new(),\n            tooltip_requests: Vec::new(),\n            cursor_styles: Vec::new(),\n\n            #[cfg(any(test, feature = \"test-support\"))]\n            debug_bounds: FxHashMap::default(),\n        }\n    }\n\n    pub(crate) fn clear(&mut self) {\n        self.element_states.clear();\n        self.accessed_element_states.clear();\n        self.mouse_listeners.clear();\n        self.dispatch_tree.clear();\n        self.scene.clear();\n        self.input_handlers.clear();\n        self.tooltip_requests.clear();\n        self.cursor_styles.clear();\n        self.hitboxes.clear();\n        self.deferred_draws.clear();\n        self.focus = None;\n    }\n\n    pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {\n        let mut hit_test = HitTest::default();\n        for hitbox in self.hitboxes.iter().rev() {\n            let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds);\n            if bounds.contains(&position) {\n                hit_test.0.push(hitbox.id);\n                if hitbox.opaque {\n                    break;\n                }\n            }\n        }\n        hit_test\n    }\n\n    pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {\n        self.focus\n            .map(|focus_id| self.dispatch_tree.focus_path(focus_id))\n            .unwrap_or_default()\n    }\n\n    pub(crate) fn finish(&mut self, prev_frame: &mut Self) {\n        for element_state_key in &self.accessed_element_states {\n            if let Some((element_state_key, element_state)) =\n                prev_frame.element_states.remove_entry(element_state_key)\n            {\n                self.element_states.insert(element_state_key, element_state);\n            }\n        }\n\n        self.scene.finish();\n    }\n}\n\n/// Holds the state for a specific window.\npub struct Window {\n    pub(crate) handle: AnyWindowHandle,\n    pub(crate) invalidator: WindowInvalidator,\n    pub(crate) removed: bool,\n    pub(crate) platform_window: Box<dyn PlatformWindow>,\n    display_id: Option<DisplayId>,\n    sprite_atlas: Arc<dyn PlatformAtlas>,\n    text_system: Arc<WindowTextSystem>,\n    rem_size: Pixels,\n    /// The stack of override values for the window's rem size.\n    ///\n    /// This is used by `with_rem_size` to allow rendering an element tree with\n    /// a given rem size.\n    rem_size_override_stack: SmallVec<[Pixels; 8]>,\n    pub(crate) viewport_size: Size<Pixels>,\n    layout_engine: Option<TaffyLayoutEngine>,\n    pub(crate) root: Option<AnyView>,\n    pub(crate) element_id_stack: SmallVec<[ElementId; 32]>,\n    pub(crate) text_style_stack: Vec<TextStyleRefinement>,\n    pub(crate) rendered_entity_stack: Vec<EntityId>,\n    pub(crate) element_offset_stack: Vec<Point<Pixels>>,\n    pub(crate) element_opacity: Option<f32>,\n    pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,\n    pub(crate) requested_autoscroll: Option<Bounds<Pixels>>,\n    pub(crate) image_cache_stack: Vec<AnyImageCache>,\n    pub(crate) rendered_frame: Frame,\n    pub(crate) next_frame: Frame,\n    pub(crate) next_hitbox_id: HitboxId,\n    pub(crate) next_tooltip_id: TooltipId,\n    pub(crate) tooltip_bounds: Option<TooltipBounds>,\n    next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,\n    pub(crate) dirty_views: FxHashSet<EntityId>,\n    focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,\n    pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,\n    default_prevented: bool,\n    mouse_position: Point<Pixels>,\n    mouse_hit_test: HitTest,\n    modifiers: Modifiers,\n    scale_factor: f32,\n    pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,\n    appearance: WindowAppearance,\n    pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,\n    active: Rc<Cell<bool>>,\n    hovered: Rc<Cell<bool>>,\n    pub(crate) needs_present: Rc<Cell<bool>>,\n    pub(crate) last_input_timestamp: Rc<Cell<Instant>>,\n    pub(crate) refreshing: bool,\n    pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,\n    pub(crate) focus: Option<FocusId>,\n    focus_enabled: bool,\n    pending_input: Option<PendingInput>,\n    pending_modifier: ModifierState,\n    pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,\n    prompt: Option<RenderablePromptHandle>,\n    pub(crate) client_inset: Option<Pixels>,\n}\n\n#[derive(Clone, Debug, Default)]\nstruct ModifierState {\n    modifiers: Modifiers,\n    saw_keystroke: bool,\n}\n\n#[derive(Clone, Copy, Debug, Eq, PartialEq)]\npub(crate) enum DrawPhase {\n    None,\n    Prepaint,\n    Paint,\n    Focus,\n}\n\n#[derive(Default, Debug)]\nstruct PendingInput {\n    keystrokes: SmallVec<[Keystroke; 1]>,\n    focus: Option<FocusId>,\n    timer: Option<Task<()>>,\n}\n\npub(crate) struct ElementStateBox {\n    pub(crate) inner: Box<dyn Any>,\n    #[cfg(debug_assertions)]\n    pub(crate) type_name: &'static str,\n}\n\nfn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> Bounds<Pixels> {\n    const DEFAULT_WINDOW_OFFSET: Point<Pixels> = point(px(0.), px(35.));\n\n    // TODO, BUG: if you open a window with the currently active window\n    // on the stack, this will erroneously select the 'unwrap_or_else'\n    // code path\n    cx.active_window()\n        .and_then(|w| w.update(cx, |_, window, _| window.bounds()).ok())\n        .map(|mut bounds| {\n            bounds.origin += DEFAULT_WINDOW_OFFSET;\n            bounds\n        })\n        .unwrap_or_else(|| {\n            let display = display_id\n                .map(|id| cx.find_display(id))\n                .unwrap_or_else(|| cx.primary_display());\n\n            display\n                .map(|display| display.default_bounds())\n                .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE))\n        })\n}\n\nimpl Window {\n    pub(crate) fn new(\n        handle: AnyWindowHandle,\n        options: WindowOptions,\n        cx: &mut App,\n    ) -> Result<Self> {\n        let WindowOptions {\n            window_bounds,\n            titlebar,\n            focus,\n            show,\n            kind,\n            is_movable,\n            display_id,\n            window_background,\n            app_id,\n            window_min_size,\n            window_decorations,\n        } = options;\n\n        let bounds = window_bounds\n            .map(|bounds| bounds.get_bounds())\n            .unwrap_or_else(|| default_bounds(display_id, cx));\n        let mut platform_window = cx.platform.open_window(\n            handle,\n            WindowParams {\n                bounds,\n                titlebar,\n                kind,\n                is_movable,\n                focus,\n                show,\n                display_id,\n                window_min_size,\n            },\n        )?;\n        let display_id = platform_window.display().map(|display| display.id());\n        let sprite_atlas = platform_window.sprite_atlas();\n        let mouse_position = platform_window.mouse_position();\n        let modifiers = platform_window.modifiers();\n        let content_size = platform_window.content_size();\n        let scale_factor = platform_window.scale_factor();\n        let appearance = platform_window.appearance();\n        let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));\n        let invalidator = WindowInvalidator::new();\n        let active = Rc::new(Cell::new(platform_window.is_active()));\n        let hovered = Rc::new(Cell::new(platform_window.is_hovered()));\n        let needs_present = Rc::new(Cell::new(false));\n        let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();\n        let last_input_timestamp = Rc::new(Cell::new(Instant::now()));\n\n        platform_window\n            .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server));\n        platform_window.set_background_appearance(window_background);\n\n        if let Some(ref window_open_state) = window_bounds {\n            match window_open_state {\n                WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),\n                WindowBounds::Maximized(_) => platform_window.zoom(),\n                WindowBounds::Windowed(_) => {}\n            }\n        }\n\n        platform_window.on_close(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                let _ = handle.update(&mut cx, |_, window, _| window.remove_window());\n            }\n        }));\n        platform_window.on_request_frame(Box::new({\n            let mut cx = cx.to_async();\n            let invalidator = invalidator.clone();\n            let active = active.clone();\n            let needs_present = needs_present.clone();\n            let next_frame_callbacks = next_frame_callbacks.clone();\n            let last_input_timestamp = last_input_timestamp.clone();\n            move |request_frame_options| {\n                let next_frame_callbacks = next_frame_callbacks.take();\n                if !next_frame_callbacks.is_empty() {\n                    handle\n                        .update(&mut cx, |_, window, cx| {\n                            for callback in next_frame_callbacks {\n                                callback(window, cx);\n                            }\n                        })\n                        .log_err();\n                }\n\n                // Keep presenting the current scene for 1 extra second since the\n                // last input to prevent the display from underclocking the refresh rate.\n                let needs_present = request_frame_options.require_presentation\n                    || needs_present.get()\n                    || (active.get()\n                        && last_input_timestamp.get().elapsed() < Duration::from_secs(1));\n\n                if invalidator.is_dirty() {\n                    measure(\"frame duration\", || {\n                        handle\n                            .update(&mut cx, |_, window, cx| {\n                                window.draw(cx);\n                                window.present();\n                            })\n                            .log_err();\n                    })\n                } else if needs_present {\n                    handle\n                        .update(&mut cx, |_, window, _| window.present())\n                        .log_err();\n                }\n\n                handle\n                    .update(&mut cx, |_, window, _| {\n                        window.complete_frame();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_resize(Box::new({\n            let mut cx = cx.to_async();\n            move |_, _| {\n                handle\n                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_moved(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                handle\n                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_appearance_changed(Box::new({\n            let mut cx = cx.to_async();\n            move || {\n                handle\n                    .update(&mut cx, |_, window, cx| window.appearance_changed(cx))\n                    .log_err();\n            }\n        }));\n        platform_window.on_active_status_change(Box::new({\n            let mut cx = cx.to_async();\n            move |active| {\n                handle\n                    .update(&mut cx, |_, window, cx| {\n                        window.active.set(active);\n                        window.modifiers = window.platform_window.modifiers();\n                        window\n                            .activation_observers\n                            .clone()\n                            .retain(&(), |callback| callback(window, cx));\n                        window.refresh();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_hover_status_change(Box::new({\n            let mut cx = cx.to_async();\n            move |active| {\n                handle\n                    .update(&mut cx, |_, window, _| {\n                        window.hovered.set(active);\n                        window.refresh();\n                    })\n                    .log_err();\n            }\n        }));\n        platform_window.on_input({\n            let mut cx = cx.to_async();\n            Box::new(move |event| {\n                handle\n                    .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))\n                    .log_err()\n                    .unwrap_or(DispatchEventResult::default())\n            })\n        });\n\n        if let Some(app_id) = app_id {\n            platform_window.set_app_id(&app_id);\n        }\n\n        platform_window.map_window().unwrap();\n\n        Ok(Window {\n            handle,\n            invalidator,\n            removed: false,\n            platform_window,\n            display_id,\n            sprite_atlas,\n            text_system,\n            rem_size: px(16.),\n            rem_size_override_stack: SmallVec::new(),\n            viewport_size: content_size,\n            layout_engine: Some(TaffyLayoutEngine::new()),\n            root: None,\n            element_id_stack: SmallVec::default(),\n            text_style_stack: Vec::new(),\n            rendered_entity_stack: Vec::new(),\n            element_offset_stack: Vec::new(),\n            content_mask_stack: Vec::new(),\n            element_opacity: None,\n            requested_autoscroll: None,\n            rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),\n            next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),\n            next_frame_callbacks,\n            next_hitbox_id: HitboxId::default(),\n            next_tooltip_id: TooltipId::default(),\n            tooltip_bounds: None,\n            dirty_views: FxHashSet::default(),\n            focus_listeners: SubscriberSet::new(),\n            focus_lost_listeners: SubscriberSet::new(),\n            default_prevented: true,\n            mouse_position,\n            mouse_hit_test: HitTest::default(),\n            modifiers,\n            scale_factor,\n            bounds_observers: SubscriberSet::new(),\n            appearance,\n            appearance_observers: SubscriberSet::new(),\n            active,\n            hovered,\n            needs_present,\n            last_input_timestamp,\n            refreshing: false,\n            activation_observers: SubscriberSet::new(),\n            focus: None,\n            focus_enabled: true,\n            pending_input: None,\n            pending_modifier: ModifierState::default(),\n            pending_input_observers: SubscriberSet::new(),\n            prompt: None,\n            client_inset: None,\n            image_cache_stack: Vec::new(),\n        })\n    }\n\n    pub(crate) fn new_focus_listener(\n        &self,\n        value: AnyWindowFocusListener,\n    ) -> (Subscription, impl FnOnce() + use<>) {\n        self.focus_listeners.insert((), value)\n    }\n}\n\n#[derive(Clone, Debug, Default, PartialEq, Eq)]\npub(crate) struct DispatchEventResult {\n    pub propagate: bool,\n    pub default_prevented: bool,\n}\n\n/// Indicates which region of the window is visible. Content falling outside of this mask will not be\n/// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type\n/// to leave room to support more complex shapes in the future.\n#[derive(Clone, Debug, Default, PartialEq, Eq)]\n#[repr(C)]\npub struct ContentMask<P: Clone + Default + Debug> {\n    /// The bounds\n    pub bounds: Bounds<P>,\n}\n\nimpl ContentMask<Pixels> {\n    /// Scale the content mask's pixel units by the given scaling factor.\n    pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {\n        ContentMask {\n            bounds: self.bounds.scale(factor),\n        }\n    }\n\n    /// Intersect the content mask with the given content mask.\n    pub fn intersect(&self, other: &Self) -> Self {\n        let bounds = self.bounds.intersect(&other.bounds);\n        ContentMask { bounds }\n    }\n}\n\nimpl Window {\n    fn mark_view_dirty(&mut self, view_id: EntityId) {\n        // Mark ancestor views as dirty. If already in the `dirty_views` set, then all its ancestors\n        // should already be dirty.\n        for view_id in self\n            .rendered_frame\n            .dispatch_tree\n            .view_path(view_id)\n            .into_iter()\n            .rev()\n        {\n            if !self.dirty_views.insert(view_id) {\n                break;\n            }\n        }\n    }\n\n    /// Registers a callback to be invoked when the window appearance changes.\n    pub fn observe_window_appearance(\n        &self,\n        mut callback: impl FnMut(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let (subscription, activate) = self.appearance_observers.insert(\n            (),\n            Box::new(move |window, cx| {\n                callback(window, cx);\n                true\n            }),\n        );\n        activate();\n        subscription\n    }\n\n    /// Replaces the root entity of the window with a new one.\n    pub fn replace_root<E>(\n        &mut self,\n        cx: &mut App,\n        build_view: impl FnOnce(&mut Window, &mut Context<E>) -> E,\n    ) -> Entity<E>\n    where\n        E: 'static + Render,\n    {\n        let view = cx.new(|cx| build_view(self, cx));\n        self.root = Some(view.clone().into());\n        self.refresh();\n        view\n    }\n\n    /// Returns the root entity of the window, if it has one.\n    pub fn root<E>(&self) -> Option<Option<Entity<E>>>\n    where\n        E: 'static + Render,\n    {\n        self.root\n            .as_ref()\n            .map(|view| view.clone().downcast::<E>().ok())\n    }\n\n    /// Obtain a handle to the window that belongs to this context.\n    pub fn window_handle(&self) -> AnyWindowHandle {\n        self.handle\n    }\n\n    /// Mark the window as dirty, scheduling it to be redrawn on the next frame.\n    pub fn refresh(&mut self) {\n        if self.invalidator.not_drawing() {\n            self.refreshing = true;\n            self.invalidator.set_dirty(true);\n        }\n    }\n\n    /// Close this window.\n    pub fn remove_window(&mut self) {\n        self.removed = true;\n    }\n\n    /// Obtain the currently focused [`FocusHandle`]. If no elements are focused, returns `None`.\n    pub fn focused(&self, cx: &App) -> Option<FocusHandle> {\n        self.focus\n            .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))\n    }\n\n    /// Move focus to the element associated with the given [`FocusHandle`].\n    pub fn focus(&mut self, handle: &FocusHandle) {\n        if !self.focus_enabled || self.focus == Some(handle.id) {\n            return;\n        }\n\n        self.focus = Some(handle.id);\n        self.clear_pending_keystrokes();\n        self.refresh();\n    }\n\n    /// Remove focus from all elements within this context's window.\n    pub fn blur(&mut self) {\n        if !self.focus_enabled {\n            return;\n        }\n\n        self.focus = None;\n        self.refresh();\n    }\n\n    /// Blur the window and don't allow anything in it to be focused again.\n    pub fn disable_focus(&mut self) {\n        self.blur();\n        self.focus_enabled = false;\n    }\n\n    /// Accessor for the text system.\n    pub fn text_system(&self) -> &Arc<WindowTextSystem> {\n        &self.text_system\n    }\n\n    /// The current text style. Which is composed of all the style refinements provided to `with_text_style`.\n    pub fn text_style(&self) -> TextStyle {\n        let mut style = TextStyle::default();\n        for refinement in &self.text_style_stack {\n            style.refine(refinement);\n        }\n        style\n    }\n\n    /// Check if the platform window is maximized\n    /// On some platforms (namely Windows) this is different than the bounds being the size of the display\n    pub fn is_maximized(&self) -> bool {\n        self.platform_window.is_maximized()\n    }\n\n    /// request a certain window decoration (Wayland)\n    pub fn request_decorations(&self, decorations: WindowDecorations) {\n        self.platform_window.request_decorations(decorations);\n    }\n\n    /// Start a window resize operation (Wayland)\n    pub fn start_window_resize(&self, edge: ResizeEdge) {\n        self.platform_window.start_window_resize(edge);\n    }\n\n    /// Return the `WindowBounds` to indicate that how a window should be opened\n    /// after it has been closed\n    pub fn window_bounds(&self) -> WindowBounds {\n        self.platform_window.window_bounds()\n    }\n\n    /// Return the `WindowBounds` excluding insets (Wayland and X11)\n    pub fn inner_window_bounds(&self) -> WindowBounds {\n        self.platform_window.inner_window_bounds()\n    }\n\n    /// Dispatch the given action on the currently focused element.\n    pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {\n        let focus_handle = self.focused(cx);\n\n        let window = self.handle;\n        cx.defer(move |cx| {\n            window\n                .update(cx, |_, window, cx| {\n                    let node_id = focus_handle\n                        .and_then(|handle| {\n                            window\n                                .rendered_frame\n                                .dispatch_tree\n                                .focusable_node_id(handle.id)\n                        })\n                        .unwrap_or_else(|| window.rendered_frame.dispatch_tree.root_node_id());\n\n                    window.dispatch_action_on_node(node_id, action.as_ref(), cx);\n                })\n                .log_err();\n        })\n    }\n\n    pub(crate) fn dispatch_keystroke_observers(\n        &mut self,\n        event: &dyn Any,\n        action: Option<Box<dyn Action>>,\n        context_stack: Vec<KeyContext>,\n        cx: &mut App,\n    ) {\n        let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {\n            return;\n        };\n\n        cx.keystroke_observers.clone().retain(&(), move |callback| {\n            (callback)(\n                &KeystrokeEvent {\n                    keystroke: key_down_event.keystroke.clone(),\n                    action: action.as_ref().map(|action| action.boxed_clone()),\n                    context_stack: context_stack.clone(),\n                },\n                self,\n                cx,\n            )\n        });\n    }\n\n    /// Schedules the given function to be run at the end of the current effect cycle, allowing entities\n    /// that are currently on the stack to be returned to the app.\n    pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {\n        let handle = self.handle;\n        cx.defer(move |cx| {\n            handle.update(cx, |_, window, cx| f(window, cx)).ok();\n        });\n    }\n\n    /// Subscribe to events emitted by a entity.\n    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.\n    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.\n    pub fn observe<T: 'static>(\n        &mut self,\n        observed: &Entity<T>,\n        cx: &mut App,\n        mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let entity_id = observed.entity_id();\n        let observed = observed.downgrade();\n        let window_handle = self.handle;\n        cx.new_observer(\n            entity_id,\n            Box::new(move |cx| {\n                window_handle\n                    .update(cx, |_, window, cx| {\n                        if let Some(handle) = observed.upgrade() {\n                            on_notify(handle, window, cx);\n                            true\n                        } else {\n                            false\n                        }\n                    })\n                    .unwrap_or(false)\n            }),\n        )\n    }\n\n    /// Subscribe to events emitted by a entity.\n    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.\n    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.\n    pub fn subscribe<Emitter, Evt>(\n        &mut self,\n        entity: &Entity<Emitter>,\n        cx: &mut App,\n        mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,\n    ) -> Subscription\n    where\n        Emitter: EventEmitter<Evt>,\n        Evt: 'static,\n    {\n        let entity_id = entity.entity_id();\n        let handle = entity.downgrade();\n        let window_handle = self.handle;\n        cx.new_subscription(\n            entity_id,\n            (\n                TypeId::of::<Evt>(),\n                Box::new(move |event, cx| {\n                    window_handle\n                        .update(cx, |_, window, cx| {\n                            if let Some(entity) = handle.upgrade() {\n                                let event = event.downcast_ref().expect(\"invalid event type\");\n                                on_event(entity, event, window, cx);\n                                true\n                            } else {\n                                false\n                            }\n                        })\n                        .unwrap_or(false)\n                }),\n            ),\n        )\n    }\n\n    /// Register a callback to be invoked when the given `Entity` is released.\n    pub fn observe_release<T>(\n        &self,\n        entity: &Entity<T>,\n        cx: &mut App,\n        mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,\n    ) -> Subscription\n    where\n        T: 'static,\n    {\n        let entity_id = entity.entity_id();\n        let window_handle = self.handle;\n        let (subscription, activate) = cx.release_listeners.insert(\n            entity_id,\n            Box::new(move |entity, cx| {\n                let entity = entity.downcast_mut().expect(\"invalid entity type\");\n                let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));\n            }),\n        );\n        activate();\n        subscription\n    }\n\n    /// Creates an [`AsyncWindowContext`], which has a static lifetime and can be held across\n    /// await points in async code.\n    pub fn to_async(&self, cx: &App) -> AsyncWindowContext {\n        AsyncWindowContext::new_context(cx.to_async(), self.handle)\n    }\n\n    /// Schedule the given closure to be run directly after the current frame is rendered.\n    pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) {\n        RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback));\n    }\n\n    /// Schedule a frame to be drawn on the next animation frame.\n    ///\n    /// This is useful for elements that need to animate continuously, such as a video player or an animated GIF.\n    /// It will cause the window to redraw on the next frame, even if no other changes have occurred.\n    ///\n    /// If called from within a view, it will notify that view on the next frame. Otherwise, it will refresh the entire window.\n    pub fn request_animation_frame(&self) {\n        let entity = self.current_view();\n        self.on_next_frame(move |_, cx| cx.notify(entity));\n    }\n\n    /// Spawn the future returned by the given closure on the application thread pool.\n    /// The closure is provided a handle to the current window and an `AsyncWindowContext` for\n    /// use within your future.\n    #[track_caller]\n    pub fn spawn<AsyncFn, R>(&self, cx: &App, f: AsyncFn) -> Task<R>\n    where\n        R: 'static,\n        AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,\n    {\n        let handle = self.handle;\n        cx.spawn(async move |app| {\n            let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);\n            f(&mut async_window_cx).await\n        })\n    }\n\n    fn bounds_changed(&mut self, cx: &mut App) {\n        self.scale_factor = self.platform_window.scale_factor();\n        self.viewport_size = self.platform_window.content_size();\n        self.display_id = self.platform_window.display().map(|display| display.id());\n\n        self.refresh();\n\n        self.bounds_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    /// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays.\n    pub fn bounds(&self) -> Bounds<Pixels> {\n        self.platform_window.bounds()\n    }\n\n    /// Set the content size of the window.\n    pub fn resize(&mut self, size: Size<Pixels>) {\n        self.platform_window.resize(size);\n    }\n\n    /// Returns whether or not the window is currently fullscreen\n    pub fn is_fullscreen(&self) -> bool {\n        self.platform_window.is_fullscreen()\n    }\n\n    pub(crate) fn appearance_changed(&mut self, cx: &mut App) {\n        self.appearance = self.platform_window.appearance();\n\n        self.appearance_observers\n            .clone()\n            .retain(&(), |callback| callback(self, cx));\n    }\n\n    /// Returns the appearance of the current window.\n    pub fn appearance(&self) -> WindowAppearance {\n        self.appearance\n    }\n\n    /// Returns the size of the drawable area within the window.\n    pub fn viewport_size(&self) -> Size<Pixels> {\n        self.viewport_size\n    }\n\n    /// Returns whether this window is focused by the operating system (receiving key events).\n    pub fn is_window_active(&self) -> bool {\n        self.active.get()\n    }\n\n    /// Returns whether this window is considered to be the window\n    /// that currently owns the mouse cursor.\n    /// On mac, this is equivalent to `is_window_active`.\n    pub fn is_window_hovered(&self) -> bool {\n        if cfg!(any(\n            target_os = \"windows\",\n            target_os = \"linux\",\n            target_os = \"freebsd\"\n        )) {\n            self.hovered.get()\n        } else {\n            self.is_window_active()\n        }\n    }\n\n    /// Toggle zoom on the window.\n    pub fn zoom_window(&self) {\n        self.platform_window.zoom();\n    }\n\n    /// Opens the native title bar context menu, useful when implementing client side decorations (Wayland and X11)\n    pub fn show_window_menu(&self, position: Point<Pixels>) {\n        self.platform_window.show_window_menu(position)\n    }\n\n    /// Tells the compositor to take control of window movement (Wayland and X11)\n    ///\n    /// Events may not be received during a move operation.\n    pub fn start_window_move(&self) {\n        self.platform_window.start_window_move()\n    }\n\n    /// When using client side decorations, set this to the width of the invisible decorations (Wayland and X11)\n    pub fn set_client_inset(&mut self, inset: Pixels) {\n        self.client_inset = Some(inset);\n        self.platform_window.set_client_inset(inset);\n    }\n\n    /// Returns the client_inset value by [`Self::set_client_inset`].\n    pub fn client_inset(&self) -> Option<Pixels> {\n        self.client_inset\n    }\n\n    /// Returns whether the title bar window controls need to be rendered by the application (Wayland and X11)\n    pub fn window_decorations(&self) -> Decorations {\n        self.platform_window.window_decorations()\n    }\n\n    /// Returns which window controls are currently visible (Wayland)\n    pub fn window_controls(&self) -> WindowControls {\n        self.platform_window.window_controls()\n    }\n\n    /// Updates the window's title at the platform level.\n    pub fn set_window_title(&mut self, title: &str) {\n        self.platform_window.set_title(title);\n    }\n\n    /// Sets the application identifier.\n    pub fn set_app_id(&mut self, app_id: &str) {\n        self.platform_window.set_app_id(app_id);\n    }\n\n    /// Sets the window background appearance.\n    pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {\n        self.platform_window\n            .set_background_appearance(background_appearance);\n    }\n\n    /// Mark the window as dirty at the platform level.\n    pub fn set_window_edited(&mut self, edited: bool) {\n        self.platform_window.set_edited(edited);\n    }\n\n    /// Determine the display on which the window is visible.\n    pub fn display(&self, cx: &App) -> Option<Rc<dyn PlatformDisplay>> {\n        cx.platform\n            .displays()\n            .into_iter()\n            .find(|display| Some(display.id()) == self.display_id)\n    }\n\n    /// Show the platform character palette.\n    pub fn show_character_palette(&self) {\n        self.platform_window.show_character_palette();\n    }\n\n    /// The scale factor of the display associated with the window. For example, it could\n    /// return 2.0 for a \"retina\" display, indicating that each logical pixel should actually\n    /// be rendered as two pixels on screen.\n    pub fn scale_factor(&self) -> f32 {\n        self.scale_factor\n    }\n\n    /// The size of an em for the base font of the application. Adjusting this value allows the\n    /// UI to scale, just like zooming a web page.\n    pub fn rem_size(&self) -> Pixels {\n        self.rem_size_override_stack\n            .last()\n            .copied()\n            .unwrap_or(self.rem_size)\n    }\n\n    /// Sets the size of an em for the base font of the application. Adjusting this value allows the\n    /// UI to scale, just like zooming a web page.\n    pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {\n        self.rem_size = rem_size.into();\n    }\n\n    /// Acquire a globally unique identifier for the given ElementId.\n    /// Only valid for the duration of the provided closure.\n    pub fn with_global_id<R>(\n        &mut self,\n        element_id: ElementId,\n        f: impl FnOnce(&GlobalElementId, &mut Self) -> R,\n    ) -> R {\n        self.element_id_stack.push(element_id);\n        let global_id = GlobalElementId(self.element_id_stack.clone());\n        let result = f(&global_id, self);\n        self.element_id_stack.pop();\n        result\n    }\n\n    /// Executes the provided function with the specified rem size.\n    ///\n    /// This method must only be called as part of element drawing.\n    pub fn with_rem_size<F, R>(&mut self, rem_size: Option<impl Into<Pixels>>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        if let Some(rem_size) = rem_size {\n            self.rem_size_override_stack.push(rem_size.into());\n            let result = f(self);\n            self.rem_size_override_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// The line height associated with the current text style.\n    pub fn line_height(&self) -> Pixels {\n        self.text_style().line_height_in_pixels(self.rem_size())\n    }\n\n    /// Call to prevent the default action of an event. Currently only used to prevent\n    /// parent elements from becoming focused on mouse down.\n    pub fn prevent_default(&mut self) {\n        self.default_prevented = true;\n    }\n\n    /// Obtain whether default has been prevented for the event currently being dispatched.\n    pub fn default_prevented(&self) -> bool {\n        self.default_prevented\n    }\n\n    /// Determine whether the given action is available along the dispatch path to the currently focused element.\n    pub fn is_action_available(&self, action: &dyn Action, cx: &mut App) -> bool {\n        let target = self\n            .focused(cx)\n            .and_then(|focused_handle| {\n                self.rendered_frame\n                    .dispatch_tree\n                    .focusable_node_id(focused_handle.id)\n            })\n            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id());\n        self.rendered_frame\n            .dispatch_tree\n            .is_action_available(action, target)\n    }\n\n    /// The position of the mouse relative to the window.\n    pub fn mouse_position(&self) -> Point<Pixels> {\n        self.mouse_position\n    }\n\n    /// The current state of the keyboard's modifiers\n    pub fn modifiers(&self) -> Modifiers {\n        self.modifiers\n    }\n\n    fn complete_frame(&self) {\n        self.platform_window.completed_frame();\n    }\n\n    /// Produces a new frame and assigns it to `rendered_frame`. To actually show\n    /// the contents of the new [Scene], use [present].\n    #[profiling::function]\n    pub fn draw(&mut self, cx: &mut App) {\n        self.invalidate_entities();\n        cx.entities.clear_accessed();\n        debug_assert!(self.rendered_entity_stack.is_empty());\n        self.invalidator.set_dirty(false);\n        self.requested_autoscroll = None;\n\n        // Restore the previously-used input handler.\n        if let Some(input_handler) = self.platform_window.take_input_handler() {\n            self.rendered_frame.input_handlers.push(Some(input_handler));\n        }\n        self.draw_roots(cx);\n        self.dirty_views.clear();\n        self.next_frame.window_active = self.active.get();\n\n        // Register requested input handler with the platform window.\n        if let Some(input_handler) = self.next_frame.input_handlers.pop() {\n            self.platform_window\n                .set_input_handler(input_handler.unwrap());\n        }\n\n        self.layout_engine.as_mut().unwrap().clear();\n        self.text_system().finish_frame();\n        self.next_frame.finish(&mut self.rendered_frame);\n        ELEMENT_ARENA.with_borrow_mut(|element_arena| {\n            let percentage = (element_arena.len() as f32 / element_arena.capacity() as f32) * 100.;\n            if percentage >= 80. {\n                log::warn!(\"elevated element arena occupation: {}.\", percentage);\n            }\n            element_arena.clear();\n        });\n\n        self.invalidator.set_phase(DrawPhase::Focus);\n        let previous_focus_path = self.rendered_frame.focus_path();\n        let previous_window_active = self.rendered_frame.window_active;\n        mem::swap(&mut self.rendered_frame, &mut self.next_frame);\n        self.next_frame.clear();\n        let current_focus_path = self.rendered_frame.focus_path();\n        let current_window_active = self.rendered_frame.window_active;\n\n        if previous_focus_path != current_focus_path\n            || previous_window_active != current_window_active\n        {\n            if !previous_focus_path.is_empty() && current_focus_path.is_empty() {\n                self.focus_lost_listeners\n                    .clone()\n                    .retain(&(), |listener| listener(self, cx));\n            }\n\n            let event = WindowFocusEvent {\n                previous_focus_path: if previous_window_active {\n                    previous_focus_path\n                } else {\n                    Default::default()\n                },\n                current_focus_path: if current_window_active {\n                    current_focus_path\n                } else {\n                    Default::default()\n                },\n            };\n            self.focus_listeners\n                .clone()\n                .retain(&(), |listener| listener(&event, self, cx));\n        }\n\n        debug_assert!(self.rendered_entity_stack.is_empty());\n        self.record_entities_accessed(cx);\n        self.reset_cursor_style(cx);\n        self.refreshing = false;\n        self.invalidator.set_phase(DrawPhase::None);\n        self.needs_present.set(true);\n    }\n\n    fn record_entities_accessed(&mut self, cx: &mut App) {\n        let mut entities_ref = cx.entities.accessed_entities.borrow_mut();\n        let mut entities = mem::take(entities_ref.deref_mut());\n        drop(entities_ref);\n        let handle = self.handle;\n        cx.record_entities_accessed(\n            handle,\n            // Try moving window invalidator into the Window\n            self.invalidator.clone(),\n            &entities,\n        );\n        let mut entities_ref = cx.entities.accessed_entities.borrow_mut();\n        mem::swap(&mut entities, entities_ref.deref_mut());\n    }\n\n    fn invalidate_entities(&mut self) {\n        let mut views = self.invalidator.take_views();\n        for entity in views.drain() {\n            self.mark_view_dirty(entity);\n        }\n        self.invalidator.replace_views(views);\n    }\n\n    #[profiling::function]\n    fn present(&self) {\n        self.platform_window.draw(&self.rendered_frame.scene);\n        self.needs_present.set(false);\n        profiling::finish_frame!();\n    }\n\n    fn draw_roots(&mut self, cx: &mut App) {\n        self.invalidator.set_phase(DrawPhase::Prepaint);\n        self.tooltip_bounds.take();\n\n        // Layout all root elements.\n        let mut root_element = self.root.as_ref().unwrap().clone().into_any();\n        root_element.prepaint_as_root(Point::default(), self.viewport_size.into(), self, cx);\n\n        let mut sorted_deferred_draws =\n            (0..self.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>();\n        sorted_deferred_draws.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);\n        self.prepaint_deferred_draws(&sorted_deferred_draws, cx);\n\n        let mut prompt_element = None;\n        let mut active_drag_element = None;\n        let mut tooltip_element = None;\n        if let Some(prompt) = self.prompt.take() {\n            let mut element = prompt.view.any_view().into_any();\n            element.prepaint_as_root(Point::default(), self.viewport_size.into(), self, cx);\n            prompt_element = Some(element);\n            self.prompt = Some(prompt);\n        } else if let Some(active_drag) = cx.active_drag.take() {\n            let mut element = active_drag.view.clone().into_any();\n            let offset = self.mouse_position() - active_drag.cursor_offset;\n            element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx);\n            active_drag_element = Some(element);\n            cx.active_drag = Some(active_drag);\n        } else {\n            tooltip_element = self.prepaint_tooltip(cx);\n        }\n\n        self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position);\n\n        // Now actually paint the elements.\n        self.invalidator.set_phase(DrawPhase::Paint);\n        root_element.paint(self, cx);\n\n        self.paint_deferred_draws(&sorted_deferred_draws, cx);\n\n        if let Some(mut prompt_element) = prompt_element {\n            prompt_element.paint(self, cx);\n        } else if let Some(mut drag_element) = active_drag_element {\n            drag_element.paint(self, cx);\n        } else if let Some(mut tooltip_element) = tooltip_element {\n            tooltip_element.paint(self, cx);\n        }\n    }\n\n    fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {\n        // Use indexing instead of iteration to avoid borrowing self for the duration of the loop.\n        for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() {\n            let Some(Some(tooltip_request)) = self\n                .next_frame\n                .tooltip_requests\n                .get(tooltip_request_index)\n                .cloned()\n            else {\n                log::error!(\"Unexpectedly absent TooltipRequest\");\n                continue;\n            };\n            let mut element = tooltip_request.tooltip.view.clone().into_any();\n            let mouse_position = tooltip_request.tooltip.mouse_position;\n            let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);\n\n            let mut tooltip_bounds =\n                Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);\n            let window_bounds = Bounds {\n                origin: Point::default(),\n                size: self.viewport_size(),\n            };\n\n            if tooltip_bounds.right() > window_bounds.right() {\n                let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);\n                if new_x >= Pixels::ZERO {\n                    tooltip_bounds.origin.x = new_x;\n                } else {\n                    tooltip_bounds.origin.x = cmp::max(\n                        Pixels::ZERO,\n                        tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),\n                    );\n                }\n            }\n\n            if tooltip_bounds.bottom() > window_bounds.bottom() {\n                let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);\n                if new_y >= Pixels::ZERO {\n                    tooltip_bounds.origin.y = new_y;\n                } else {\n                    tooltip_bounds.origin.y = cmp::max(\n                        Pixels::ZERO,\n                        tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),\n                    );\n                }\n            }\n\n            // It's possible for an element to have an active tooltip while not being painted (e.g.\n            // via the `visible_on_hover` method). Since mouse listeners are not active in this\n            // case, instead update the tooltip's visibility here.\n            let is_visible =\n                (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);\n            if !is_visible {\n                continue;\n            }\n\n            self.with_absolute_element_offset(tooltip_bounds.origin, |window| {\n                element.prepaint(window, cx)\n            });\n\n            self.tooltip_bounds = Some(TooltipBounds {\n                id: tooltip_request.id,\n                bounds: tooltip_bounds,\n            });\n            return Some(element);\n        }\n        None\n    }\n\n    fn prepaint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {\n        assert_eq!(self.element_id_stack.len(), 0);\n\n        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);\n        for deferred_draw_ix in deferred_draw_indices {\n            let deferred_draw = &mut deferred_draws[*deferred_draw_ix];\n            self.element_id_stack\n                .clone_from(&deferred_draw.element_id_stack);\n            self.text_style_stack\n                .clone_from(&deferred_draw.text_style_stack);\n            self.next_frame\n                .dispatch_tree\n                .set_active_node(deferred_draw.parent_node);\n\n            let prepaint_start = self.prepaint_index();\n            if let Some(element) = deferred_draw.element.as_mut() {\n                self.with_rendered_view(deferred_draw.current_view, |window| {\n                    window.with_absolute_element_offset(deferred_draw.absolute_offset, |window| {\n                        element.prepaint(window, cx)\n                    });\n                })\n            } else {\n                self.reuse_prepaint(deferred_draw.prepaint_range.clone());\n            }\n            let prepaint_end = self.prepaint_index();\n            deferred_draw.prepaint_range = prepaint_start..prepaint_end;\n        }\n        assert_eq!(\n            self.next_frame.deferred_draws.len(),\n            0,\n            \"cannot call defer_draw during deferred drawing\"\n        );\n        self.next_frame.deferred_draws = deferred_draws;\n        self.element_id_stack.clear();\n        self.text_style_stack.clear();\n    }\n\n    fn paint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {\n        assert_eq!(self.element_id_stack.len(), 0);\n\n        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);\n        for deferred_draw_ix in deferred_draw_indices {\n            let mut deferred_draw = &mut deferred_draws[*deferred_draw_ix];\n            self.element_id_stack\n                .clone_from(&deferred_draw.element_id_stack);\n            self.next_frame\n                .dispatch_tree\n                .set_active_node(deferred_draw.parent_node);\n\n            let paint_start = self.paint_index();\n            if let Some(element) = deferred_draw.element.as_mut() {\n                self.with_rendered_view(deferred_draw.current_view, |window| {\n                    element.paint(window, cx);\n                })\n            } else {\n                self.reuse_paint(deferred_draw.paint_range.clone());\n            }\n            let paint_end = self.paint_index();\n            deferred_draw.paint_range = paint_start..paint_end;\n        }\n        self.next_frame.deferred_draws = deferred_draws;\n        self.element_id_stack.clear();\n    }\n\n    pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {\n        PrepaintStateIndex {\n            hitboxes_index: self.next_frame.hitboxes.len(),\n            tooltips_index: self.next_frame.tooltip_requests.len(),\n            deferred_draws_index: self.next_frame.deferred_draws.len(),\n            dispatch_tree_index: self.next_frame.dispatch_tree.len(),\n            accessed_element_states_index: self.next_frame.accessed_element_states.len(),\n            line_layout_index: self.text_system.layout_index(),\n        }\n    }\n\n    pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {\n        self.next_frame.hitboxes.extend(\n            self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]\n                .iter()\n                .cloned(),\n        );\n        self.next_frame.tooltip_requests.extend(\n            self.rendered_frame.tooltip_requests\n                [range.start.tooltips_index..range.end.tooltips_index]\n                .iter_mut()\n                .map(|request| request.take()),\n        );\n        self.next_frame.accessed_element_states.extend(\n            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index\n                ..range.end.accessed_element_states_index]\n                .iter()\n                .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),\n        );\n        self.text_system\n            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);\n\n        let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree(\n            range.start.dispatch_tree_index..range.end.dispatch_tree_index,\n            &mut self.rendered_frame.dispatch_tree,\n            self.focus,\n        );\n\n        if reused_subtree.contains_focus() {\n            self.next_frame.focus = self.focus;\n        }\n\n        self.next_frame.deferred_draws.extend(\n            self.rendered_frame.deferred_draws\n                [range.start.deferred_draws_index..range.end.deferred_draws_index]\n                .iter()\n                .map(|deferred_draw| DeferredDraw {\n                    current_view: deferred_draw.current_view,\n                    parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),\n                    element_id_stack: deferred_draw.element_id_stack.clone(),\n                    text_style_stack: deferred_draw.text_style_stack.clone(),\n                    priority: deferred_draw.priority,\n                    element: None,\n                    absolute_offset: deferred_draw.absolute_offset,\n                    prepaint_range: deferred_draw.prepaint_range.clone(),\n                    paint_range: deferred_draw.paint_range.clone(),\n                }),\n        );\n    }\n\n    pub(crate) fn paint_index(&self) -> PaintIndex {\n        PaintIndex {\n            scene_index: self.next_frame.scene.len(),\n            mouse_listeners_index: self.next_frame.mouse_listeners.len(),\n            input_handlers_index: self.next_frame.input_handlers.len(),\n            cursor_styles_index: self.next_frame.cursor_styles.len(),\n            accessed_element_states_index: self.next_frame.accessed_element_states.len(),\n            line_layout_index: self.text_system.layout_index(),\n        }\n    }\n\n    pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {\n        self.next_frame.cursor_styles.extend(\n            self.rendered_frame.cursor_styles\n                [range.start.cursor_styles_index..range.end.cursor_styles_index]\n                .iter()\n                .cloned(),\n        );\n        self.next_frame.input_handlers.extend(\n            self.rendered_frame.input_handlers\n                [range.start.input_handlers_index..range.end.input_handlers_index]\n                .iter_mut()\n                .map(|handler| handler.take()),\n        );\n        self.next_frame.mouse_listeners.extend(\n            self.rendered_frame.mouse_listeners\n                [range.start.mouse_listeners_index..range.end.mouse_listeners_index]\n                .iter_mut()\n                .map(|listener| listener.take()),\n        );\n        self.next_frame.accessed_element_states.extend(\n            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index\n                ..range.end.accessed_element_states_index]\n                .iter()\n                .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),\n        );\n\n        self.text_system\n            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);\n        self.next_frame.scene.replay(\n            range.start.scene_index..range.end.scene_index,\n            &self.rendered_frame.scene,\n        );\n    }\n\n    /// Push a text style onto the stack, and call a function with that style active.\n    /// Use [`Window::text_style`] to get the current, combined text style. This method\n    /// should only be called as part of element drawing.\n    pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        if let Some(style) = style {\n            self.text_style_stack.push(style);\n            let result = f(self);\n            self.text_style_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Updates the cursor style at the platform level. This method should only be called\n    /// during the prepaint phase of element drawing.\n    pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: Option<&Hitbox>) {\n        self.invalidator.debug_assert_paint();\n        self.next_frame.cursor_styles.push(CursorStyleRequest {\n            hitbox_id: hitbox.map(|hitbox| hitbox.id),\n            style,\n        });\n    }\n\n    /// Sets a tooltip to be rendered for the upcoming frame. This method should only be called\n    /// during the paint phase of element drawing.\n    pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {\n        self.invalidator.debug_assert_prepaint();\n        let id = TooltipId(post_inc(&mut self.next_tooltip_id.0));\n        self.next_frame\n            .tooltip_requests\n            .push(Some(TooltipRequest { id, tooltip }));\n        id\n    }\n\n    /// Invoke the given function with the given content mask after intersecting it\n    /// with the current mask. This method should only be called during element drawing.\n    pub fn with_content_mask<R>(\n        &mut self,\n        mask: Option<ContentMask<Pixels>>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        if let Some(mask) = mask {\n            let mask = mask.intersect(&self.content_mask());\n            self.content_mask_stack.push(mask);\n            let result = f(self);\n            self.content_mask_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Updates the global element offset relative to the current offset. This is used to implement\n    /// scrolling. This method should only be called during the prepaint phase of element drawing.\n    pub fn with_element_offset<R>(\n        &mut self,\n        offset: Point<Pixels>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_prepaint();\n\n        if offset.is_zero() {\n            return f(self);\n        };\n\n        let abs_offset = self.element_offset() + offset;\n        self.with_absolute_element_offset(abs_offset, f)\n    }\n\n    /// Updates the global element offset based on the given offset. This is used to implement\n    /// drag handles and other manual painting of elements. This method should only be called during\n    /// the prepaint phase of element drawing.\n    pub fn with_absolute_element_offset<R>(\n        &mut self,\n        offset: Point<Pixels>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.invalidator.debug_assert_prepaint();\n        self.element_offset_stack.push(offset);\n        let result = f(self);\n        self.element_offset_stack.pop();\n        result\n    }\n\n    pub(crate) fn with_element_opacity<R>(\n        &mut self,\n        opacity: Option<f32>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        if opacity.is_none() {\n            return f(self);\n        }\n\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.element_opacity = opacity;\n        let result = f(self);\n        self.element_opacity = None;\n        result\n    }\n\n    /// Perform prepaint on child elements in a \"retryable\" manner, so that any side effects\n    /// of prepaints can be discarded before prepainting again. This is used to support autoscroll\n    /// where we need to prepaint children to detect the autoscroll bounds, then adjust the\n    /// element offset and prepaint again. See [`List`] for an example. This method should only be\n    /// called during the prepaint phase of element drawing.\n    pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {\n        self.invalidator.debug_assert_prepaint();\n        let index = self.prepaint_index();\n        let result = f(self);\n        if result.is_err() {\n            self.next_frame.hitboxes.truncate(index.hitboxes_index);\n            self.next_frame\n                .tooltip_requests\n                .truncate(index.tooltips_index);\n            self.next_frame\n                .deferred_draws\n                .truncate(index.deferred_draws_index);\n            self.next_frame\n                .dispatch_tree\n                .truncate(index.dispatch_tree_index);\n            self.next_frame\n                .accessed_element_states\n                .truncate(index.accessed_element_states_index);\n            self.text_system.truncate_layouts(index.line_layout_index);\n        }\n        result\n    }\n\n    /// When you call this method during [`prepaint`], containing elements will attempt to\n    /// scroll to cause the specified bounds to become visible. When they decide to autoscroll, they will call\n    /// [`prepaint`] again with a new set of bounds. See [`List`] for an example of an element\n    /// that supports this method being called on the elements it contains. This method should only be\n    /// called during the prepaint phase of element drawing.\n    pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {\n        self.invalidator.debug_assert_prepaint();\n        self.requested_autoscroll = Some(bounds);\n    }\n\n    /// This method can be called from a containing element such as [`List`] to support the autoscroll behavior\n    /// described in [`request_autoscroll`].\n    pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {\n        self.invalidator.debug_assert_prepaint();\n        self.requested_autoscroll.take()\n    }\n\n    /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.\n    /// Your view will be re-drawn once the asset has finished loading.\n    ///\n    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a\n    /// time.\n    pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {\n        let (task, is_first) = cx.fetch_asset::<A>(source);\n        task.clone().now_or_never().or_else(|| {\n            if is_first {\n                let entity_id = self.current_view();\n                self.spawn(cx, {\n                    let task = task.clone();\n                    async move |cx| {\n                        task.await;\n\n                        cx.on_next_frame(move |_, cx| {\n                            cx.notify(entity_id);\n                        });\n                    }\n                })\n                .detach();\n            }\n\n            None\n        })\n    }\n\n    /// Asynchronously load an asset, if the asset hasn't finished loading or doesn't exist this will return None.\n    /// Your view will not be re-drawn once the asset has finished loading.\n    ///\n    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a\n    /// time.\n    pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {\n        let (task, _) = cx.fetch_asset::<A>(source);\n        task.clone().now_or_never()\n    }\n    /// Obtain the current element offset. This method should only be called during the\n    /// prepaint phase of element drawing.\n    pub fn element_offset(&self) -> Point<Pixels> {\n        self.invalidator.debug_assert_prepaint();\n        self.element_offset_stack\n            .last()\n            .copied()\n            .unwrap_or_default()\n    }\n\n    /// Obtain the current element opacity. This method should only be called during the\n    /// prepaint phase of element drawing.\n    pub(crate) fn element_opacity(&self) -> f32 {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.element_opacity.unwrap_or(1.0)\n    }\n\n    /// Obtain the current content mask. This method should only be called during element drawing.\n    pub fn content_mask(&self) -> ContentMask<Pixels> {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.content_mask_stack\n            .last()\n            .cloned()\n            .unwrap_or_else(|| ContentMask {\n                bounds: Bounds {\n                    origin: Point::default(),\n                    size: self.viewport_size,\n                },\n            })\n    }\n\n    /// Provide elements in the called function with a new namespace in which their identifiers must be unique.\n    /// This can be used within a custom element to distinguish multiple sets of child elements.\n    pub fn with_element_namespace<R>(\n        &mut self,\n        element_id: impl Into<ElementId>,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.element_id_stack.push(element_id.into());\n        let result = f(self);\n        self.element_id_stack.pop();\n        result\n    }\n\n    /// Updates or initializes state for an element with the given id that lives across multiple\n    /// frames. If an element with this ID existed in the rendered frame, its state will be passed\n    /// to the given closure. The state returned by the closure will be stored so it can be referenced\n    /// when drawing the next frame. This method should only be called as part of element drawing.\n    pub fn with_element_state<S, R>(\n        &mut self,\n        global_id: &GlobalElementId,\n        f: impl FnOnce(Option<S>, &mut Self) -> (R, S),\n    ) -> R\n    where\n        S: 'static,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        let key = (GlobalElementId(global_id.0.clone()), TypeId::of::<S>());\n        self.next_frame\n            .accessed_element_states\n            .push((GlobalElementId(key.0.clone()), TypeId::of::<S>()));\n\n        if let Some(any) = self\n            .next_frame\n            .element_states\n            .remove(&key)\n            .or_else(|| self.rendered_frame.element_states.remove(&key))\n        {\n            let ElementStateBox {\n                inner,\n                #[cfg(debug_assertions)]\n                type_name,\n            } = any;\n            // Using the extra inner option to avoid needing to reallocate a new box.\n            let mut state_box = inner\n                .downcast::<Option<S>>()\n                .map_err(|_| {\n                    #[cfg(debug_assertions)]\n                    {\n                        anyhow::anyhow!(\n                            \"invalid element state type for id, requested {:?}, actual: {:?}\",\n                            std::any::type_name::<S>(),\n                            type_name\n                        )\n                    }\n\n                    #[cfg(not(debug_assertions))]\n                    {\n                        anyhow::anyhow!(\n                            \"invalid element state type for id, requested {:?}\",\n                            std::any::type_name::<S>(),\n                        )\n                    }\n                })\n                .unwrap();\n\n            let state = state_box.take().expect(\n                \"reentrant call to with_element_state for the same state type and element id\",\n            );\n            let (result, state) = f(Some(state), self);\n            state_box.replace(state);\n            self.next_frame.element_states.insert(\n                key,\n                ElementStateBox {\n                    inner: state_box,\n                    #[cfg(debug_assertions)]\n                    type_name,\n                },\n            );\n            result\n        } else {\n            let (result, state) = f(None, self);\n            self.next_frame.element_states.insert(\n                key,\n                ElementStateBox {\n                    inner: Box::new(Some(state)),\n                    #[cfg(debug_assertions)]\n                    type_name: std::any::type_name::<S>(),\n                },\n            );\n            result\n        }\n    }\n\n    /// A variant of `with_element_state` that allows the element's id to be optional. This is a convenience\n    /// method for elements where the element id may or may not be assigned. Prefer using `with_element_state`\n    /// when the element is guaranteed to have an id.\n    ///\n    /// The first option means 'no ID provided'\n    /// The second option means 'not yet initialized'\n    pub fn with_optional_element_state<S, R>(\n        &mut self,\n        global_id: Option<&GlobalElementId>,\n        f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),\n    ) -> R\n    where\n        S: 'static,\n    {\n        self.invalidator.debug_assert_paint_or_prepaint();\n\n        if let Some(global_id) = global_id {\n            self.with_element_state(global_id, |state, cx| {\n                let (result, state) = f(Some(state), cx);\n                let state =\n                    state.expect(\"you must return some state when you pass some element id\");\n                (result, state)\n            })\n        } else {\n            let (result, state) = f(None, self);\n            debug_assert!(\n                state.is_none(),\n                \"you must not return an element state when passing None for the global id\"\n            );\n            result\n        }\n    }\n\n    /// Defers the drawing of the given element, scheduling it to be painted on top of the currently-drawn tree\n    /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements,\n    /// with higher values being drawn on top.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn defer_draw(\n        &mut self,\n        element: AnyElement,\n        absolute_offset: Point<Pixels>,\n        priority: usize,\n    ) {\n        self.invalidator.debug_assert_prepaint();\n        let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();\n        self.next_frame.deferred_draws.push(DeferredDraw {\n            current_view: self.current_view(),\n            parent_node,\n            element_id_stack: self.element_id_stack.clone(),\n            text_style_stack: self.text_style_stack.clone(),\n            priority,\n            element: Some(element),\n            absolute_offset,\n            prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),\n            paint_range: PaintIndex::default()..PaintIndex::default(),\n        });\n    }\n\n    /// Creates a new painting layer for the specified bounds. A \"layer\" is a batch\n    /// of geometry that are non-overlapping and have the same draw order. This is typically used\n    /// for performance reasons.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let clipped_bounds = bounds.intersect(&content_mask.bounds);\n        if !clipped_bounds.is_empty() {\n            self.next_frame\n                .scene\n                .push_layer(clipped_bounds.scale(scale_factor));\n        }\n\n        let result = f(self);\n\n        if !clipped_bounds.is_empty() {\n            self.next_frame.scene.pop_layer();\n        }\n\n        result\n    }\n\n    /// Paint one or more drop shadows into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_shadows(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        corner_radii: Corners<Pixels>,\n        shadows: &[BoxShadow],\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        for shadow in shadows {\n            let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius);\n            self.next_frame.scene.insert_primitive(Shadow {\n                order: 0,\n                blur_radius: shadow.blur_radius.scale(scale_factor),\n                bounds: shadow_bounds.scale(scale_factor),\n                content_mask: content_mask.scale(scale_factor),\n                corner_radii: corner_radii.scale(scale_factor),\n                color: shadow.color.opacity(opacity),\n            });\n        }\n    }\n\n    /// Paint one or more quads into the scene for the next frame at the current stacking context.\n    /// Quads are colored rectangular regions with an optional background, border, and corner radius.\n    /// see [`fill`](crate::fill), [`outline`](crate::outline), and [`quad`](crate::quad) to construct this type.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    ///\n    /// Note that the `quad.corner_radii` are allowed to exceed the bounds, creating sharp corners\n    /// where the circular arcs meet. This will not display well when combined with dashed borders.\n    /// Use `Corners::clamp_radii_for_quad_size` if the radii should fit within the bounds.\n    pub fn paint_quad(&mut self, quad: PaintQuad) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        self.next_frame.scene.insert_primitive(Quad {\n            order: 0,\n            bounds: quad.bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            background: quad.background.opacity(opacity),\n            border_color: quad.border_color.opacity(opacity),\n            corner_radii: quad.corner_radii.scale(scale_factor),\n            border_widths: quad.border_widths.scale(scale_factor),\n            border_style: quad.border_style,\n            transformation: quad.transformation,\n        });\n    }\n\n    /// Paint the given `Path` into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n        path.content_mask = content_mask;\n        let color: Background = color.into();\n        path.color = color.opacity(opacity);\n        self.next_frame\n            .scene\n            .insert_primitive(path.scale(scale_factor));\n    }\n\n    /// Paint an underline into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_underline(\n        &mut self,\n        origin: Point<Pixels>,\n        width: Pixels,\n        style: &UnderlineStyle,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let height = if style.wavy {\n            style.thickness * 3.\n        } else {\n            style.thickness\n        };\n        let bounds = Bounds {\n            origin,\n            size: size(width, height),\n        };\n        let content_mask = self.content_mask();\n        let element_opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(Underline {\n            order: 0,\n            pad: 0,\n            bounds: bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            color: style.color.unwrap_or_default().opacity(element_opacity),\n            thickness: style.thickness.scale(scale_factor),\n            wavy: style.wavy,\n        });\n    }\n\n    /// Paint a strikethrough into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_strikethrough(\n        &mut self,\n        origin: Point<Pixels>,\n        width: Pixels,\n        style: &StrikethroughStyle,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let height = style.thickness;\n        let bounds = Bounds {\n            origin,\n            size: size(width, height),\n        };\n        let content_mask = self.content_mask();\n        let opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(Underline {\n            order: 0,\n            pad: 0,\n            bounds: bounds.scale(scale_factor),\n            content_mask: content_mask.scale(scale_factor),\n            thickness: style.thickness.scale(scale_factor),\n            color: style.color.unwrap_or_default().opacity(opacity),\n            wavy: false,\n        });\n    }\n\n    /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.\n    ///\n    /// The y component of the origin is the baseline of the glyph.\n    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or\n    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).\n    /// This method is only useful if you need to paint a single glyph that has already been shaped.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_glyph(\n        &mut self,\n        origin: Point<Pixels>,\n        font_id: FontId,\n        glyph_id: GlyphId,\n        font_size: Pixels,\n        color: Hsla,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let element_opacity = self.element_opacity();\n        let scale_factor = self.scale_factor();\n        let glyph_origin = origin.scale(scale_factor);\n        let subpixel_variant = Point {\n            x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,\n            y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,\n        };\n        let params = RenderGlyphParams {\n            font_id,\n            glyph_id,\n            font_size,\n            subpixel_variant,\n            scale_factor,\n            is_emoji: false,\n        };\n\n        let raster_bounds = self.text_system().raster_bounds(&params)?;\n        if !raster_bounds.is_zero() {\n            let tile = self\n                .sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;\n                    Ok(Some((size, Cow::Owned(bytes))))\n                })?\n                .expect(\"Callback above only errors or returns Some\");\n            let bounds = Bounds {\n                origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),\n                size: tile.bounds.size.map(Into::into),\n            };\n            let content_mask = self.content_mask().scale(scale_factor);\n            self.next_frame.scene.insert_primitive(MonochromeSprite {\n                order: 0,\n                pad: 0,\n                bounds,\n                content_mask,\n                color: color.opacity(element_opacity),\n                tile,\n                transformation: TransformationMatrix::unit(),\n            });\n        }\n        Ok(())\n    }\n\n    /// Paints an emoji glyph into the scene for the next frame at the current z-index.\n    ///\n    /// The y component of the origin is the baseline of the glyph.\n    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or\n    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).\n    /// This method is only useful if you need to paint a single emoji that has already been shaped.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_emoji(\n        &mut self,\n        origin: Point<Pixels>,\n        font_id: FontId,\n        glyph_id: GlyphId,\n        font_size: Pixels,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let glyph_origin = origin.scale(scale_factor);\n        let params = RenderGlyphParams {\n            font_id,\n            glyph_id,\n            font_size,\n            // We don't render emojis with subpixel variants.\n            subpixel_variant: Default::default(),\n            scale_factor,\n            is_emoji: true,\n        };\n\n        let raster_bounds = self.text_system().raster_bounds(&params)?;\n        if !raster_bounds.is_zero() {\n            let tile = self\n                .sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;\n                    Ok(Some((size, Cow::Owned(bytes))))\n                })?\n                .expect(\"Callback above only errors or returns Some\");\n\n            let bounds = Bounds {\n                origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),\n                size: tile.bounds.size.map(Into::into),\n            };\n            let content_mask = self.content_mask().scale(scale_factor);\n            let opacity = self.element_opacity();\n\n            self.next_frame.scene.insert_primitive(PolychromeSprite {\n                order: 0,\n                pad: 0,\n                grayscale: false,\n                bounds,\n                corner_radii: Default::default(),\n                content_mask,\n                tile,\n                opacity,\n            });\n        }\n        Ok(())\n    }\n\n    /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_svg(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        path: SharedString,\n        transformation: TransformationMatrix,\n        color: Hsla,\n        cx: &App,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let element_opacity = self.element_opacity();\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let params = RenderSvgParams {\n            path,\n            size: bounds.size.map(|pixels| {\n                DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)\n            }),\n        };\n\n        let Some(tile) =\n            self.sprite_atlas\n                .get_or_insert_with(&params.clone().into(), &mut || {\n                    let Some(bytes) = cx.svg_renderer.render(&params)? else {\n                        return Ok(None);\n                    };\n                    Ok(Some((params.size, Cow::Owned(bytes))))\n                })?\n        else {\n            return Ok(());\n        };\n        let content_mask = self.content_mask().scale(scale_factor);\n\n        self.next_frame.scene.insert_primitive(MonochromeSprite {\n            order: 0,\n            pad: 0,\n            bounds: bounds\n                .map_origin(|origin| origin.floor())\n                .map_size(|size| size.ceil()),\n            content_mask,\n            color: color.opacity(element_opacity),\n            tile,\n            transformation,\n        });\n\n        Ok(())\n    }\n\n    /// Paint an image into the scene for the next frame at the current z-index.\n    /// This method will panic if the frame_index is not valid\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn paint_image(\n        &mut self,\n        bounds: Bounds<Pixels>,\n        corner_radii: Corners<Pixels>,\n        data: Arc<RenderImage>,\n        frame_index: usize,\n        grayscale: bool,\n    ) -> Result<()> {\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let params = RenderImageParams {\n            image_id: data.id,\n            frame_index,\n        };\n\n        let tile = self\n            .sprite_atlas\n            .get_or_insert_with(&params.clone().into(), &mut || {\n                Ok(Some((\n                    data.size(frame_index),\n                    Cow::Borrowed(\n                        data.as_bytes(frame_index)\n                            .expect(\"It's the caller's job to pass a valid frame index\"),\n                    ),\n                )))\n            })?\n            .expect(\"Callback above only returns Some\");\n        let content_mask = self.content_mask().scale(scale_factor);\n        let corner_radii = corner_radii.scale(scale_factor);\n        let opacity = self.element_opacity();\n\n        self.next_frame.scene.insert_primitive(PolychromeSprite {\n            order: 0,\n            pad: 0,\n            grayscale,\n            bounds: bounds\n                .map_origin(|origin| origin.floor())\n                .map_size(|size| size.ceil()),\n            content_mask,\n            corner_radii,\n            tile,\n            opacity,\n        });\n        Ok(())\n    }\n\n    /// Paint a surface into the scene for the next frame at the current z-index.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    #[cfg(target_os = \"macos\")]\n    pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVPixelBuffer) {\n        use crate::PaintSurface;\n\n        self.invalidator.debug_assert_paint();\n\n        let scale_factor = self.scale_factor();\n        let bounds = bounds.scale(scale_factor);\n        let content_mask = self.content_mask().scale(scale_factor);\n        self.next_frame.scene.insert_primitive(PaintSurface {\n            order: 0,\n            bounds,\n            content_mask,\n            image_buffer,\n        });\n    }\n\n    /// Removes an image from the sprite atlas.\n    pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {\n        for frame_index in 0..data.frame_count() {\n            let params = RenderImageParams {\n                image_id: data.id,\n                frame_index,\n            };\n\n            self.sprite_atlas.remove(&params.clone().into());\n        }\n\n        Ok(())\n    }\n\n    /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which\n    /// layout is being requested, along with the layout ids of any children. This method is called during\n    /// calls to the [`Element::request_layout`] trait method and enables any element to participate in layout.\n    ///\n    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.\n    #[must_use]\n    pub fn request_layout(\n        &mut self,\n        style: Style,\n        children: impl IntoIterator<Item = LayoutId>,\n        cx: &mut App,\n    ) -> LayoutId {\n        self.invalidator.debug_assert_prepaint();\n\n        cx.layout_id_buffer.clear();\n        cx.layout_id_buffer.extend(children);\n        let rem_size = self.rem_size();\n\n        self.layout_engine\n            .as_mut()\n            .unwrap()\n            .request_layout(style, rem_size, &cx.layout_id_buffer)\n    }\n\n    /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,\n    /// this variant takes a function that is invoked during layout so you can use arbitrary logic to\n    /// determine the element's size. One place this is used internally is when measuring text.\n    ///\n    /// The given closure is invoked at layout time with the known dimensions and available space and\n    /// returns a `Size`.\n    ///\n    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.\n    pub fn request_measured_layout<\n        F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>\n            + 'static,\n    >(\n        &mut self,\n        style: Style,\n        measure: F,\n    ) -> LayoutId {\n        self.invalidator.debug_assert_prepaint();\n\n        let rem_size = self.rem_size();\n        self.layout_engine\n            .as_mut()\n            .unwrap()\n            .request_measured_layout(style, rem_size, measure)\n    }\n\n    /// Compute the layout for the given id within the given available space.\n    /// This method is called for its side effect, typically by the framework prior to painting.\n    /// After calling it, you can request the bounds of the given layout node id or any descendant.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn compute_layout(\n        &mut self,\n        layout_id: LayoutId,\n        available_space: Size<AvailableSpace>,\n        cx: &mut App,\n    ) {\n        self.invalidator.debug_assert_prepaint();\n\n        let mut layout_engine = self.layout_engine.take().unwrap();\n        layout_engine.compute_layout(layout_id, available_space, self, cx);\n        self.layout_engine = Some(layout_engine);\n    }\n\n    /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by\n    /// GPUI itself automatically in order to pass your element its `Bounds` automatically.\n    ///\n    /// This method should only be called as part of element drawing.\n    pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {\n        self.invalidator.debug_assert_prepaint();\n\n        let mut bounds = self\n            .layout_engine\n            .as_mut()\n            .unwrap()\n            .layout_bounds(layout_id)\n            .map(Into::into);\n        bounds.origin += self.element_offset();\n        bounds\n    }\n\n    /// This method should be called during `prepaint`. You can use\n    /// the returned [Hitbox] during `paint` or in an event handler\n    /// to determine whether the inserted hitbox was the topmost.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, opaque: bool) -> Hitbox {\n        self.invalidator.debug_assert_prepaint();\n\n        let content_mask = self.content_mask();\n        let id = self.next_hitbox_id;\n        self.next_hitbox_id.0 += 1;\n        let hitbox = Hitbox {\n            id,\n            bounds,\n            content_mask,\n            opaque,\n        };\n        self.next_frame.hitboxes.push(hitbox.clone());\n        hitbox\n    }\n\n    /// Sets the key context for the current element. This context will be used to translate\n    /// keybindings into actions.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn set_key_context(&mut self, context: KeyContext) {\n        self.invalidator.debug_assert_paint();\n        self.next_frame.dispatch_tree.set_key_context(context);\n    }\n\n    /// Sets the focus handle for the current element. This handle will be used to manage focus state\n    /// and keyboard event dispatch for the element.\n    ///\n    /// This method should only be called as part of the prepaint phase of element drawing.\n    pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {\n        self.invalidator.debug_assert_prepaint();\n        if focus_handle.is_focused(self) {\n            self.next_frame.focus = Some(focus_handle.id);\n        }\n        self.next_frame.dispatch_tree.set_focus_id(focus_handle.id);\n    }\n\n    /// Sets the view id for the current element, which will be used to manage view caching.\n    ///\n    /// This method should only be called as part of element prepaint. We plan on removing this\n    /// method eventually when we solve some issues that require us to construct editor elements\n    /// directly instead of always using editors via views.\n    pub fn set_view_id(&mut self, view_id: EntityId) {\n        self.invalidator.debug_assert_prepaint();\n        self.next_frame.dispatch_tree.set_view_id(view_id);\n    }\n\n    /// Get the entity ID for the currently rendering view\n    pub fn current_view(&self) -> EntityId {\n        self.invalidator.debug_assert_paint_or_prepaint();\n        self.rendered_entity_stack.last().copied().unwrap()\n    }\n\n    pub(crate) fn with_rendered_view<R>(\n        &mut self,\n        id: EntityId,\n        f: impl FnOnce(&mut Self) -> R,\n    ) -> R {\n        self.rendered_entity_stack.push(id);\n        let result = f(self);\n        self.rendered_entity_stack.pop();\n        result\n    }\n\n    /// Executes the provided function with the specified image cache.\n    pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        if let Some(image_cache) = image_cache {\n            self.image_cache_stack.push(image_cache);\n            let result = f(self);\n            self.image_cache_stack.pop();\n            result\n        } else {\n            f(self)\n        }\n    }\n\n    /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the\n    /// platform to receive textual input with proper integration with concerns such\n    /// as IME interactions. This handler will be active for the upcoming frame until the following frame is\n    /// rendered.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    ///\n    /// [element_input_handler]: crate::ElementInputHandler\n    pub fn handle_input(\n        &mut self,\n        focus_handle: &FocusHandle,\n        input_handler: impl InputHandler,\n        cx: &App,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        if focus_handle.is_focused(self) {\n            let cx = self.to_async(cx);\n            self.next_frame\n                .input_handlers\n                .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));\n        }\n    }\n\n    /// Register a mouse event listener on the window for the next frame. The type of event\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_mouse_event<Event: MouseEvent>(\n        &mut self,\n        mut handler: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.mouse_listeners.push(Some(Box::new(\n            move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {\n                if let Some(event) = event.downcast_ref() {\n                    handler(event, phase, window, cx)\n                }\n            },\n        )));\n    }\n\n    /// Register a key event listener on the window for the next frame. The type of event\n    /// is determined by the first parameter of the given listener. When the next frame is rendered\n    /// the listener will be cleared.\n    ///\n    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have\n    /// a specific need to register a global listener.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_key_event<Event: KeyEvent>(\n        &mut self,\n        listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.dispatch_tree.on_key_event(Rc::new(\n            move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {\n                if let Some(event) = event.downcast_ref::<Event>() {\n                    listener(event, phase, window, cx)\n                }\n            },\n        ));\n    }\n\n    /// Register a modifiers changed event listener on the window for the next frame.\n    ///\n    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have\n    /// a specific need to register a global listener.\n    ///\n    /// This method should only be called as part of the paint phase of element drawing.\n    pub fn on_modifiers_changed(\n        &mut self,\n        listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,\n    ) {\n        self.invalidator.debug_assert_paint();\n\n        self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new(\n            move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {\n                listener(event, window, cx)\n            },\n        ));\n    }\n\n    /// Register a listener to be called when the given focus handle or one of its descendants receives focus.\n    /// This does not fire if the given focus handle - or one of its descendants - was previously focused.\n    /// Returns a subscription and persists until the subscription is dropped.\n    pub fn on_focus_in(\n        &mut self,\n        handle: &FocusHandle,\n        cx: &mut App,\n        mut listener: impl FnMut(&mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let focus_id = handle.id;\n        let (subscription, activate) =\n            self.new_focus_listener(Box::new(move |event, window, cx| {\n                if event.is_focus_in(focus_id) {\n                    listener(window, cx);\n                }\n                true\n            }));\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    /// Register a listener to be called when the given focus handle or one of its descendants loses focus.\n    /// Returns a subscription and persists until the subscription is dropped.\n    pub fn on_focus_out(\n        &mut self,\n        handle: &FocusHandle,\n        cx: &mut App,\n        mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,\n    ) -> Subscription {\n        let focus_id = handle.id;\n        let (subscription, activate) =\n            self.new_focus_listener(Box::new(move |event, window, cx| {\n                if let Some(blurred_id) = event.previous_focus_path.last().copied() {\n                    if event.is_focus_out(focus_id) {\n                        let event = FocusOutEvent {\n                            blurred: WeakFocusHandle {\n                                id: blurred_id,\n                                handles: Arc::downgrade(&cx.focus_handles),\n                            },\n                        };\n                        listener(event, window, cx)\n                    }\n                }\n                true\n            }));\n        cx.defer(move |_| activate());\n        subscription\n    }\n\n    fn reset_cursor_style(&self, cx: &mut App) {\n        // Set the cursor only if we're the active window.\n        if self.is_window_hovered() {\n            let style = self\n                .rendered_frame\n                .cursor_styles\n                .iter()\n                .rev()\n                .find(|request| {\n                    request\n                        .hitbox_id\n                        .map_or(true, |hitbox_id| hitbox_id.is_hovered(self))\n                })\n                .map(|request| request.style)\n                .unwrap_or(CursorStyle::Arrow);\n            cx.platform.set_cursor_style(style);\n        }\n    }\n\n    /// Dispatch a given keystroke as though the user had typed it.\n    /// You can create a keystroke with Keystroke::parse(\"\").\n    pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {\n        let keystroke = keystroke.with_simulated_ime();\n        let result = self.dispatch_event(\n            PlatformInput::KeyDown(KeyDownEvent {\n                keystroke: keystroke.clone(),\n                is_held: false,\n            }),\n            cx,\n        );\n        if !result.propagate {\n            return true;\n        }\n\n        if let Some(input) = keystroke.key_char {\n            if let Some(mut input_handler) = self.platform_window.take_input_handler() {\n                input_handler.dispatch_input(&input, self, cx);\n                self.platform_window.set_input_handler(input_handler);\n                return true;\n            }\n        }\n\n        false\n    }\n\n    /// Return a key binding string for an action, to display in the UI. Uses the highest precedence\n    /// binding for the action (last binding added to the keymap).\n    pub fn keystroke_text_for(&self, action: &dyn Action) -> String {\n        self.bindings_for_action(action)\n            .last()\n            .map(|binding| {\n                binding\n                    .keystrokes()\n                    .iter()\n                    .map(ToString::to_string)\n                    .collect::<Vec<_>>()\n                    .join(\" \")\n            })\n            .unwrap_or_else(|| action.name().to_string())\n    }\n\n    /// Dispatch a mouse or keyboard event on the window.\n    #[profiling::function]\n    pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {\n        self.last_input_timestamp.set(Instant::now());\n        // Handlers may set this to false by calling `stop_propagation`.\n        cx.propagate_event = true;\n        // Handlers may set this to true by calling `prevent_default`.\n        self.default_prevented = false;\n\n        let event = match event {\n            // Track the mouse position with our own state, since accessing the platform\n            // API for the mouse position can only occur on the main thread.\n            PlatformInput::MouseMove(mouse_move) => {\n                self.mouse_position = mouse_move.position;\n                self.modifiers = mouse_move.modifiers;\n                PlatformInput::MouseMove(mouse_move)\n            }\n            PlatformInput::MouseDown(mouse_down) => {\n                self.mouse_position = mouse_down.position;\n                self.modifiers = mouse_down.modifiers;\n                PlatformInput::MouseDown(mouse_down)\n            }\n            PlatformInput::MouseUp(mouse_up) => {\n                self.mouse_position = mouse_up.position;\n                self.modifiers = mouse_up.modifiers;\n                PlatformInput::MouseUp(mouse_up)\n            }\n            PlatformInput::MouseExited(mouse_exited) => {\n                self.modifiers = mouse_exited.modifiers;\n                PlatformInput::MouseExited(mouse_exited)\n            }\n            PlatformInput::ModifiersChanged(modifiers_chang
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment