test: adapt the change of policy request
[platform/core/uifw/libds-tizen.git] / src / screen_rotation / screen_rotation.c
1 #include <assert.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <wayland-server.h>
5 #include <tizen-extension-server-protocol.h>
6 #include <libds/log.h>
7
8 #include "util.h"
9 #include "libds-tizen/screen_rotation.h"
10
11 #define TIZEN_SCREEN_ROTATION_VERSION 1
12
13 struct ds_tizen_screen_rotation
14 {
15     struct wl_global *global;
16
17     struct wl_list clients;
18
19     struct wl_listener destroy;
20
21     struct {
22         struct wl_signal destroy;
23         struct wl_signal get_ignore_output_transfrom;
24     } events;
25 };
26
27 struct ds_tizen_screen_rotation_client
28 {
29     struct ds_tizen_screen_rotation *screen_rotation;
30
31     struct wl_resource *resource;
32     struct wl_client *wl_client;
33
34     struct wl_list infos;
35
36     struct {
37         struct wl_signal destroy;
38     } events;
39
40     struct wl_list link; // ds_tizen_screen_rotation::clients
41 };
42
43 struct ds_tizen_screen_rotation_info
44 {
45     struct ds_tizen_screen_rotation_client *client;
46
47     struct ds_surface *surface;
48
49     struct wl_list link; // ds_tizen_screen_rotation_client::infos
50 };
51
52 static void screen_rotation_handle_display_destroy(struct wl_listener *listener,
53         void *data);
54
55 static void screen_rotation_bind(struct wl_client *wl_client, void *data,
56         uint32_t version, uint32_t id);
57
58 static struct ds_tizen_screen_rotation_info *tizen_screen_rotation_client_find_info(
59     struct ds_tizen_screen_rotation_client *client,
60     struct ds_surface *surface);
61
62 static struct ds_tizen_screen_rotation_info *tizen_screen_rotation_client_get_info(
63         struct ds_tizen_screen_rotation_client *client,
64         struct ds_surface *surface);
65
66 WL_EXPORT struct ds_tizen_screen_rotation *
67 ds_tizen_screen_rotation_create(struct wl_display *display)
68 {
69     struct ds_tizen_screen_rotation *screen_rotation;
70
71     screen_rotation = calloc(1, sizeof *screen_rotation);
72     if (!screen_rotation) {
73         ds_err("calloc() failed.");
74         return NULL;
75     }
76
77     screen_rotation->global = wl_global_create(display,
78             &tizen_screen_rotation_interface, TIZEN_SCREEN_ROTATION_VERSION,
79             screen_rotation, screen_rotation_bind);
80     if (!screen_rotation->global) {
81         ds_err("wl_global_create() failed. tizen_screen_rotation_interface");
82         free(screen_rotation);
83         return NULL;
84     }
85
86     wl_list_init(&screen_rotation->clients);
87
88     screen_rotation->destroy.notify = screen_rotation_handle_display_destroy;
89     wl_display_add_destroy_listener(display, &screen_rotation->destroy);
90
91     wl_signal_init(&screen_rotation->events.destroy);
92     wl_signal_init(&screen_rotation->events.get_ignore_output_transfrom);
93
94         ds_inf("Global created: tizen_screen_rotation(%p)", screen_rotation);
95
96     return screen_rotation;
97 }
98
99 WL_EXPORT void
100 ds_tizen_screen_rotation_add_destroy_listener(
101     struct ds_tizen_screen_rotation *screen_rotation,
102     struct wl_listener *listener)
103 {
104     wl_signal_add(&screen_rotation->events.destroy, listener);
105 }
106
107 WL_EXPORT void
108 ds_tizen_screen_rotation_add_get_ignore_output_transform_info_listener(
109     struct ds_tizen_screen_rotation *screen_rotation,
110     struct wl_listener *listener)
111 {
112     wl_signal_add(&screen_rotation->events.get_ignore_output_transfrom,
113         listener);
114 }
115
116 WL_EXPORT void
117 ds_tizen_screen_rotation_info_add_destroy_listener(
118         struct ds_tizen_screen_rotation_info *info,
119         struct wl_listener *listener)
120 {
121     wl_signal_add(&info->client->events.destroy, listener);
122 }
123
124 WL_EXPORT struct ds_surface *
125 ds_tizen_screen_rotation_info_get_surface(
126         struct ds_tizen_screen_rotation_info *info)
127 {
128     return info->surface;
129 }
130
131 WL_EXPORT void
132 ds_tizen_screen_rotation_send_ignore_output_transform(
133     struct ds_tizen_screen_rotation_info *info, uint32_t ignore)
134 {
135     tizen_screen_rotation_send_ignore_output_transform(info->client->resource,
136         ds_surface_get_wl_resource(info->surface), ignore);
137 }
138
139 static struct ds_tizen_screen_rotation_info *
140 tizen_screen_rotation_client_find_info(struct ds_tizen_screen_rotation_client *client,
141     struct ds_surface *surface)
142 {
143     struct ds_tizen_screen_rotation_info *info;
144
145     wl_list_for_each(info, &client->infos, link) {
146         if (surface == info->surface)
147             return info;
148     }
149
150     return NULL;
151 }
152
153 static struct ds_tizen_screen_rotation_info *
154 tizen_screen_rotation_client_get_info(struct ds_tizen_screen_rotation_client *client,
155     struct ds_surface *surface)
156 {
157     struct ds_tizen_screen_rotation_info *info;
158
159     info = tizen_screen_rotation_client_find_info(client, surface);
160     if (info)
161         return info;
162
163     info = calloc(1, sizeof *info);
164     if (info == NULL) {
165         ds_err("calloc() failed. tizen_screen_rotation");
166         return NULL;
167     }
168
169     info->client = client;
170     info->surface = surface;
171
172     wl_list_insert(&client->infos, &info->link);
173
174     return info;
175 }
176
177 static void
178 screen_rotation_handle_display_destroy(struct wl_listener *listener, void *data)
179 {
180     struct ds_tizen_screen_rotation *screen_rotation;
181
182     screen_rotation = wl_container_of(listener, screen_rotation, destroy);
183
184     ds_inf("Global destroy: screen_rotation(%p)", screen_rotation);
185
186     wl_signal_emit(&screen_rotation->events.destroy, screen_rotation);
187     wl_list_remove(&screen_rotation->destroy.link);
188     wl_global_destroy(screen_rotation->global);
189     free(screen_rotation);
190 }
191
192 static void
193 screen_rotation_handle_destroy(struct wl_client *wl_client,
194     struct wl_resource *resource)
195 {
196     struct ds_tizen_screen_rotation_client *client;
197
198     client = wl_resource_get_user_data(resource);
199
200     if (!wl_list_empty(&client->infos)) {
201         ds_err("tizen_screen_rotation was destroyed before children");
202         return;
203     }
204
205     wl_resource_destroy(resource);
206 }
207
208 static void
209 screen_rotation_handle_get_ignore_output_transfrom(struct wl_client *wl_client,
210     struct wl_resource *resource, struct wl_resource *surface_resource)
211 {
212     struct ds_tizen_screen_rotation_client *client;
213     struct ds_tizen_screen_rotation_info *info;
214     struct ds_surface *surface;
215
216     ds_inf("tizen_screen_rotation: get_ignore_output_transfrom");
217
218     client = wl_resource_get_user_data(resource);
219     surface = ds_surface_from_resource(surface_resource);
220
221     info = tizen_screen_rotation_client_get_info(client, surface);
222     if (info == NULL) {
223         ds_err("tizen_screen_rotation_client_get_info() failed. tizen_screen_rotation");
224         wl_client_post_no_memory(wl_client);
225         return;
226     }
227
228     wl_signal_emit(&client->screen_rotation->events.get_ignore_output_transfrom, info);
229 }
230
231 static const struct tizen_screen_rotation_interface screen_rotation_impl =
232 {
233    screen_rotation_handle_get_ignore_output_transfrom,
234    screen_rotation_handle_destroy,
235 };
236
237 static void
238 _tizen_screen_rotation_client_handle_destroy(struct wl_resource *resource)
239 {
240     struct ds_tizen_screen_rotation_client *client;
241     struct ds_tizen_screen_rotation_info *info, *tmp;
242
243     client = wl_resource_get_user_data(resource);
244
245     ds_inf("_tizen_screen_rotation_client_handle_destroy (client:%p)", client);
246
247     wl_list_for_each_safe(info, tmp, &client->infos, link) {
248         wl_signal_emit(&client->events.destroy, info);
249         wl_list_remove(&info->link);
250         free(info);
251     }
252
253     wl_list_remove(&client->link);
254     free(client);
255 }
256
257 static void
258 screen_rotation_bind(struct wl_client *wl_client, void *data, uint32_t version,
259         uint32_t id)
260 {
261     struct ds_tizen_screen_rotation *screen_rotation = data;
262     struct ds_tizen_screen_rotation_client *client;
263
264     client = calloc(1, sizeof *client);
265     if (client == NULL) {
266         ds_err("calloc() failed. tizen_screen_rotation");
267         wl_client_post_no_memory(wl_client);
268         return;
269     }
270
271     ds_inf("tizen_screen_rotation_client binds. (client:%p)", client);
272
273     client->screen_rotation = screen_rotation;
274     client->wl_client = wl_client;
275
276     wl_list_init(&client->infos);
277
278     client->resource = wl_resource_create(wl_client, &tizen_screen_rotation_interface,
279             MIN(version, TIZEN_SCREEN_ROTATION_VERSION), id);
280
281     if (client->resource == NULL) {
282         ds_err("tizen_screen_rotation : wl_resource_create() failed.");
283         free(client);
284         wl_client_post_no_memory(wl_client);
285         return;
286     }
287
288     wl_resource_set_implementation(client->resource, &screen_rotation_impl, client,
289             _tizen_screen_rotation_client_handle_destroy);
290
291     wl_signal_init(&client->events.destroy);
292
293     wl_list_insert(&screen_rotation->clients, &client->link);
294 }