window: Stop using glib mainloop in toy toolkit

This commit is contained in:
Kristian Høgsberg 2011-09-14 17:33:48 -04:00
parent 1e164b9afd
commit 3a69627f43
14 changed files with 125 additions and 202 deletions

View File

@ -34,8 +34,6 @@ AM_CPPFLAGS = \
libtoytoolkit_a_SOURCES = \
window.c \
window.h \
wayland-glib.c \
wayland-glib.h \
cairo-util.c \
cairo-util.h

View File

@ -32,7 +32,6 @@
#include <linux/input.h>
#include "wayland-client.h"
#include "wayland-glib.h"
#include "window.h"
#include <desktop-shell-client-protocol.h>

View File

@ -29,11 +29,10 @@
#include <math.h>
#include <sys/time.h>
#include <cairo.h>
#include <glib.h>
#include <sys/epoll.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "wayland-client.h"
#include "wayland-glib.h"
#include "window.h"
@ -60,9 +59,11 @@ struct dnd_offer {
int refcount;
struct dnd *dnd;
struct wl_array types;
struct task io_task;
const char *drag_type;
uint32_t tag;
int x, y;
int fd;
};
struct item {
@ -421,24 +422,21 @@ drag_offer_motion(void *data,
}
}
static gboolean
drop_io_func(GIOChannel *source, GIOCondition condition, gpointer data)
static void
drop_io_func(struct task *task, uint32_t events)
{
struct dnd_offer *dnd_offer = data;
struct dnd_offer *dnd_offer =
container_of(task, struct dnd_offer, io_task);
struct dnd *dnd = dnd_offer->dnd;
struct dnd_flower_message dnd_flower_message;
int fd;
unsigned int len;
struct item *item;
fd = g_io_channel_unix_get_fd(source);
len = read(fd, &dnd_flower_message, sizeof dnd_flower_message);
len = read(dnd_offer->fd,
&dnd_flower_message, sizeof dnd_flower_message);
fprintf(stderr, "read %d bytes\n", len);
close(fd);
g_source_remove(dnd_offer->tag);
g_io_channel_unref(source);
close(dnd_offer->fd);
item = item_create(dnd->display,
dnd_offer->x - dnd_flower_message.x_offset - 26,
@ -449,15 +447,12 @@ drop_io_func(GIOChannel *source, GIOCondition condition, gpointer data)
window_schedule_redraw(dnd->window);
dnd_offer_destroy(dnd_offer);
return TRUE;
}
static void
drag_offer_drop(void *data, struct wl_drag_offer *offer)
{
struct dnd_offer *dnd_offer = data;
GIOChannel *channel;
int p[2];
if (!dnd_offer->drag_type) {
@ -473,9 +468,10 @@ drag_offer_drop(void *data, struct wl_drag_offer *offer)
wl_drag_offer_receive(offer, p[1]);
close(p[1]);
channel = g_io_channel_unix_new(p[0]);
dnd_offer->tag = g_io_add_watch(channel, G_IO_IN,
drop_io_func, dnd_offer);
dnd_offer->io_task.run = drop_io_func;
dnd_offer->fd = p[0];
display_watch_fd(dnd_offer->dnd->display,
p[0], EPOLLIN, &dnd_offer->io_task);
}
static const struct wl_drag_offer_listener drag_offer_listener = {

View File

@ -34,7 +34,6 @@
#include <glib.h>
#include "wayland-client.h"
#include "wayland-glib.h"
#include "window.h"
static void

View File

@ -38,7 +38,6 @@
#include "wayland-util.h"
#include "wayland-client.h"
#include "wayland-glib.h"
#include "window.h"

View File

@ -34,7 +34,6 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "wayland-client.h"
#include "wayland-glib.h"
#include "window.h"

View File

@ -29,7 +29,6 @@
#include "wayland-util.h"
#include "wayland-client.h"
#include "wayland-glib.h"
#include "window.h"

View File

@ -31,7 +31,6 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "wayland-client.h"
#include "wayland-glib.h"
#include "screenshooter-client-protocol.h"
/* The screenshooter is a good example of a custom object exposed by

View File

@ -33,7 +33,6 @@
#include <glib.h>
#include "wayland-client.h"
#include "wayland-glib.h"
#include "window.h"
struct smoke {

View File

@ -32,12 +32,12 @@
#include <ctype.h>
#include <cairo.h>
#include <glib.h>
#include <sys/epoll.h>
#include <X11/keysym.h>
#include "wayland-util.h"
#include "wayland-client.h"
#include "wayland-glib.h"
#include "window.h"
@ -359,6 +359,7 @@ struct terminal {
struct window *window;
struct display *display;
union utf8_char *data;
struct task io_task;
char *tab_ruler;
struct attr *data_attr;
struct attr curr_attr;
@ -375,7 +376,6 @@ struct terminal {
int width, height, start, row, column;
int saved_row, saved_column;
int fd, master;
GIOChannel *channel;
uint32_t modifiers;
char escape[MAX_ESCAPE+1];
int escape_length;
@ -2326,25 +2326,22 @@ terminal_create(struct display *display, int fullscreen)
return terminal;
}
static gboolean
io_handler(GIOChannel *source,
GIOCondition condition,
gpointer data)
static void
io_handler(struct task *task, uint32_t events)
{
struct terminal *terminal = data;
gchar buffer[256];
gsize bytes_read;
GError *error = NULL;
struct terminal *terminal =
container_of(task, struct terminal, io_task);
char buffer[256];
int len;
if(condition == G_IO_HUP)
exit(0);
if (events & EPOLLHUP)
exit(0);
g_io_channel_read_chars(source, buffer, sizeof buffer,
&bytes_read, &error);
len = read(terminal->master, buffer, sizeof buffer);
if (len < 0)
exit(0);
terminal_data(terminal, buffer, bytes_read);
return TRUE;
terminal_data(terminal, buffer, len);
}
static int
@ -2367,10 +2364,10 @@ terminal_run(struct terminal *terminal, const char *path)
}
terminal->master = master;
terminal->channel = g_io_channel_unix_new(master);
fcntl(master, F_SETFL, O_NONBLOCK);
g_io_add_watch(terminal->channel, G_IO_IN, io_handler, terminal);
g_io_add_watch(terminal->channel, G_IO_HUP, io_handler, terminal);
terminal->io_task.run = io_handler;
display_watch_fd(terminal->display, terminal->master,
EPOLLIN | EPOLLHUP, &terminal->io_task);
window_set_fullscreen(terminal->window, terminal->fullscreen);
if (!terminal->fullscreen)

View File

@ -1,105 +0,0 @@
/*
* Copyright © 2008 Kristian Høgsberg
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include <stdint.h>
#include <glib/giochannel.h>
#include "wayland-client.h"
#include "wayland-glib.h"
typedef struct _WlSource {
GSource source;
GPollFD pfd;
uint32_t mask;
struct wl_display *display;
} WlSource;
static gboolean
wl_glib_source_prepare(GSource *base, gint *timeout)
{
WlSource *source = (WlSource *) base;
*timeout = -1;
/* We have to add/remove the GPollFD if we want to update our
* poll event mask dynamically. Instead, let's just flush all
* write on idle instead, which is what this amounts to. */
while (source->mask & WL_DISPLAY_WRITABLE)
wl_display_iterate(source->display,
WL_DISPLAY_WRITABLE);
return FALSE;
}
static gboolean
wl_glib_source_check(GSource *base)
{
WlSource *source = (WlSource *) base;
return source->pfd.revents;
}
static gboolean
wl_glib_source_dispatch(GSource *base,
GSourceFunc callback,
gpointer data)
{
WlSource *source = (WlSource *) base;
wl_display_iterate(source->display,
WL_DISPLAY_READABLE);
return TRUE;
}
static GSourceFuncs wl_glib_source_funcs = {
wl_glib_source_prepare,
wl_glib_source_check,
wl_glib_source_dispatch,
NULL
};
static int
wl_glib_source_update(uint32_t mask, void *data)
{
WlSource *source = data;
source->mask = mask;
return 0;
}
GSource *
wl_glib_source_new(struct wl_display *display)
{
WlSource *source;
source = (WlSource *) g_source_new(&wl_glib_source_funcs,
sizeof (WlSource));
source->display = display;
source->pfd.fd = wl_display_get_fd(display,
wl_glib_source_update, source);
source->pfd.events = G_IO_IN | G_IO_ERR;
g_source_add_poll(&source->source, &source->pfd);
return &source->source;
}

View File

@ -1,32 +0,0 @@
/*
* Copyright © 2008 Kristian Høgsberg
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef _WAYLAND_GLIB_H_
#define _WAYLAND_GLIB_H_
#include <glib/gmain.h>
#include <wayland-client.h>
GSource *wl_glib_source_new(struct wl_display *display);
#endif

View File

@ -32,9 +32,9 @@
#include <time.h>
#include <cairo.h>
#include <glib.h>
#include <glib-object.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <sys/mman.h>
#include <sys/epoll.h>
#include <wayland-egl.h>
@ -51,7 +51,6 @@
#include <linux/input.h>
#include "wayland-util.h"
#include "wayland-client.h"
#include "wayland-glib.h"
#include "cairo-util.h"
#include "window.h"
@ -68,9 +67,14 @@ struct display {
EGLConfig premultiplied_argb_config;
EGLContext ctx;
cairo_device_t *device;
int fd;
GMainLoop *loop;
GSource *source;
int display_fd;
uint32_t mask;
struct task display_task;
int epoll_fd;
struct wl_list deferred_list;
struct wl_list window_list;
struct wl_list input_list;
char *device_name;
@ -99,6 +103,7 @@ struct window {
int x, y;
int resize_edges;
int redraw_scheduled;
struct task redraw_task;
int minimum_width, minimum_height;
int margin;
int type;
@ -1374,23 +1379,22 @@ window_set_child_size(struct window *window, int32_t width, int32_t height)
}
}
static gboolean
idle_redraw(void *data)
static void
idle_redraw(struct task *task, uint32_t events)
{
struct window *window = data;
struct window *window =
container_of(task, struct window, redraw_task);
window->redraw_handler(window, window->user_data);
window->redraw_scheduled = 0;
return FALSE;
}
void
window_schedule_redraw(struct window *window)
{
if (!window->redraw_scheduled) {
g_idle_add(idle_redraw, window);
window->redraw_task.run = idle_redraw;
display_defer(window->display, &window->redraw_task);
window->redraw_scheduled = 1;
}
}
@ -1927,6 +1931,25 @@ init_egl(struct display *d)
return 0;
}
static int
event_mask_update(uint32_t mask, void *data)
{
struct display *d = data;
d->mask = mask;
return 0;
}
static void
handle_display_data(struct task *task, uint32_t events)
{
struct display *display =
container_of(task, struct display, display_task);
wl_display_iterate(display->display, display->mask);
}
struct display *
display_create(int *argc, char **argv[], const GOptionEntry *option_entries)
{
@ -1967,6 +1990,12 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries)
return NULL;
}
d->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
d->display_fd = wl_display_get_fd(d->display, event_mask_update, d);
d->display_task.run = handle_display_data;
display_watch_fd(d, d->display_fd, EPOLLIN, &d->display_task);
wl_list_init(&d->deferred_list);
wl_list_init(&d->input_list);
/* Set up listener so we'll catch all events. */
@ -1987,10 +2016,6 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries)
display_render_frame(d);
d->loop = g_main_loop_new(NULL, FALSE);
d->source = wl_glib_source_new(d->display);
g_source_attach(d->source, NULL);
wl_list_init(&d->window_list);
init_xkb(d);
@ -2060,7 +2085,46 @@ display_release(struct display *display)
}
void
display_run(struct display *d)
display_defer(struct display *display, struct task *task)
{
g_main_loop_run(d->loop);
wl_list_insert(&display->deferred_list, &task->link);
}
void
display_watch_fd(struct display *display,
int fd, uint32_t events, struct task *task)
{
struct epoll_event ep;
ep.events = events;
ep.data.ptr = task;
epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep);
}
void
display_run(struct display *display)
{
struct task *task;
struct epoll_event ep[16];
int i, count;
while (1) {
while (display->mask & WL_DISPLAY_WRITABLE)
wl_display_iterate(display->display,
WL_DISPLAY_WRITABLE);
count = epoll_wait(display->epoll_fd,
ep, ARRAY_LENGTH(ep), -1);
for (i = 0; i < count; i++) {
task = ep[i].data.ptr;
task->run(task, ep[i].events);
}
while (!wl_list_empty(&display->deferred_list)) {
task = container_of(display->deferred_list.next,
struct task, link);
wl_list_remove(&task->link);
task->run(task, 0);
}
}
}

View File

@ -30,6 +30,11 @@
struct window;
struct task {
void (*run)(struct task *task, uint32_t events);
struct wl_list link;
};
struct rectangle {
int32_t x;
int32_t y;
@ -98,6 +103,13 @@ display_add_drag_listener(struct display *display,
void
display_flush_cairo_device(struct display *display);
void
display_defer(struct display *display, struct task *task);
void
display_watch_fd(struct display *display,
int fd, uint32_t events, struct task *task);
void
display_run(struct display *d);