mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	Generalize event loop a bit and pull in the timerfd stuff.
This commit is contained in:
		
							parent
							
								
									fbdbbdc153
								
							
						
					
					
						commit
						4a29890da7
					
				
					 6 changed files with 261 additions and 95 deletions
				
			
		| 
						 | 
					@ -17,7 +17,6 @@
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
#include <linux/input.h>
 | 
					#include <linux/input.h>
 | 
				
			||||||
#include <xf86drmMode.h>
 | 
					#include <xf86drmMode.h>
 | 
				
			||||||
#include <sys/timerfd.h>
 | 
					 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "wayland.h"
 | 
					#include "wayland.h"
 | 
				
			||||||
| 
						 | 
					@ -46,7 +45,6 @@ struct egl_compositor {
 | 
				
			||||||
	struct wl_event_source *timer_source;
 | 
						struct wl_event_source *timer_source;
 | 
				
			||||||
	int repaint_needed;
 | 
						int repaint_needed;
 | 
				
			||||||
	int repaint_on_timeout;
 | 
						int repaint_on_timeout;
 | 
				
			||||||
	int timer_fd;
 | 
					 | 
				
			||||||
	struct timespec previous_swap;
 | 
						struct timespec previous_swap;
 | 
				
			||||||
	uint32_t current_frame;
 | 
						uint32_t current_frame;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -527,20 +525,15 @@ animate_overlay(struct egl_compositor *ec)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
repaint(int fd, uint32_t mask, void *data)
 | 
					repaint(void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct egl_compositor *ec = data;
 | 
						struct egl_compositor *ec = data;
 | 
				
			||||||
	struct itimerspec its;
 | 
					 | 
				
			||||||
	struct wl_surface_iterator *iterator;
 | 
						struct wl_surface_iterator *iterator;
 | 
				
			||||||
	struct wl_surface *surface;
 | 
						struct wl_surface *surface;
 | 
				
			||||||
	struct egl_surface *es;
 | 
						struct egl_surface *es;
 | 
				
			||||||
	struct timespec ts;
 | 
						struct timespec ts;
 | 
				
			||||||
	uint64_t expires;
 | 
					 | 
				
			||||||
	uint32_t msecs;
 | 
						uint32_t msecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ec->repaint_on_timeout)
 | 
					 | 
				
			||||||
		read(fd, &expires, sizeof expires);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!ec->repaint_needed) {
 | 
						if (!ec->repaint_needed) {
 | 
				
			||||||
		ec->repaint_on_timeout = 0;
 | 
							ec->repaint_on_timeout = 0;
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -570,25 +563,12 @@ repaint(int fd, uint32_t mask, void *data)
 | 
				
			||||||
	wl_display_post_frame(ec->wl_display, ec->current_frame, msecs);
 | 
						wl_display_post_frame(ec->wl_display, ec->current_frame, msecs);
 | 
				
			||||||
	ec->current_frame++;
 | 
						ec->current_frame++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	its.it_interval.tv_sec = 0;
 | 
						wl_event_source_timer_update(ec->timer_source, 10);
 | 
				
			||||||
	its.it_interval.tv_nsec = 0;
 | 
					 | 
				
			||||||
	its.it_value.tv_sec = 0;
 | 
					 | 
				
			||||||
	its.it_value.tv_nsec = 10 * 1000 * 1000;
 | 
					 | 
				
			||||||
	if (timerfd_settime(ec->timer_fd, 0, &its, NULL) < 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "could not set timerfd\n: %m");
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ec->repaint_on_timeout = 1;
 | 
						ec->repaint_on_timeout = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	animate_overlay(ec);
 | 
						animate_overlay(ec);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
idle_repaint(void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	repaint(0, 0, data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
schedule_repaint(struct egl_compositor *ec)
 | 
					schedule_repaint(struct egl_compositor *ec)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -597,7 +577,7 @@ schedule_repaint(struct egl_compositor *ec)
 | 
				
			||||||
	ec->repaint_needed = 1;
 | 
						ec->repaint_needed = 1;
 | 
				
			||||||
	if (!ec->repaint_on_timeout) {
 | 
						if (!ec->repaint_on_timeout) {
 | 
				
			||||||
		loop = wl_display_get_event_loop(ec->wl_display);
 | 
							loop = wl_display_get_event_loop(ec->wl_display);
 | 
				
			||||||
		wl_event_loop_add_idle(loop, idle_repaint, ec);
 | 
							wl_event_loop_add_idle(loop, repaint, ec);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1010,16 +990,8 @@ wl_compositor_create(struct wl_display *display)
 | 
				
			||||||
	wl_display_add_object(display, &shooter->base);
 | 
						wl_display_add_object(display, &shooter->base);
 | 
				
			||||||
	wl_display_add_global(display, &shooter->base);
 | 
						wl_display_add_global(display, &shooter->base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ec->timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
 | 
					 | 
				
			||||||
	if (ec->timer_fd < 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "could not create timerfd\n: %m");
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	loop = wl_display_get_event_loop(ec->wl_display);
 | 
						loop = wl_display_get_event_loop(ec->wl_display);
 | 
				
			||||||
	ec->timer_source = wl_event_loop_add_fd(loop, ec->timer_fd,
 | 
						ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec);
 | 
				
			||||||
						WL_EVENT_READABLE,
 | 
					 | 
				
			||||||
						repaint, ec);
 | 
					 | 
				
			||||||
	ec->repaint_needed = 0;
 | 
						ec->repaint_needed = 0;
 | 
				
			||||||
	ec->repaint_on_timeout = 0;
 | 
						ec->repaint_on_timeout = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										294
									
								
								event-loop.c
									
										
									
									
									
								
							
							
						
						
									
										294
									
								
								event-loop.c
									
										
									
									
									
								
							| 
						 | 
					@ -6,34 +6,84 @@
 | 
				
			||||||
#include <sys/socket.h>
 | 
					#include <sys/socket.h>
 | 
				
			||||||
#include <sys/un.h>
 | 
					#include <sys/un.h>
 | 
				
			||||||
#include <sys/epoll.h>
 | 
					#include <sys/epoll.h>
 | 
				
			||||||
 | 
					#include <sys/timerfd.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
#include "wayland.h"
 | 
					#include "wayland.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wl_event_loop {
 | 
					struct wl_event_loop {
 | 
				
			||||||
	int epoll_fd;
 | 
						int epoll_fd;
 | 
				
			||||||
	wl_event_loop_idle_func_t idle_func;
 | 
						struct wl_list idle_list;
 | 
				
			||||||
	void *idle_data;
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_event_source_interface {
 | 
				
			||||||
 | 
						void (*dispatch)(struct wl_event_source *source,
 | 
				
			||||||
 | 
								 struct epoll_event *ep);
 | 
				
			||||||
 | 
						int (*remove)(struct wl_event_source *source);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wl_event_source {
 | 
					struct wl_event_source {
 | 
				
			||||||
 | 
						struct wl_event_source_interface *interface;
 | 
				
			||||||
 | 
						struct wl_event_loop *loop;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_event_source_fd {
 | 
				
			||||||
 | 
						struct wl_event_source base;
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	wl_event_loop_fd_func_t func;
 | 
						wl_event_loop_fd_func_t func;
 | 
				
			||||||
	void *data;
 | 
						void *data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					wl_event_source_fd_dispatch(struct wl_event_source *source,
 | 
				
			||||||
 | 
								    struct epoll_event *ep)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_event_source_fd *fd_source = (struct wl_event_source_fd *) source;
 | 
				
			||||||
 | 
						uint32_t mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mask = 0;
 | 
				
			||||||
 | 
						if (ep->events & EPOLLIN)
 | 
				
			||||||
 | 
							mask |= WL_EVENT_READABLE;
 | 
				
			||||||
 | 
						if (ep->events & EPOLLOUT)
 | 
				
			||||||
 | 
							mask |= WL_EVENT_WRITEABLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fd_source->func(fd_source->fd, mask, fd_source->data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					wl_event_source_fd_remove(struct wl_event_source *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_event_source_fd *fd_source =
 | 
				
			||||||
 | 
							(struct wl_event_source_fd *) source;
 | 
				
			||||||
 | 
						struct wl_event_loop *loop = source->loop;
 | 
				
			||||||
 | 
						int fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fd = fd_source->fd;
 | 
				
			||||||
 | 
						free(source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_event_source_interface fd_source_interface = {
 | 
				
			||||||
 | 
						wl_event_source_fd_dispatch,
 | 
				
			||||||
 | 
						wl_event_source_fd_remove
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT struct wl_event_source *
 | 
					WL_EXPORT struct wl_event_source *
 | 
				
			||||||
wl_event_loop_add_fd(struct wl_event_loop *loop,
 | 
					wl_event_loop_add_fd(struct wl_event_loop *loop,
 | 
				
			||||||
		     int fd, uint32_t mask,
 | 
							     int fd, uint32_t mask,
 | 
				
			||||||
		     wl_event_loop_fd_func_t func,
 | 
							     wl_event_loop_fd_func_t func,
 | 
				
			||||||
		     void *data)
 | 
							     void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wl_event_source *source;
 | 
						struct wl_event_source_fd *source;
 | 
				
			||||||
	struct epoll_event ep;
 | 
						struct epoll_event ep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	source = malloc(sizeof *source);
 | 
						source = malloc(sizeof *source);
 | 
				
			||||||
	if (source == NULL)
 | 
						if (source == NULL)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						source->base.interface = &fd_source_interface;
 | 
				
			||||||
 | 
						source->base.loop = loop;
 | 
				
			||||||
	source->fd = fd;
 | 
						source->fd = fd;
 | 
				
			||||||
	source->func = func;
 | 
						source->func = func;
 | 
				
			||||||
	source->data = data;
 | 
						source->data = data;
 | 
				
			||||||
| 
						 | 
					@ -50,33 +100,15 @@ wl_event_loop_add_fd(struct wl_event_loop *loop,
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return source;
 | 
						return &source->base;
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct wl_event_source idle_source;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WL_EXPORT int
 | 
					 | 
				
			||||||
wl_event_loop_remove_source(struct wl_event_loop *loop,
 | 
					 | 
				
			||||||
			    struct wl_event_source *source)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int fd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (source == &idle_source) {
 | 
					 | 
				
			||||||
		loop->idle_func = NULL;
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		fd = source->fd;
 | 
					 | 
				
			||||||
		free(source);
 | 
					 | 
				
			||||||
		return epoll_ctl(loop->epoll_fd,
 | 
					 | 
				
			||||||
				 EPOLL_CTL_DEL, fd, NULL);
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT int
 | 
					WL_EXPORT int
 | 
				
			||||||
wl_event_loop_update_source(struct wl_event_loop *loop,
 | 
					wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask)
 | 
				
			||||||
			    struct wl_event_source *source,
 | 
					 | 
				
			||||||
			    uint32_t mask)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct wl_event_source_fd *fd_source =
 | 
				
			||||||
 | 
							(struct wl_event_source_fd *) source;
 | 
				
			||||||
 | 
						struct wl_event_loop *loop = source->loop;
 | 
				
			||||||
	struct epoll_event ep;
 | 
						struct epoll_event ep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ep.events = 0;
 | 
						ep.events = 0;
 | 
				
			||||||
| 
						 | 
					@ -87,7 +119,160 @@ wl_event_loop_update_source(struct wl_event_loop *loop,
 | 
				
			||||||
	ep.data.ptr = source;
 | 
						ep.data.ptr = source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return epoll_ctl(loop->epoll_fd,
 | 
						return epoll_ctl(loop->epoll_fd,
 | 
				
			||||||
			 EPOLL_CTL_MOD, source->fd, &ep);
 | 
								 EPOLL_CTL_MOD, fd_source->fd, &ep);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_event_source_timer {
 | 
				
			||||||
 | 
						struct wl_event_source base;
 | 
				
			||||||
 | 
						int fd;
 | 
				
			||||||
 | 
						wl_event_loop_timer_func_t func;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					wl_event_source_timer_dispatch(struct wl_event_source *source,
 | 
				
			||||||
 | 
								       struct epoll_event *ep)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_event_source_timer *timer_source =
 | 
				
			||||||
 | 
							(struct wl_event_source_timer *) source;
 | 
				
			||||||
 | 
						uint64_t expires;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						read(timer_source->fd, &expires, sizeof expires);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						timer_source->func(timer_source->data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					wl_event_source_timer_remove(struct wl_event_source *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_event_source_timer *timer_source =
 | 
				
			||||||
 | 
							(struct wl_event_source_timer *) source;
 | 
				
			||||||
 | 
						struct wl_event_loop *loop = source->loop;
 | 
				
			||||||
 | 
						int fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fd = timer_source->fd;
 | 
				
			||||||
 | 
						free(source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_event_source_interface timer_source_interface = {
 | 
				
			||||||
 | 
						wl_event_source_timer_dispatch,
 | 
				
			||||||
 | 
						wl_event_source_timer_remove
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WL_EXPORT struct wl_event_source *
 | 
				
			||||||
 | 
					wl_event_loop_add_timer(struct wl_event_loop *loop,
 | 
				
			||||||
 | 
								wl_event_loop_timer_func_t func,
 | 
				
			||||||
 | 
								void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_event_source_timer *source;
 | 
				
			||||||
 | 
						struct epoll_event ep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						source = malloc(sizeof *source);
 | 
				
			||||||
 | 
						if (source == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						source->base.interface = &timer_source_interface;
 | 
				
			||||||
 | 
						source->base.loop = loop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						source->fd = timerfd_create(CLOCK_MONOTONIC, 0);
 | 
				
			||||||
 | 
						if (source->fd < 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "could not create timerfd\n: %m");
 | 
				
			||||||
 | 
							free(source);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						source->func = func;
 | 
				
			||||||
 | 
						source->data = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ep.events = EPOLLIN;
 | 
				
			||||||
 | 
						ep.data.ptr = source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) {
 | 
				
			||||||
 | 
							free(source);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &source->base;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WL_EXPORT int
 | 
				
			||||||
 | 
					wl_event_source_timer_update(struct wl_event_source *source, int ms_delay)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_event_source_timer *timer_source =
 | 
				
			||||||
 | 
							(struct wl_event_source_timer *) source;
 | 
				
			||||||
 | 
						struct itimerspec its;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						its.it_interval.tv_sec = 0;
 | 
				
			||||||
 | 
						its.it_interval.tv_nsec = 0;
 | 
				
			||||||
 | 
						its.it_value.tv_sec = 0;
 | 
				
			||||||
 | 
						its.it_value.tv_nsec = ms_delay * 1000 * 1000;
 | 
				
			||||||
 | 
						if (timerfd_settime(timer_source->fd, 0, &its, NULL) < 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "could not set timerfd\n: %m");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_event_source_idle {
 | 
				
			||||||
 | 
						struct wl_event_source base;
 | 
				
			||||||
 | 
						struct wl_list link;
 | 
				
			||||||
 | 
						wl_event_loop_idle_func_t func;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					wl_event_source_idle_dispatch(struct wl_event_source *source,
 | 
				
			||||||
 | 
								      struct epoll_event *ep)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						assert(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					wl_event_source_idle_remove(struct wl_event_source *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_event_source_idle *idle_source =
 | 
				
			||||||
 | 
							(struct wl_event_source_idle *) source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&idle_source->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_event_source_interface idle_source_interface = {
 | 
				
			||||||
 | 
						wl_event_source_idle_dispatch,
 | 
				
			||||||
 | 
						wl_event_source_idle_remove
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WL_EXPORT struct wl_event_source *
 | 
				
			||||||
 | 
					wl_event_loop_add_idle(struct wl_event_loop *loop,
 | 
				
			||||||
 | 
							       wl_event_loop_idle_func_t func,
 | 
				
			||||||
 | 
							       void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_event_source_idle *source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						source = malloc(sizeof *source);
 | 
				
			||||||
 | 
						if (source == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						source->base.interface = &idle_source_interface;
 | 
				
			||||||
 | 
						source->base.loop = loop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						source->func = func;
 | 
				
			||||||
 | 
						source->data = data;
 | 
				
			||||||
 | 
						wl_list_insert(loop->idle_list.prev, &source->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &source->base;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WL_EXPORT int
 | 
				
			||||||
 | 
					wl_event_source_remove(struct wl_event_source *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						source->interface->remove(source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT struct wl_event_loop *
 | 
					WL_EXPORT struct wl_event_loop *
 | 
				
			||||||
| 
						 | 
					@ -104,6 +289,7 @@ wl_event_loop_create(void)
 | 
				
			||||||
		free(loop);
 | 
							free(loop);
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						wl_list_init(&loop->idle_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return loop;
 | 
						return loop;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -115,32 +301,38 @@ wl_event_loop_destroy(struct wl_event_loop *loop)
 | 
				
			||||||
	free(loop);
 | 
						free(loop);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT struct wl_event_source *
 | 
					 | 
				
			||||||
wl_event_loop_add_idle(struct wl_event_loop *loop,
 | 
					 | 
				
			||||||
		       wl_event_loop_idle_func_t func,
 | 
					 | 
				
			||||||
		       void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	loop->idle_func = func;
 | 
					 | 
				
			||||||
	loop->idle_data = data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &idle_source;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
 | 
					#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					dispatch_idles(struct wl_event_loop *loop)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_event_source_idle *source, *next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						source = container_of(loop->idle_list.next,
 | 
				
			||||||
 | 
								      struct wl_event_source_idle, link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (&source->link != &loop->idle_list) {
 | 
				
			||||||
 | 
							source->func(source->data);
 | 
				
			||||||
 | 
							next = container_of(source->link.next,
 | 
				
			||||||
 | 
									    struct wl_event_source_idle, link);
 | 
				
			||||||
 | 
							free(source);
 | 
				
			||||||
 | 
							source = next;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_init(&loop->idle_list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT int
 | 
					WL_EXPORT int
 | 
				
			||||||
wl_event_loop_wait(struct wl_event_loop *loop)
 | 
					wl_event_loop_wait(struct wl_event_loop *loop)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct epoll_event ep[32];
 | 
						struct epoll_event ep[32];
 | 
				
			||||||
	struct wl_event_source *source;
 | 
						struct wl_event_source *source;
 | 
				
			||||||
	wl_event_loop_idle_func_t idle_func;
 | 
					 | 
				
			||||||
	int i, count, timeout;
 | 
						int i, count, timeout;
 | 
				
			||||||
	uint32_t mask;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (loop->idle_func)
 | 
						if (wl_list_empty(&loop->idle_list))
 | 
				
			||||||
		timeout = 0;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		timeout = -1;
 | 
							timeout = -1;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							timeout = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
 | 
						count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
 | 
				
			||||||
	if (count < 0)
 | 
						if (count < 0)
 | 
				
			||||||
| 
						 | 
					@ -148,20 +340,12 @@ wl_event_loop_wait(struct wl_event_loop *loop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < count; i++) {
 | 
						for (i = 0; i < count; i++) {
 | 
				
			||||||
		source = ep[i].data.ptr;
 | 
							source = ep[i].data.ptr;
 | 
				
			||||||
		mask = 0;
 | 
							source->interface->dispatch(source, &ep[i]);
 | 
				
			||||||
		if (ep[i].events & EPOLLIN)
 | 
					 | 
				
			||||||
			mask |= WL_EVENT_READABLE;
 | 
					 | 
				
			||||||
		if (ep[i].events & EPOLLOUT)
 | 
					 | 
				
			||||||
			mask |= WL_EVENT_WRITEABLE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		source->func(source->fd, mask, source->data);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (count == 0 && loop->idle_func != NULL) {
 | 
						if (count == 0)
 | 
				
			||||||
		idle_func = loop->idle_func;
 | 
							dispatch_idles(loop);
 | 
				
			||||||
		loop->idle_func = NULL;
 | 
					
 | 
				
			||||||
		idle_func(loop->idle_data);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,3 +81,9 @@ wl_list_length(struct wl_list *list)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return count;
 | 
						return count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					wl_list_empty(struct wl_list *list)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return list->next == list;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@ void wl_list_init(struct wl_list *list);
 | 
				
			||||||
void wl_list_insert(struct wl_list *list, struct wl_list *elm);
 | 
					void wl_list_insert(struct wl_list *list, struct wl_list *elm);
 | 
				
			||||||
void wl_list_remove(struct wl_list *elm);
 | 
					void wl_list_remove(struct wl_list *elm);
 | 
				
			||||||
int wl_list_length(struct wl_list *list);
 | 
					int wl_list_length(struct wl_list *list);
 | 
				
			||||||
 | 
					int wl_list_empty(struct wl_list *list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -385,8 +385,7 @@ wl_client_connection_update(struct wl_connection *connection,
 | 
				
			||||||
	if (mask & WL_CONNECTION_WRITABLE)
 | 
						if (mask & WL_CONNECTION_WRITABLE)
 | 
				
			||||||
		emask |= WL_EVENT_WRITEABLE;
 | 
							emask |= WL_EVENT_WRITEABLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return wl_event_loop_update_source(client->display->loop,
 | 
						return wl_event_source_fd_update(client->source, mask);
 | 
				
			||||||
					   client->source, mask);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					@ -466,7 +465,7 @@ wl_client_destroy(struct wl_client *client)
 | 
				
			||||||
		free(ref);
 | 
							free(ref);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_event_loop_remove_source(client->display->loop, client->source);
 | 
						wl_event_source_remove(client->source);
 | 
				
			||||||
	wl_connection_destroy(client->connection);
 | 
						wl_connection_destroy(client->connection);
 | 
				
			||||||
	free(client);
 | 
						free(client);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								wayland.h
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								wayland.h
									
										
									
									
									
								
							| 
						 | 
					@ -12,6 +12,7 @@ enum {
 | 
				
			||||||
struct wl_event_loop;
 | 
					struct wl_event_loop;
 | 
				
			||||||
struct wl_event_source;
 | 
					struct wl_event_source;
 | 
				
			||||||
typedef void (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data);
 | 
					typedef void (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data);
 | 
				
			||||||
 | 
					typedef void (*wl_event_loop_timer_func_t)(void *data);
 | 
				
			||||||
typedef void (*wl_event_loop_idle_func_t)(void *data);
 | 
					typedef void (*wl_event_loop_idle_func_t)(void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wl_event_loop *wl_event_loop_create(void);
 | 
					struct wl_event_loop *wl_event_loop_create(void);
 | 
				
			||||||
| 
						 | 
					@ -20,12 +21,15 @@ struct wl_event_source *wl_event_loop_add_fd(struct wl_event_loop *loop,
 | 
				
			||||||
					     int fd, uint32_t mask,
 | 
										     int fd, uint32_t mask,
 | 
				
			||||||
					     wl_event_loop_fd_func_t func,
 | 
										     wl_event_loop_fd_func_t func,
 | 
				
			||||||
					     void *data);
 | 
										     void *data);
 | 
				
			||||||
int wl_event_loop_update_source(struct wl_event_loop *loop,
 | 
					int wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask);
 | 
				
			||||||
				struct wl_event_source *source,
 | 
					struct wl_event_source *wl_event_loop_add_timer(struct wl_event_loop *loop,
 | 
				
			||||||
				uint32_t mask);
 | 
											wl_event_loop_timer_func_t func,
 | 
				
			||||||
 | 
											void *data);
 | 
				
			||||||
 | 
					int wl_event_source_timer_update(struct wl_event_source *source,
 | 
				
			||||||
 | 
									 int ms_delay);
 | 
				
			||||||
 | 
					int wl_event_source_remove(struct wl_event_source *source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int wl_event_loop_remove_source(struct wl_event_loop *loop,
 | 
					 | 
				
			||||||
				struct wl_event_source *source);
 | 
					 | 
				
			||||||
int wl_event_loop_wait(struct wl_event_loop *loop);
 | 
					int wl_event_loop_wait(struct wl_event_loop *loop);
 | 
				
			||||||
struct wl_event_source *wl_event_loop_add_idle(struct wl_event_loop *loop,
 | 
					struct wl_event_source *wl_event_loop_add_idle(struct wl_event_loop *loop,
 | 
				
			||||||
					       wl_event_loop_idle_func_t func,
 | 
										       wl_event_loop_idle_func_t func,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue