1 /* 2 * Copyright (c) 2014 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial 14 * portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 */ 25 26 #include <stdint.h> 27 #include <unistd.h> 28 29 #include "wayland-server.h" 30 #include "wayland-client.h" 31 32 /* info about a client on server side */ 33 struct client_info { 34 struct display *display; 35 struct wl_client *wl_client; 36 struct wl_listener destroy_listener; 37 const char *name; /* for debugging */ 38 39 int pipe; 40 pid_t pid; 41 int exit_code; 42 43 struct wl_list link; 44 void *data; /* for arbitrary use */ 45 }; 46 47 struct display { 48 struct wl_display *wl_display; 49 50 struct wl_list clients; 51 uint32_t clients_no; 52 uint32_t clients_terminated_no; 53 54 /* list of clients waiting for display_resumed event */ 55 struct wl_list waiting_for_resume; 56 uint32_t wfr_num; 57 }; 58 59 /* This is a helper structure for clients. 60 * Instead of calling wl_display_connect() and all the other stuff, 61 * client can use client_connect and it will return this structure 62 * filled. */ 63 struct client { 64 struct wl_display *wl_display; 65 struct test_compositor *tc; 66 67 int display_stopped; 68 }; 69 70 struct client *client_connect(void); 71 void client_disconnect(struct client *); 72 int stop_display(struct client *, int); 73 void noop_request(struct client *); 74 75 /** 76 * Usual workflow: 77 * 78 * d = display_create(); 79 * 80 * wl_global_create(d->wl_display, ...); 81 * ... other setups ... 82 * 83 * client_create(d, client_main, data); 84 * client_create(d, client_main2, data); 85 * 86 * display_run(d); 87 * display_destroy(d); 88 */ 89 struct display *display_create(void); 90 void display_destroy(struct display *d); 91 void display_run(struct display *d); 92 93 /* This function posts the display_resumed event to all waiting clients, 94 * so that after flushing events the clients will stop waiting and continue. 95 * 96 * (Calling `display_run` after this function will resume the display loop.) 97 */ 98 void display_post_resume_events(struct display *d); 99 /* After n clients called stop_display(..., n), the display 100 * is stopped and can process the code after display_run(). 101 * 102 * This function posts the display_resumed event to the waiting 103 * clients, so that the clients will stop waiting and continue; 104 * it then reruns the display. */ 105 void display_resume(struct display *d); 106 107 108 struct client_info *client_create_with_name(struct display *d, 109 void (*client_main)(void *data), 110 void *data, 111 const char *name); 112 #define client_create(d, c, data) client_create_with_name((d), (c), data, (#c)) 113 #define client_create_noarg(d, c) \ 114 client_create_with_name((d), (void(*)(void *)) (c), NULL, (#c)) 115