Dunst
Lightweight notification daemon
Loading...
Searching...
No Matches
foreign_toplevel.c
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-3-Clause */
7
8#define _POSIX_C_SOURCE 200112L
9#include <stdio.h>
10#include <stdbool.h>
11#include <stdlib.h>
12
13#include "protocols/wlr-foreign-toplevel-management-unstable-v1-client-header.h"
14
15#include "foreign_toplevel.h"
16#include "../dunst.h"
17#include "wl_output.h"
18#include "wl.h"
19
20struct wl_list toplevel_list;
21
22static void copy_state(struct toplevel_state *current,
23 struct toplevel_state *pending)
24{
25 if (!(pending->state & TOPLEVEL_STATE_INVALID)) {
26 current->state = pending->state;
27 }
28
29 pending->state = TOPLEVEL_STATE_INVALID;
30}
31
32static uint32_t global_id = 0;
33
34static void toplevel_handle_output_enter(void *data,
35 struct zwlr_foreign_toplevel_handle_v1 *zwlr_toplevel,
36 struct wl_output *wl_output)
37{
38 (void)zwlr_toplevel;
39
40 struct toplevel_v1 *toplevel = data;
41 struct toplevel_output *toplevel_output = calloc(1, sizeof(struct toplevel_output));
42 struct dunst_output *dunst_output = wl_output_get_user_data(wl_output);
43 toplevel_output->dunst_output = dunst_output;
44
45 wl_list_insert(&toplevel->output_list, &toplevel_output->link);
46}
47
48static void toplevel_handle_output_leave(void *data,
49 struct zwlr_foreign_toplevel_handle_v1 *zwlr_toplevel,
50 struct wl_output *wl_output)
51{
52 (void)zwlr_toplevel;
53
54 struct toplevel_v1 *toplevel = data;
55
56 struct dunst_output *output = wl_output_get_user_data(wl_output);
57 struct toplevel_output *pos, *tmp;
58 wl_list_for_each_safe(pos, tmp, &toplevel->output_list, link){
59 if (pos->dunst_output->name == output->name) {
60 wl_list_remove(&pos->link);
61 }
62 }
63}
64
65static uint32_t array_to_state(struct wl_array *array) {
66 uint32_t state = 0;
67 uint32_t *entry;
68 wl_array_for_each(entry, array) {
69 if (*entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED)
70 state |= TOPLEVEL_STATE_ACTIVATED;
71 if (*entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN)
72 state |= TOPLEVEL_STATE_FULLSCREEN;
73 }
74
75 return state;
76}
77
78static void toplevel_handle_state(void *data,
79 struct zwlr_foreign_toplevel_handle_v1 *zwlr_toplevel,
80 struct wl_array *state)
81{
82 (void)zwlr_toplevel;
83
84 struct toplevel_v1 *toplevel = data;
85 toplevel->pending.state = array_to_state(state);
86}
87
88static void toplevel_handle_done(void *data,
89 struct zwlr_foreign_toplevel_handle_v1 *zwlr_toplevel)
90{
91 (void)zwlr_toplevel;
92 struct toplevel_v1 *toplevel = data;
93
94 bool was_fullscreen = wl_have_fullscreen_window();
95 copy_state(&toplevel->current, &toplevel->pending);
96 bool is_fullscreen = wl_have_fullscreen_window();
97
98 if (was_fullscreen != is_fullscreen) {
99 wake_up();
100 }
101}
102
103static void toplevel_handle_closed(void *data,
104 struct zwlr_foreign_toplevel_handle_v1 *zwlr_toplevel)
105{
106 struct toplevel_v1 *toplevel = data;
107
108 wl_list_remove(&toplevel->link);
109 struct toplevel_output *pos, *tmp;
110 wl_list_for_each_safe(pos, tmp, &toplevel->output_list, link){
111 free(pos);
112 }
113 free(toplevel);
114 zwlr_foreign_toplevel_handle_v1_destroy(zwlr_toplevel);
115}
116
117static void toplevel_handle_title(void *data,
118 struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel,
119 const char *title)
120{
121 (void)data;
122 (void)zwlr_foreign_toplevel;
123 (void)title;
124}
125
126static void toplevel_handle_app_id(void *data,
127 struct zwlr_foreign_toplevel_handle_v1 *zwlr_foreign_toplevel,
128 const char *title)
129{
130 (void)data;
131 (void)zwlr_foreign_toplevel;
132 (void)title;
133}
134
135static const struct zwlr_foreign_toplevel_handle_v1_listener toplevel_impl = {
136 .title = toplevel_handle_title,
137 .app_id = toplevel_handle_app_id,
138 .output_enter = toplevel_handle_output_enter,
139 .output_leave = toplevel_handle_output_leave,
140 .state = toplevel_handle_state,
141 .done = toplevel_handle_done,
142 .closed = toplevel_handle_closed,
143};
144
145static void toplevel_manager_handle_toplevel(void *data,
146 struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager,
147 struct zwlr_foreign_toplevel_handle_v1 *zwlr_toplevel)
148{
149 (void)data;
150 (void)toplevel_manager;
151
152 struct toplevel_v1 *toplevel = calloc(1, sizeof(struct toplevel_v1));
153 if (!toplevel) {
154 fprintf(stderr, "Failed to allocate memory for toplevel\n");
155 return;
156 }
157
158 toplevel->id = global_id++;
159 toplevel->zwlr_toplevel = zwlr_toplevel;
160 wl_list_insert(&toplevel_list, &toplevel->link);
161 wl_list_init(&toplevel->output_list);
162
163 zwlr_foreign_toplevel_handle_v1_add_listener(zwlr_toplevel, &toplevel_impl,
164 toplevel);
165}
166
167static void toplevel_manager_handle_finished(void *data,
168 struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager)
169{
170 (void)data;
171 zwlr_foreign_toplevel_manager_v1_destroy(toplevel_manager);
172}
173
174const struct zwlr_foreign_toplevel_manager_v1_listener toplevel_manager_impl = {
175 .toplevel = toplevel_manager_handle_toplevel,
176 .finished = toplevel_manager_handle_finished,
177};
Main event loop logic.
Wayland foreign toplevel support.
Definition ini.h:17
Wayland window managment.
Wayland output wrapper.