sdk: be C++ friendly
[platform/upstream/weston.git] / tests / weston-test.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <signal.h>
27 #include <unistd.h>
28 #include "../src/compositor.h"
29 #include "wayland-test-server-protocol.h"
30
31 struct weston_test {
32         struct weston_compositor *compositor;
33         struct weston_layer layer;
34         struct weston_process process;
35 };
36
37 struct weston_test_surface {
38         struct weston_surface *surface;
39         int32_t x, y;
40         struct weston_test *test;
41 };
42
43 static void
44 test_client_sigchld(struct weston_process *process, int status)
45 {
46         struct weston_test *test =
47                 container_of(process, struct weston_test, process);
48
49         assert(status == 0);
50
51         wl_display_terminate(test->compositor->wl_display);
52 }
53
54 static struct weston_seat *
55 get_seat(struct weston_test *test)
56 {
57         struct wl_list *seat_list;
58         struct weston_seat *seat;
59
60         seat_list = &test->compositor->seat_list;
61         assert(wl_list_length(seat_list) == 1);
62         seat = container_of(seat_list->next, struct weston_seat, link);
63
64         return seat;
65 }
66
67 static void
68 notify_pointer_position(struct weston_test *test, struct wl_resource *resource)
69 {
70         struct weston_seat *seat = get_seat(test);
71         struct wl_pointer *pointer = seat->seat.pointer;
72
73         wl_test_send_pointer_position(resource, pointer->x, pointer->y);
74 }
75
76 static void
77 test_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
78 {
79         struct weston_test_surface *test_surface = surface->configure_private;
80         struct weston_test *test = test_surface->test;
81
82         if (wl_list_empty(&surface->layer_link))
83                 wl_list_insert(&test->layer.surface_list,
84                                &surface->layer_link);
85
86         weston_surface_configure(surface, test_surface->x, test_surface->y,
87                                  width, height);
88
89         if (!weston_surface_is_mapped(surface))
90                 weston_surface_update_transform(surface);
91 }
92
93 static void
94 move_surface(struct wl_client *client, struct wl_resource *resource,
95              struct wl_resource *surface_resource,
96              int32_t x, int32_t y)
97 {
98         struct weston_surface *surface = surface_resource->data;
99         struct weston_test_surface *test_surface;
100
101         surface->configure = test_surface_configure;
102         if (surface->configure_private == NULL)
103                 surface->configure_private = malloc(sizeof *test_surface);
104         test_surface = surface->configure_private;
105         if (test_surface == NULL) {
106                 wl_resource_post_no_memory(resource);
107                 return;
108         }
109
110         test_surface->surface = surface;
111         test_surface->test = resource->data;
112         test_surface->x = x;
113         test_surface->y = y;
114 }
115
116 static void
117 move_pointer(struct wl_client *client, struct wl_resource *resource,
118              int32_t x, int32_t y)
119 {
120         struct weston_test *test = resource->data;
121         struct weston_seat *seat = get_seat(test);
122         struct wl_pointer *pointer = seat->seat.pointer;
123
124         test->compositor->focus = 1;
125
126         notify_motion(seat, 100,
127                       wl_fixed_from_int(x) - pointer->x,
128                       wl_fixed_from_int(y) - pointer->y);
129
130         notify_pointer_position(test, resource);
131 }
132
133 static void
134 send_button(struct wl_client *client, struct wl_resource *resource,
135             int32_t button, uint32_t state)
136 {
137         struct weston_test *test = resource->data;
138         struct weston_seat *seat = get_seat(test);
139
140         test->compositor->focus = 1;
141
142         notify_button(seat, 100, button, state);
143 }
144
145 static void
146 activate_surface(struct wl_client *client, struct wl_resource *resource,
147                  struct wl_resource *surface_resource)
148 {
149         struct weston_surface *surface = surface_resource ?
150                                         surface_resource->data : NULL;
151         struct weston_test *test = resource->data;
152         struct weston_seat *seat;
153
154         seat = get_seat(test);
155
156         if (surface) {
157                 weston_surface_activate(surface, seat);
158                 notify_keyboard_focus_in(seat, &seat->keyboard.keyboard.keys,
159                                          STATE_UPDATE_AUTOMATIC);
160         }
161         else {
162                 notify_keyboard_focus_out(seat);
163                 weston_surface_activate(surface, seat);
164         }
165 }
166
167 static void
168 send_key(struct wl_client *client, struct wl_resource *resource,
169          uint32_t key, enum wl_keyboard_key_state state)
170 {
171         struct weston_test *test = resource->data;
172         struct weston_seat *seat = get_seat(test);
173
174         test->compositor->focus = 1;
175
176         notify_key(seat, 100, key, state, STATE_UPDATE_AUTOMATIC);
177 }
178
179 static const struct wl_test_interface test_implementation = {
180         move_surface,
181         move_pointer,
182         send_button,
183         activate_surface,
184         send_key
185 };
186
187 static void
188 bind_test(struct wl_client *client, void *data, uint32_t version, uint32_t id)
189 {
190         struct weston_test *test = data;
191         struct wl_resource *resource;
192
193         resource = wl_client_add_object(client, &wl_test_interface,
194                                         &test_implementation, id, test);
195
196         notify_pointer_position(test, resource);
197 }
198
199 static void
200 idle_launch_client(void *data)
201 {
202         struct weston_test *test = data;
203         pid_t pid;
204         sigset_t allsigs;
205         char *path;
206
207         path = getenv("WESTON_TEST_CLIENT_PATH");
208         if (path == NULL)
209                 exit(EXIT_FAILURE);
210         pid = fork();
211         if (pid == -1)
212                 exit(EXIT_FAILURE);
213         if (pid == 0) {
214                 sigfillset(&allsigs);
215                 sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
216                 execl(path, path, NULL);
217                 weston_log("compositor: executing '%s' failed: %m\n", path);
218                 exit(EXIT_FAILURE);
219         }
220
221         test->process.pid = pid;
222         test->process.cleanup = test_client_sigchld;
223         weston_watch_process(&test->process);
224 }
225
226 WL_EXPORT int
227 module_init(struct weston_compositor *ec,
228             int *argc, char *argv[], const char *config_file)
229 {
230         struct weston_test *test;
231         struct wl_event_loop *loop;
232
233         test = malloc(sizeof *test);
234         if (test == NULL)
235                 return -1;
236
237         memset(test, 0, sizeof *test);
238         test->compositor = ec;
239         weston_layer_init(&test->layer, &ec->cursor_layer.link);
240
241         if (wl_display_add_global(ec->wl_display, &wl_test_interface,
242                                   test, bind_test) == NULL)
243                 return -1;
244
245         loop = wl_display_get_event_loop(ec->wl_display);
246         wl_event_loop_add_idle(loop, idle_launch_client, test);
247
248         return 0;
249 }