<commit_before>#include <algorithm>
#include <cstring>

#include "xdg-shell.hpp"
#include "core.hpp"
#include "debug.hpp"
#include "output.hpp"
#include "workspace-manager.hpp"
#include "output-layout.hpp"
#include "view-impl.hpp"

extern "C"
{
#define namespace namespace_t
#include <wlr/types/wlr_layer_shell_v1.h>
#undef namespace
}

static const uint32_t both_vert =
    ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
static const uint32_t both_horiz =
    ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;

static wf::layer_t zwlr_layer_to_wf_layer(zwlr_layer_shell_v1_layer layer)
{
    switch (layer)
    {
        case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY:
            return wf::LAYER_LOCK;
        case ZWLR_LAYER_SHELL_V1_LAYER_TOP:
            return wf::LAYER_TOP;
        case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM:
            return wf::LAYER_BOTTOM;
        case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND:
            return wf::LAYER_BACKGROUND;
        default:
            throw std::domain_error("Invalid layer for layer surface!");
    }
}

class wayfire_layer_shell_view : public wf::wlr_view_t
{
    wf::wl_listener_wrapper on_map, on_unmap, on_destroy, on_new_popup;

  public:
    wlr_layer_surface_v1 *lsurface;
    wlr_layer_surface_v1_state prev_state;

    std::unique_ptr<wf::workspace_manager::anchored_area> anchored_area;

    wayfire_layer_shell_view(wlr_layer_surface_v1 *lsurf);
    virtual ~wayfire_layer_shell_view() {}

    void map(wlr_surface *surface) override;
    void unmap() override;
    void commit() override;
    void close() override;
    void destroy() override;

    void configure(wf_geometry geometry);
};

wf::workspace_manager::anchored_edge anchor_to_edge(uint32_t edges)
{
    if (edges == ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)
        return wf::workspace_manager::ANCHORED_EDGE_TOP;
    if (edges == ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)
        return wf::workspace_manager::ANCHORED_EDGE_BOTTOM;
    if (edges == ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)
        return wf::workspace_manager::ANCHORED_EDGE_LEFT;
    if (edges == ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)
        return wf::workspace_manager::ANCHORED_EDGE_RIGHT;

    assert(false);
}

struct wf_layer_shell_manager
{
    using layer_t = std::vector<wayfire_layer_shell_view*>;
    layer_t layers[4];

    void handle_map(wayfire_layer_shell_view *view)
    {
        layers[view->lsurface->layer].push_back(view);
        arrange_layers(view->get_output());
    }

    void handle_unmap(wayfire_layer_shell_view *view)
    {
        auto& cont = layers[view->lsurface->layer];
        auto it = std::find(cont.begin(), cont.end(), view);

        if (view->anchored_area)
            view->get_output()->workspace->remove_reserved_area(view->anchored_area.get());

        cont.erase(it);
        arrange_layers(view->get_output());
    }

    layer_t filter_views(wf::output_t *output, int layer)
    {
        layer_t result;
        for (auto view : layers[layer])
        {
            if (view->get_output() == output)
                result.push_back(view);
        }

        return result;
    }

    layer_t filter_views(wf::output_t *output)
    {
        layer_t result;
        for (int i = 0; i < 4; i++)
        {
            auto layer_result = filter_views(output, i);
            result.insert(result.end(), layer_result.begin(), layer_result.end());
        }

        return result;
    }

    void set_exclusive_zone(wayfire_layer_shell_view *v)
    {
        int edges = v->lsurface->current.anchor;

        /* Special case we support */
        if (__builtin_popcount(edges) == 3)
        {
            if ((edges & both_horiz) == both_horiz)
                edges ^= both_horiz;

            if ((edges & both_vert) == both_vert)
                edges ^= both_vert;
        }

        if (__builtin_popcount(edges) > 1)
        {
            log_error ("Unsupported: layer-shell exclusive zone for surfaces anchored to 0, 2 or 4 edges");
            return;
        }<commit_msg>layer-shell: actually check for anchoring to 0 edges<commit_after>#include <algorithm>
#include <cstring>

#include "xdg-shell.hpp"
#include "core.hpp"
#include "debug.hpp"
#include "output.hpp"
#include "workspace-manager.hpp"
#include "output-layout.hpp"
#include "view-impl.hpp"

extern "C"
{
#define namespace namespace_t
#include <wlr/types/wlr_layer_shell_v1.h>
#undef namespace
}

static const uint32_t both_vert =
    ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
static const uint32_t both_horiz =
    ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;

static wf::layer_t zwlr_layer_to_wf_layer(zwlr_layer_shell_v1_layer layer)
{
    switch (layer)
    {
        case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY:
            return wf::LAYER_LOCK;
        case ZWLR_LAYER_SHELL_V1_LAYER_TOP:
            return wf::LAYER_TOP;
        case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM:
            return wf::LAYER_BOTTOM;
        case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND:
            return wf::LAYER_BACKGROUND;
        default:
            throw std::domain_error("Invalid layer for layer surface!");
    }
}

class wayfire_layer_shell_view : public wf::wlr_view_t
{
    wf::wl_listener_wrapper on_map, on_unmap, on_destroy, on_new_popup;

  public:
    wlr_layer_surface_v1 *lsurface;
    wlr_layer_surface_v1_state prev_state;

    std::unique_ptr<wf::workspace_manager::anchored_area> anchored_area;

    wayfire_layer_shell_view(wlr_layer_surface_v1 *lsurf);
    virtual ~wayfire_layer_shell_view() {}

    void map(wlr_surface *surface) override;
    void unmap() override;
    void commit() override;
    void close() override;
    void destroy() override;

    void configure(wf_geometry geometry);
};

wf::workspace_manager::anchored_edge anchor_to_edge(uint32_t edges)
{
    if (edges == ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)
        return wf::workspace_manager::ANCHORED_EDGE_TOP;
    if (edges == ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)
        return wf::workspace_manager::ANCHORED_EDGE_BOTTOM;
    if (edges == ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)
        return wf::workspace_manager::ANCHORED_EDGE_LEFT;
    if (edges == ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)
        return wf::workspace_manager::ANCHORED_EDGE_RIGHT;

    assert(false);
}

struct wf_layer_shell_manager
{
    using layer_t = std::vector<wayfire_layer_shell_view*>;
    layer_t layers[4];

    void handle_map(wayfire_layer_shell_view *view)
    {
        layers[view->lsurface->layer].push_back(view);
        arrange_layers(view->get_output());
    }

    void handle_unmap(wayfire_layer_shell_view *view)
    {
        auto& cont = layers[view->lsurface->layer];
        auto it = std::find(cont.begin(), cont.end(), view);

        if (view->anchored_area)
            view->get_output()->workspace->remove_reserved_area(view->anchored_area.get());

        cont.erase(it);
        arrange_layers(view->get_output());
    }

    layer_t filter_views(wf::output_t *output, int layer)
    {
        layer_t result;
        for (auto view : layers[layer])
        {
            if (view->get_output() == output)
                result.push_back(view);
        }

        return result;
    }

    layer_t filter_views(wf::output_t *output)
    {
        layer_t result;
        for (int i = 0; i < 4; i++)
        {
            auto layer_result = filter_views(output, i);
            result.insert(result.end(), layer_result.begin(), layer_result.end());
        }

        return result;
    }

    void set_exclusive_zone(wayfire_layer_shell_view *v)
    {
        int edges = v->lsurface->current.anchor;

        /* Special case we support */
        if (__builtin_popcount(edges) == 3)
        {
            if ((edges & both_horiz) == both_horiz)
                edges ^= both_horiz;

            if ((edges & both_vert) == both_vert)
                edges ^= both_vert;
        }

        if (edges == 0 || __builtin_popcount(edges) > 1)
        {
            log_error ("Unsupported: layer-shell exclusive zone for surfaces anchored to 0, 2 or 4 edges");
            return;
        }
{'fraction_non_alphanumeric': 0.1019982836827265, 'fraction_numerical': 0.007846021821748192, 'mean_word_length': 3.08104052026013, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 43, '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': '889519', 'n_tokens_mistral': 2973, 'n_tokens_neox': 2887, 'n_words': 489}