[gnome-shell] Import MxEntry, MxLabel, MxClipboard



commit 58325fca76909174bf4566cb71cd7608aa00e622
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Thu Sep 10 04:39:27 2009 -0400

    Import MxEntry, MxLabel, MxClipboard
    
    For now this commit introduces an external dependency on clutter-imcontext.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=591245

 configure.ac                    |    2 +-
 src/Makefile-st.am              |    6 +
 src/st/st-clipboard.c           |  380 ++++++++++++++++
 src/st/st-clipboard.h           |  102 ++++
 src/st/st-entry.c               |  961 +++++++++++++++++++++++++++++++++++++++
 src/st/st-entry.h               |   88 ++++
 src/st/st-label.c               |  363 +++++++++++++++
 src/st/st-label.h               |   75 +++
 tools/build/gnome-shell.modules |    9 +
 9 files changed, 1985 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 5c7efed..050b375 100644
--- a/configure.ac
+++ b/configure.ac
@@ -57,7 +57,7 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugin
                                  gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
                                  gobject-introspection-1.0 >= 0.6.5)
 PKG_CHECK_MODULES(TIDY, clutter-1.0)
-PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 libccss-1 >= 0.3.1)
+PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 libccss-1 >= 0.3.1 clutter-imcontext-0.1)
 PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
 PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
 PKG_CHECK_MODULES(TRAY, gtk+-2.0)
diff --git a/src/Makefile-st.am b/src/Makefile-st.am
index d0f4877..2967054 100644
--- a/src/Makefile-st.am
+++ b/src/Makefile-st.am
@@ -70,6 +70,9 @@ st_source_h =					\
     st/st-box-layout.h				\
     st/st-box-layout-child.h			\
     st/st-button.h				\
+    st/st-clipboard.h				\
+    st/st-entry.h				\
+    st/st-label.h				\
     st/st-private.h				\
     st/st-stylable.h				\
     st/st-style.h				\
@@ -91,6 +94,9 @@ st_source_c =					\
     st/st-box-layout.c				\
     st/st-box-layout-child.c			\
     st/st-button.c				\
+    st/st-clipboard.c				\
+    st/st-entry.c				\
+    st/st-label.c				\
     st/st-private.c				\
     st/st-scrollable.c				\
     st/st-scroll-bar.c				\
diff --git a/src/st/st-clipboard.c b/src/st/st-clipboard.c
new file mode 100644
index 0000000..c6507c1
--- /dev/null
+++ b/src/st/st-clipboard.c
@@ -0,0 +1,380 @@
+/*
+ * st-clipboard.c: clipboard object
+ *
+ * Copyright 2009 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+/**
+ * SECTION:st-clipboard
+ * @short_description: a simple representation of the X clipboard
+ *
+ * #StCliboard is a very simple object representation of the clipboard
+ * available to applications. Text is always assumed to be UTF-8 and non-text
+ * items are not handled.
+ */
+
+
+#include "st-clipboard.h"
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <clutter/x11/clutter-x11.h>
+#include <string.h>
+
+G_DEFINE_TYPE (StClipboard, st_clipboard, G_TYPE_OBJECT)
+
+#define CLIPBOARD_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_CLIPBOARD, StClipboardPrivate))
+
+struct _StClipboardPrivate
+{
+  Window clipboard_window;
+  gchar *clipboard_text;
+
+  Atom  *supported_targets;
+  gint   n_targets;
+};
+
+typedef struct _EventFilterData EventFilterData;
+struct _EventFilterData
+{
+  StClipboard            *clipboard;
+  StClipboardCallbackFunc callback;
+  gpointer                user_data;
+};
+
+static Atom __atom_clip = None;
+static Atom __utf8_string = None;
+static Atom __atom_targets = None;
+
+static void
+st_clipboard_get_property (GObject    *object,
+                           guint       property_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+st_clipboard_set_property (GObject      *object,
+                           guint         property_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+st_clipboard_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (st_clipboard_parent_class)->dispose (object);
+}
+
+static void
+st_clipboard_finalize (GObject *object)
+{
+  StClipboardPrivate *priv = ((StClipboard *) object)->priv;
+
+  g_free (priv->clipboard_text);
+  priv->clipboard_text = NULL;
+
+  g_free (priv->supported_targets);
+  priv->supported_targets = NULL;
+  priv->n_targets = 0;
+
+  G_OBJECT_CLASS (st_clipboard_parent_class)->finalize (object);
+}
+
+static ClutterX11FilterReturn
+st_clipboard_provider (XEvent       *xev,
+                       ClutterEvent *cev,
+                       StClipboard  *clipboard)
+{
+  XSelectionEvent notify_event;
+  XSelectionRequestEvent *req_event;
+
+  if (xev->type != SelectionRequest)
+    return CLUTTER_X11_FILTER_CONTINUE;
+
+  req_event = &xev->xselectionrequest;
+
+  clutter_x11_trap_x_errors ();
+
+  if (req_event->target == __atom_targets)
+    {
+      XChangeProperty (req_event->display,
+                       req_event->requestor,
+                       req_event->property,
+                       XA_ATOM,
+                       32,
+                       PropModeReplace,
+                       (guchar*) clipboard->priv->supported_targets,
+                       clipboard->priv->n_targets);
+    }
+  else
+    {
+      XChangeProperty (req_event->display,
+                       req_event->requestor,
+                       req_event->property,
+                       req_event->target,
+                       8,
+                       PropModeReplace,
+                       (guchar*) clipboard->priv->clipboard_text,
+                       strlen (clipboard->priv->clipboard_text));
+    }
+
+  notify_event.type = SelectionNotify;
+  notify_event.display = req_event->display;
+  notify_event.requestor = req_event->requestor;
+  notify_event.selection = req_event->selection;
+  notify_event.target = req_event->target;
+  notify_event.time = req_event->time;
+
+  if (req_event->property == None)
+    notify_event.property = req_event->target;
+  else
+    notify_event.property = req_event->property;
+
+  /* notify the requestor that they have a copy of the selection */
+  XSendEvent (req_event->display, req_event->requestor, False, 0,
+              (XEvent *) &notify_event);
+  /* Make it happen non async */
+  XSync (clutter_x11_get_default_display(), FALSE);
+
+  clutter_x11_untrap_x_errors (); /* FIXME: Warn here on fail ? */
+
+  return CLUTTER_X11_FILTER_REMOVE;
+}
+
+
+static void
+st_clipboard_class_init (StClipboardClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (StClipboardPrivate));
+
+  object_class->get_property = st_clipboard_get_property;
+  object_class->set_property = st_clipboard_set_property;
+  object_class->dispose = st_clipboard_dispose;
+  object_class->finalize = st_clipboard_finalize;
+}
+
+static void
+st_clipboard_init (StClipboard *self)
+{
+  Display *dpy;
+  StClipboardPrivate *priv;
+
+  priv = self->priv = CLIPBOARD_PRIVATE (self);
+
+  priv->clipboard_window =
+    XCreateSimpleWindow (clutter_x11_get_default_display (),
+                         clutter_x11_get_root_window (),
+                         -1, -1, 1, 1, 0, 0, 0);
+
+  dpy = clutter_x11_get_default_display ();
+
+  /* Only create once */
+  if (__atom_clip == None)
+    __atom_clip = XInternAtom (dpy, "CLIPBOARD", 0);
+
+  if (__utf8_string == None)
+    __utf8_string = XInternAtom (dpy, "UTF8_STRING", 0);
+
+  if (__atom_targets == None)
+    __atom_targets = XInternAtom (dpy, "TARGETS", 0);
+
+  priv->n_targets = 2;
+  priv->supported_targets = g_new (Atom, priv->n_targets);
+
+  priv->supported_targets[0] = __utf8_string;
+  priv->supported_targets[1] = __atom_targets;
+
+  clutter_x11_add_filter ((ClutterX11FilterFunc) st_clipboard_provider,
+                          self);
+}
+
+static ClutterX11FilterReturn
+st_clipboard_x11_event_filter (XEvent          *xev,
+                               ClutterEvent    *cev,
+                               EventFilterData *filter_data)
+{
+  Atom actual_type;
+  int actual_format, result;
+  unsigned long nitems, bytes_after;
+  unsigned char *data = NULL;
+
+  if(xev->type != SelectionNotify)
+    return CLUTTER_X11_FILTER_CONTINUE;
+
+  if (xev->xselection.property == None)
+    {
+      /* clipboard empty */
+      filter_data->callback (filter_data->clipboard,
+                             NULL,
+                             filter_data->user_data);
+
+      clutter_x11_remove_filter ((ClutterX11FilterFunc) st_clipboard_x11_event_filter,
+                                 filter_data);
+      g_free (filter_data);
+      return CLUTTER_X11_FILTER_REMOVE;
+    }
+
+  clutter_x11_trap_x_errors ();
+
+  result = XGetWindowProperty (xev->xselection.display,
+                               xev->xselection.requestor,
+                               xev->xselection.property,
+                               0L, G_MAXINT,
+                               True,
+                               AnyPropertyType,
+                               &actual_type,
+                               &actual_format,
+                               &nitems,
+                               &bytes_after,
+                               &data);
+
+  if (clutter_x11_untrap_x_errors () || result != Success)
+    {
+      /* FIXME: handle failure better */
+      g_warning ("Clipboard: prop retrival failed");
+    }
+
+  filter_data->callback (filter_data->clipboard, (char*) data,
+                         filter_data->user_data);
+
+  clutter_x11_remove_filter
+                          ((ClutterX11FilterFunc) st_clipboard_x11_event_filter,
+                          filter_data);
+
+  g_free (filter_data);
+
+  if (data)
+    XFree (data);
+
+  return CLUTTER_X11_FILTER_REMOVE;
+}
+
+/**
+ * st_clipboard_get_default:
+ *
+ * Get the global #StClipboard object that represents the clipboard.
+ *
+ * Returns: a #StClipboard owned by St and must not be unrefferenced or
+ * freed.
+ */
+StClipboard*
+st_clipboard_get_default (void)
+{
+  static StClipboard *default_clipboard = NULL;
+
+  if (!default_clipboard)
+    {
+      default_clipboard = g_object_new (ST_TYPE_CLIPBOARD, NULL);
+    }
+
+  return default_clipboard;
+}
+
+/**
+ * st_clipboard_get_text:
+ * @clipboard: A #StCliboard
+ * @callback: function to be called when the text is retreived
+ * @user_data: data to be passed to the callback
+ *
+ * Request the data from the clipboard in text form. @callback is executed
+ * when the data is retreived.
+ *
+ */
+void
+st_clipboard_get_text (StClipboard            *clipboard,
+                       StClipboardCallbackFunc callback,
+                       gpointer                user_data)
+{
+  EventFilterData *data;
+
+  Display *dpy;
+
+  g_return_if_fail (ST_IS_CLIPBOARD (clipboard));
+  g_return_if_fail (callback != NULL);
+
+  data = g_new0 (EventFilterData, 1);
+  data->clipboard = clipboard;
+  data->callback = callback;
+  data->user_data = user_data;
+
+  clutter_x11_add_filter ((ClutterX11FilterFunc) st_clipboard_x11_event_filter,
+                          data);
+
+  dpy = clutter_x11_get_default_display ();
+
+  clutter_x11_trap_x_errors (); /* safety on */
+
+  XConvertSelection (dpy,
+                     __atom_clip,
+                     __utf8_string, __utf8_string,
+                     clipboard->priv->clipboard_window,
+                     CurrentTime);
+
+  clutter_x11_untrap_x_errors ();
+}
+
+/**
+ * st_clipboard_set_text:
+ * @clipboard: A #StClipboard
+ * @text: text to copy to the clipboard
+ *
+ * Sets text as the current contents of the clipboard.
+ *
+ */
+void
+st_clipboard_set_text (StClipboard *clipboard,
+                       const gchar *text)
+{
+  StClipboardPrivate *priv;
+  Display *dpy;
+
+  g_return_if_fail (ST_IS_CLIPBOARD (clipboard));
+  g_return_if_fail (text != NULL);
+
+  priv = clipboard->priv;
+
+  /* make a copy of the text */
+  g_free (priv->clipboard_text);
+  priv->clipboard_text = g_strdup (text);
+
+  /* tell X we own the clipboard selection */
+  dpy = clutter_x11_get_default_display ();
+
+  clutter_x11_trap_x_errors ();
+
+  XSetSelectionOwner (dpy, __atom_clip, priv->clipboard_window, CurrentTime);
+  XSync (dpy, FALSE);
+
+  clutter_x11_untrap_x_errors ();
+}
diff --git a/src/st/st-clipboard.h b/src/st/st-clipboard.h
new file mode 100644
index 0000000..b1751a3
--- /dev/null
+++ b/src/st/st-clipboard.h
@@ -0,0 +1,102 @@
+/*
+ * st-clipboard.h: clipboard object
+ *
+ * Copyright 2009 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
+#error "Only <st/st.h> can be included directly.h"
+#endif
+
+#ifndef _ST_CLIPBOARD_H
+#define _ST_CLIPBOARD_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define ST_TYPE_CLIPBOARD st_clipboard_get_type()
+
+#define ST_CLIPBOARD(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  ST_TYPE_CLIPBOARD, StClipboard))
+
+#define ST_CLIPBOARD_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  ST_TYPE_CLIPBOARD, StClipboardClass))
+
+#define ST_IS_CLIPBOARD(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  ST_TYPE_CLIPBOARD))
+
+#define ST_IS_CLIPBOARD_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  ST_TYPE_CLIPBOARD))
+
+#define ST_CLIPBOARD_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  ST_TYPE_CLIPBOARD, StClipboardClass))
+
+typedef struct _StClipboard StClipboard;
+typedef struct _StClipboardClass StClipboardClass;
+typedef struct _StClipboardPrivate StClipboardPrivate;
+
+/**
+ * StClipboard:
+ *
+ * The contents of this structure is private and should only be accessed using
+ * the provided API.
+ */
+struct _StClipboard
+{
+  /*< private >*/
+  GObject parent;
+  StClipboardPrivate *priv;
+};
+
+struct _StClipboardClass
+{
+  GObjectClass parent_class;
+};
+
+/**
+ * StClipboardCallbackFunc:
+ * @clipboard: A #StClipboard
+ * @text: text from the clipboard
+ * @user_data: user data
+ *
+ * Callback function called when text is retrieved from the clipboard.
+ */
+typedef void (*StClipboardCallbackFunc) (StClipboard *clipboard,
+                                         const gchar *text,
+                                         gpointer     user_data);
+
+GType st_clipboard_get_type (void);
+
+StClipboard* st_clipboard_get_default (void);
+
+void st_clipboard_get_text (StClipboard             *clipboard,
+                            StClipboardCallbackFunc  callback,
+                            gpointer                 user_data);
+void st_clipboard_set_text (StClipboard             *clipboard,
+                            const gchar             *text);
+
+G_END_DECLS
+
+#endif /* _ST_CLIPBOARD_H */
diff --git a/src/st/st-entry.c b/src/st/st-entry.c
new file mode 100644
index 0000000..20151bf
--- /dev/null
+++ b/src/st/st-entry.c
@@ -0,0 +1,961 @@
+/*
+ * st-entry.c: Plain entry actor
+ *
+ * Copyright 2008, 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+/**
+ * SECTION:st-entry
+ * @short_description: Widget for displaying text
+ *
+ * #StEntry is a simple widget for displaying text. It derives from
+ * #StWidget to add extra style and placement functionality over
+ * #ClutterText. The internal #ClutterText is publicly accessibly to allow
+ * applications to set further properties.
+ *
+ * #StEntry supports the following pseudo style states:
+ * <itemizedlist>
+ *  <listitem>
+ *   <para>focus: the widget has focus</para>
+ *  </listitem>
+ *  <listitem>
+ *   <para>indeterminate: the widget is showing the hint text</para>
+ *  </listitem>
+ * </itemizedlist>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <clutter/clutter.h>
+#include <clutter-imcontext/clutter-imtext.h>
+
+#include "st-entry.h"
+
+#include "st-widget.h"
+#include "st-stylable.h"
+#include "st-texture-cache.h"
+#include "st-marshal.h"
+#include "st-clipboard.h"
+
+#define HAS_FOCUS(actor) (clutter_actor_get_stage (actor) && clutter_stage_get_key_focus ((ClutterStage *) clutter_actor_get_stage (actor)) == actor)
+
+
+/* properties */
+enum
+{
+  PROP_0,
+
+  PROP_ENTRY,
+  PROP_HINT
+};
+
+/* signals */
+enum
+{
+  PRIMARY_ICON_CLICKED,
+  SECONDARY_ICON_CLICKED,
+
+  LAST_SIGNAL
+};
+
+#define ST_ENTRY_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_ENTRY, StEntryPrivate))
+#define ST_ENTRY_PRIV(x) ((StEntry *) x)->priv
+
+
+struct _StEntryPrivate
+{
+  ClutterActor *entry;
+  gchar        *hint;
+
+  ClutterActor *primary_icon;
+  ClutterActor *secondary_icon;
+
+  gfloat        spacing;
+};
+
+static guint entry_signals[LAST_SIGNAL] = { 0, };
+
+static void st_stylable_iface_init (StStylableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (StEntry, st_entry, ST_TYPE_WIDGET,
+                         G_IMPLEMENT_INTERFACE (ST_TYPE_STYLABLE,
+                                                st_stylable_iface_init));
+
+static void
+st_entry_set_property (GObject      *gobject,
+                       guint         prop_id,
+                       const GValue *value,
+                       GParamSpec   *pspec)
+{
+  StEntry *entry = ST_ENTRY (gobject);
+
+  switch (prop_id)
+    {
+    case PROP_ENTRY:
+      st_entry_set_text (entry, g_value_get_string (value));
+      break;
+
+    case PROP_HINT:
+      st_entry_set_hint_text (entry, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+st_entry_get_property (GObject    *gobject,
+                       guint       prop_id,
+                       GValue     *value,
+                       GParamSpec *pspec)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (gobject);
+
+  switch (prop_id)
+    {
+    case PROP_ENTRY:
+      g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->entry)));
+      break;
+
+    case PROP_HINT:
+      g_value_set_string (value, priv->hint);
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+st_entry_dispose (GObject *object)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (object);
+
+  if (priv->entry)
+    {
+      clutter_actor_unparent (priv->entry);
+      priv->entry = NULL;
+    }
+}
+
+static void
+st_entry_finalize (GObject *object)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (object);
+
+  g_free (priv->hint);
+  priv->hint = NULL;
+}
+
+static void
+st_stylable_iface_init (StStylableIface *iface)
+{
+  static gboolean is_initialized = FALSE;
+
+  if (!is_initialized)
+    {
+      GParamSpec *pspec;
+      static const ClutterColor default_color
+        = { 0x0, 0x9c, 0xcf, 0xff };
+
+      is_initialized = TRUE;
+
+      pspec = clutter_param_spec_color ("caret-color",
+                                        "Caret Color",
+                                        "Color of the entry's caret",
+                                        &default_color,
+                                        G_PARAM_READWRITE);
+      st_stylable_iface_install_property (iface, ST_TYPE_ENTRY, pspec);
+
+      pspec = clutter_param_spec_color ("selection-background-color",
+                                        "Selection Background Color",
+                                        "Color of the entry's selection",
+                                        &default_color,
+                                        G_PARAM_READWRITE);
+      st_stylable_iface_install_property (iface, ST_TYPE_ENTRY, pspec);
+    }
+}
+
+static void
+st_entry_style_changed (StWidget *self)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (self);
+  ClutterColor *color = NULL;
+  ClutterColor *caret_color = NULL;
+  ClutterColor *selection_background_color = NULL;
+  gchar *font_name;
+  gchar *font_string;
+  gint font_size;
+
+  st_stylable_get (ST_STYLABLE (self),
+                   "color", &color,
+                   "caret-color", &caret_color,
+                   "selection-background-color", &selection_background_color,
+                   "font-family", &font_name,
+                   "font-size", &font_size,
+                   NULL);
+
+  if (color)
+    {
+      clutter_text_set_color (CLUTTER_TEXT (priv->entry), color);
+      clutter_color_free (color);
+    }
+
+  if (caret_color)
+    {
+      clutter_text_set_cursor_color (CLUTTER_TEXT (priv->entry), caret_color);
+      clutter_color_free (caret_color);
+    }
+
+  if (selection_background_color)
+    {
+      clutter_text_set_selection_color (CLUTTER_TEXT (priv->entry),
+                                        selection_background_color);
+      clutter_color_free (selection_background_color);
+    }
+
+  if (font_name || font_size)
+    {
+      if (font_name && font_size)
+        {
+          font_string = g_strdup_printf ("%s %dpx", font_name, font_size);
+          g_free (font_name);
+        }
+      else
+        {
+          if (font_size)
+            font_string = g_strdup_printf ("%dpx", font_size);
+          else
+            font_string = font_name;
+        }
+
+      clutter_text_set_font_name (CLUTTER_TEXT (priv->entry), font_string);
+      g_free (font_string);
+    }
+}
+
+static void
+st_entry_get_preferred_width (ClutterActor *actor,
+                              gfloat        for_height,
+                              gfloat       *min_width_p,
+                              gfloat       *natural_width_p)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
+  StPadding padding;
+  gfloat icon_w;
+
+  st_widget_get_padding (ST_WIDGET (actor), &padding);
+
+  for_height -= padding.top + padding.bottom;
+
+  clutter_actor_get_preferred_width (priv->entry, for_height,
+                                     min_width_p,
+                                     natural_width_p);
+
+  if (priv->primary_icon)
+    {
+      clutter_actor_get_preferred_width (priv->primary_icon, -1, NULL, &icon_w);
+
+      if (min_width_p)
+        *min_width_p += icon_w + priv->spacing;
+
+      if (natural_width_p)
+        *natural_width_p += icon_w + priv->spacing;
+    }
+
+  if (priv->secondary_icon)
+    {
+      clutter_actor_get_preferred_width (priv->secondary_icon,
+                                         -1, NULL, &icon_w);
+
+      if (min_width_p)
+        *min_width_p += icon_w + priv->spacing;
+
+      if (natural_width_p)
+        *natural_width_p += icon_w + priv->spacing;
+    }
+
+  if (min_width_p)
+    *min_width_p += padding.left + padding.right;
+
+  if (natural_width_p)
+    *natural_width_p += padding.left + padding.right;
+}
+
+static void
+st_entry_get_preferred_height (ClutterActor *actor,
+                               gfloat        for_width,
+                               gfloat       *min_height_p,
+                               gfloat       *natural_height_p)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
+  StPadding padding;
+  gfloat icon_h;
+
+  st_widget_get_padding (ST_WIDGET (actor), &padding);
+
+  for_width -= padding.left + padding.right;
+
+  clutter_actor_get_preferred_height (priv->entry, for_width,
+                                      min_height_p,
+                                      natural_height_p);
+
+  if (priv->primary_icon)
+    {
+      clutter_actor_get_preferred_height (priv->primary_icon,
+                                          -1, NULL, &icon_h);
+
+      if (min_height_p && icon_h > *min_height_p)
+        *min_height_p = icon_h;
+
+      if (natural_height_p && icon_h > *natural_height_p)
+        *natural_height_p = icon_h;
+    }
+
+  if (priv->secondary_icon)
+    {
+      clutter_actor_get_preferred_height (priv->secondary_icon,
+                                          -1, NULL, &icon_h);
+
+      if (min_height_p && icon_h > *min_height_p)
+        *min_height_p = icon_h;
+
+      if (natural_height_p && icon_h > *natural_height_p)
+        *natural_height_p = icon_h;
+    }
+
+  if (min_height_p)
+    *min_height_p += padding.top + padding.bottom;
+
+  if (natural_height_p)
+    *natural_height_p += padding.top + padding.bottom;
+}
+
+static void
+st_entry_allocate (ClutterActor          *actor,
+                   const ClutterActorBox *box,
+                   ClutterAllocationFlags flags)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
+  ClutterActorClass *parent_class;
+  ClutterActorBox child_box, icon_box;
+  StPadding padding;
+  gfloat icon_w, icon_h;
+  gfloat entry_h, min_h, pref_h, avail_h;
+
+  st_widget_get_padding (ST_WIDGET (actor), &padding);
+
+  parent_class = CLUTTER_ACTOR_CLASS (st_entry_parent_class);
+  parent_class->allocate (actor, box, flags);
+
+  avail_h = (box->y2 - box->y1) - padding.top - padding.bottom;
+
+  child_box.x1 = padding.left;
+  child_box.x2 = box->x2 - box->x1 - padding.right;
+
+  if (priv->primary_icon)
+    {
+      clutter_actor_get_preferred_width (priv->primary_icon,
+                                         -1, NULL, &icon_w);
+      clutter_actor_get_preferred_height (priv->primary_icon,
+                                          -1, NULL, &icon_h);
+
+      icon_box.x1 = padding.left;
+      icon_box.x2 = icon_box.x1 + icon_w;
+
+      icon_box.y1 = (int)(padding.top + avail_h / 2 - icon_h / 2);
+      icon_box.y2 = icon_box.y1 + icon_h;
+
+      clutter_actor_allocate (priv->primary_icon,
+                              &icon_box,
+                              flags);
+
+      /* reduce the size for the entry */
+      child_box.x1 += icon_w + priv->spacing;
+    }
+
+  if (priv->secondary_icon)
+    {
+      clutter_actor_get_preferred_width (priv->secondary_icon,
+                                         -1, NULL, &icon_w);
+      clutter_actor_get_preferred_height (priv->secondary_icon,
+                                          -1, NULL, &icon_h);
+
+      icon_box.x2 = (box->x2 - box->x1) - padding.right;
+      icon_box.x1 = icon_box.x2 - icon_w;
+
+      icon_box.y1 = (int)(padding.top + avail_h / 2 - icon_h / 2);
+      icon_box.y2 = icon_box.y1 + icon_h;
+
+      clutter_actor_allocate (priv->secondary_icon,
+                              &icon_box,
+                              flags);
+
+      /* reduce the size for the entry */
+      child_box.x2 -= icon_w - priv->spacing;
+    }
+
+  clutter_actor_get_preferred_height (priv->entry, child_box.x2 - child_box.x1,
+                                      &min_h, &pref_h);
+
+  entry_h = CLAMP (pref_h, min_h, avail_h);
+
+  child_box.y1 = (int)(padding.top + avail_h / 2 - entry_h / 2);
+  child_box.y2 = child_box.y1 + entry_h;
+
+  clutter_actor_allocate (priv->entry, &child_box, flags);
+}
+
+static void
+clutter_text_focus_in_cb (ClutterText  *text,
+                          ClutterActor *actor)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
+
+  /* remove the hint if visible */
+  if (priv->hint
+      && !strcmp (clutter_text_get_text (text), priv->hint))
+    {
+      clutter_text_set_text (text, "");
+    }
+  st_widget_set_style_pseudo_class (ST_WIDGET (actor), "focus");
+  clutter_text_set_cursor_visible (text, TRUE);
+}
+
+static void
+clutter_text_focus_out_cb (ClutterText  *text,
+                           ClutterActor *actor)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
+
+  /* add a hint if the entry is empty */
+  if (priv->hint && !strcmp (clutter_text_get_text (text), ""))
+    {
+      clutter_text_set_text (text, priv->hint);
+      st_widget_set_style_pseudo_class (ST_WIDGET (actor), "indeterminate");
+    }
+  else
+    {
+      st_widget_set_style_pseudo_class (ST_WIDGET (actor), NULL);
+    }
+  clutter_text_set_cursor_visible (text, FALSE);
+}
+
+static void
+st_entry_paint (ClutterActor *actor)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
+  ClutterActorClass *parent_class;
+
+  parent_class = CLUTTER_ACTOR_CLASS (st_entry_parent_class);
+  parent_class->paint (actor);
+
+  clutter_actor_paint (priv->entry);
+
+  if (priv->primary_icon)
+    clutter_actor_paint (priv->primary_icon);
+
+  if (priv->secondary_icon)
+    clutter_actor_paint (priv->secondary_icon);
+}
+
+static void
+st_entry_pick (ClutterActor       *actor,
+               const ClutterColor *c)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
+
+  CLUTTER_ACTOR_CLASS (st_entry_parent_class)->pick (actor, c);
+
+  clutter_actor_paint (priv->entry);
+
+  if (priv->primary_icon)
+    clutter_actor_paint (priv->primary_icon);
+
+  if (priv->secondary_icon)
+    clutter_actor_paint (priv->secondary_icon);
+}
+
+static void
+st_entry_map (ClutterActor *actor)
+{
+  StEntryPrivate *priv = ST_ENTRY (actor)->priv;
+
+  CLUTTER_ACTOR_CLASS (st_entry_parent_class)->map (actor);
+
+  clutter_actor_map (priv->entry);
+
+  if (priv->primary_icon)
+    clutter_actor_map (priv->primary_icon);
+
+  if (priv->secondary_icon)
+    clutter_actor_map (priv->secondary_icon);
+}
+
+static void
+st_entry_unmap (ClutterActor *actor)
+{
+  StEntryPrivate *priv = ST_ENTRY (actor)->priv;
+
+  CLUTTER_ACTOR_CLASS (st_entry_parent_class)->unmap (actor);
+
+  clutter_actor_unmap (priv->entry);
+
+  if (priv->primary_icon)
+    clutter_actor_unmap (priv->primary_icon);
+
+  if (priv->secondary_icon)
+    clutter_actor_unmap (priv->secondary_icon);
+}
+
+static void
+st_entry_clipboard_callback (StClipboard *clipboard,
+                             const gchar *text,
+                             gpointer     data)
+{
+  ClutterText *ctext = (ClutterText*)((StEntry *) data)->priv->entry;
+  gint cursor_pos;
+
+  if (!text)
+    return;
+
+  /* delete the current selection before pasting */
+  clutter_text_delete_selection (ctext);
+
+  /* "paste" the clipboard text into the entry */
+  cursor_pos = clutter_text_get_cursor_position (ctext);
+  clutter_text_insert_text (ctext, text, cursor_pos);
+}
+
+static gboolean
+st_entry_key_press_event (ClutterActor    *actor,
+                          ClutterKeyEvent *event)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
+
+  /* This is expected to handle events that were emitted for the inner
+     ClutterText. They only reach this function if the ClutterText
+     didn't handle them */
+
+  /* paste */
+  if ((event->modifier_state & CLUTTER_CONTROL_MASK)
+      && event->keyval == CLUTTER_v)
+    {
+      StClipboard *clipboard;
+
+      clipboard = st_clipboard_get_default ();
+
+      st_clipboard_get_text (clipboard, st_entry_clipboard_callback, actor);
+
+      return TRUE;
+    }
+
+  /* copy */
+  if ((event->modifier_state & CLUTTER_CONTROL_MASK)
+      && event->keyval == CLUTTER_c)
+    {
+      StClipboard *clipboard;
+      gchar *text;
+
+      clipboard = st_clipboard_get_default ();
+
+      text = clutter_text_get_selection ((ClutterText*) priv->entry);
+
+      if (text && strlen (text))
+        st_clipboard_set_text (clipboard, text);
+
+      return TRUE;
+    }
+
+
+  /* cut */
+  if ((event->modifier_state & CLUTTER_CONTROL_MASK)
+      && event->keyval == CLUTTER_x)
+    {
+      StClipboard *clipboard;
+      gchar *text;
+
+      clipboard = st_clipboard_get_default ();
+
+      text = clutter_text_get_selection ((ClutterText*) priv->entry);
+
+      if (text && strlen (text))
+        {
+          st_clipboard_set_text (clipboard, text);
+
+          /* now delete the text */
+          clutter_text_delete_selection ((ClutterText *) priv->entry);
+        }
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+st_entry_key_focus_in (ClutterActor *actor)
+{
+  StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
+
+  /* We never want key focus. The ClutterText should be given first
+     pass for all key events */
+  clutter_actor_grab_key_focus (priv->entry);
+}
+
+static void
+st_entry_class_init (StEntryClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  GParamSpec *pspec;
+
+  g_type_class_add_private (klass, sizeof (StEntryPrivate));
+
+  gobject_class->set_property = st_entry_set_property;
+  gobject_class->get_property = st_entry_get_property;
+  gobject_class->finalize = st_entry_finalize;
+  gobject_class->dispose = st_entry_dispose;
+
+  actor_class->get_preferred_width = st_entry_get_preferred_width;
+  actor_class->get_preferred_height = st_entry_get_preferred_height;
+  actor_class->allocate = st_entry_allocate;
+  actor_class->paint = st_entry_paint;
+  actor_class->pick = st_entry_pick;
+  actor_class->map = st_entry_map;
+  actor_class->unmap = st_entry_unmap;
+
+  actor_class->key_press_event = st_entry_key_press_event;
+  actor_class->key_focus_in = st_entry_key_focus_in;
+
+  pspec = g_param_spec_string ("text",
+                               "Text",
+                               "Text of the entry",
+                               NULL, G_PARAM_READWRITE);
+  g_object_class_install_property (gobject_class, PROP_ENTRY, pspec);
+
+  pspec = g_param_spec_string ("hint-text",
+                               "Hint Text",
+                               "Text to display when the entry is not focused "
+                               "and the text property is empty",
+                               NULL, G_PARAM_READWRITE);
+  g_object_class_install_property (gobject_class, PROP_ENTRY, pspec);
+
+  /* signals */
+  /**
+   * StEntry::primary-icon-clicked:
+   *
+   * Emitted when the primary icon is clicked
+   */
+  entry_signals[PRIMARY_ICON_CLICKED] =
+    g_signal_new ("primary-icon-clicked",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (StEntryClass, primary_icon_clicked),
+                  NULL, NULL,
+                  _st_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+  /**
+   * StEntry::secondary-icon-clicked:
+   *
+   * Emitted when the secondary icon is clicked
+   */
+  entry_signals[SECONDARY_ICON_CLICKED] =
+    g_signal_new ("secondary-icon-clicked",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (StEntryClass, secondary_icon_clicked),
+                  NULL, NULL,
+                  _st_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+}
+
+static void
+st_entry_init (StEntry *entry)
+{
+  StEntryPrivate *priv;
+
+  priv = entry->priv = ST_ENTRY_GET_PRIVATE (entry);
+
+  priv->entry = g_object_new (CLUTTER_TYPE_IMTEXT,
+                              "line-alignment", PANGO_ALIGN_LEFT,
+                              "editable", TRUE,
+                              "reactive", TRUE,
+                              "single-line-mode", TRUE,
+                              NULL);
+
+  g_signal_connect (priv->entry, "key-focus-in",
+                    G_CALLBACK (clutter_text_focus_in_cb), entry);
+
+  g_signal_connect (priv->entry, "key-focus-out",
+                    G_CALLBACK (clutter_text_focus_out_cb), entry);
+
+  priv->spacing = 6.0f;
+
+  clutter_actor_set_parent (priv->entry, CLUTTER_ACTOR (entry));
+  clutter_actor_set_reactive ((ClutterActor *) entry, TRUE);
+
+  /* set cursor hidden until we receive focus */
+  clutter_text_set_cursor_visible ((ClutterText *) priv->entry, FALSE);
+
+  g_signal_connect (entry, "style-changed",
+                    G_CALLBACK (st_entry_style_changed), NULL);
+}
+
+/**
+ * st_entry_new:
+ * @text: text to set the entry to
+ *
+ * Create a new #StEntry with the specified entry
+ *
+ * Returns: a new #StEntry
+ */
+StWidget *
+st_entry_new (const gchar *text)
+{
+  StWidget *entry;
+
+  /* add the entry to the stage, but don't allow it to be visible */
+  entry = g_object_new (ST_TYPE_ENTRY,
+                        "text", text,
+                        NULL);
+
+  return entry;
+}
+
+/**
+ * st_entry_get_text:
+ * @entry: a #StEntry
+ *
+ * Get the text displayed on the entry
+ *
+ * Returns: the text for the entry. This must not be freed by the application
+ */
+G_CONST_RETURN gchar *
+st_entry_get_text (StEntry *entry)
+{
+  g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
+
+  return clutter_text_get_text (CLUTTER_TEXT (entry->priv->entry));
+}
+
+/**
+ * st_entry_set_text:
+ * @entry: a #StEntry
+ * @text: text to set the entry to
+ *
+ * Sets the text displayed on the entry
+ */
+void
+st_entry_set_text (StEntry     *entry,
+                   const gchar *text)
+{
+  StEntryPrivate *priv;
+
+  g_return_if_fail (ST_IS_ENTRY (entry));
+
+  priv = entry->priv;
+
+  /* set a hint if we are blanking the entry */
+  if (priv->hint
+      && text && !strcmp ("", text)
+      && !HAS_FOCUS (priv->entry))
+    {
+      text = priv->hint;
+      st_widget_set_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
+    }
+  else
+    {
+      if (HAS_FOCUS (priv->entry))
+        st_widget_set_style_pseudo_class (ST_WIDGET (entry), "focus");
+      else
+        st_widget_set_style_pseudo_class (ST_WIDGET (entry), NULL);
+    }
+
+  clutter_text_set_text (CLUTTER_TEXT (priv->entry), text);
+
+  g_object_notify (G_OBJECT (entry), "text");
+}
+
+/**
+ * st_entry_get_clutter_text:
+ * @entry: a #StEntry
+ *
+ * Retrieve the internal #ClutterText so that extra parameters can be set
+ *
+ * Returns: the #ClutterText used by #StEntry. The entry is owned by the
+ * #StEntry and should not be unref'ed by the application.
+ */
+ClutterActor*
+st_entry_get_clutter_text (StEntry *entry)
+{
+  g_return_val_if_fail (ST_ENTRY (entry), NULL);
+
+  return entry->priv->entry;
+}
+
+/**
+ * st_entry_set_hint_text:
+ * @entry: a #StEntry
+ * @text: text to set as the entry hint
+ *
+ * Sets the text to display when the entry is empty and unfocused. When the
+ * entry is displaying the hint, it has a pseudo class of "indeterminate".
+ * A value of NULL unsets the hint.
+ */
+void
+st_entry_set_hint_text (StEntry     *entry,
+                        const gchar *text)
+{
+  StEntryPrivate *priv;
+
+  g_return_if_fail (ST_IS_ENTRY (entry));
+
+  priv = entry->priv;
+
+  g_free (priv->hint);
+
+  priv->hint = g_strdup (text);
+
+  if (!strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), ""))
+    {
+      clutter_text_set_text (CLUTTER_TEXT (priv->entry), priv->hint);
+      st_widget_set_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
+    }
+}
+
+/**
+ * st_entry_get_hint_text:
+ * @entry: a #StEntry
+ *
+ * Gets the text that is displayed when the entry is empty and unfocused
+ *
+ * Returns: the current value of the hint property. This string is owned by the
+ * #StEntry and should not be freed or modified.
+ */
+G_CONST_RETURN
+gchar *
+st_entry_get_hint_text (StEntry *entry)
+{
+  g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
+
+  return entry->priv->hint;
+}
+
+static gboolean
+_st_entry_icon_press_cb (ClutterActor       *actor,
+                         ClutterButtonEvent *event,
+                         StEntry            *entry)
+{
+  StEntryPrivate *priv = entry->priv;
+
+  if (actor == priv->primary_icon)
+    g_signal_emit (entry, entry_signals[PRIMARY_ICON_CLICKED], 0);
+  else
+    g_signal_emit (entry, entry_signals[SECONDARY_ICON_CLICKED], 0);
+
+  return FALSE;
+}
+
+static void
+_st_entry_set_icon_from_file (StEntry       *entry,
+                              ClutterActor **icon,
+                              const gchar   *filename)
+{
+  if (*icon)
+    {
+      g_signal_handlers_disconnect_by_func (*icon,
+                                            _st_entry_icon_press_cb,
+                                            entry);
+      clutter_actor_unparent (*icon);
+      *icon = NULL;
+    }
+
+  if (filename)
+    {
+      StTextureCache *cache;
+
+      cache = st_texture_cache_get_default ();
+
+
+
+      *icon = (ClutterActor*) st_texture_cache_get_texture (cache, filename);
+
+      clutter_actor_set_reactive (*icon, TRUE);
+      clutter_actor_set_parent (*icon, CLUTTER_ACTOR (entry));
+      g_signal_connect (*icon, "button-release-event",
+                        G_CALLBACK (_st_entry_icon_press_cb), entry);
+    }
+
+  clutter_actor_queue_relayout (CLUTTER_ACTOR (entry));
+}
+
+/**
+ * st_entry_set_primary_icon_from_file:
+ * @entry: a #StEntry
+ * @filename: filename of an icon
+ *
+ * Set the primary icon of the entry to the given filename
+ */
+void
+st_entry_set_primary_icon_from_file (StEntry     *entry,
+                                     const gchar *filename)
+{
+  StEntryPrivate *priv;
+
+  g_return_if_fail (ST_IS_ENTRY (entry));
+
+  priv = entry->priv;
+
+  _st_entry_set_icon_from_file (entry, &priv->primary_icon, filename);
+
+}
+
+/**
+ * st_entry_set_secondary_icon_from_file:
+ * @entry: a #StEntry
+ * @filename: filename of an icon
+ *
+ * Set the primary icon of the entry to the given filename
+ */
+void
+st_entry_set_secondary_icon_from_file (StEntry     *entry,
+                                       const gchar *filename)
+{
+  StEntryPrivate *priv;
+
+  g_return_if_fail (ST_IS_ENTRY (entry));
+
+  priv = entry->priv;
+
+  _st_entry_set_icon_from_file (entry, &priv->secondary_icon, filename);
+
+}
+
diff --git a/src/st/st-entry.h b/src/st/st-entry.h
new file mode 100644
index 0000000..5f9ff18
--- /dev/null
+++ b/src/st/st-entry.h
@@ -0,0 +1,88 @@
+/*
+ * st-entry.h: Plain entry actor
+ *
+ * Copyright 2008, 2009 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * Boston, MA 02111-1307, USA.
+ *
+ * Written by: Thomas Wood <thomas linux intel com>
+ *
+ */
+
+#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
+#error "Only <st/st.h> can be included directly.h"
+#endif
+
+#ifndef __ST_ENTRY_H__
+#define __ST_ENTRY_H__
+
+G_BEGIN_DECLS
+
+#include <st/st-widget.h>
+
+#define ST_TYPE_ENTRY                (st_entry_get_type ())
+#define ST_ENTRY(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_ENTRY, StEntry))
+#define ST_IS_ENTRY(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_ENTRY))
+#define ST_ENTRY_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_ENTRY, StEntryClass))
+#define ST_IS_ENTRY_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_ENTRY))
+#define ST_ENTRY_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_ENTRY, StEntryClass))
+
+typedef struct _StEntry              StEntry;
+typedef struct _StEntryPrivate       StEntryPrivate;
+typedef struct _StEntryClass         StEntryClass;
+
+/**
+ * StEntry:
+ *
+ * The contents of this structure is private and should only be accessed using
+ * the provided API.
+ */
+struct _StEntry
+{
+  /*< private >*/
+  StWidget parent_instance;
+
+  StEntryPrivate *priv;
+};
+
+struct _StEntryClass
+{
+  StWidgetClass parent_class;
+
+  /* signals */
+  void (*primary_icon_clicked)   (StEntry *entry);
+  void (*secondary_icon_clicked) (StEntry *entry);
+};
+
+GType st_entry_get_type (void) G_GNUC_CONST;
+
+StWidget *            st_entry_new              (const gchar *text);
+G_CONST_RETURN gchar *st_entry_get_text         (StEntry     *entry);
+void                  st_entry_set_text         (StEntry     *entry,
+                                                 const gchar *text);
+ClutterActor*         st_entry_get_clutter_text (StEntry     *entry);
+
+void                  st_entry_set_hint_text    (StEntry     *entry,
+                                                 const gchar *text);
+G_CONST_RETURN gchar *st_entry_get_hint_text    (StEntry     *entry);
+
+void st_entry_set_primary_icon_from_file   (StEntry     *entry,
+                                            const gchar *filename);
+void st_entry_set_secondary_icon_from_file (StEntry     *entry,
+                                            const gchar *filename);
+
+G_END_DECLS
+
+#endif /* __ST_ENTRY_H__ */
diff --git a/src/st/st-label.c b/src/st/st-label.c
new file mode 100644
index 0000000..bcfcac6
--- /dev/null
+++ b/src/st/st-label.c
@@ -0,0 +1,363 @@
+/*
+ * st-label.c: Plain label actor
+ *
+ * Copyright 2008,2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by: Thomas Wood <thomas linux intel com>
+ *
+ */
+
+/**
+ * SECTION:st-label
+ * @short_description: Widget for displaying text
+ *
+ * #StLabel is a simple widget for displaying text. It derives from
+ * #StWidget to add extra style and placement functionality over
+ * #ClutterText. The internal #ClutterText is publicly accessibly to allow
+ * applications to set further properties.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <clutter/clutter.h>
+
+#include "st-label.h"
+
+#include "st-widget.h"
+#include "st-stylable.h"
+
+enum
+{
+  PROP_0,
+
+  PROP_LABEL
+};
+
+#define ST_LABEL_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_LABEL, StLabelPrivate))
+
+struct _StLabelPrivate
+{
+  ClutterActor *label;
+};
+
+G_DEFINE_TYPE (StLabel, st_label, ST_TYPE_WIDGET);
+
+static void
+st_label_set_property (GObject      *gobject,
+                       guint         prop_id,
+                       const GValue *value,
+                       GParamSpec   *pspec)
+{
+  StLabel *label = ST_LABEL (gobject);
+
+  switch (prop_id)
+    {
+    case PROP_LABEL:
+      st_label_set_text (label, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+st_label_get_property (GObject    *gobject,
+                       guint       prop_id,
+                       GValue     *value,
+                       GParamSpec *pspec)
+{
+  StLabelPrivate *priv = ST_LABEL (gobject)->priv;
+
+  switch (prop_id)
+    {
+    case PROP_LABEL:
+      g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->label)));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+st_label_style_changed (StWidget *self)
+{
+  StLabelPrivate *priv = ST_LABEL (self)->priv;
+  ClutterColor *color = NULL;
+  gchar *font_name;
+  gchar *font_string;
+  gint font_size;
+
+  st_stylable_get (ST_STYLABLE (self),
+                   "color", &color,
+                   "font-family", &font_name,
+                   "font-size", &font_size,
+                   NULL);
+
+  if (color)
+    {
+      clutter_text_set_color (CLUTTER_TEXT (priv->label), color);
+      clutter_color_free (color);
+    }
+
+  if (font_name || font_size)
+    {
+      if (font_name && font_size)
+        {
+          font_string = g_strdup_printf ("%s %dpx", font_name, font_size);
+          g_free (font_name);
+        }
+      else
+        {
+          if (font_size)
+            font_string = g_strdup_printf ("%dpx", font_size);
+          else
+            font_string = font_name;
+        }
+
+      clutter_text_set_font_name (CLUTTER_TEXT (priv->label), font_string);
+      g_free (font_string);
+    }
+
+}
+
+static void
+st_label_get_preferred_width (ClutterActor *actor,
+                              gfloat        for_height,
+                              gfloat       *min_width_p,
+                              gfloat       *natural_width_p)
+{
+  StLabelPrivate *priv = ST_LABEL (actor)->priv;
+  StPadding padding = { 0, };
+
+  st_widget_get_padding (ST_WIDGET (actor), &padding);
+
+  clutter_actor_get_preferred_width (priv->label, for_height,
+                                     min_width_p,
+                                     natural_width_p);
+
+  if (min_width_p)
+    *min_width_p += padding.left + padding.right;
+
+  if (natural_width_p)
+    *natural_width_p += padding.left + padding.right;
+}
+
+static void
+st_label_get_preferred_height (ClutterActor *actor,
+                               gfloat        for_width,
+                               gfloat       *min_height_p,
+                               gfloat       *natural_height_p)
+{
+  StLabelPrivate *priv = ST_LABEL (actor)->priv;
+  StPadding padding = { 0, };
+
+  st_widget_get_padding (ST_WIDGET (actor), &padding);
+
+  clutter_actor_get_preferred_height (priv->label, for_width,
+                                      min_height_p,
+                                      natural_height_p);
+
+  if (min_height_p)
+    *min_height_p += padding.top + padding.bottom;
+
+  if (natural_height_p)
+    *natural_height_p += padding.top + padding.bottom;
+}
+
+static void
+st_label_allocate (ClutterActor          *actor,
+                   const ClutterActorBox *box,
+                   ClutterAllocationFlags flags)
+{
+  StLabelPrivate *priv = ST_LABEL (actor)->priv;
+  ClutterActorClass *parent_class;
+  ClutterActorBox child_box;
+  StPadding padding = { 0, };
+
+  st_widget_get_padding (ST_WIDGET (actor), &padding);
+
+  parent_class = CLUTTER_ACTOR_CLASS (st_label_parent_class);
+  parent_class->allocate (actor, box, flags);
+
+  child_box.x1 = padding.left;
+  child_box.y1 = padding.top;
+  child_box.x2 = box->x2 - box->x1 - padding.right;
+  child_box.y2 = box->y2 - box->y1 - padding.bottom;
+
+  clutter_actor_allocate (priv->label, &child_box, flags);
+}
+
+static void
+st_label_paint (ClutterActor *actor)
+{
+  StLabelPrivate *priv = ST_LABEL (actor)->priv;
+  ClutterActorClass *parent_class;
+
+  parent_class = CLUTTER_ACTOR_CLASS (st_label_parent_class);
+  parent_class->paint (actor);
+
+  clutter_actor_paint (priv->label);
+}
+
+static void
+st_label_map (ClutterActor *actor)
+{
+  StLabelPrivate *priv = ST_LABEL (actor)->priv;
+
+  CLUTTER_ACTOR_CLASS (st_label_parent_class)->map (actor);
+
+  clutter_actor_map (priv->label);
+}
+
+static void
+st_label_unmap (ClutterActor *actor)
+{
+  StLabelPrivate *priv = ST_LABEL (actor)->priv;
+
+  CLUTTER_ACTOR_CLASS (st_label_parent_class)->unmap (actor);
+
+  clutter_actor_unmap (priv->label);
+}
+
+static void
+st_label_class_init (StLabelClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  GParamSpec *pspec;
+
+  g_type_class_add_private (klass, sizeof (StLabelPrivate));
+
+  gobject_class->set_property = st_label_set_property;
+  gobject_class->get_property = st_label_get_property;
+
+  actor_class->paint = st_label_paint;
+  actor_class->allocate = st_label_allocate;
+  actor_class->get_preferred_width = st_label_get_preferred_width;
+  actor_class->get_preferred_height = st_label_get_preferred_height;
+  actor_class->map = st_label_map;
+  actor_class->unmap = st_label_unmap;
+
+  pspec = g_param_spec_string ("text",
+                               "Text",
+                               "Text of the label",
+                               NULL, G_PARAM_READWRITE);
+  g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
+
+}
+
+static void
+st_label_init (StLabel *label)
+{
+  StLabelPrivate *priv;
+
+  label->priv = priv = ST_LABEL_GET_PRIVATE (label);
+
+  label->priv->label = g_object_new (CLUTTER_TYPE_TEXT,
+                                     "ellipsize", PANGO_ELLIPSIZE_END,
+                                     NULL);
+
+  clutter_actor_set_parent (priv->label, CLUTTER_ACTOR (label));
+
+  g_signal_connect (label, "style-changed",
+                    G_CALLBACK (st_label_style_changed), NULL);
+}
+
+/**
+ * st_label_new:
+ * @text: text to set the label to
+ *
+ * Create a new #StLabel with the specified label
+ *
+ * Returns: a new #StLabel
+ */
+StWidget *
+st_label_new (const gchar *text)
+{
+  if (text == NULL || *text == '\0')
+    return g_object_new (ST_TYPE_LABEL, NULL);
+  else
+    return g_object_new (ST_TYPE_LABEL,
+                         "text", text,
+                         NULL);
+}
+
+/**
+ * st_label_get_text:
+ * @label: a #StLabel
+ *
+ * Get the text displayed on the label
+ *
+ * Returns: the text for the label. This must not be freed by the application
+ */
+G_CONST_RETURN gchar *
+st_label_get_text (StLabel *label)
+{
+  g_return_val_if_fail (ST_IS_LABEL (label), NULL);
+
+  return clutter_text_get_text (CLUTTER_TEXT (label->priv->label));
+}
+
+/**
+ * st_label_set_text:
+ * @label: a #StLabel
+ * @text: text to set the label to
+ *
+ * Sets the text displayed on the label
+ */
+void
+st_label_set_text (StLabel     *label,
+                   const gchar *text)
+{
+  StLabelPrivate *priv;
+
+  g_return_if_fail (ST_IS_LABEL (label));
+  g_return_if_fail (text != NULL);
+
+  priv = label->priv;
+
+  clutter_text_set_text (CLUTTER_TEXT (priv->label), text);
+
+  g_object_notify (G_OBJECT (label), "text");
+}
+
+/**
+ * st_label_get_clutter_text:
+ * @label: a #StLabel
+ *
+ * Retrieve the internal #ClutterText so that extra parameters can be set
+ *
+ * Returns: the #ClutterText used by #StLabel. The label is owned by the
+ * #StLabel and should not be unref'ed by the application.
+ */
+ClutterActor*
+st_label_get_clutter_text (StLabel *label)
+{
+  g_return_val_if_fail (ST_LABEL (label), NULL);
+
+  return label->priv->label;
+}
diff --git a/src/st/st-label.h b/src/st/st-label.h
new file mode 100644
index 0000000..fe9985a
--- /dev/null
+++ b/src/st/st-label.h
@@ -0,0 +1,75 @@
+/*
+ * st-label.h: Plain label actor
+ *
+ * Copyright 2008, 2009 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * Boston, MA 02111-1307, USA.
+ *
+ * Written by: Thomas Wood <thomas linux intel com>
+ *
+ */
+
+#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
+#error "Only <st/st.h> can be included directly.h"
+#endif
+
+#ifndef __ST_LABEL_H__
+#define __ST_LABEL_H__
+
+G_BEGIN_DECLS
+
+#include <st/st-widget.h>
+
+#define ST_TYPE_LABEL                (st_label_get_type ())
+#define ST_LABEL(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_LABEL, StLabel))
+#define ST_IS_LABEL(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_LABEL))
+#define ST_LABEL_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_LABEL, StLabelClass))
+#define ST_IS_LABEL_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_LABEL))
+#define ST_LABEL_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_LABEL, StLabelClass))
+
+typedef struct _StLabel              StLabel;
+typedef struct _StLabelPrivate       StLabelPrivate;
+typedef struct _StLabelClass         StLabelClass;
+
+/**
+ * StLabel:
+ *
+ * The contents of this structure is private and should only be accessed using
+ * the provided API.
+ */
+struct _StLabel
+{
+  /*< private >*/
+  StWidget parent_instance;
+
+  StLabelPrivate *priv;
+};
+
+struct _StLabelClass
+{
+  StWidgetClass parent_class;
+};
+
+GType st_label_get_type (void) G_GNUC_CONST;
+
+StWidget *            st_label_new              (const gchar *text);
+G_CONST_RETURN gchar *st_label_get_text         (StLabel     *label);
+void                  st_label_set_text         (StLabel     *label,
+                                                 const gchar *text);
+ClutterActor *        st_label_get_clutter_text (StLabel     *label);
+
+G_END_DECLS
+
+#endif /* __ST_LABEL_H__ */
diff --git a/tools/build/gnome-shell.modules b/tools/build/gnome-shell.modules
index 095bc9d..6395eb5 100644
--- a/tools/build/gnome-shell.modules
+++ b/tools/build/gnome-shell.modules
@@ -7,6 +7,8 @@
       href="git://git.clutter-project.org/"/>
   <repository type="git" name="git.gnome.org"
       href="git://git.gnome.org/"/>
+  <repository type="git" name="git.moblin.org"
+      href="git://git.moblin.org"/>
 
   <autotools id="gobject-introspection">
     <branch repo="git.gnome.org" module="gobject-introspection"/>
@@ -36,6 +38,13 @@
     </dependencies>
   </autotools>
 
+  <autotools id="clutter-imcontext">
+    <branch repo="git.moblin.org" module="clutter-imcontext"/>
+    <dependencies>
+        <dep package="clutter"/>
+    </dependencies>
+  </autotools>
+
   <autotools id="gconf" autogenargs="--disable-defaults-service">
     <branch repo="git.gnome.org" module="gconf"/>
   </autotools>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]