Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/HTML/Focus.cpp (C++)

Code before:
    //    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.
    auto top_level_traversable = old_focus_target->document().browsing_context()->top_level_traversable();
    auto old_chain = focus_chain(top_level_traversable->currently_focused_area());

    // 5. If old focus target is not one of the entries in old chain, then return.
    auto it = old_chain.find_if([&](auto const& node) { return old_focus_target == node; });
    if (it == old_chain.end())
        return;

    // 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.
    auto& top_document = as<DOM::Document>(*old_chain.last());

    // 8. If topDocument's node navigable has system focus, then run the focusing steps for topDocument's viewport.
    if (top_document.navigable()->traversable_navigable()->is_focused()) {

        // AD-HOC: Remove top_document from old_chain so step 1 in run_focus_update_steps doesn't cancel the blur.
        auto without_viewport_surrogate = old_chain;
        without_viewport_surrogate.take_last();

        auto with_viewport_surrogate = focus_chain(&top_document);

        run_focus_update_steps(move(without_viewport_surrogate), move(with_viewport_surrogate), &top_document);
    } else {
        // 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.

        run_focus_update_steps(move(old_chain), {}, nullptr);
    }

    // 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.
}

}


Review comment (suggestion):
Do you understand what the spec is saying above? I guess spec might just be saying to let UI toolkit handle with it or something (and maybe this is just a no-op realistically for us)? In any case, I think this comment is pretty paired to the FIXME above

Code after:
    // 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.
    auto top_level_traversable = old_focus_target->document().browsing_context()->top_level_traversable();
    auto old_chain = focus_chain(top_level_traversable->currently_focused_area());

    // 5. If old focus target is not one of the entries in old chain, then return.
    auto it = old_chain.find_if([&](auto const& node) { return old_focus_target == node; });
    if (it == old_chain.end())
        return;

    // 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.
    auto& top_document = as<DOM::Document>(*old_chain.last());

    // 8. If topDocument's node navigable has system focus, then run the focusing steps for topDocument's viewport.
    if (top_document.navigable()->traversable_navigable()->is_focused()) {

        // AD-HOC: Remove top_document from old_chain so step 1 in run_focus_update_steps doesn't cancel the blur.
        auto without_viewport_surrogate = old_chain;
        without_viewport_surrogate.take_last();

        auto with_viewport_surrogate = focus_chain(&top_document);

        run_focus_update_steps(move(without_viewport_surrogate), move(with_viewport_surrogate), &top_document);
    } else {
        // 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.

        run_focus_update_steps(move(old_chain), {}, nullptr);
    }

    // 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.

    // What? It already doesn't have system focus, what possible platform-specific conventions are there?
}

}