aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/wm/layer.c
blob: bfac7442e4ea554081be9169d17dab10ab4d1178 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include "wm.h"

static
void
map(struct wl_listener *l, void *data)
{
    Layer *layer = wl_container_of(l, layer, event.map);
    wlr_surface_send_enter(layer->surface->surface, layer->surface->output);
    notify_move(0);
}

static
void
finalize(Layer *layer)
{
    layer->surface->mapped = 0;
    if (layer->surface->surface == server.input.seat->keyboard_state.focused_surface)
        focus(selected_client(), 1);
    notify_move(0);
}

static
void
unmap(struct wl_listener *l, void *data)
{
    Layer *layer = wl_container_of(l, layer, event.unmap);
    finalize(layer);
}

static
void
destroy(struct wl_listener *l, void *data)
{
    Monitor *monitor;
    Layer *layer = wl_container_of(l, layer, event.destroy);

    if (layer->surface->mapped)
        finalize(layer);

    wl_list_remove(&layer->link);
    wl_list_remove(&layer->event.destroy.link);
    wl_list_remove(&layer->event.map.link);
    wl_list_remove(&layer->event.unmap.link);
    wl_list_remove(&layer->event.commit.link);

    if(layer->surface->output) {
        monitor = layer->surface->output->data;
        if(monitor)
            stratify(monitor);
        layer->surface->output = nil;
    }
    free(layer);
}

static
void
commit(struct wl_listener *l, void *data)
{
    Monitor *monitor;
    Layer *layer = wl_container_of(l, layer, event.commit);
    struct wlr_layer_surface_v1 *surface = layer->surface;
    struct wlr_output *output = surface->output;

    if(!output)
        return;

    monitor = output->data;
    stratify(monitor);

    if (layer->type != surface->current.layer) {
        wl_list_remove(&layer->link);
        wl_list_insert(&monitor->layer[surface->current.layer], &layer->link);
        layer->type = surface->current.layer;
    }
}

void
make_layer_surface(struct wl_listener *l, void *data)
{
    Layer   *layer;
    Monitor *monitor;
    struct wlr_layer_surface_v1_state state;
    struct wlr_layer_surface_v1 *surface = data;

    if(!surface->output)
        surface->output = server.monitor.selected->output;

    layer = surface->data = calloc(1, sizeof(*layer));
    layer->surface = surface;

    layer->event.map.notify = map;
    wl_signal_add(&surface->events.map, &layer->event.map);
    layer->event.unmap.notify = unmap;
    wl_signal_add(&surface->events.unmap, &layer->event.unmap);
    layer->event.destroy.notify = destroy;
    wl_signal_add(&surface->events.destroy, &layer->event.destroy);
    layer->event.commit.notify = commit;
    wl_signal_add(&surface->surface->events.commit, &layer->event.commit);

    monitor = surface->output->data;
    wl_list_insert(&monitor->layer[surface->client_pending.layer], &layer->link);

    state = surface->current;
    surface->current = surface->client_pending;
    stratify(monitor);
    surface->current = state;
}