diff options
author | Richard Hughes <richard@hughsie.com> | 2012-05-03 10:27:41 +0100 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2012-05-03 16:12:31 +0100 |
commit | 257d03d5e39f63ba7a2409ed1a3a3deecd6d5d91 (patch) | |
tree | e06fbe9b77ab7994cea79ea79d01e49111dfaad1 | |
parent | dc65fc9e88e775bf4a838ed6bca8e11e40581d11 (diff) | |
download | colord-257d03d5e39f63ba7a2409ed1a3a3deecd6d5d91.tar.gz |
Add CdWindow which allows us to get the color profile for a GtkWidget
This commit adds a gtk-3.0 dep to the new libcolord-gtk. You can split this out
into a seporate subpackage if this makes things easier to install on headless
things like print servers.
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | contrib/colord.spec.in | 30 | ||||
-rw-r--r-- | examples/cd-gtk-demo.c | 86 | ||||
-rw-r--r-- | libcolord-gtk/Makefile.am | 119 | ||||
-rw-r--r-- | libcolord-gtk/cd-self-test.c | 101 | ||||
-rw-r--r-- | libcolord-gtk/cd-window.c | 584 | ||||
-rw-r--r-- | libcolord-gtk/cd-window.h | 103 | ||||
-rw-r--r-- | libcolord-gtk/colord-gtk.h | 44 | ||||
-rw-r--r-- | libcolord-gtk/colord-gtk.pc.in | 9 |
10 files changed, 1101 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index 6818189..2e39cb8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,12 +18,19 @@ SUBDIRS = \ src \ po +if HAVE_GTK +SUBDIRS += \ + libcolord-gtk +endif + snapshot: $(MAKE) dist distdir=$(PACKAGE)-$(VERSION)-`date +"%Y%m%d"` DISTCHECK_CONFIGURE_FLAGS = \ --enable-introspection \ --enable-fd-fallback \ + --enable-gtk \ + --enable-gtk-doc \ --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) EXTRA_DIST = \ diff --git a/configure.ac b/configure.ac index 19d915e..21b3e20 100644 --- a/configure.ac +++ b/configure.ac @@ -272,6 +272,23 @@ else fi AC_SUBST(slashlibdir) +dnl **** Check for GTK **** +AC_ARG_ENABLE(gtk, AS_HELP_STRING([--enable-gtk],[Enable GTK support]), + enable_gtk=$enableval) +has_gtk=no +if test x$enable_gtk != xno; then + PKG_CHECK_MODULES(GTK, gtk+-3.0, has_gtk=yes, has_gtk=no) + if test $has_gtk = "no"; then + if test x$enable_gtk = xyes -a $has_gtk = "no"; then + AC_MSG_ERROR([--enable-gtk was specified and GTK was not found]) + fi + fi +fi +AM_CONDITIONAL(HAVE_GTK, test x$has_gtk = xyes) +if test x$has_gtk = xyes; then + AC_DEFINE(HAVE_GTK,1,[Use GTK support]) +fi + # per-machine directory AC_SUBST(CD_SYSTEM_PROFILES_DIR, "\$(localstatedir)/lib/colord/icc") @@ -303,6 +320,8 @@ client/Makefile libcolord/cd-version.h libcolord/colord.pc libcolord/Makefile +libcolord-gtk/colord-gtk.pc +libcolord-gtk/Makefile ]) AC_OUTPUT @@ -322,6 +341,7 @@ echo " File descriptor fallback: ${enable_fd_fallback} External volume searching: ${enable_volume_search} SANE support: ${has_sane} + GTK support: ${has_gtk} GUDEV support: ${enable_gudev} Vala API generator: ${has_vapigen} Daemon user: ${daemon_user} diff --git a/contrib/colord.spec.in b/contrib/colord.spec.in index 09ef22a..0e2696b 100644 --- a/contrib/colord.spec.in +++ b/contrib/colord.spec.in @@ -21,6 +21,7 @@ BuildRequires: sqlite-devel BuildRequires: gobject-introspection-devel BuildRequires: vala-tools BuildRequires: libgusb-devel +BuildRequires: gtk3-devel Requires: shared-color-profiles Requires: colord-sane @@ -39,6 +40,13 @@ Requires: %{name} = %{version}-%{release} %description devel Files for development with %{name}. +%package gtk-devel +Summary: GTK development package for %{name} +Requires: %{name} = %{version}-%{release} + +%description gtk-devel +Files for development with %{name} using GTK. + %package sane Summary: SANE helper package for %{name} Requires: %{name} = %{version}-%{release} @@ -48,6 +56,14 @@ SANE helper package for %{name} that monitors scanners that are added and removed. This is a seporate process as libsane is craptastic, but useful. +%package gtk +Summary: GTK helper library for %{name} +Requires: %{name} = %{version}-%{release} + +%description gtk +This package contains extra functionality for %{name} that can be used +when running GTK applications. + %prep %setup -q @@ -113,11 +129,17 @@ exit 0 %{_includedir}/colord-1 %{_libdir}/libcolord.so %{_libdir}/pkgconfig/colord.pc -%{_datadir}/gir-1.0/*.gir -%{_datadir}/vala/vapi/*.vapi +%{_datadir}/gir-1.0/Colord-1.0.gir +%{_datadir}/vala/vapi/colord.vapi %dir %{_datadir}/gtk-doc/html/colord %{_datadir}/gtk-doc/html/colord/* +%files gtk-devel +%defattr(-,root,root,-) +%{_libdir}/libcolord-gtk.so +%{_libdir}/pkgconfig/colord-gtk.pc +%{_datadir}/gir-1.0/ColordGtk-1.0.gir + %files sane %defattr(-,root,root,-) %{_datadir}/dbus-1/interfaces/org.freedesktop.colord.sane.xml @@ -126,6 +148,10 @@ exit 0 %{_libexecdir}/colord-sane %{_sysconfdir}/dbus-1/system.d/org.freedesktop.colord-sane.conf +%files gtk +%defattr(-,root,root,-) +%{_libdir}/libcolord-gtk.so.* + %changelog * #LONGDATE# Richard Hughes <richard@hughsie.com> #VERSION#-0.#BUILD##ALPHATAG# - Update from git diff --git a/examples/cd-gtk-demo.c b/examples/cd-gtk-demo.c new file mode 100644 index 0000000..e54e737 --- /dev/null +++ b/examples/cd-gtk-demo.c @@ -0,0 +1,86 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +//gcc -o cd-gtk-demo cd-gtk-demo.c `pkg-config --cflags --libs colord-gtk` -Wall + +#include <stdlib.h> +#include <colord-gtk.h> +#include <gtk/gtk.h> + +static void +cd_window_set_widget_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + CdProfile *profile; + CdWindow *window = CD_WINDOW (source); + GError *error = NULL; + + profile = cd_window_set_widget_finish (window, + res, + &error); + if (profile == NULL) { + g_warning ("failed to get output profile: %s", error->message); + g_error_free (error); + return; + } + + g_debug ("screen profile to use %s", cd_profile_get_filename (profile)); + g_object_unref (profile); +} + +static void +map_cb (GtkWidget *this_widget, gpointer user_data) +{ + CdWindow *window = CD_WINDOW (user_data); + + /* get the profile for this widget */ + cd_window_set_widget (window, + this_widget, + NULL, + cd_window_set_widget_cb, + this_widget); +} + +int +main (int argc, char *argv[]) +{ + CdWindow *window; + gint retval = EXIT_FAILURE; + GtkWidget *dialog; + + gtk_init (&argc, &argv); + window = cd_window_new (); + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + "%s", "Hello world"); + g_signal_connect (dialog, "map", + G_CALLBACK (map_cb), + window); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + g_object_unref (window); + + retval = EXIT_SUCCESS; + return retval; +} diff --git a/libcolord-gtk/Makefile.am b/libcolord-gtk/Makefile.am new file mode 100644 index 0000000..44bca5b --- /dev/null +++ b/libcolord-gtk/Makefile.am @@ -0,0 +1,119 @@ +if HAVE_INTROSPECTION +-include $(INTROSPECTION_MAKEFILE) +INTROSPECTION_GIRS = +INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) +INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) +endif + +INCLUDES = \ + $(GLIB_CFLAGS) \ + $(GTK_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/libcolord \ + -DCD_COMPILATION \ + -DG_LOG_DOMAIN=\"libcolord-gtk\" \ + -DTESTDATADIR=\""$(top_srcdir)/data/tests"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" + +lib_LTLIBRARIES = \ + libcolord-gtk.la + +libcolord_includedir = $(includedir)/colord-1 +libcolord_include_HEADERS = \ + colord-gtk.h + +libcolordgtkbase_includedir = $(libcolord_includedir)/colord-gtk +libcolordgtkbase_include_HEADERS = \ + cd-window.h + +libcolord_gtk_la_SOURCES = \ + cd-window.c + +libcolord_gtk_la_LIBADD = \ + $(GTK_LIBS) \ + $(top_builddir)/libcolord/libcolord.la \ + $(GLIB_LIBS) + +libcolord_gtk_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -export-dynamic \ + -no-undefined \ + -export-symbols-regex '^cd_.*' + +libcolord_gtk_la_CFLAGS = \ + $(WARNINGFLAGS_C) + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = colord-gtk.pc + +check_PROGRAMS = \ + cd-self-test + +cd_self_test_SOURCES = \ + cd-self-test.c + +cd_self_test_LDADD = \ + $(GLIB_LIBS) \ + $(GTK_LIBS) \ + $(lib_LTLIBRARIES) + +cd_self_test_CFLAGS = $(WARNINGFLAGS_C) + +TESTS = cd-self-test + +EXTRA_DIST = \ + colord-gtk.pc.in + +MAINTAINERCLEANFILES = \ + $(noinst_LIBRARIES) + +CLEANFILES = $(BUILT_SOURCES) + +if HAVE_INTROSPECTION +introspection_sources = \ + $(libcolordgtk_la_SOURCES) \ + $(libcolordgtkbase_include_HEADERS) + +ColordGtk-1.0.gir: libcolord-gtk.la +ColordGtk_1_0_gir_INCLUDES = GObject-2.0 Gio-2.0 Colord-1.0 +ColordGtk_1_0_gir_CFLAGS = $(INCLUDES) +ColordGtk_1_0_gir_SCANNERFLAGS = --identifier-prefix=Cd \ + --symbol-prefix=cd_ \ + --warn-all \ + --add-include-path=$(srcdir) \ + --c-include="colord-gtk.h" +ColordGtk_1_0_gir_EXPORT_PACKAGES = colord-gtk +ColordGtk_1_0_gir_LIBS = libcolord-gtk.la +ColordGtk_1_0_gir_FILES = $(introspection_sources) +INTROSPECTION_GIRS += ColordGtk-1.0.gir + +girdir = $(datadir)/gir-1.0 +gir_DATA = $(INTROSPECTION_GIRS) + +typelibdir = $(libdir)/girepository-1.0 +typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) + +CLEANFILES += $(gir_DATA) $(typelib_DATA) + +if FALSE +if HAVE_VAPIGEN +colord-gtk.vapi: ColordGtk-1.0.gir + $(MAKE) $(AM_MAKEFLAGS) ColordGtk-1.0.gir + $(AM_V_GEN)$(VAPIGEN) $(VAPIGENFLAGS) \ + --library colord-gtk \ + --pkg gio-2.0 \ + ColordGtk-1.0.gir + touch $@ +vapidir = $(datadir)/vala/vapi +dist_vapi_DATA = \ + colord-gtk.vapi +CLEANFILES += $(dist_vapi_DATA) +endif +endif + +endif + +clean-local: + rm -f *~ + +-include $(top_srcdir)/git.mk diff --git a/libcolord-gtk/cd-self-test.c b/libcolord-gtk/cd-self-test.c new file mode 100644 index 0000000..570ff76 --- /dev/null +++ b/libcolord-gtk/cd-self-test.c @@ -0,0 +1,101 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include <glib.h> +#include <glib-object.h> +#include <gtk/gtk.h> + +#include "../libcolord/cd-profile.h" +#include "cd-window.h" + +static void +cd_window_set_widget_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + CdWindow *window = CD_WINDOW (source); + GtkWidget *widget = GTK_WIDGET (user_data); + GError *error = NULL; + CdProfile *profile; + + profile = cd_window_set_widget_finish (window, + res, + &error); + g_assert_no_error (error); + g_assert (profile != NULL); + g_assert (cd_profile_get_has_vcgt (profile)); + + g_debug ("profile was %s", cd_profile_get_filename (profile)); + g_object_unref (profile); + + /* kill the dialog */ + gtk_widget_destroy (widget); +} + +static void +map_cb (GtkWidget *this_widget, gpointer user_data) +{ + CdWindow *window = CD_WINDOW (user_data); + + /* get the profile for this widget */ + cd_window_set_widget (window, + this_widget, + NULL, + cd_window_set_widget_cb, + this_widget); +} + +static void +colord_window_func (void) +{ + CdWindow *window; + GtkWidget *dialog; + + window = cd_window_new (); + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + "%s", "Hello world"); + g_signal_connect (dialog, "map", + G_CALLBACK (map_cb), + window); + gtk_dialog_run (GTK_DIALOG (dialog)); + g_object_unref (window); +} + +int +main (int argc, char **argv) +{ + g_type_init (); + g_test_init (&argc, &argv, NULL); + gtk_init (&argc, &argv); + + /* only critical and error are fatal */ + g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL); + + /* tests go here */ + g_test_add_func ("/colord/window", colord_window_func); + return g_test_run (); +} + diff --git a/libcolord-gtk/cd-window.c b/libcolord-gtk/cd-window.c new file mode 100644 index 0000000..0cbcdf0 --- /dev/null +++ b/libcolord-gtk/cd-window.c @@ -0,0 +1,584 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2012 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * SECTION:cd-window + * @short_description: Additional helper classes for working with GTK + * + * These functions are useful when GTK is being used alongside colord and + * are just provided for convenience. + * + * See also: #CdDevice + */ + +#include "config.h" + +#include <gio/gio.h> +#include <glib.h> +#include <gtk/gtk.h> +#include <gdk/gdkx.h> + +#include "cd-client.h" +#include "cd-window.h" +#include "cd-device.h" +#include "cd-profile.h" + +static void cd_window_class_init (CdWindowClass *klass); +static void cd_window_init (CdWindow *window); +static void cd_window_finalize (GObject *object); + +#define CD_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CD_TYPE_WINDOW, CdWindowPrivate)) + +/** + * CdWindowPrivate: + * + * Private #CdWindow data + **/ +struct _CdWindowPrivate +{ + CdClient *client; + CdDevice *device; + CdProfile *profile; + gchar *plug_name; + GtkWidget *widget; + guint device_changed_id; +}; + +enum { + SIGNAL_CHANGED, + SIGNAL_LAST +}; + +enum { + PROP_0, + PROP_PROFILE, + PROP_LAST +}; + +static guint signals [SIGNAL_LAST] = { 0 }; + +G_DEFINE_TYPE (CdWindow, cd_window, G_TYPE_OBJECT) + +/** + * cd_window_error_quark: + * + * Return value: An error quark. + * + * Since: 0.1.20 + **/ +GQuark +cd_window_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) { + quark = g_quark_from_static_string ("cd_window_error"); + } + return quark; +} + +/** + * cd_window_get_profile: + * @window: a #CdWindow instance. + * + * Gets the color profile to use for this widget. + * + * Return value: (transfer none): a #CdProfile + * + * Since: 0.1.20 + **/ +CdProfile * +cd_window_get_profile (CdWindow *window) +{ + g_return_val_if_fail (CD_IS_WINDOW (window), NULL); + return window->priv->profile; +} + +typedef struct { + CdWindow *window; + GCancellable *cancellable; + GSimpleAsyncResult *res; +} CdWindowSetWidgetHelper; + +/** + * cd_window_set_widget_finish: + * @window: a #CdWindow instance. + * @res: the #GAsyncResult + * @error: A #GError or %NULL + * + * Gets the result from the asynchronous function. + * + * Return value: (transfer full): a #CdProfile or %NULL + * + * Since: 0.1.20 + **/ +CdProfile * +cd_window_set_widget_finish (CdWindow *window, + GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (CD_IS_WINDOW (window), NULL); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + simple = G_SIMPLE_ASYNC_RESULT (res); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +static void +cd_window_import_free_helper (CdWindowSetWidgetHelper *helper) +{ + if (helper->cancellable != NULL) + g_object_unref (helper->cancellable); + g_object_unref (helper->window); + g_object_unref (helper->res); + g_free (helper); +} + +static void cd_window_set_widget_new_data (CdWindowSetWidgetHelper *helper); + +static void +cd_window_set_widget_client_connect_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + CdClient *client = CD_CLIENT (source); + CdWindowSetWidgetHelper *helper = (CdWindowSetWidgetHelper *) user_data; + gboolean ret; + GError *error = NULL; + + ret = cd_client_connect_finish (client, res, &error); + if (!ret) { + g_simple_async_result_set_error (helper->res, + CD_WINDOW_ERROR, + CD_WINDOW_ERROR_FAILED, + "failed to connect to colord: %s", + error->message); + g_simple_async_result_complete_in_idle (helper->res); + cd_window_import_free_helper (helper); + g_error_free (error); + return; + } + cd_window_set_widget_new_data (helper); +} + +static void +cd_window_set_widget_device_connect_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + CdDevice *device = CD_DEVICE (source); + CdWindowSetWidgetHelper *helper = (CdWindowSetWidgetHelper *) user_data; + CdWindowPrivate *priv = helper->window->priv; + gboolean ret; + GError *error = NULL; + + ret = cd_device_connect_finish (device, res, &error); + if (!ret) { + g_simple_async_result_set_error (helper->res, + CD_WINDOW_ERROR, + CD_WINDOW_ERROR_FAILED, + "failed to connect to device: %s", + error->message); + g_simple_async_result_complete_in_idle (helper->res); + cd_window_import_free_helper (helper); + g_error_free (error); + return; + } + + /* get the default profile for the device */ + priv->profile = cd_device_get_default_profile (priv->device); + if (priv->profile == NULL) { + g_simple_async_result_set_error (helper->res, + CD_WINDOW_ERROR, + CD_WINDOW_ERROR_FAILED, + "no default profile for device: %s", + priv->plug_name); + g_simple_async_result_complete_in_idle (helper->res); + cd_window_import_free_helper (helper); + return; + } + + cd_window_set_widget_new_data (helper); +} + +static void +cd_window_set_widget_profile_connect_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + CdProfile *profile = CD_PROFILE (source); + CdWindowSetWidgetHelper *helper = (CdWindowSetWidgetHelper *) user_data; + CdWindowPrivate *priv = helper->window->priv; + const gchar *filename; + gboolean ret; + GError *error = NULL; + + ret = cd_profile_connect_finish (profile, res, &error); + if (!ret) { + g_simple_async_result_set_error (helper->res, + CD_WINDOW_ERROR, + CD_WINDOW_ERROR_FAILED, + "failed to connect to profile: %s", + error->message); + g_simple_async_result_complete_in_idle (helper->res); + cd_window_import_free_helper (helper); + g_error_free (error); + return; + } + + /* get the filename of the profile */ + filename = cd_profile_get_filename (priv->profile); + if (filename == NULL) { + g_simple_async_result_set_error (helper->res, + CD_WINDOW_ERROR, + CD_WINDOW_ERROR_FAILED, + "profile has no physical file, must be virtual"); + g_simple_async_result_complete_in_idle (helper->res); + cd_window_import_free_helper (helper); + return; + } + + /* SUCCESS! */ + g_simple_async_result_set_op_res_gpointer (helper->res, + g_object_ref (priv->profile), + (GDestroyNotify) g_object_unref); + g_simple_async_result_complete_in_idle (helper->res); + cd_window_import_free_helper (helper); +} + +static void +cd_window_set_widget_device_find_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + CdClient *client = CD_CLIENT (source); + CdWindowSetWidgetHelper *helper = (CdWindowSetWidgetHelper *) user_data; + CdWindowPrivate *priv = helper->window->priv; + GError *error = NULL; + + priv->device = cd_client_find_device_by_property_finish (client, + res, + &error); + if (priv->device == NULL) { + g_simple_async_result_set_error (helper->res, + CD_WINDOW_ERROR, + CD_WINDOW_ERROR_FAILED, + "no device with that property: %s", + error->message); + g_simple_async_result_complete_in_idle (helper->res); + cd_window_import_free_helper (helper); + g_error_free (error); + return; + } + cd_window_set_widget_new_data (helper); +} + +static void +cd_window_device_changed_cb (CdDevice *device, CdWindow *window) +{ + CdProfile *profile; + + /* no device set yet */ + if (window->priv->device == NULL) + return; + + /* the same device */ + if (!cd_device_equal (device, window->priv->device)) + return; + + /* get new default profile */ + profile = cd_device_get_default_profile (window->priv->device); + if (cd_profile_equal (profile, window->priv->profile)) + return; + + /* replace profile instance and emit if changed */ + if (window->priv->profile != NULL) + g_object_unref (window->priv->profile); + window->priv->profile = g_object_ref (profile); + g_signal_emit (window, signals[SIGNAL_CHANGED], 0, + window->priv->profile); +} + +static void +cd_window_set_widget_new_data (CdWindowSetWidgetHelper *helper) +{ + CdWindowPrivate *priv = helper->window->priv; + + /* connect to the daemon */ + if (priv->client == NULL) { + priv->client = cd_client_new (); + priv->device_changed_id = + g_signal_connect (priv->client, "device-changed", + G_CALLBACK (cd_window_device_changed_cb), + helper->window); + cd_client_connect (priv->client, + helper->cancellable, + cd_window_set_widget_client_connect_cb, + helper); + goto out; + } + + /* find the new device */ + if (priv->device == NULL && priv->plug_name != NULL) { + cd_client_find_device_by_property (priv->client, + CD_DEVICE_METADATA_XRANDR_NAME, + priv->plug_name, + helper->cancellable, + cd_window_set_widget_device_find_cb, + helper); + goto out; + } + + /* connect to the device */ + if (priv->device != NULL && !cd_device_get_connected (priv->device)) { + cd_device_connect (priv->device, + helper->cancellable, + cd_window_set_widget_device_connect_cb, + helper); + goto out; + } + + /* connect to the profile */ + if (priv->profile != NULL && !cd_profile_get_connected (priv->profile)) { + cd_profile_connect (priv->profile, + helper->cancellable, + cd_window_set_widget_profile_connect_cb, + helper); + goto out; + } +out: + return; +} + +static void +cd_window_update_widget_plug_name (CdWindow *window, + GtkWidget *widget) +{ + CdWindowPrivate *priv = window->priv; + const gchar *plug_name; + GdkRectangle rect; + GdkScreen *screen; + GdkWindow *gdk_window; + gint monitor_num; + + /* get xid */ + gdk_window = gtk_widget_get_window (widget); + screen = gdk_window_get_screen (gdk_window); + + gdk_window_get_frame_extents (gdk_window, &rect); + + /* the monitor where the center of the window is */ + monitor_num = gdk_screen_get_monitor_at_point (screen, + rect.x + (rect.width / 2), + rect.y + (rect.height / 2)); + plug_name = gdk_screen_get_monitor_plug_name (screen, monitor_num); + + /* ignoring MAP as plug_name has not changed */ + if (g_strcmp0 (plug_name, priv->plug_name) == 0) + return; + + /* refresh data */ + g_free (priv->plug_name); + priv->plug_name = g_strdup (plug_name); + if (priv->device != NULL) { + g_object_unref (priv->device); + priv->device = NULL; + } + if (priv->profile != NULL) { + g_object_unref (priv->profile); + priv->profile = NULL; + } +} + +/** + * cd_window_set_widget: + * @window: a #CdWindow instance. + * @widget: a #GtkWidget + * @cancellable: a #GCancellable or %NULL + * @callback: the function to run on completion + * @user_data: the data to pass to @callback + * + * Gets the screen profile that should be used for the widget, + * which corresponds to the screen output under the center of the widget. + * + * This method should be called when the widget has mapped, i.e. + * g_signal_connect (dialog, "map", G_CALLBACK (map_cb), priv); + * + * Note, the returned profile from cd_client_get_profile_for_widget_finish() + * has already been connected to, as is ready to use. + * + * Since: 0.1.20 + **/ +void +cd_window_set_widget (CdWindow *window, + GtkWidget *widget, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + CdWindowSetWidgetHelper *helper; + + g_return_if_fail (CD_IS_WINDOW (window)); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + + helper = g_new0 (CdWindowSetWidgetHelper, 1); + helper->window = g_object_ref (window); + helper->res = g_simple_async_result_new (G_OBJECT (window), + callback, + user_data, + cd_window_set_widget); + if (cancellable != NULL) + helper->cancellable = g_object_ref (cancellable); + + /* intially set the plug name */ + window->priv->widget = g_object_ref (widget); + cd_window_update_widget_plug_name (window, widget); + cd_window_set_widget_new_data (helper); +} + +/**********************************************************************/ + +/* + * cd_window_get_property: + */ +static void +cd_window_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + CdWindow *window = CD_WINDOW (object); + + switch (prop_id) { + case PROP_PROFILE: + g_value_set_object (value, window->priv->profile); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* + * cd_window_class_init: + */ +static void +cd_window_class_init (CdWindowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = cd_window_get_property; + object_class->finalize = cd_window_finalize; + + /** + * CdWindow:profile: + * + * The window profile. + * + * Since: 0.1.20 + */ + g_object_class_install_property (object_class, + PROP_PROFILE, + g_param_spec_string ("Profile", + "Color profile", + NULL, + NULL, + G_PARAM_READABLE)); + + /** + * CdWindow::changed: + * @window: the #CdDevice instance that emitted the signal + * + * The ::changed signal is emitted when the device profile has + * changed. The #CdProfile that is referenced in the callback + * has not been connected to, and you will need to call + * cd_profile_connect() if the ICC filename is required. + * + * Since: 0.1.20 + **/ + signals [SIGNAL_CHANGED] = + g_signal_new ("changed", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CdWindowClass, changed), + NULL, NULL, g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, CD_TYPE_PROFILE); + + g_type_class_add_private (klass, sizeof (CdWindowPrivate)); +} + +/* + * cd_window_init: + */ +static void +cd_window_init (CdWindow *window) +{ + window->priv = CD_WINDOW_GET_PRIVATE (window); + + /* ensure the remote errors are registered */ + cd_window_error_quark (); +} + +/* + * cd_window_finalize: + */ +static void +cd_window_finalize (GObject *object) +{ + CdWindow *window = CD_WINDOW (object); + + g_return_if_fail (CD_IS_WINDOW (object)); + + if (window->priv->client != NULL) { + g_signal_handler_disconnect (window->priv->client, + window->priv->device_changed_id); + g_object_unref (window->priv->client); + } + if (window->priv->device != NULL) + g_object_unref (window->priv->device); + if (window->priv->profile != NULL) + g_object_unref (window->priv->profile); + g_free (window->priv->plug_name); + + G_OBJECT_CLASS (cd_window_parent_class)->finalize (object); +} + +/** + * cd_window_new: + * + * Creates a new #CdWindow object. + * + * Return value: a new CdWindow object. + * + * Since: 0.1.20 + **/ +CdWindow * +cd_window_new (void) +{ + CdWindow *window; + window = g_object_new (CD_TYPE_WINDOW, NULL); + return CD_WINDOW (window); +} diff --git a/libcolord-gtk/cd-window.h b/libcolord-gtk/cd-window.h new file mode 100644 index 0000000..15b334b --- /dev/null +++ b/libcolord-gtk/cd-window.h @@ -0,0 +1,103 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2012 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined (__COLORD_H_INSIDE__) && !defined (CD_COMPILATION) +#error "Only <colord-gtk.h> can be included directly." +#endif + +#ifndef __CD_WINDOW_H +#define __CD_WINDOW_H + +#include <glib-object.h> +#include <gio/gio.h> +#include <gtk/gtk.h> + +#include "cd-window.h" + +G_BEGIN_DECLS + +#define CD_TYPE_WINDOW (cd_window_get_type ()) +#define CD_WINDOW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CD_TYPE_WINDOW, CdWindow)) +#define CD_WINDOW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CD_TYPE_WINDOW, CdWindowClass)) +#define CD_IS_WINDOW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CD_TYPE_WINDOW)) +#define CD_IS_WINDOW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CD_TYPE_WINDOW)) +#define CD_WINDOW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CD_TYPE_WINDOW, CdWindowClass)) +#define CD_WINDOW_ERROR (cd_window_error_quark ()) +#define CD_WINDOW_TYPE_ERROR (cd_window_error_get_type ()) + +typedef struct _CdWindowPrivate CdWindowPrivate; + +typedef struct +{ + GObject parent; + CdWindowPrivate *priv; +} CdWindow; + +typedef struct +{ + GObjectClass parent_class; + void (*changed) (CdWindow *window, + CdProfile *profile); + /*< private >*/ + /* Padding for future expansion */ + void (*_cd_window_reserved1) (void); + void (*_cd_window_reserved2) (void); + void (*_cd_window_reserved3) (void); + void (*_cd_window_reserved4) (void); + void (*_cd_window_reserved5) (void); + void (*_cd_window_reserved6) (void); + void (*_cd_window_reserved7) (void); + void (*_cd_window_reserved8) (void); +} CdWindowClass; + +/** + * CdWindowError: + * @CD_WINDOW_ERROR_FAILED: the transaction failed for an unknown reason + * + * Errors that can be thrown + */ +typedef enum +{ + CD_WINDOW_ERROR_FAILED, + CD_WINDOW_ERROR_LAST +} CdWindowError; + +GType cd_window_get_type (void); +GQuark cd_window_error_quark (void); +CdWindow *cd_window_new (void); + +/* async */ +void cd_window_set_widget (CdWindow *window, + GtkWidget *widget, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +CdProfile *cd_window_set_widget_finish (CdWindow *window, + GAsyncResult *res, + GError **error); + +/* getters */ +CdProfile *cd_window_get_profile (CdWindow *window); + +G_END_DECLS + +#endif /* __CD_WINDOW_H */ + diff --git a/libcolord-gtk/colord-gtk.h b/libcolord-gtk/colord-gtk.h new file mode 100644 index 0000000..2d50286 --- /dev/null +++ b/libcolord-gtk/colord-gtk.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010-2011 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * SECTION:colord + * @short_description: Client objects for accessing colord with GTK + * + * These objects allow client programs to get access to profiles. + * + * See also: #CdClient, #CdDevice + */ + +#ifndef __COLORD_GTK_H__ +#define __COLORD_GTK_H__ + +#define __COLORD_H_INSIDE__ + +#include <colord/cd-client.h> +#include <colord/cd-device.h> +#include <colord/cd-profile.h> +#include <colord-gtk/cd-window.h> + +#undef __COLORD_H_INSIDE__ + +#endif /* __COLORD_GTK_H__ */ + diff --git a/libcolord-gtk/colord-gtk.pc.in b/libcolord-gtk/colord-gtk.pc.in new file mode 100644 index 0000000..906fbe6 --- /dev/null +++ b/libcolord-gtk/colord-gtk.pc.in @@ -0,0 +1,9 @@ +libdir=@libdir@ +includedir=@includedir@ + +Name: colord-gtk +Description: colord-gtk is GTK integration for libcolord +Version: @VERSION@ +Requires: colord, gtk+-3.0 +Libs: -L${libdir} -lcolord-gtk +Cflags: -I${includedir}/colord-1 |