2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								/*
 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-04 13:19:50 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  Copyright  ( c )  2022 ,  Andreas  Kling  < andreas @ ladybird . org > 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								 *  Copyright  ( c )  2022 ,  Andrew  Kaster  < akaster @ serenityos . org > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Copyright  ( c )  2022 ,  Luke  Wilde  < lukew @ serenityos . org > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SPDX - License - Identifier :  BSD - 2 - Clause 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <AK/TypeCasts.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <AK/Vector.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibGC/Root.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibWeb/DOM/Document.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibWeb/DOM/Element.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibWeb/DOM/ShadowRoot.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibWeb/HTML/Focus.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-03 08:24:16 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibWeb/HTML/HTMLInputElement.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-19 20:24:18 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibWeb/HTML/TraversableNavigable.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibWeb/UIEvents/FocusEvent.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								namespace  Web : : HTML  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 11:39:32 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// https://html.spec.whatwg.org/multipage/interaction.html#fire-a-focus-event
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  fire_a_focus_event ( GC : : Ptr < DOM : : EventTarget >  focus_event_target ,  GC : : Ptr < DOM : : EventTarget >  related_focus_target ,  FlyString  const &  event_name ,  bool  bubbles ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 11:39:32 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // To fire a focus event named e at an element t with a given related target r, fire an event named e at t, using FocusEvent,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // with the relatedTarget attribute initialized to r, the view attribute initialized to t's node document's relevant global
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // object, and the composed flag set.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    UIEvents : : FocusEventInit  focus_event_init  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    focus_event_init . related_target  =  related_focus_target ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-21 09:12:05 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    focus_event_init . view  =  as < HTML : : Window > ( focus_event_target - > realm ( ) . global_object ( ) ) . window ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 11:39:32 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  focus_event  =  UIEvents : : FocusEvent : : create ( focus_event_target - > realm ( ) ,  event_name ,  focus_event_init ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // AD-HOC: support bubbling focus events, used for focusin & focusout.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //         See: https://github.com/whatwg/html/issues/3514
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    focus_event - > set_bubbles ( bubbles ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    focus_event - > set_composed ( true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    focus_event_target - > dispatch_event ( focus_event ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								// https://html.spec.whatwg.org/multipage/interaction.html#focus-update-steps
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  run_focus_update_steps ( Vector < GC : : Root < DOM : : Node > >  old_chain ,  Vector < GC : : Root < DOM : : Node > >  new_chain ,  DOM : : Node *  new_focus_target ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-02 20:41:23 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // The focus update steps, given an old chain, a new chain, and a new focus target respectively, are as follows:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 1. If the last entry in old chain and the last entry in new chain are the same, pop the last entry from old chain
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //    and the last entry from new chain and redo this step.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    while  ( ! old_chain . is_empty ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        & &  ! new_chain . is_empty ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-30 14:32:24 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        & &  old_chain . last ( )  = =  new_chain . last ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        ( void ) old_chain . take_last ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ( void ) new_chain . take_last ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 2. For each entry entry in old chain, in order, run these substeps:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( auto &  entry  :  old_chain )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-02 20:41:23 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // 1. If entry is an input element
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( auto *  input_element  =  as_if < HTMLInputElement > ( * entry ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-03 08:24:16 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // FIXME: Spec issue: It doesn't make sense to check if the element has a defined activation behavior, as
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            //        that is always true. Instead, we check if it has an *input* activation behavior.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            //        https://github.com/whatwg/html/issues/9973
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // and the change event applies to the element, and the element does not have a defined activation behavior,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // and the user has changed the element's value or its list of selected files while the control was focused
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // without committing that change (such that it is different to what it was when the control was first
 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-02 20:41:23 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // focused), then:
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( input_element - > change_event_applies ( )  & &  ! input_element - > has_input_activation_behavior ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                & &  input_element - > has_uncommitted_changes ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-02 20:41:23 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                // 1. Set entry's user validity to true.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                input_element - > set_user_validity ( true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-02 20:41:23 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // 2. Fire an event named change at the element, with the bubbles attribute initialized to true.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                input_element - > commit_pending_changes ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-03 08:24:16 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // 2. If entry is an element, let blur event target be entry.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //    If entry is a Document object, let blur event target be that Document object's relevant global object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //    Otherwise, let blur event target be null.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        GC : : Ptr < DOM : : EventTarget >  blur_event_target ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( is < DOM : : Element > ( * entry ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            blur_event_target  =  entry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else  if  ( is < DOM : : Document > ( * entry ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            blur_event_target  =  as < Window > ( relevant_global_object ( * entry ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // 3. If entry is the last entry in old chain, and entry is an Element, and the last entry in new chain is also
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //    an Element, then let related blur target be the last entry in new chain. Otherwise, let related blur
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //    target be null.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        GC : : Ptr < DOM : : EventTarget >  related_blur_target ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! old_chain . is_empty ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            & &  & entry  = =  & old_chain . last ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            & &  is < DOM : : Element > ( * entry ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            & &  ! new_chain . is_empty ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            & &  is < DOM : : Element > ( * new_chain . last ( ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            related_blur_target  =  new_chain . last ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // 4. If blur event target is not null, fire a focus event named blur at blur event target, with related blur
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //    target as the related target.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // FIXME: NOTE: In some cases, e.g., if entry is an area element's shape, a scrollable region, or a viewport, no event
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //       is fired.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  ( blur_event_target )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 11:39:32 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            fire_a_focus_event ( blur_event_target ,  related_blur_target ,  HTML : : EventNames : : blur ,  false ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-25 06:51:28 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 11:39:32 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // AD-HOC: dispatch focusout
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            fire_a_focus_event ( blur_event_target ,  related_blur_target ,  HTML : : EventNames : : focusout ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // FIXME: 3. Apply any relevant platform-specific conventions for focusing new focus target. (For example, some platforms
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //    select the contents of a text control when that control is focused.)
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    ( void ) new_focus_target ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 4. For each entry entry in new chain, in reverse order, run these substeps:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( auto &  entry  :  new_chain . in_reverse ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // 1. If entry is a focusable area, and the focused area of the document is not entry:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( entry - > is_focusable ( )  & &  entry - > document ( ) . focused_area ( )  ! =  entry . ptr ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // 1. Set document's relevant global object's navigation API's focus changed during ongoing navigation to
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            //    true.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            as < Window > ( relevant_global_object ( * entry ) ) . navigation ( ) - > set_focus_changed_during_ongoing_navigation ( true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // 2. Designate entry as the focused area of the document.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            entry - > document ( ) . set_focused_area ( * entry ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // 2. If entry is an element, let focus event target be entry.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //    If entry is a Document object, let focus event target be that Document object's relevant global object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //    Otherwise, let focus event target be null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GC : : Ptr < DOM : : EventTarget >  focus_event_target ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( is < DOM : : Document > ( * entry ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            focus_event_target  =  as < Window > ( relevant_global_object ( * entry ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else  if  ( is < DOM : : Element > ( * entry ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            focus_event_target  =  * entry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // 3. If entry is the last entry in new chain, and entry is an Element, and the last entry in old chain is also
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //    an Element, then let related focus target be the last entry in old chain. Otherwise, let related focus
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //    target be null.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        GC : : Ptr < DOM : : EventTarget >  related_focus_target ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! new_chain . is_empty ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            & &  & entry  = =  & new_chain . last ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            & &  is < DOM : : Element > ( * entry ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            & &  ! old_chain . is_empty ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            & &  is < DOM : : Element > ( * old_chain . last ( ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            related_focus_target  =  old_chain . last ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // 4. If focus event target is not null, fire a focus event named focus at focus event target, with related
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //    focus target as the related target.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // FIXME: NOTE: In some cases, e.g. if entry is an area element's shape, a scrollable region, or a viewport, no event
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //       is fired.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  ( focus_event_target )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 11:39:32 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            fire_a_focus_event ( focus_event_target ,  related_focus_target ,  HTML : : EventNames : : focus ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // AD-HOC: dispatch focusin
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            fire_a_focus_event ( focus_event_target ,  related_focus_target ,  HTML : : EventNames : : focusin ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// https://html.spec.whatwg.org/multipage/interaction.html#focus-chain
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  Vector < GC : : Root < DOM : : Node > >  focus_chain ( DOM : : Node *  subject ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // FIXME: Move this somewhere more spec-friendly.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! subject ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 1. Let output be an empty list.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    Vector < GC : : Root < DOM : : Node > >  output ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 2. Let currentObject be subject.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto *  current_object  =  subject ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 3. While true:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    while  ( true )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // 1. Append currentObject to output.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        output . append ( GC : : make_root ( * current_object ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // FIXME: 2. If currentObject is an area element's shape, then append that area element to output.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // FIXME:    Otherwise, if currentObject's DOM anchor is an element that is not currentObject itself, then append currentObject's DOM anchor to output.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // FIXME: Everything below needs work. The conditions are not entirely right.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! is < DOM : : Document > ( * current_object ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // 3. If currentObject is a focusable area, then set currentObject to currentObject's DOM anchor's node document.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            current_object  =  & current_object - > document ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if  ( is < DOM : : Document > ( * current_object ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-07 01:19:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            & &  current_object - > navigable ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            & &  current_object - > navigable ( ) - > parent ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Otherwise, if currentObject is a Document whose node navigable's parent is non-null, then set currentObject to currentObject's node navigable's parent.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            current_object  =  current_object - > navigable ( ) - > container ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-07 01:19:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // Otherwise, break.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 4. Return output.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  output ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// https://html.spec.whatwg.org/multipage/interaction.html#focusing-steps
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// FIXME: This should accept more types.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-13 14:10:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  run_focusing_steps ( DOM : : Node *  new_focus_target ,  DOM : : Node *  fallback_target ,  FocusTrigger  focus_trigger ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // FIXME: 1. If new focus target is not a focusable area, then set new focus target to the result of getting the focusable
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //    area for new focus target, given focus trigger if it was passed.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 2. If new focus target is null, then:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! new_focus_target )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // 1. If no fallback target was specified, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! fallback_target ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // 2. Otherwise, set new focus target to the fallback target.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        new_focus_target  =  fallback_target ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-03 17:22:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 3. If new focus target is a navigable container with non-null content navigable, then set new focus target to the content navigable's active document.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( auto *  navigable_container  =  as_if < NavigableContainer > ( * new_focus_target ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( auto  content_navigable  =  navigable_container - > content_navigable ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-03 17:22:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            new_focus_target  =  content_navigable - > active_document ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 23:27:09 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 4. If new focus target is a focusable area and its DOM anchor is inert, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( new_focus_target - > is_inert ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 5. If new focus target is the currently focused area of a top-level browsing context, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! new_focus_target - > document ( ) . browsing_context ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 16:59:04 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  top_level_traversable  =  new_focus_target - > document ( ) . browsing_context ( ) - > top_level_traversable ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( new_focus_target  = =  top_level_traversable - > currently_focused_area ( ) . ptr ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 6. Let old chain be the current focus chain of the top-level browsing context in which
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //    new focus target finds itself.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 16:59:04 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  old_chain  =  focus_chain ( top_level_traversable - > currently_focused_area ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 7. Let new chain be the focus chain of new focus target.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  new_chain  =  focus_chain ( new_focus_target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-13 14:10:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // AD-HOC: Remember last focus trigger for :focus-visible / focus indication.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    new_focus_target - > document ( ) . set_last_focus_trigger ( focus_trigger ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    // 8. Run the focus update steps with old chain, new chain, and new focus target respectively.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    run_focus_update_steps ( old_chain ,  new_chain ,  new_focus_target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-03 08:42:32 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// https://html.spec.whatwg.org/multipage/interaction.html#unfocusing-steps
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								void  run_unfocusing_steps ( DOM : : Node *  old_focus_target ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // NOTE: The unfocusing steps do not always result in the focus changing, even when applied to the currently focused
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // area of a top-level browsing context. For example, if the currently focused area of a top-level browsing context
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // is a viewport, then it will usually keep its focus regardless until another focusable area is explicitly focused
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // with the focusing steps.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  is_shadow_host  =  [ ] ( DOM : : Node *  node )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-28 20:33:36 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  is < DOM : : Element > ( node )  & &  static_cast < DOM : : Element * > ( node ) - > is_shadow_host ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 1. If old focus target is a shadow host whose shadow root's delegates focus is true, and old focus target's
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //    shadow root is a shadow-including inclusive ancestor of the currently focused area of a top-level browsing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //    context's DOM anchor, then set old focus target to that currently focused area of a top-level browsing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //    context.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( is_shadow_host ( old_focus_target ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-25 11:28:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        auto  shadow_root  =  static_cast < DOM : : Element * > ( old_focus_target ) - > shadow_root ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  ( shadow_root - > delegates_focus ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 16:59:04 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            auto  top_level_traversable  =  old_focus_target - > document ( ) . browsing_context ( ) - > top_level_traversable ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( auto  currently_focused_area  =  top_level_traversable - > currently_focused_area ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								                if  ( shadow_root - > is_shadow_including_ancestor_of ( * currently_focused_area ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    old_focus_target  =  currently_focused_area ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 23:27:09 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 2. If old focus target is inert, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( old_focus_target - > is_inert ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // FIXME: 3. If old focus target is an area element and one of its shapes is the currently focused area of a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //    top-level browsing context, or, if old focus target is an element with one or more scrollable regions, and one
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //    of them is the currently focused area of a top-level browsing context, then let old focus target be that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //    currently focused area of a top-level browsing context.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // NOTE: HTMLAreaElement is currently missing the shapes property
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 4. Let old chain be the current focus chain of the top-level browsing context in which old focus target finds itself.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  top_level_traversable  =  old_focus_target - > document ( ) . browsing_context ( ) - > top_level_traversable ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 16:59:04 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  old_chain  =  focus_chain ( top_level_traversable - > currently_focused_area ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 5. If old focus target is not one of the entries in old chain, then return.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-03 08:42:32 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  it  =  old_chain . find_if ( [ & ] ( auto  const &  node )  {  return  old_focus_target  = =  node ;  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( it  = =  old_chain . end ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 6. If old focus target is not a focusable area, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! old_focus_target - > is_focusable ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 7. Let topDocument be old chain's last entry.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto &  top_document  =  as < DOM : : Document > ( * old_chain . last ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-19 20:24:18 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 8. If topDocument's node navigable has system focus, then run the focusing steps for topDocument's viewport.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( top_document . navigable ( ) - > traversable_navigable ( ) - > system_visibility_state ( )  = =  HTML : : VisibilityState : : Visible )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        run_focusing_steps ( & top_document ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // FIXME: Otherwise, apply any relevant platform-specific conventions for removing system focus from topDocument's
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // browsing context, and run the focus update steps with old chain, an empty list, and null respectively.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // What? It already doesn't have system focus, what possible platform-specific conventions are there?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        run_focus_update_steps ( old_chain ,  { } ,  nullptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:04:24 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // NOTE: The unfocusing steps do not always result in the focus changing, even when applied to the currently focused
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //       area of a top-level traversable. For example, if the currently focused area of a top-level traversable is a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //       viewport, then it will usually keep its focus regardless until another focusable area is explicitly focused
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //       with the focusing steps.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-05 14:30:49 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}