[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