[RFC wayland] Add libwayland-glib for GLib main loop integration
Quentin Glidic
sardemff7+wayland at sardemff7.net
Mon Oct 7 16:31:03 CEST 2013
From: Quentin Glidic <sardemff7+git at sardemff7.net>
Signed-off-by: Quentin Glidic <sardemff7+git at sardemff7.net>
---
I added Wayland support to a GLib-based daemon, which needed main loop
integration. It required a GSource for the Wayland fd, and I decided to
split this part to make it easier for other projects to reuse that.
Here is the code, as a tiny library. I added more relevant to have it
integrated in the libwayland codebase rather than in its onw project wrt
the size of the library.
The coding style is not fully Wayland-compliant but I will fix that if
this code is to be accepted.
Makefile.am | 6 +-
configure.ac | 23 +++++-
glib/Makefile.am | 33 ++++++++
glib/libwayland-glib.c | 182 +++++++++++++++++++++++++++++++++++++++++++++
glib/libwayland-glib.h | 43 +++++++++++
glib/libwayland-glib.pc.in | 12 +++
6 files changed, 297 insertions(+), 2 deletions(-)
create mode 100644 glib/Makefile.am
create mode 100644 glib/libwayland-glib.c
create mode 100644 glib/libwayland-glib.h
create mode 100644 glib/libwayland-glib.pc.in
diff --git a/Makefile.am b/Makefile.am
index ddf39d1..1be6fed 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,11 @@ if BUILD_DOCS
doc_subdir = doc
endif
-SUBDIRS = src protocol $(doc_subdir) tests cursor
+if ENABLE_GLIB
+glib_subdir = glib
+endif
+
+SUBDIRS = src protocol $(doc_subdir) tests cursor $(glib_subdir)
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
diff --git a/configure.ac b/configure.ac
index 3b79c54..ec71188 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,7 +50,7 @@ AC_CHECK_DECL(TFD_CLOEXEC,[],
AC_CHECK_DECL(CLOCK_MONOTONIC,[],
[AC_MSG_ERROR("CLOCK_MONOTONIC is needed to compile wayland")],
[[#include <time.h>]])
-AC_CHECK_HEADERS([execinfo.h])
+AC_CHECK_HEADERS([execinfo.h errno.h])
AC_ARG_ENABLE([scanner],
[AC_HELP_STRING([--disable-scanner],
@@ -126,6 +126,25 @@ if test "x$enable_documentation" = "xyes"; then
fi
AM_CONDITIONAL([HAVE_PUBLICAN], [test "x$PUBLICAN" != "x"])
+
+# GLib main loop integration library
+
+glib_min_major="2"
+glib_min_minor="36"
+glib_min_version="${glib_min_major}.${glib_min_minor}"
+
+AC_ARG_ENABLE([glib],
+ [AC_HELP_STRING([--enable-glib],
+ [Enable GLib main loop integration library])],
+ [],
+ [enable_glib=no])
+if test "x$enable_glib" = "xyes"; then
+ PKG_CHECK_MODULES(GLIB, [glib-2.0 >= $glib_min_version])
+ AC_DEFINE_UNQUOTED([GLIB_VERSION_MIN_REQUIRED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The lower GLib version supported])
+fi
+AM_CONDITIONAL([ENABLE_GLIB], [test "x$enable_glib" = "xyes"])
+
+
AC_CONFIG_FILES([Makefile
cursor/Makefile
cursor/wayland-cursor.pc
@@ -134,6 +153,8 @@ AC_CONFIG_FILES([Makefile
doc/publican/Makefile
doc/doxygen/Makefile
doc/man/Makefile
+ glib/Makefile
+ glib/libwayland-glib.pc
src/Makefile
src/wayland-server-uninstalled.pc
src/wayland-client-uninstalled.pc
diff --git a/glib/Makefile.am b/glib/Makefile.am
new file mode 100644
index 0000000..68acece
--- /dev/null
+++ b/glib/Makefile.am
@@ -0,0 +1,33 @@
+LIBWAYLAND_GLIB_CURRENT=0
+LIBWAYLAND_GLIB_REVISION=0
+LIBWAYLAND_GLIB_AGE=0
+
+lib_LTLIBRARIES = \
+ libwayland-glib.la
+
+pkginclude_HEADERS = \
+ libwayland-glib.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = \
+ libwayland-glib.pc
+
+
+libwayland_glib_la_SOURCES = \
+ libwayland-glib.c
+
+libwayland_glib_la_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"GWayland\"
+
+libwayland_glib_la_CFLAGS = \
+ $(GCC_CFLAGS) \
+ -I$(top_srcdir)/src \
+ $(GLIB_CFLAGS)
+
+libwayland_glib_la_LDFLAGS = \
+ -version-info $(LIBWAYLAND_GLIB_CURRENT):$(LIBWAYLAND_GLIB_REVISION):$(LIBWAYLAND_GLIB_AGE) \
+ -export-dynamic
+
+libwayland_glib_la_LIBADD = \
+ $(top_builddir)/src/libwayland-client.la \
+ $(GLIB_LIBS)
diff --git a/glib/libwayland-glib.c b/glib/libwayland-glib.c
new file mode 100644
index 0000000..c918374
--- /dev/null
+++ b/glib/libwayland-glib.c
@@ -0,0 +1,182 @@
+/*
+ * libwayland-glib - Library to integrate Wayland nicely with GLib
+ *
+ * Copyright © 2012-2013 Quentin "Sardem FF7" Glidic
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif /* HAVE_ERRNO_H */
+
+#include <glib.h>
+#include <wayland-client.h>
+
+#include <libwayland-glib.h>
+
+struct _GWaylandSource {
+ GSource source;
+ gboolean display_owned;
+ struct wl_display *display;
+ gpointer fd;
+ int error;
+};
+
+static gboolean
+_g_wayland_source_prepare(GSource *source, gint *timeout)
+{
+ GWaylandSource *self = (GWaylandSource *)source;
+
+ if ( wl_display_flush(self->display) < 0)
+ self->error = errno;
+
+ *timeout = -1;
+ return FALSE;
+}
+
+static gboolean
+_g_wayland_source_check(GSource *source)
+{
+ GWaylandSource *self = (GWaylandSource *)source;
+
+ return ( g_source_query_unix_fd(source, self->fd) > 0 );
+}
+
+static gboolean
+_g_wayland_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
+{
+ GWaylandSource *self = (GWaylandSource *)source;
+
+ if ( self->error > 0 )
+ {
+ errno = self->error;
+ if ( callback != NULL )
+ return callback(user_data);
+ return FALSE;
+ }
+
+ GIOCondition revents;
+ revents = g_source_query_unix_fd(source, self->fd);
+
+ if ( revents & G_IO_IN )
+ {
+ if ( wl_display_dispatch(self->display) < 0 )
+ {
+ if ( callback != NULL )
+ return callback(user_data);
+ return FALSE;
+ }
+ }
+
+ errno = 0;
+ if ( revents & (G_IO_ERR | G_IO_HUP) )
+ {
+ if ( callback != NULL )
+ return callback(user_data);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+_g_wayland_source_finalize(GSource *source)
+{
+ GWaylandSource *self = (GWaylandSource *)source;
+
+ if ( self->display_owned )
+ wl_display_disconnect(self->display);
+}
+
+static GSourceFuncs _g_wayland_source_funcs = {
+ _g_wayland_source_prepare,
+ _g_wayland_source_check,
+ _g_wayland_source_dispatch,
+ _g_wayland_source_finalize
+};
+
+
+GWaylandSource *
+g_wayland_source_new(GMainContext *context, const gchar *name)
+{
+ struct wl_display *display;
+ GWaylandSource *source;
+
+ display = wl_display_connect(name);
+ if ( display == NULL )
+ return NULL;
+
+ source = g_wayland_source_new_for_display(context, display);
+ source->display_owned = TRUE;
+ return source;
+}
+
+GWaylandSource *
+g_wayland_source_new_for_display(GMainContext *context, struct wl_display *display)
+{
+ GWaylandSource *source;
+
+ source = (GWaylandSource *)g_source_new(&_g_wayland_source_funcs, sizeof(GWaylandSource));
+
+ source->display = display;
+
+ source->fd = g_source_add_unix_fd((GSource *)source, wl_display_get_fd(display), G_IO_IN | G_IO_ERR | G_IO_HUP);
+
+ g_source_attach((GSource *)source, context);
+
+ return source;
+}
+
+void
+g_wayland_source_ref(GWaylandSource *self)
+{
+ g_return_if_fail(self != NULL);
+
+ g_source_ref((GSource *)self);
+}
+
+void
+g_wayland_source_unref(GWaylandSource *self)
+{
+ g_return_if_fail(self != NULL);
+
+ g_source_unref((GSource *)self);
+}
+
+void
+g_wayland_source_set_error_callback(GWaylandSource *self, GSourceFunc callback, gpointer user_data, GDestroyNotify destroy_notify)
+{
+ g_return_if_fail(self != NULL);
+
+ g_source_set_callback((GSource *)self, callback, user_data, destroy_notify);
+}
+
+struct wl_display *
+g_wayland_source_get_display(GWaylandSource *self)
+{
+ g_return_val_if_fail(self != NULL, NULL);
+
+ return self->display;
+}
diff --git a/glib/libwayland-glib.h b/glib/libwayland-glib.h
new file mode 100644
index 0000000..ac6a6bb
--- /dev/null
+++ b/glib/libwayland-glib.h
@@ -0,0 +1,43 @@
+/*
+ * libwayland-glib - Library to integrate Wayland nicely with GLib
+ *
+ * Copyright © 2012-2013 Quentin "Sardem FF7" Glidic
+ *
+ * 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 __LIBWAYLAND_GLIB_H__
+#define __LIBWAYLAND_GLIB_H__
+
+G_BEGIN_DECLS
+
+typedef struct _GWaylandSource GWaylandSource;
+
+GWaylandSource *g_wayland_source_new(GMainContext *context, const gchar *name);
+GWaylandSource *g_wayland_source_new_for_display(GMainContext *context, struct wl_display *display);
+void g_wayland_source_ref(GWaylandSource *self);
+void g_wayland_source_unref(GWaylandSource *self);
+
+void g_wayland_source_set_error_callback(GWaylandSource *self, GSourceFunc callback, gpointer user_data, GDestroyNotify destroy_notify);
+struct wl_display *g_wayland_source_get_display(GWaylandSource *source);
+
+G_END_DECLS
+
+#endif /* __LIBWAYLAND_GLIB_H__ */
diff --git a/glib/libwayland-glib.pc.in b/glib/libwayland-glib.pc.in
new file mode 100644
index 0000000..17a2387
--- /dev/null
+++ b/glib/libwayland-glib.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+pkgincludedir=${includedir}/@PACKAGE@
+
+Name: libwayland-glib
+Description: Library to integrate Wayland nicely with GLib
+Version: @VERSION@
+Requires: glib-2.0
+Libs: -L${libdir} -lwayland-glib
+Cflags: -I${pkgincludedir}
--
1.8.4
More information about the wayland-devel
mailing list