window: Stop using glib mainloop in toy toolkit

dev
Kristian Høgsberg 13 years ago
parent 1e164b9afd
commit 3a69627f43
  1. 2
      clients/Makefile.am
  2. 1
      clients/desktop-shell.c
  3. 32
      clients/dnd.c
  4. 1
      clients/flower.c
  5. 1
      clients/gears.c
  6. 1
      clients/image.c
  7. 1
      clients/resizor.c
  8. 1
      clients/screenshot.c
  9. 1
      clients/smoke.c
  10. 37
      clients/terminal.c
  11. 105
      clients/wayland-glib.c
  12. 32
      clients/wayland-glib.h
  13. 100
      clients/window.c
  14. 12
      clients/window.h

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

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

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

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

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

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

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

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

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

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

@ -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;
}

@ -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

@ -32,9 +32,9 @@
#include <time.h> #include <time.h>
#include <cairo.h> #include <cairo.h>
#include <glib.h> #include <glib.h>
#include <glib-object.h>
#include <gdk-pixbuf/gdk-pixbuf.h> #include <gdk-pixbuf/gdk-pixbuf.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/epoll.h>
#include <wayland-egl.h> #include <wayland-egl.h>
@ -51,7 +51,6 @@
#include <linux/input.h> #include <linux/input.h>
#include "wayland-util.h" #include "wayland-util.h"
#include "wayland-client.h" #include "wayland-client.h"
#include "wayland-glib.h"
#include "cairo-util.h" #include "cairo-util.h"
#include "window.h" #include "window.h"
@ -68,9 +67,14 @@ struct display {
EGLConfig premultiplied_argb_config; EGLConfig premultiplied_argb_config;
EGLContext ctx; EGLContext ctx;
cairo_device_t *device; cairo_device_t *device;
int fd;
GMainLoop *loop; int display_fd;
GSource *source; uint32_t mask;
struct task display_task;
int epoll_fd;
struct wl_list deferred_list;
struct wl_list window_list; struct wl_list window_list;
struct wl_list input_list; struct wl_list input_list;
char *device_name; char *device_name;
@ -99,6 +103,7 @@ struct window {
int x, y; int x, y;
int resize_edges; int resize_edges;
int redraw_scheduled; int redraw_scheduled;
struct task redraw_task;
int minimum_width, minimum_height; int minimum_width, minimum_height;
int margin; int margin;
int type; int type;
@ -1374,23 +1379,22 @@ window_set_child_size(struct window *window, int32_t width, int32_t height)
} }
} }
static gboolean static void
idle_redraw(void *data) 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_handler(window, window->user_data);
window->redraw_scheduled = 0; window->redraw_scheduled = 0;
return FALSE;
} }
void void
window_schedule_redraw(struct window *window) window_schedule_redraw(struct window *window)
{ {
if (!window->redraw_scheduled) { 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; window->redraw_scheduled = 1;
} }
} }
@ -1927,6 +1931,25 @@ init_egl(struct display *d)
return 0; 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 * struct display *
display_create(int *argc, char **argv[], const GOptionEntry *option_entries) 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; 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); wl_list_init(&d->input_list);
/* Set up listener so we'll catch all events. */ /* 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); 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); wl_list_init(&d->window_list);
init_xkb(d); init_xkb(d);
@ -2060,7 +2085,46 @@ display_release(struct display *display)
} }
void void
display_run(struct display *d) display_defer(struct display *display, struct task *task)
{
wl_list_insert(&display->deferred_list, &task->link);
}
void
display_watch_fd(struct display *display,
int fd, uint32_t events, struct task *task)
{ {
g_main_loop_run(d->loop); 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);
}
}
} }

@ -30,6 +30,11 @@
struct window; struct window;
struct task {
void (*run)(struct task *task, uint32_t events);
struct wl_list link;
};
struct rectangle { struct rectangle {
int32_t x; int32_t x;
int32_t y; int32_t y;
@ -98,6 +103,13 @@ display_add_drag_listener(struct display *display,
void void
display_flush_cairo_device(struct display *display); 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 void
display_run(struct display *d); display_run(struct display *d);

Loading…
Cancel
Save