<commit_before>#include <wayfire/util/log.hpp>
#include "../core/core-impl.hpp"
#include "view-impl.hpp"
#include "wayfire/opengl.hpp"
#include "wayfire/output.hpp"
#include "wayfire/view.hpp"
#include "wayfire/view-transform.hpp"
#include "wayfire/decorator.hpp"
#include "wayfire/workspace-manager.hpp"
#include "wayfire/render-manager.hpp"
#include "xdg-shell.hpp"
#include "../output/gtk-shell.hpp"

#include <algorithm>
#include <glm/glm.hpp>
#include "wayfire/signal-definitions.hpp"

extern "C"
{
#define static
#include <wlr/config.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/util/region.h>
#include <wlr/util/edges.h>
#undef static
}

static void reposition_relative_to_parent(wayfire_view view)
{
    if (!view->parent)
        return;

    auto workarea = view->get_output()->workspace->get_workarea();
    auto wm_geometry = view->get_wm_geometry();

    if (view->parent->is_mapped())
    {
        auto parent_g = view->parent->get_wm_geometry();
        wm_geometry.x = parent_g.x + (parent_g.width  - wm_geometry.width) / 2;
        wm_geometry.y = parent_g.y + (parent_g.height - wm_geometry.height) / 2;
    }
    else
    {
        /* if we have a parent which still isn't mapped, we cannot determine
         * the view's position, so we center it on the screen */
        wm_geometry.x = workarea.width / 2 - wm_geometry.width / 2;
        wm_geometry.y = workarea.height/ 2 - wm_geometry.height/ 2;
    }

    /* make sure view is visible afterwards */
    wm_geometry = wf::clamp(wm_geometry, workarea);
    view->move(wm_geometry.x, wm_geometry.y);
    if (wm_geometry.width != view->get_wm_geometry().width ||
        wm_geometry.height != view->get_wm_geometry().height)
    {
        view->resize(wm_geometry.width, wm_geometry.height);
    }
}

static void unset_toplevel_parent(wayfire_view view)
{
    if (view->parent)
    {
        auto& container = view->parent->children;
        auto it = std::remove(container.begin(), container.end(), view);
        container.erase(it, container.end());
    }
}

static wayfire_view find_toplevel_parent(wayfire_view view)
{
    while (view->parent)
        view = view->parent;

    return view;
}

/**
 * Check whether the toplevel parent needs refocus.
 * This may be needed because when focusing a view, its topmost child is given
 * keyboard focus. When the parent-child relations change, it may happen that
 * the parent needs to be focused again, this time with a different keyboard
 * focus surface.
 */
static void check_refocus_parent(wayfire_view view)
{
    view = find_toplevel_parent(view);
    if (view->get_output() && view->get_output()->get_active_view() == view)
        view->get_output()->focus_view(view, false);
};

void wf::view_interface_t::set_toplevel_parent(wayfire_view new_parent)
{
    auto old_parent = parent;
    if (parent != new_parent)
    {
        /* Erase from the old parent */
        unset_toplevel_parent(self());

        /* Add in the list of the new parent */
        if (new_parent)
            new_parent->children.insert(new_parent->children.begin(), self());

        parent = new_parent;
    }

    if (parent)
    {
        /* Make sure the view is available only as a child */
        if (this->get_output())
            this->get_output()->workspace->remove_view(self());

        /* if the view isn't mapped, then it will be positioned properly in map() */
        if (is_mapped())
            reposition_relative_to_parent(self());

        check_refocus_parent(parent);
    }
    else if (old_parent)
    {
        /* At this point, we are a regular view. We should try to position ourselves
         * directly above the old parent */
        if (this->get_output())
        {
            this->get_output()->workspace->add_view(
                self(), wf::LAYER_WORKSPACE);

            check_refocus_parent(old_parent);
            this->get_output()->workspace->restack_above(self(),
                find_toplevel_parent(old_parent));
        }
    }
}

std::vector<wayfire_view> wf::view_interface_t::enumerate_views(
    bool mapped_only)
{
    if (!this->is_mapped() && mapped_only)
        return {};

    std::vector<wayfire_view> result;
    for (auto& v : this->children)<commit_msg>view: move to the parent's output when parent is set<commit_after>#include <wayfire/util/log.hpp>
#include "../core/core-impl.hpp"
#include "view-impl.hpp"
#include "wayfire/opengl.hpp"
#include "wayfire/output.hpp"
#include "wayfire/view.hpp"
#include "wayfire/view-transform.hpp"
#include "wayfire/decorator.hpp"
#include "wayfire/workspace-manager.hpp"
#include "wayfire/render-manager.hpp"
#include "xdg-shell.hpp"
#include "../output/gtk-shell.hpp"

#include <algorithm>
#include <glm/glm.hpp>
#include "wayfire/signal-definitions.hpp"

extern "C"
{
#define static
#include <wlr/config.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/util/region.h>
#include <wlr/util/edges.h>
#undef static
}

static void reposition_relative_to_parent(wayfire_view view)
{
    if (!view->parent)
        return;

    auto workarea = view->get_output()->workspace->get_workarea();
    auto wm_geometry = view->get_wm_geometry();

    if (view->parent->is_mapped())
    {
        auto parent_g = view->parent->get_wm_geometry();
        wm_geometry.x = parent_g.x + (parent_g.width  - wm_geometry.width) / 2;
        wm_geometry.y = parent_g.y + (parent_g.height - wm_geometry.height) / 2;
    }
    else
    {
        /* if we have a parent which still isn't mapped, we cannot determine
         * the view's position, so we center it on the screen */
        wm_geometry.x = workarea.width / 2 - wm_geometry.width / 2;
        wm_geometry.y = workarea.height/ 2 - wm_geometry.height/ 2;
    }

    /* make sure view is visible afterwards */
    wm_geometry = wf::clamp(wm_geometry, workarea);
    view->move(wm_geometry.x, wm_geometry.y);
    if (wm_geometry.width != view->get_wm_geometry().width ||
        wm_geometry.height != view->get_wm_geometry().height)
    {
        view->resize(wm_geometry.width, wm_geometry.height);
    }
}

static void unset_toplevel_parent(wayfire_view view)
{
    if (view->parent)
    {
        auto& container = view->parent->children;
        auto it = std::remove(container.begin(), container.end(), view);
        container.erase(it, container.end());
    }
}

static wayfire_view find_toplevel_parent(wayfire_view view)
{
    while (view->parent)
        view = view->parent;

    return view;
}

/**
 * Check whether the toplevel parent needs refocus.
 * This may be needed because when focusing a view, its topmost child is given
 * keyboard focus. When the parent-child relations change, it may happen that
 * the parent needs to be focused again, this time with a different keyboard
 * focus surface.
 */
static void check_refocus_parent(wayfire_view view)
{
    view = find_toplevel_parent(view);
    if (view->get_output() && view->get_output()->get_active_view() == view)
        view->get_output()->focus_view(view, false);
};

void wf::view_interface_t::set_toplevel_parent(wayfire_view new_parent)
{
    auto old_parent = parent;
    if (parent != new_parent)
    {
        /* Erase from the old parent */
        unset_toplevel_parent(self());

        /* Add in the list of the new parent */
        if (new_parent)
            new_parent->children.insert(new_parent->children.begin(), self());

        parent = new_parent;
    }

    if (parent)
    {
        /* Make sure the view is available only as a child */
        if (this->get_output())
            this->get_output()->workspace->remove_view(self());

        this->set_output(parent->get_output());
        /* if the view isn't mapped, then it will be positioned properly in map() */
        if (is_mapped())
            reposition_relative_to_parent(self());

        check_refocus_parent(parent);
    }
    else if (old_parent)
    {
        /* At this point, we are a regular view. We should try to position ourselves
         * directly above the old parent */
        if (this->get_output())
        {
            this->get_output()->workspace->add_view(
                self(), wf::LAYER_WORKSPACE);

            check_refocus_parent(old_parent);
            this->get_output()->workspace->restack_above(self(),
                find_toplevel_parent(old_parent));
        }
    }
}

std::vector<wayfire_view> wf::view_interface_t::enumerate_views(
    bool mapped_only)
{
    if (!this->is_mapped() && mapped_only)
        return {};

    std::vector<wayfire_view> result;
    for (auto& v : this->children)
{'fraction_non_alphanumeric': 0.130233097529862, 'fraction_numerical': 0.0013916270439522209, 'mean_word_length': 2.9723629663749422, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 101, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1309142', 'n_tokens_mistral': 2811, 'n_tokens_neox': 2758, 'n_words': 641}