diff --git a/ChangeLog b/ChangeLog index c3f6b0a4e..6a7eef5fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2006-06-06 Iain Holmes + + * gtk/: Add a gtk widget for clutter. + + * configure.ac: Add GTK checks + + * Makefile.am: Go into gtk/ + 2006-06-05 Matthew Allum * clutter/clutter-group.c: (clutter_group_remove): diff --git a/Makefile.am b/Makefile.am index 5f19271de..75850fc97 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=clutter bindings doc examples +SUBDIRS=clutter gtk bindings doc examples pcfiles = clutter-@CLUTTER_MAJORMINOR@.pc @@ -17,4 +17,4 @@ DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc # Extra clean files so that maintainer-clean removes *everything* MAINTAINERCLEANFILES = aclocal.m4 compile config.guess config.sub \ configure depcomp install-sh ltmain.sh \ - Makefile.in missing config.h.in \ No newline at end of file + Makefile.in missing config.h.in diff --git a/configure.ac b/configure.ac index 97b687856..e9513f7f7 100644 --- a/configure.ac +++ b/configure.ac @@ -104,6 +104,11 @@ GST_LIBS="$GST_LIBS -lgstinterfaces-$GST_MAJORMINOR -lgstvideo-$GST_MAJORMINOR - dnl ======================================================================== +pkg_modules="gtk+-2.0" +PKG_CHECK_MODULES(GTK, [$pkg_modules]) + +dnl ======================================================================== + if test "x$GCC" = "xyes"; then GCC_FLAGS="-g -Wall" fi @@ -175,6 +180,8 @@ dnl ======================================================================== AC_SUBST(GCC_FLAGS) AC_SUBST(GST_CFLAGS) AC_SUBST(GST_LIBS) +AC_SUBST(GTK_CFLAGS) +AC_SUBST(GTK_LIBS) CLUTTER_CFLAGS="$GLX_CLAGS $CLUTTER_CFLAGS" CLUTTER_LIBS="$GLX_LIBS $CLUTTER_LIBS" @@ -184,6 +191,7 @@ AC_SUBST(CLUTTER_LIBS) AC_OUTPUT([Makefile clutter/Makefile +gtk/Makefile bindings/Makefile bindings/python/Makefile examples/Makefile diff --git a/gtk/Makefile.am b/gtk/Makefile.am new file mode 100644 index 000000000..8ffe77d8e --- /dev/null +++ b/gtk/Makefile.am @@ -0,0 +1,22 @@ +INCLUDES = @GCC_FLAGS@ @CLUTTER_CFLAGS@ $(GST_CFLAGS) $(GTK_CFLAGS) + +lib_LTLIBRARIES = libgtkclutter-@CLUTTER_MAJORMINOR@.la + +libgtkclutter_@CLUTTER_MAJORMINOR@_la_SOURCES = gtk-clutter.c + +libgtkclutter_@CLUTTER_MAJORMINOR@_la_LIBADD = @CLUTTER_LIBS@ $(GST_LIBS) $(GTK_LIBS) +libgtkclutter_@CLUTTER_MAJORMINOR@_la_LDFLAGS = @CLUTTER_LT_LDFLAGS@ + +gtkclutterheadersdir = $(includedir)/gtk-clutter-@CLUTTER_MAJORMINOR@/gtk-clutter +gtkclutterheaders_DATA = gtk-clutter.h + +noinst_PROGRAMS = gtk-clutter-test + +gtk_clutter_test_SOURCES = gtk-clutter-test.c +gtk_clutter_test_LDADD = libgtkclutter-@CLUTTER_MAJORMINOR@.la \ + $(CLUTTER_LIBS) \ + $(GST_LIBS) \ + $(GTK_LIBS) \ + $(top_builddir)/clutter/libclutter-@CLUTTER_MAJORMINOR@.la + +gtk_clutter_test_CFLAGS = $(CLUTTER_CFLAGS) $(GST_CFLAGS) $(GTK_CFLAGS) diff --git a/gtk/gtk-clutter-test.c b/gtk/gtk-clutter-test.c new file mode 100644 index 000000000..d567f6c8f --- /dev/null +++ b/gtk/gtk-clutter-test.c @@ -0,0 +1,209 @@ +#include +#include +#include + +#include "gtk-clutter.h" + +#define TRAILS 0 +#define NHANDS 6 +#define WINWIDTH 800 +#define WINHEIGHT 800 +#define RADIUS 250 + +typedef struct SuperOH +{ + ClutterElement *hand[NHANDS], *bgtex; + ClutterGroup *group; + GdkPixbuf *bgpixb; + +} SuperOH; + +/* input handler */ +void +input_cb (ClutterStage *stage, + ClutterEvent *event, + gpointer data) +{ + SuperOH *oh = (SuperOH *)data; + + if (event->type == CLUTTER_BUTTON_PRESS) + { + ClutterButtonEvent *bev = (ClutterButtonEvent *) event; + ClutterElement *e; + + g_print ("*** button press event (button:%d) ***\n", + bev->button); + + e = clutter_stage_get_element_at_pos (stage, + clutter_button_event_x (event), + clutter_button_event_y (event)); + + if (e) + clutter_element_hide(e); + } + else if (event->type == CLUTTER_KEY_PRESS) + { + ClutterKeyEvent *kev = (ClutterKeyEvent *) event; + + g_print ("*** key press event (key:%c) ***\n", + clutter_key_event_symbol (kev)); + + if (clutter_key_event_symbol (kev) == CLUTTER_q) + clutter_main_quit (); + } +} + + +/* Timeline handler */ +void +frame_cb (ClutterTimeline *timeline, + gint frame_num, + gpointer data) +{ + SuperOH *oh = (SuperOH *)data; + ClutterElement *stage = clutter_stage_get_default (); + gint i; + +#if TRAILS + oh->bgpixb = clutter_stage_snapshot (CLUTTER_STAGE (stage), + 0, 0, + WINWIDTH, + WINHEIGHT); + clutter_texture_set_pixbuf (CLUTTER_TEXTURE (oh->bgtex), oh->bgpixb); + g_object_unref (G_OBJECT (oh->bgpixb)); + g_object_unref (stage); +#endif + + /* Rotate everything clockwise about stage center*/ + clutter_element_rotate_z (CLUTTER_ELEMENT(oh->group), + frame_num, + WINWIDTH/2, + WINHEIGHT/2); + for (i = 0; i < NHANDS; i++) + { + /* rotate each hand around there centers */ + clutter_element_rotate_z (oh->hand[i], + - 6.0 * frame_num, + clutter_element_get_width (oh->hand[i])/2, + clutter_element_get_height (oh->hand[i])/2); + } + + /* + clutter_element_rotate_x (CLUTTER_ELEMENT(oh->group), + 75.0, + WINHEIGHT/2, 0); + */ +} + +int +main (int argc, char *argv[]) +{ + ClutterTimeline *timeline; + ClutterElement *stage; + ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff }; + GtkWidget *window, *plug, *clutter; + GtkWidget *label, *button, *vbox; + GdkPixbuf *pixbuf; + SuperOH *oh; + gint i; + + clutter_init (&argc, &argv); + gtk_init (&argc, &argv); + + + pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL); + + if (!pixbuf) + g_error("pixbuf load failed"); + + clutter = g_object_new (GTK_TYPE_CLUTTER, NULL); + stage = gtk_clutter_get_stage (GTK_CLUTTER (clutter)); + + /* Set our stage size */ + clutter_element_set_size (stage, WINWIDTH, WINHEIGHT); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (window), vbox); + + gtk_container_add (GTK_CONTAINER (vbox), clutter); + + label = gtk_label_new ("This is a label"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + button = gtk_button_new_with_label ("This is a button...clicky"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + /* and its background color */ + + clutter_stage_set_color (CLUTTER_STAGE (stage), + &stage_color); + + oh = g_new(SuperOH, 1); + +#if TRAILS + oh->bgtex = clutter_texture_new(); + clutter_element_set_size (oh->bgtex, WINWIDTH, WINHEIGHT); + clutter_element_set_opacity (oh->bgtex, 0x99); + clutter_group_add (CLUTTER_GROUP (stage), oh->bgtex); +#endif + + /* create a new group to hold multiple elements in a group */ + oh->group = clutter_group_new(); + + for (i = 0; i < NHANDS; i++) + { + gint x, y, w, h; + + /* Create a texture from pixbuf, then clone in to same resources */ + if (i == 0) + oh->hand[i] = clutter_texture_new_from_pixbuf (pixbuf); + else + oh->hand[i] = clutter_clone_texture_new (CLUTTER_TEXTURE(oh->hand[0])); + + /* Place around a circle */ + w = clutter_element_get_width (oh->hand[0]); + h = clutter_element_get_height (oh->hand[0]); + + x = WINWIDTH/2 + RADIUS * cos (i * M_PI / (NHANDS/2)) - w/2; + y = WINHEIGHT/2 + RADIUS * sin (i * M_PI / (NHANDS/2)) - h/2; + + clutter_element_set_position (oh->hand[i], x, y); + + /* Add to our group group */ + clutter_group_add (oh->group, oh->hand[i]); + } + + /* Add the group to the stage */ + clutter_group_add (CLUTTER_GROUP (stage), CLUTTER_ELEMENT(oh->group)); + + /* Show everying ( and map window ) */ + clutter_group_show_all (oh->group); + clutter_group_show_all (CLUTTER_GROUP (stage)); + + g_signal_connect (stage, "button-press-event", + G_CALLBACK (input_cb), + oh); + g_signal_connect (stage, "key-release-event", + G_CALLBACK (input_cb), + oh); + + gtk_widget_show_all (window); + + /* Create a timeline to manage animation */ + timeline = clutter_timeline_new (360, 60); /* num frames, fps */ + g_object_set(timeline, "loop", TRUE, 0); /* have it loop */ + + /* fire a callback for frame change */ + g_signal_connect(timeline, "new-frame", G_CALLBACK (frame_cb), oh); + + /* and start it */ + clutter_timeline_start (timeline); + + gtk_main(); + + return 0; +} diff --git a/gtk/gtk-clutter.c b/gtk/gtk-clutter.c new file mode 100644 index 000000000..5ac1f7536 --- /dev/null +++ b/gtk/gtk-clutter.c @@ -0,0 +1,115 @@ +/* + * GTK-Clutter. + * + * GTK+ widget for Clutter. + * + * Authored By Iain Holmes + * + * Copyright (C) 2006 OpenedHand + * + * 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 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include +#include + +#include + +#include "gtk-clutter.h" + +#define GTK_CLUTTER_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CLUTTER, GtkClutterPrivate)) + +struct _GtkClutterPrivate { + ClutterElement *stage; + gboolean anchored; +}; + +static GtkSocketClass *parent_class; + +static void +dispose (GObject *object) +{ + GtkClutter *clutter; + GtkClutterPrivate *priv; + + clutter = GTK_CLUTTER (object); + priv = GTK_CLUTTER_GET_PRIVATE (clutter); + + if (priv->stage) { + g_object_unref (G_OBJECT (priv->stage)); + priv->stage = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +hierarchy_changed (GtkWidget *widget, + GtkWidget *parent) +{ + GtkClutter *clutter; + GtkClutterPrivate *priv; + + clutter = GTK_CLUTTER (widget); + priv = GTK_CLUTTER_GET_PRIVATE (clutter); + + if (!priv->anchored) { + /* Now we can add our stage to the socket */ + gtk_socket_add_id + (GTK_SOCKET (clutter), (GdkNativeWindow) clutter_stage_get_xwindow (CLUTTER_STAGE (priv->stage))); + + priv->anchored = TRUE; + } +} + +static void +gtk_clutter_class_init (GtkClutterClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GtkWidgetClass *widget_class = (GtkWidgetClass *) klass; + + gobject_class->dispose = dispose; + + widget_class->hierarchy_changed = hierarchy_changed; + + g_type_class_add_private (gobject_class, sizeof (GtkClutterPrivate)); + + parent_class = g_type_class_peek_parent (klass); +} + +static void +gtk_clutter_init (GtkClutter *clutter) +{ + GtkClutterPrivate *priv; + + clutter->priv = priv = GTK_CLUTTER_GET_PRIVATE (clutter); + + priv->stage = clutter_stage_get_default (); + priv->anchored = FALSE; +} + +G_DEFINE_TYPE (GtkClutter, gtk_clutter, GTK_TYPE_SOCKET); + +ClutterElement * +gtk_clutter_get_stage (GtkClutter *clutter) +{ + g_return_val_if_fail (GTK_IS_CLUTTER (clutter), NULL); + + return clutter->priv->stage; +} diff --git a/gtk/gtk-clutter.h b/gtk/gtk-clutter.h new file mode 100644 index 000000000..a6cf46d12 --- /dev/null +++ b/gtk/gtk-clutter.h @@ -0,0 +1,80 @@ +/* + * GTK-Clutter. + * + * GTK+ widget for Clutter. + * + * Authored By Iain Holmes + * + * Copyright (C) 2006 OpenedHand + * + * 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 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _HAVE_GTK_CLUTTER_H +#define _HAVE_GTK_CLUTTER_H + +#include + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_CLUTTER gtk_clutter_get_type () + +#define GTK_CLUTTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + GTK_TYPE_CLUTTER, GtkClutter)) + +#define GTK_CLUTTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CASE ((klass), \ + GTK_TYPE_CLUTTER, GtkClutterClass)) + +#define GTK_IS_CLUTTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + GTK_TYPE_CLUTTER)) + +#define GTK_IS_CLUTTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + GTK_TYPE_CLUTTER)) + +#define GTK_CLUTTER_STAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + GTK_TYPE_CLUTTER, GtkClutterClass)) + +typedef struct _GtkClutterPrivate GtkClutterPrivate; +typedef struct _GtkClutter GtkClutter; +typedef struct _GtkClutterClass GtkClutterClass; + +struct _GtkClutter +{ + GtkSocket parent; + + /*< private >*/ + GtkClutterPrivate *priv; +}; + +struct _GtkClutterClass +{ + GtkSocketClass parent_class; +}; + +GType gtk_clutter_get_type (void); + +ClutterElement *gtk_clutter_get_stage (GtkClutter *clutter); + +G_END_DECLS + +#endif diff --git a/gtk/redhand.png b/gtk/redhand.png new file mode 100644 index 000000000..c07d8acd3 Binary files /dev/null and b/gtk/redhand.png differ