mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	This change ensures that the compositor process is not able to respond to any of the noop requests sent by the client process, by using the test compositor's `stop_display` mechanism to coordinate when the compositor should stop processing messages. (Before this change, it was possible that one of the calls of wl_event_loop_dispatch in the compositor process could respond to all the client's noop requests before returning.) Signed-off-by: Manuel Stoeckl <code@mstoeckl.com>
		
			
				
	
	
		
			114 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) 2014 Red Hat, Inc.
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining
 | 
						|
 * a copy of this software and associated documentation files (the
 | 
						|
 * "Software"), to deal in the Software without restriction, including
 | 
						|
 * without limitation the rights to use, copy, modify, merge, publish,
 | 
						|
 * distribute, sublicense, and/or sell copies of the Software, and to
 | 
						|
 * permit persons to whom the Software is furnished to do so, subject to
 | 
						|
 * the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice (including the
 | 
						|
 * next paragraph) shall be included in all copies or substantial
 | 
						|
 * portions of the Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
						|
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
						|
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
						|
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 | 
						|
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
						|
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						|
 * SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdint.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
#include "wayland-server.h"
 | 
						|
#include "wayland-client.h"
 | 
						|
 | 
						|
/* info about a client on server side */
 | 
						|
struct client_info {
 | 
						|
	struct display *display;
 | 
						|
	struct wl_client *wl_client;
 | 
						|
	struct wl_listener destroy_listener;
 | 
						|
	const char *name; /* for debugging */
 | 
						|
 | 
						|
	int pipe;
 | 
						|
	pid_t pid;
 | 
						|
	int exit_code;
 | 
						|
 | 
						|
	struct wl_list link;
 | 
						|
	void *data; /* for arbitrary use */
 | 
						|
};
 | 
						|
 | 
						|
struct display {
 | 
						|
	struct wl_display *wl_display;
 | 
						|
 | 
						|
	struct wl_list clients;
 | 
						|
	uint32_t clients_no;
 | 
						|
	uint32_t clients_terminated_no;
 | 
						|
 | 
						|
	/* list of clients waiting for display_resumed event */
 | 
						|
	struct wl_list waiting_for_resume;
 | 
						|
	uint32_t wfr_num;
 | 
						|
};
 | 
						|
 | 
						|
/* This is a helper structure for clients.
 | 
						|
 * Instead of calling wl_display_connect() and all the other stuff,
 | 
						|
 * client can use client_connect and it will return this structure
 | 
						|
 * filled. */
 | 
						|
struct client {
 | 
						|
	struct wl_display *wl_display;
 | 
						|
	struct test_compositor *tc;
 | 
						|
 | 
						|
	int display_stopped;
 | 
						|
};
 | 
						|
 | 
						|
struct client *client_connect(void);
 | 
						|
void client_disconnect(struct client *);
 | 
						|
int stop_display(struct client *, int);
 | 
						|
void noop_request(struct client *);
 | 
						|
 | 
						|
/**
 | 
						|
 * Usual workflow:
 | 
						|
 *
 | 
						|
 *    d = display_create();
 | 
						|
 *
 | 
						|
 *    wl_global_create(d->wl_display, ...);
 | 
						|
 *    ... other setups ...
 | 
						|
 *
 | 
						|
 *    client_create(d, client_main, data);
 | 
						|
 *    client_create(d, client_main2, data);
 | 
						|
 *
 | 
						|
 *    display_run(d);
 | 
						|
 *    display_destroy(d);
 | 
						|
 */
 | 
						|
struct display *display_create(void);
 | 
						|
void display_destroy(struct display *d);
 | 
						|
void display_run(struct display *d);
 | 
						|
 | 
						|
/* This function posts the display_resumed event to all waiting clients,
 | 
						|
 * so that after flushing events the clients will stop waiting and continue.
 | 
						|
 *
 | 
						|
 * (Calling `display_run` after this function will resume the display loop.)
 | 
						|
 */
 | 
						|
void display_post_resume_events(struct display *d);
 | 
						|
/* After n clients called stop_display(..., n), the display
 | 
						|
 * is stopped and can process the code after display_run().
 | 
						|
 *
 | 
						|
 * This function posts the display_resumed event to the waiting
 | 
						|
 * clients, so that the clients will stop waiting and continue;
 | 
						|
 * it then reruns the display. */
 | 
						|
void display_resume(struct display *d);
 | 
						|
 | 
						|
 | 
						|
struct client_info *client_create_with_name(struct display *d,
 | 
						|
					    void (*client_main)(void *data),
 | 
						|
					    void *data,
 | 
						|
					    const char *name);
 | 
						|
#define client_create(d, c, data) client_create_with_name((d), (c), data, (#c))
 | 
						|
#define client_create_noarg(d, c) \
 | 
						|
	client_create_with_name((d), (void(*)(void *)) (c), NULL, (#c))
 |