Back to index

unity  6.0.0
Classes | Defines | Enumerations | Functions | Variables
panel-service.c File Reference
#include "panel-marshal.h"
#include "panel-service.h"
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gconf/gconf-client.h>
#include <X11/extensions/XInput2.h>
#include <X11/XKBlib.h>

Go to the source code of this file.

Classes

struct  _PanelServicePrivate

Defines

#define GET_PRIVATE(o)   (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_SERVICE, PanelServicePrivate))
#define NOTIFY_TIMEOUT   80
#define N_TIMEOUT_SLOTS   50
#define MAX_INDICATOR_ENTRIES   50
#define COMPIZ_OPTIONS_PATH   "/apps/compiz-1/plugins/unityshell/screen0/options"
#define MENU_TOGGLE_KEYBINDING_PATH   COMPIZ_OPTIONS_PATH"/panel_first_menu"

Enumerations

enum  {
  ENTRY_ACTIVATED = 0, RE_SYNC, ENTRY_ACTIVATE_REQUEST, ENTRY_SHOW_NOW_CHANGED,
  GEOMETRIES_CHANGED, INDICATORS_CLEARED, LAST_SIGNAL
}
enum  { SYNC_WAITING = -1, SYNC_NEUTRAL = 0 }

Functions

 G_DEFINE_TYPE (PanelService, panel_service, G_TYPE_OBJECT)
static void load_indicator (PanelService *self, IndicatorObject *object, const gchar *_name)
static void load_indicators (PanelService *self)
static void sort_indicators (PanelService *self)
static void notify_object (IndicatorObject *object)
static GdkFilterReturn event_filter (GdkXEvent *ev, GdkEvent *gev, PanelService *self)
static void panel_service_class_dispose (GObject *object)
static void panel_service_class_finalize (GObject *object)
static void panel_service_class_init (PanelServiceClass *klass)
static IndicatorObjectEntry * get_entry_at (PanelService *self, gint x, gint y)
static IndicatorObject * get_entry_parent_indicator (IndicatorObjectEntry *entry)
static gchar * get_indicator_entry_id_by_entry (IndicatorObjectEntry *entry)
static IndicatorObjectEntry * get_indicator_entry_by_id (PanelService *self, const gchar *entry_id)
static gboolean initial_resync (PanelService *self)
static void panel_service_update_menu_keybinding (PanelService *self)
void on_keybinding_changed (GConfClient *client, guint id, GConfEntry *entry, gpointer data)
static void panel_service_init (PanelService *self)
static gboolean panel_service_check_cleared (PanelService *self)
static void panel_service_actually_remove_indicator (PanelService *self, IndicatorObject *indicator)
static gboolean panel_service_indicator_remove_timeout (IndicatorObject *indicator)
PanelService * panel_service_get_default ()
PanelService * panel_service_get_default_with_indicators (GList *indicators)
guint panel_service_get_n_indicators (PanelService *self)
IndicatorObject * panel_service_get_indicator_nth (PanelService *self, guint position)
IndicatorObject * panel_service_get_indicator (PanelService *self, const gchar *indicator_id)
void panel_service_remove_indicator (PanelService *self, IndicatorObject *indicator)
void panel_service_clear_indicators (PanelService *self)
static gboolean actually_notify_object (IndicatorObject *object)
static void on_entry_property_changed (GObject *o, GParamSpec *pspec, IndicatorObject *object)
static void on_entry_changed (GObject *o, IndicatorObject *object)
static void on_entry_added (IndicatorObject *object, IndicatorObjectEntry *entry, PanelService *self)
static void on_entry_removed (IndicatorObject *object, IndicatorObjectEntry *entry, PanelService *self)
static void on_entry_moved (IndicatorObject *object, IndicatorObjectEntry *entry, PanelService *self)
static void on_indicator_menu_show (IndicatorObject *object, IndicatorObjectEntry *entry, guint32 timestamp, PanelService *self)
static void on_indicator_menu_show_now_changed (IndicatorObject *object, IndicatorObjectEntry *entry, gboolean show_now_changed, PanelService *self)
static gint name2order (const gchar *name, const gchar *hint)
static gint name2priority (const gchar *name, const gchar *hint)
static int indicator_compare_func (IndicatorObject *o1, IndicatorObject *o2)
static gchar * gtk_image_to_data (GtkImage *image)
static void indicator_entry_to_variant (IndicatorObjectEntry *entry, const gchar *id, const gchar *indicator_id, GVariantBuilder *b, gint prio)
static void indicator_entry_null_to_variant (const gchar *indicator_id, GVariantBuilder *b)
static void indicator_object_to_variant (IndicatorObject *object, const gchar *indicator_id, GVariantBuilder *b)
static void positon_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push, gpointer user_data)
static void on_active_menu_hidden (GtkMenu *menu, PanelService *self)
GVariant * panel_service_sync (PanelService *self)
GVariant * panel_service_sync_one (PanelService *self, const gchar *indicator_id)
void panel_service_sync_geometry (PanelService *self, const gchar *panel_id, const gchar *entry_id, gint x, gint y, gint width, gint height)
static gboolean panel_service_entry_is_visible (PanelService *self, IndicatorObjectEntry *entry)
static int indicator_entry_compare_func (gpointer *v1, gpointer *v2)
static void activate_next_prev_menu (PanelService *self, IndicatorObject *object, IndicatorObjectEntry *entry, GtkMenuDirectionType direction)
static void on_active_menu_move_current (GtkMenu *menu, GtkMenuDirectionType direction, PanelService *self)
static void menu_deactivated (GtkWidget *menu)
static void panel_service_show_entry_common (PanelService *self, IndicatorObject *object, IndicatorObjectEntry *entry, guint32 xid, gint32 x, gint32 y, guint32 button, guint32 timestamp)
void panel_service_show_entry (PanelService *self, const gchar *entry_id, guint32 xid, gint32 x, gint32 y, guint32 button, guint32 timestamp)
void panel_service_show_app_menu (PanelService *self, guint32 xid, gint32 x, gint32 y, guint32 timestamp)
void panel_service_secondary_activate_entry (PanelService *self, const gchar *entry_id, guint32 timestamp)
void panel_service_scroll_entry (PanelService *self, const gchar *entry_id, gint32 delta)

Variables

static PanelService * static_service = NULL
static gboolean suppress_signals = FALSE
static guint32 _service_signals [LAST_SIGNAL] = { 0 }
static const gchar * indicator_order [][2]
static const gchar * indicator_environment []

Class Documentation

struct _PanelServicePrivate

Definition at line 54 of file panel-service.c.

Class Members
GHashTable * id2entry_hash
GSList * indicators
guint initial_sync_id
guint32 key_monitor_id
gint last_bottom
IndicatorObjectEntry * last_entry
gint last_left
GtkMenu * last_menu
guint32 last_menu_button
guint32 last_menu_id
guint32 last_menu_move_id
gint last_right
gint last_top
gint32 last_x
gint32 last_y
GtkWidget * menubar
GtkWidget * offscreen_window
GHashTable * panel2entries_hash
IndicatorObjectEntry * pressed_entry
gint32 timeouts
KeyCode toggle_key
guint32 toggle_modifiers
gboolean use_event

Define Documentation

#define COMPIZ_OPTIONS_PATH   "/apps/compiz-1/plugins/unityshell/screen0/options"

Definition at line 49 of file panel-service.c.

#define GET_PRIVATE (   o)    (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_SERVICE, PanelServicePrivate))

Definition at line 42 of file panel-service.c.

#define MAX_INDICATOR_ENTRIES   50

Definition at line 47 of file panel-service.c.

#define MENU_TOGGLE_KEYBINDING_PATH   COMPIZ_OPTIONS_PATH"/panel_first_menu"

Definition at line 50 of file panel-service.c.

#define N_TIMEOUT_SLOTS   50

Definition at line 46 of file panel-service.c.

#define NOTIFY_TIMEOUT   80

Definition at line 45 of file panel-service.c.


Enumeration Type Documentation

anonymous enum
Enumerator:
ENTRY_ACTIVATED 
RE_SYNC 
ENTRY_ACTIVATE_REQUEST 
ENTRY_SHOW_NOW_CHANGED 
GEOMETRIES_CHANGED 
INDICATORS_CLEARED 
LAST_SIGNAL 

Definition at line 88 of file panel-service.c.

anonymous enum
Enumerator:
SYNC_WAITING 
SYNC_NEUTRAL 

Definition at line 100 of file panel-service.c.

{
  SYNC_WAITING = -1,
  SYNC_NEUTRAL = 0,
};

Function Documentation

static void activate_next_prev_menu ( PanelService *  self,
IndicatorObject *  object,
IndicatorObjectEntry *  entry,
GtkMenuDirectionType  direction 
) [static]

Definition at line 1500 of file panel-service.c.

{
  IndicatorObjectEntry *new_entry;
  PanelServicePrivate *priv = self->priv;
  GSList *indicators = priv->indicators;
  GList  *ordered_entries = NULL;
  GList  *entries;
  gchar  *id;
  GSList *l;
  GList *ll;

  for (l = indicators; l; l = l->next)
    {
      const gchar *indicator_id = g_object_get_data (G_OBJECT (l->data), "id");
      gint parent_priority = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (l->data), "priority"));
      entries = indicator_object_get_entries (l->data);
      if (entries)
        {
          int index = 0;

          for (ll = entries; ll; ll = ll->next)
            {
              gint prio = -1;
              new_entry = ll->data;

              if (!panel_service_entry_is_visible (self, new_entry))
                continue;

              if (new_entry->name_hint)
                {
                  prio = name2priority(indicator_id, new_entry->name_hint);
                }

              if (prio == -1)
                {
                  prio = parent_priority + index;
                  index++;
                }

              gpointer *values = g_new (gpointer, 2);
              values[0] = new_entry;
              values[1] = GINT_TO_POINTER (prio);
              ordered_entries = g_list_insert_sorted (ordered_entries, values,
                                                      (GCompareFunc) indicator_entry_compare_func);
            }

          g_list_free (entries);
        }
    }

  new_entry = NULL;
  for (ll = ordered_entries; ll; ll = ll->next)
    {
      gpointer *values = ll->data;
      if (entry == values[0])
        {
          if (direction == GTK_MENU_DIR_CHILD)
            {
              values = ll->next ? ll->next->data : ordered_entries->data;
            }
          else
            {
              values = ll->prev ? ll->prev->data : g_list_last(ordered_entries)->data;
            }

          new_entry = values[0];
          break;
        }
    }

  if (new_entry)
    {
      id = get_indicator_entry_id_by_entry (new_entry);
      g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, id);
      g_free (id);
    }

  g_list_free_full (ordered_entries, g_free);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean actually_notify_object ( IndicatorObject *  object) [static]

Definition at line 748 of file panel-service.c.

{
  PanelService *self;
  PanelServicePrivate *priv;
  gint position;

  if (!PANEL_IS_SERVICE (static_service))
    return FALSE;

  if (!INDICATOR_IS_OBJECT (object))
    return FALSE;

  self = panel_service_get_default ();
  priv = self->priv;

  position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (object), "position"));
  priv->timeouts[position] = SYNC_WAITING;

  if (!suppress_signals)
    g_signal_emit (self, _service_signals[RE_SYNC],
                   0, g_object_get_data (G_OBJECT (object), "id"));

  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static GdkFilterReturn event_filter ( GdkXEvent *  ev,
GdkEvent *  gev,
PanelService *  self 
) [static]

Definition at line 351 of file panel-service.c.

{
  PanelServicePrivate *priv = self->priv;
  XEvent *e = (XEvent *)ev;
  GdkFilterReturn ret = GDK_FILTER_CONTINUE;

  if (!PANEL_IS_SERVICE (self))
  {
    g_warning ("%s: Invalid PanelService instance", G_STRLOC);
    return ret;
  }

  if (!GTK_IS_WIDGET (self->priv->last_menu))
    return ret;

  /* Use XI2 to read the event data */
  XGenericEventCookie *cookie = &e->xcookie;
  if (cookie->type == GenericEvent)
    {
      XIDeviceEvent *event = cookie->data;
      if (!event)
        return ret;

      if (event->evtype == XI_KeyPress)
        {
          if (event->mods.base == priv->toggle_modifiers && event->detail == priv->toggle_key)
          {
            if (GTK_IS_MENU (priv->last_menu))
              gtk_menu_popdown (GTK_MENU (priv->last_menu));
          }
        }

      if (event->evtype == XI_ButtonPress)
        {
          priv->pressed_entry = get_entry_at (self, event->root_x, event->root_y);
          priv->use_event = (priv->pressed_entry == NULL);

          if (priv->pressed_entry)
            ret = GDK_FILTER_REMOVE;
        }

      if (event->evtype == XI_ButtonRelease)
        {
          IndicatorObjectEntry *entry;
          gboolean event_is_a_click = FALSE;
          entry = get_entry_at (self, event->root_x, event->root_y);

          if (event->detail == 1 || event->detail == 3)
            {
              /* Consider only right and left clicks over the indicators entries */
              event_is_a_click = TRUE;
            }
          else if (entry && event->detail == 2)
            {
              /* Middle clicks over an appmenu entry are considered just like
               * all other clicks */
              IndicatorObject *obj = get_entry_parent_indicator (entry);

              if (g_strcmp0 (g_object_get_data (G_OBJECT (obj), "id"), "libappmenu.so") == 0)
                {
                  event_is_a_click = TRUE;
                }
            }

          if (event_is_a_click)
            {
              if (priv->use_event)
                {
                  priv->use_event = FALSE;
                }
              else
                {
                  if (entry)
                    {
                      if (entry != priv->pressed_entry)
                        {
                          ret = GDK_FILTER_REMOVE;
                          priv->use_event = TRUE;
                        }
                      else if (priv->last_entry && entry != priv->last_entry)
                        {
                          /* If we were navigating over indicators using the keyboard
                           * and now we click over the indicator under the mouse, we
                           * must force it to show back again, not make it close */
                          gchar *entry_id = get_indicator_entry_id_by_entry (entry);
                          g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, entry_id);
                          g_free (entry_id);
                        }
                    }
                }
            }
          else if (entry && (event->detail == 2 || event->detail == 4 || event->detail == 5))
            {
              /* If we're scrolling or middle-clicking over an indicator
               * (which is not an appmenu entry) then we need to send the
               * event to the indicator itself, and avoid it to close */
              gchar *entry_id = get_indicator_entry_id_by_entry (entry);

              if (event->detail == 4 || event->detail == 5)
                {
                  gint32 delta = (event->detail == 4) ? 120 : -120;
                  panel_service_scroll_entry (self, entry_id, delta);
                }
              else if (entry == priv->pressed_entry)
                {
                  panel_service_secondary_activate_entry (self, entry_id, time(NULL));
                }

              ret = GDK_FILTER_REMOVE;
              g_free (entry_id);
            }
        }
    }

  return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

G_DEFINE_TYPE ( PanelService  ,
panel_service  ,
G_TYPE_OBJECT   
)
static IndicatorObjectEntry* get_entry_at ( PanelService *  self,
gint  x,
gint  y 
) [static]

Definition at line 275 of file panel-service.c.

{
  GHashTableIter panel_iter, entries_iter;
  gpointer key, value, k, v;

  g_hash_table_iter_init (&panel_iter, self->priv->panel2entries_hash);
  while (g_hash_table_iter_next (&panel_iter, &key, &value))
    {
      GHashTable *entry2geometry_hash = value;
      g_hash_table_iter_init (&entries_iter, entry2geometry_hash);

      while (g_hash_table_iter_next (&entries_iter, &k, &v))
        {
          IndicatorObjectEntry *entry = k;
          GdkRectangle *geo = v;

          if (x >= geo->x && x <= (geo->x + geo->width) &&
              y >= geo->y && y <= (geo->y + geo->height))
            {
              return entry;
            }
        }
    }

  return NULL;
}

Here is the caller graph for this function:

static IndicatorObject* get_entry_parent_indicator ( IndicatorObjectEntry *  entry) [static]

Definition at line 303 of file panel-service.c.

{
  if (!entry || !INDICATOR_IS_OBJECT (entry->parent_object))
    return NULL;

  return INDICATOR_OBJECT (entry->parent_object);
}

Here is the caller graph for this function:

static IndicatorObjectEntry* get_indicator_entry_by_id ( PanelService *  self,
const gchar *  entry_id 
) [static]

Definition at line 323 of file panel-service.c.

{
  IndicatorObjectEntry *entry;

  entry = g_hash_table_lookup (self->priv->id2entry_hash, entry_id);

  if (entry)
    {
      if (g_slist_find (self->priv->indicators, entry->parent_object))
        {
          if (!INDICATOR_IS_OBJECT (entry->parent_object))
            entry = NULL;
        }
      else
        {
          entry = NULL;
        }

      if (!entry)
        {
          g_warning("The entry id '%s' you're trying to lookup is not a valid IndicatorObjectEntry!", entry_id);
        }
    }

  return entry;
}

Here is the caller graph for this function:

static gchar* get_indicator_entry_id_by_entry ( IndicatorObjectEntry *  entry) [static]

Definition at line 312 of file panel-service.c.

{
  gchar *entry_id = NULL;

  if (entry)
    entry_id = g_strdup_printf ("%p", entry);

  return entry_id;
}

Here is the caller graph for this function:

static gchar* gtk_image_to_data ( GtkImage *  image) [static]

Definition at line 1091 of file panel-service.c.

{
  GtkImageType type = gtk_image_get_storage_type (image);
  gchar *ret = NULL;

  if (type == GTK_IMAGE_PIXBUF)
    {
      GdkPixbuf  *pixbuf;
      gchar      *buffer = NULL;
      gsize       buffer_size = 0;
      GError     *error = NULL;

      pixbuf = gtk_image_get_pixbuf (image);

      if (gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &buffer_size, "png", &error, NULL))
        {
          ret = g_base64_encode ((const guchar *)buffer, buffer_size);
          g_free (buffer);
        }
      else
        {
          g_warning ("Unable to convert pixbuf to png data: '%s'", error ? error->message : "unknown");
          if (error)
            g_error_free (error);

          ret = g_strdup ("");
        }
    }
  else if (type == GTK_IMAGE_STOCK)
    {
      g_object_get (G_OBJECT (image), "stock", &ret, NULL);
    }
  else if (type == GTK_IMAGE_ICON_NAME)
    {
      g_object_get (G_OBJECT (image), "icon-name", &ret, NULL);
    }
  else if (type == GTK_IMAGE_GICON)
    {
      GIcon *icon = NULL;
      gtk_image_get_gicon (image, &icon, NULL);
      if (G_IS_ICON (icon))
        {
          ret = g_icon_to_string (icon);
        }
    }
  else
    {
      ret = g_strdup ("");
      g_warning ("Unable to support GtkImageType: %d", type);
    }

  return ret;
}

Here is the caller graph for this function:

static int indicator_compare_func ( IndicatorObject *  o1,
IndicatorObject *  o2 
) [static]

Definition at line 1053 of file panel-service.c.

{
  gchar *s1;
  gchar *s2;
  int    i1;
  int    i2;

  s1 = g_object_get_data (G_OBJECT (o1), "id");
  s2 = g_object_get_data (G_OBJECT (o2), "id");

  i1 = name2order (s1, NULL);
  i2 = name2order (s2, NULL);

  return i1 - i2;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int indicator_entry_compare_func ( gpointer *  v1,
gpointer *  v2 
) [static]

Definition at line 1494 of file panel-service.c.

{
  return (GPOINTER_TO_INT (v1[1]) > GPOINTER_TO_INT (v2[1])) ? 1 : -1;
}

Here is the caller graph for this function:

static void indicator_entry_null_to_variant ( const gchar *  indicator_id,
GVariantBuilder *  b 
) [static]

Definition at line 1173 of file panel-service.c.

{
  g_variant_builder_add (b, "(ssssbbusbbi)",
                         indicator_id,
                         "",
                         "",
                         "",
                         FALSE,
                         FALSE,
                         (guint32) 0,
                         "",
                         FALSE,
                         FALSE,
                         -1);
}

Here is the caller graph for this function:

static void indicator_entry_to_variant ( IndicatorObjectEntry *  entry,
const gchar *  id,
const gchar *  indicator_id,
GVariantBuilder *  b,
gint  prio 
) [static]

Definition at line 1146 of file panel-service.c.

{
  gboolean is_label = GTK_IS_LABEL (entry->label);
  gboolean is_image = GTK_IS_IMAGE (entry->image);
  gchar *image_data = NULL;

  g_variant_builder_add (b, "(ssssbbusbbi)",
                         indicator_id,
                         id,
                         entry->name_hint ? entry->name_hint : "",
                         is_label ? gtk_label_get_label (entry->label) : "",
                         is_label ? gtk_widget_get_sensitive (GTK_WIDGET (entry->label)) : FALSE,
                         is_label ? gtk_widget_get_visible (GTK_WIDGET (entry->label)) : FALSE,
                         is_image ? (guint32)gtk_image_get_storage_type (entry->image) : (guint32) 0,
                         is_image ? (image_data = gtk_image_to_data (entry->image)) : "",
                         is_image ? gtk_widget_get_sensitive (GTK_WIDGET (entry->image)) : FALSE,
                         is_image ? gtk_widget_get_visible (GTK_WIDGET (entry->image)) : FALSE,
                         prio);

  g_free (image_data);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void indicator_object_to_variant ( IndicatorObject *  object,
const gchar *  indicator_id,
GVariantBuilder *  b 
) [static]

Definition at line 1191 of file panel-service.c.

{
  GList *entries, *e;
  gint parent_prio = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (object), "priority"));
  entries = indicator_object_get_entries (object);
  gint index = 0;

  if (entries)
    {
      for (e = entries; e; e = e->next)
        {
          gint prio = -1;
          IndicatorObjectEntry *entry = e->data;
          gchar *id = get_indicator_entry_id_by_entry (entry);

          if (entry->name_hint)
            {
              prio = name2priority(indicator_id, entry->name_hint);
            }

          if (prio == -1)
            {
              prio = parent_prio + index;
              index++;
            }

          indicator_entry_to_variant (entry, id, indicator_id, b, prio);
          g_free (id);
        }

      g_list_free (entries);
    }
  else
    {
      /* Add a null entry to indicate that there is an indicator here, it's just empty */
      indicator_entry_null_to_variant (indicator_id, b);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean initial_resync ( PanelService *  self) [static]

Definition at line 469 of file panel-service.c.

{
  if (PANEL_IS_SERVICE (self))
    {
      g_signal_emit (self, _service_signals[RE_SYNC], 0, "");
      self->priv->initial_sync_id = 0;
    }
  return FALSE;
}

Here is the caller graph for this function:

static void load_indicator ( PanelService *  self,
IndicatorObject *  object,
const gchar *  _name 
) [static]

Definition at line 948 of file panel-service.c.

{
  PanelServicePrivate *priv = self->priv;
  gchar *name;
  GList *entries, *entry;

  indicator_object_set_environment(object, (GStrv)indicator_environment);

  if (_name != NULL)
    name = g_strdup (_name);
  else
    name = g_strdup_printf ("%p", object);

  priv->indicators = g_slist_append (priv->indicators, object);

  g_object_set_data_full (G_OBJECT (object), "id", g_strdup (name), g_free);

  g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED,
                    G_CALLBACK (on_entry_added), self);
  g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED,
                    G_CALLBACK (on_entry_removed), self);
  g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED,
                    G_CALLBACK (on_entry_moved), self);
  g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_MENU_SHOW,
                    G_CALLBACK (on_indicator_menu_show), self);
  g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED,
                    G_CALLBACK (on_indicator_menu_show_now_changed), self);

  entries = indicator_object_get_entries (object);
  for (entry = entries; entry != NULL; entry = entry->next)
    {
      on_entry_added (object, entry->data, self);
    }
  g_list_free (entries);

  g_free (name);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void load_indicators ( PanelService *  self) [static]

Definition at line 987 of file panel-service.c.

{
  GDir        *dir;
  const gchar *name;

  if (!g_file_test (INDICATORDIR,
                    G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
    {
      g_warning ("%s does not exist, cannot read any indicators", INDICATORDIR);
      gtk_main_quit ();
    }

  dir = g_dir_open (INDICATORDIR, 0, NULL);
  while ((name = g_dir_read_name (dir)) != NULL)
    {
      IndicatorObject *object;
      gchar           *path;

      if (!g_str_has_suffix (name, ".so"))
        continue;

      path = g_build_filename (INDICATORDIR, name, NULL);
      g_debug ("Loading: %s", path);

      object = indicator_object_new_from_file (path);
      if (object == NULL)
        {
          g_warning ("Unable to load '%s'", path);
          g_free (path);
          continue;
        }
      load_indicator (self, object, name);

      g_free (path);
    }

  g_dir_close (dir);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void menu_deactivated ( GtkWidget *  menu) [static]

Definition at line 1631 of file panel-service.c.

{
  g_signal_handlers_disconnect_by_func (menu, menu_deactivated, NULL);
  gtk_widget_destroy (menu);
}

Here is the caller graph for this function:

static gint name2order ( const gchar *  name,
const gchar *  hint 
) [static]

Definition at line 1027 of file panel-service.c.

{
  int i;

  for (i = 0; indicator_order[i][0] != NULL; i++)
    {
      if (g_strcmp0(name, indicator_order[i][0]) == 0 &&
          g_strcmp0(hint, indicator_order[i][1]) == 0)
        {
          return i;
        }
    }
  return -1;
}

Here is the caller graph for this function:

static gint name2priority ( const gchar *  name,
const gchar *  hint 
) [static]

Definition at line 1043 of file panel-service.c.

{
  gint order = name2order (name, hint);
  if (order > -1)
    return order * MAX_INDICATOR_ENTRIES;

  return order;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void notify_object ( IndicatorObject *  object) [static]

Definition at line 774 of file panel-service.c.

{
  PanelService        *self;
  PanelServicePrivate *priv;
  gint                 position;

  if (suppress_signals)
    return;

  self = panel_service_get_default ();
  priv = self->priv;

  position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (object), "position"));

  if (priv->timeouts[position] == SYNC_WAITING)
    {
      /* No need to ping again as we're waiting for the client to sync anyway */
      return;
    }
  else if (priv->timeouts[position] != SYNC_NEUTRAL)
    {
      /* We were going to signal that a sync was needed, but since there's been another change let's
       * hold off a little longer so we're not flooding the client
       */
      g_source_remove (priv->timeouts[position]);
    }

  priv->timeouts[position] = g_timeout_add (NOTIFY_TIMEOUT,
                                            (GSourceFunc)actually_notify_object,
                                            object);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void on_active_menu_hidden ( GtkMenu *  menu,
PanelService *  self 
) [static]

Definition at line 1246 of file panel-service.c.

{
  PanelServicePrivate *priv = self->priv;

  priv->last_x = 0;
  priv->last_y = 0;
  priv->last_menu_button = 0;

  g_signal_handler_disconnect (priv->last_menu, priv->last_menu_id);
  g_signal_handler_disconnect (priv->last_menu, priv->last_menu_move_id);

  GtkWidget *top_win = gtk_widget_get_toplevel (GTK_WIDGET (priv->last_menu));
  if (GTK_IS_WINDOW (top_win))
    gtk_window_set_attached_to (GTK_WINDOW (top_win), NULL);

  priv->last_menu = NULL;
  priv->last_menu_id = 0;
  priv->last_menu_move_id = 0;
  priv->last_entry = NULL;
  priv->last_left = 0;
  priv->last_right = 0;
  priv->last_top = 0;
  priv->last_bottom = 0;

  priv->use_event = FALSE;
  priv->pressed_entry = NULL;

  g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, "", 0, 0, 0, 0);
}

Here is the caller graph for this function:

static void on_active_menu_move_current ( GtkMenu *  menu,
GtkMenuDirectionType  direction,
PanelService *  self 
) [static]

Definition at line 1584 of file panel-service.c.

{
  PanelServicePrivate *priv;
  IndicatorObject     *object;

  g_return_if_fail (PANEL_IS_SERVICE (self));
  priv = self->priv;

  /* Not interested in up or down */
  if (direction == GTK_MENU_DIR_NEXT || direction == GTK_MENU_DIR_PREV)
    return;

  /* We don't want to distrupt going into submenus */
  if (direction == GTK_MENU_DIR_CHILD)
    {
      GList               *children, *c;
      children = gtk_container_get_children (GTK_CONTAINER (menu));
      for (c = children; c; c = c->next)
        {
          GtkWidget *item = (GtkWidget *)c->data;

          if (GTK_IS_MENU_ITEM (item)
              && gtk_widget_get_state (item) == GTK_STATE_PRELIGHT
              && gtk_menu_item_get_submenu (GTK_MENU_ITEM (item)))
            {
              /* Skip direction due to there being a submenu,
               * and we don't want to inhibit going into that */
              return;
            }
        }
      g_list_free (children);
    }

  /* Find the next/prev indicator */
  object = get_entry_parent_indicator(priv->last_entry);
  if (object == NULL)
    {
      g_warning ("Unable to find IndicatorObject for entry");
      return;
    }

  activate_next_prev_menu (self, object, priv->last_entry, direction);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void on_entry_added ( IndicatorObject *  object,
IndicatorObjectEntry *  entry,
PanelService *  self 
) [static]

Definition at line 822 of file panel-service.c.

{
  g_return_if_fail (PANEL_IS_SERVICE (self));
  g_return_if_fail (entry != NULL);

  gchar *entry_id = get_indicator_entry_id_by_entry (entry);
  g_hash_table_insert (self->priv->id2entry_hash, entry_id, entry);

  if (GTK_IS_LABEL (entry->label))
    {
      g_signal_connect (entry->label, "notify::label",
                        G_CALLBACK (on_entry_property_changed), object);

      g_signal_connect (entry->label, "notify::sensitive",
                        G_CALLBACK (on_entry_property_changed), object);
      g_signal_connect (entry->label, "show",
                        G_CALLBACK (on_entry_changed), object);
      g_signal_connect (entry->label, "hide",
                        G_CALLBACK (on_entry_changed), object);

    }
  if (GTK_IS_IMAGE (entry->image))
    {
      g_signal_connect (entry->image, "notify::storage-type",
                        G_CALLBACK (on_entry_property_changed), object);
      g_signal_connect (entry->image, "notify::file",
                        G_CALLBACK (on_entry_property_changed), object);
      g_signal_connect (entry->image, "notify::gicon",
                        G_CALLBACK (on_entry_property_changed), object);
      g_signal_connect (entry->image, "notify::icon-name",
                        G_CALLBACK (on_entry_property_changed), object);
      g_signal_connect (entry->image, "notify::pixbuf",
                        G_CALLBACK (on_entry_property_changed), object);
      g_signal_connect (entry->image, "notify::stock",
                        G_CALLBACK (on_entry_property_changed), object);

      g_signal_connect (entry->image, "notify::sensitive",
                        G_CALLBACK (on_entry_property_changed), object);
      g_signal_connect (entry->image, "show",
                        G_CALLBACK (on_entry_changed), object);
      g_signal_connect (entry->image, "hide",
                        G_CALLBACK (on_entry_changed), object);

    }

  notify_object (object);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void on_entry_changed ( GObject *  o,
IndicatorObject *  object 
) [static]

Definition at line 815 of file panel-service.c.

{
  notify_object (object);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void on_entry_moved ( IndicatorObject *  object,
IndicatorObjectEntry *  entry,
PanelService *  self 
) [static]

Definition at line 893 of file panel-service.c.

{
  notify_object (object);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void on_entry_property_changed ( GObject *  o,
GParamSpec *  pspec,
IndicatorObject *  object 
) [static]

Definition at line 807 of file panel-service.c.

{
  notify_object (object);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void on_entry_removed ( IndicatorObject *  object,
IndicatorObjectEntry *  entry,
PanelService *  self 
) [static]

Definition at line 873 of file panel-service.c.

{
  g_return_if_fail (PANEL_IS_SERVICE (self));
  g_return_if_fail (entry != NULL);

  /* Don't remove here the value from panel2entries_hash, this should be
   * done during the geometries sync, to avoid false positive.
   * FIXME this in libappmenu.so to avoid to send an "entry-removed" signal
   * when switching the focus from a window to one of its dialog children */

  gchar *entry_id = get_indicator_entry_id_by_entry (entry);
  g_hash_table_remove (self->priv->id2entry_hash, entry_id);
  g_free (entry_id);

  notify_object (object);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void on_indicator_menu_show ( IndicatorObject *  object,
IndicatorObjectEntry *  entry,
guint32  timestamp,
PanelService *  self 
) [static]

Definition at line 901 of file panel-service.c.

{
  gchar *entry_id;
  
  g_return_if_fail (PANEL_IS_SERVICE (self));
  if (entry == NULL)
    {
      g_warning ("on_indicator_menu_show() called with a NULL entry");
      return;
    }

  entry_id = get_indicator_entry_id_by_entry (entry);
  g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, entry_id);
  g_free (entry_id);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void on_indicator_menu_show_now_changed ( IndicatorObject *  object,
IndicatorObjectEntry *  entry,
gboolean  show_now_changed,
PanelService *  self 
) [static]

Definition at line 921 of file panel-service.c.

{
  gchar *entry_id;
  
  g_return_if_fail (PANEL_IS_SERVICE (self));
  if (entry == NULL)
    {
      g_warning ("on_indicator_menu_show_now_changed() called with a NULL entry");
      return;
    }

  entry_id = get_indicator_entry_id_by_entry (entry);
  g_signal_emit (self, _service_signals[ENTRY_SHOW_NOW_CHANGED], 0, entry_id, show_now_changed);
  g_free (entry_id);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void on_keybinding_changed ( GConfClient *  client,
guint  id,
GConfEntry *  entry,
gpointer  data 
)

Definition at line 539 of file panel-service.c.

{
  PanelService *self = data;
  g_return_if_fail (PANEL_IS_SERVICE (data));

  panel_service_update_menu_keybinding (self);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void panel_service_actually_remove_indicator ( PanelService *  self,
IndicatorObject *  indicator 
) [static]

Definition at line 593 of file panel-service.c.

{
  g_return_if_fail (PANEL_IS_SERVICE (self));
  g_return_if_fail (INDICATOR_IS_OBJECT (indicator));

  GList *entries, *l;

  entries = indicator_object_get_entries (indicator);

  if (entries)
    {
      for (l = entries; l; l = l->next)
        {
          IndicatorObjectEntry *entry;
          gchar *entry_id;
          GHashTableIter iter;
          gpointer key, value;

          entry = l->data;
          entry_id = get_indicator_entry_id_by_entry (entry);
          g_hash_table_remove (self->priv->id2entry_hash, entry_id);
          g_free (entry_id);

          g_hash_table_iter_init (&iter, self->priv->panel2entries_hash);
          while (g_hash_table_iter_next (&iter, &key, &value))
            {
              GHashTable *entry2geometry_hash = value;

              if (g_hash_table_size (entry2geometry_hash) > 1)
                g_hash_table_remove (entry2geometry_hash, entry);
              else
                g_hash_table_iter_remove (&iter);
            }
        }

      g_list_free (entries);
    }

  self->priv->indicators = g_slist_remove (self->priv->indicators, indicator);

  if (g_object_is_floating (G_OBJECT (indicator)))
    {
      g_object_ref_sink (G_OBJECT (indicator));
    }

  g_object_unref (G_OBJECT (indicator));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean panel_service_check_cleared ( PanelService *  self) [static]

Definition at line 581 of file panel-service.c.

{
  if (self->priv->indicators == NULL)
    {
      g_signal_emit (self, _service_signals[INDICATORS_CLEARED], 0);
      return FALSE;
    }

  return TRUE;
}

Here is the caller graph for this function:

static void panel_service_class_dispose ( GObject *  object) [static]

Definition at line 143 of file panel-service.c.

{
  PanelServicePrivate *priv = PANEL_SERVICE (object)->priv;
  gint i;

  g_hash_table_destroy (priv->id2entry_hash);
  g_hash_table_destroy (priv->panel2entries_hash);

  gdk_window_remove_filter (NULL, (GdkFilterFunc)event_filter, object);

  if (GTK_IS_WIDGET (priv->menubar) &&
      gtk_widget_get_realized (GTK_WIDGET (priv->menubar)))
    {
      g_object_unref (priv->menubar);
      priv->menubar = NULL;
    }

  if (GTK_IS_WIDGET (priv->offscreen_window) &&
      gtk_widget_get_realized (GTK_WIDGET (priv->offscreen_window)))
    {
      g_object_unref (priv->offscreen_window);
      priv->offscreen_window = NULL;
    }

  if (GTK_IS_WIDGET (priv->last_menu) &&
      gtk_widget_get_realized (GTK_WIDGET (priv->last_menu)))
    {
      g_object_unref (priv->last_menu);
      priv->last_menu = NULL;
    }

  if (priv->initial_sync_id)
    {
      g_source_remove (priv->initial_sync_id);
      priv->initial_sync_id = 0;
    }

  for (i = 0; i < N_TIMEOUT_SLOTS; i++)
    {
      if (priv->timeouts[i] > 0)
        {
          g_source_remove (priv->timeouts[i]);
          priv->timeouts[i] = 0;
        }
    }

  if (priv->key_monitor_id)
    {
      gconf_client_notify_remove (gconf_client_get_default(), priv->key_monitor_id);
      priv->key_monitor_id = 0;
    }

  G_OBJECT_CLASS (panel_service_parent_class)->dispose (object);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void panel_service_class_finalize ( GObject *  object) [static]

Definition at line 199 of file panel-service.c.

{
  static_service = NULL;
}

Here is the caller graph for this function:

static void panel_service_class_init ( PanelServiceClass *  klass) [static]

Definition at line 205 of file panel-service.c.

{
  GObjectClass *obj_class = G_OBJECT_CLASS (klass);

  obj_class->dispose = panel_service_class_dispose;
  obj_class->finalize = panel_service_class_finalize;

  /* Signals */
  _service_signals[ENTRY_ACTIVATED] =
    g_signal_new ("entry-activated",
                  G_OBJECT_CLASS_TYPE (obj_class),
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
                  panel_marshal_VOID__STRING_INT_INT_UINT_UINT,
                  G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT,
                  G_TYPE_UINT, G_TYPE_UINT);

  _service_signals[RE_SYNC] =
    g_signal_new ("re-sync",
                  G_OBJECT_CLASS_TYPE (obj_class),
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
                  g_cclosure_marshal_VOID__STRING,
                  G_TYPE_NONE, 1, G_TYPE_STRING);

 _service_signals[ENTRY_ACTIVATE_REQUEST] =
    g_signal_new ("entry-activate-request",
                  G_OBJECT_CLASS_TYPE (obj_class),
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
                  g_cclosure_marshal_VOID__STRING,
                  G_TYPE_NONE, 1, G_TYPE_STRING);

 _service_signals[GEOMETRIES_CHANGED] =
    g_signal_new ("geometries-changed",
      G_OBJECT_CLASS_TYPE (obj_class),
      G_SIGNAL_RUN_LAST,
      0,
      NULL, NULL,
      panel_marshal_VOID__OBJECT_POINTER_INT_INT_INT_INT,
      G_TYPE_NONE, 6,
      G_TYPE_OBJECT, G_TYPE_POINTER,
      G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);

 _service_signals[ENTRY_SHOW_NOW_CHANGED] =
    g_signal_new ("entry-show-now-changed",
                  G_OBJECT_CLASS_TYPE (obj_class),
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
                  panel_marshal_VOID__STRING_BOOLEAN,
                  G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);

  _service_signals[INDICATORS_CLEARED] =
    g_signal_new ("indicators-cleared",
                  G_OBJECT_CLASS_TYPE (obj_class),
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
                  g_cclosure_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);


  g_type_class_add_private (obj_class, sizeof (PanelServicePrivate));
}

Here is the call graph for this function:

void panel_service_clear_indicators ( PanelService *  self)

Definition at line 729 of file panel-service.c.

{
  g_return_if_fail (PANEL_IS_SERVICE (self));
  GSList *l = self->priv->indicators;

  while (l)
    {
      IndicatorObject *ind = l->data;
      l = l->next;
      panel_service_remove_indicator (self, ind);
    }

  g_idle_add ((GSourceFunc)panel_service_check_cleared, self);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean panel_service_entry_is_visible ( PanelService *  self,
IndicatorObjectEntry *  entry 
) [static]

Definition at line 1447 of file panel-service.c.

{
  GHashTableIter panel_iter;
  gpointer key, value;
  gboolean found_geo;

  g_return_val_if_fail (PANEL_IS_SERVICE (self), FALSE);
  g_return_val_if_fail (entry != NULL, FALSE);

  found_geo = FALSE;
  g_hash_table_iter_init (&panel_iter, self->priv->panel2entries_hash);

  while (g_hash_table_iter_next (&panel_iter, &key, &value) && !found_geo)
    {
      GHashTable *entry2geometry_hash = value;

      if (g_hash_table_lookup (entry2geometry_hash, entry))
        {
          found_geo = TRUE;
        }
    }

  if (!found_geo)
    return FALSE;

  if (GTK_IS_LABEL (entry->label))
    {
      if (gtk_widget_get_visible (GTK_WIDGET (entry->label)) &&
          gtk_widget_is_sensitive (GTK_WIDGET (entry->label)))
        {
          return TRUE;
        }
    }

  if (GTK_IS_IMAGE (entry->image))
    {
      if (gtk_widget_get_visible (GTK_WIDGET (entry->image)) &&
          gtk_widget_is_sensitive (GTK_WIDGET (entry->image)))
        {
          return TRUE;
        }
    }

  return TRUE;
}

Here is the caller graph for this function:

PanelService* panel_service_get_default ( )

Definition at line 651 of file panel-service.c.

{
  if (static_service == NULL || !PANEL_IS_SERVICE (static_service))
    static_service = g_object_new (PANEL_TYPE_SERVICE, NULL);

  return static_service;
}

Here is the caller graph for this function:

PanelService* panel_service_get_default_with_indicators ( GList *  indicators)

Definition at line 660 of file panel-service.c.

{
  PanelService *service = panel_service_get_default ();
  GList        *i;

  for (i = indicators; i; i = i->next)
    {
      IndicatorObject *object = i->data;
      if (INDICATOR_IS_OBJECT (object))
          load_indicator (service, object, NULL);
    }

  return service;
}

Here is the call graph for this function:

Here is the caller graph for this function:

IndicatorObject* panel_service_get_indicator ( PanelService *  self,
const gchar *  indicator_id 
)

Definition at line 691 of file panel-service.c.

{
  g_return_val_if_fail (PANEL_IS_SERVICE (self), NULL);
  GSList *l;

  for (l = self->priv->indicators; l; l = l->next)
    {
      if (g_strcmp0 (indicator_id,
                     g_object_get_data (G_OBJECT (l->data), "id")) == 0)
        {
          return (IndicatorObject *) l->data;
        }
    }

  return NULL;
}

Here is the caller graph for this function:

IndicatorObject* panel_service_get_indicator_nth ( PanelService *  self,
guint  position 
)

Definition at line 683 of file panel-service.c.

{
  g_return_val_if_fail (PANEL_IS_SERVICE (self), NULL);

  return (IndicatorObject *) g_slist_nth_data (self->priv->indicators, position);
}

Here is the caller graph for this function:

guint panel_service_get_n_indicators ( PanelService *  self)

Definition at line 675 of file panel-service.c.

{
  g_return_val_if_fail (PANEL_IS_SERVICE (self), 0);

  return g_slist_length (self->priv->indicators);
}

Here is the caller graph for this function:

static gboolean panel_service_indicator_remove_timeout ( IndicatorObject *  indicator) [static]

Definition at line 642 of file panel-service.c.

{
  PanelService *self = panel_service_get_default ();
  panel_service_actually_remove_indicator (self, indicator);

  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void panel_service_init ( PanelService *  self) [static]

Definition at line 548 of file panel-service.c.

{
  PanelServicePrivate *priv;
  priv = self->priv = GET_PRIVATE (self);

  priv->offscreen_window = gtk_offscreen_window_new ();
  priv->menubar = gtk_menu_bar_new ();
  gtk_container_add (GTK_CONTAINER (priv->offscreen_window), priv->menubar);

  gdk_window_add_filter (NULL, (GdkFilterFunc)event_filter, self);

  priv->id2entry_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
  priv->panel2entries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                    g_free,
                                                    (GDestroyNotify) g_hash_table_destroy);

  suppress_signals = TRUE;
  load_indicators (self);
  sort_indicators (self);
  suppress_signals = FALSE;

  panel_service_update_menu_keybinding (self);

  GConfClient *client = gconf_client_get_default ();
  gconf_client_add_dir (client, COMPIZ_OPTIONS_PATH, GCONF_CLIENT_PRELOAD_NONE, NULL);
  priv->key_monitor_id = gconf_client_notify_add (client, MENU_TOGGLE_KEYBINDING_PATH,
                                                  on_keybinding_changed, self,
                                                  NULL, NULL);

  priv->initial_sync_id = g_idle_add ((GSourceFunc)initial_resync, self);
}

Here is the call graph for this function:

void panel_service_remove_indicator ( PanelService *  self,
IndicatorObject *  indicator 
)

Definition at line 709 of file panel-service.c.

{
  g_return_if_fail (PANEL_IS_SERVICE (self));
  g_return_if_fail (INDICATOR_IS_OBJECT (indicator));

  gpointer timeout = g_object_get_data (G_OBJECT (indicator), "remove-timeout");

  if (timeout)
    g_source_remove (GPOINTER_TO_UINT (timeout));

  g_object_set_data (G_OBJECT (indicator), "remove", GINT_TO_POINTER (TRUE));
  notify_object (indicator);

  guint id = g_timeout_add_seconds (1,
                                    (GSourceFunc) panel_service_indicator_remove_timeout,
                                    indicator);
  g_object_set_data (G_OBJECT (indicator), "remove-timeout", GUINT_TO_POINTER (id));
}

Here is the call graph for this function:

Here is the caller graph for this function:

void panel_service_scroll_entry ( PanelService *  self,
const gchar *  entry_id,
gint32  delta 
)

Definition at line 1824 of file panel-service.c.

{
  IndicatorObject      *object;
  IndicatorObjectEntry *entry;

  entry = get_indicator_entry_by_id (self, entry_id);
  g_return_if_fail (entry);

  GdkScrollDirection direction = delta < 0 ? GDK_SCROLL_DOWN : GDK_SCROLL_UP;

  object = get_entry_parent_indicator (entry);
  g_signal_emit_by_name(object, INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED, entry,
                        abs(delta/120), direction);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void panel_service_secondary_activate_entry ( PanelService *  self,
const gchar *  entry_id,
guint32  timestamp 
)

Definition at line 1808 of file panel-service.c.

{
  IndicatorObject      *object;
  IndicatorObjectEntry *entry;

  entry = get_indicator_entry_by_id (self, entry_id);
  g_return_if_fail (entry);

  object = get_entry_parent_indicator (entry);
  g_signal_emit_by_name(object, INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE, entry,
                        timestamp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void panel_service_show_app_menu ( PanelService *  self,
guint32  xid,
gint32  x,
gint32  y,
guint32  timestamp 
)

Definition at line 1781 of file panel-service.c.

{
  IndicatorObject      *object;
  IndicatorObjectEntry *entry;
  GList                *entries;

  g_return_if_fail (PANEL_IS_SERVICE (self));

  object = panel_service_get_indicator (self, "libappmenu.so");
  g_return_if_fail (INDICATOR_IS_OBJECT (object));

  entries = indicator_object_get_entries (object);

  if (entries)
    {
      entry = entries->data;
      g_list_free (entries);

      panel_service_show_entry_common (self, object, entry, xid, x, y, 1, timestamp);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void panel_service_show_entry ( PanelService *  self,
const gchar *  entry_id,
guint32  xid,
gint32  x,
gint32  y,
guint32  button,
guint32  timestamp 
)

Definition at line 1761 of file panel-service.c.

{
  IndicatorObject      *object;
  IndicatorObjectEntry *entry;

  g_return_if_fail (PANEL_IS_SERVICE (self));

  entry = get_indicator_entry_by_id (self, entry_id);
  object = get_entry_parent_indicator (entry);

  panel_service_show_entry_common (self, object, entry, xid, x, y, button, timestamp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void panel_service_show_entry_common ( PanelService *  self,
IndicatorObject *  object,
IndicatorObjectEntry *  entry,
guint32  xid,
gint32  x,
gint32  y,
guint32  button,
guint32  timestamp 
) [static]

Definition at line 1638 of file panel-service.c.

{
  PanelServicePrivate *priv;
  GtkWidget           *last_menu;

  g_return_if_fail (PANEL_IS_SERVICE (self));
  g_return_if_fail (INDICATOR_IS_OBJECT (object));
  g_return_if_fail (entry);

  priv = self->priv;

  if (priv->last_entry == entry)
    return;

  last_menu = GTK_WIDGET (priv->last_menu);

  if (GTK_IS_MENU (priv->last_menu))
    {
      priv->last_x = 0;
      priv->last_y = 0;

      g_signal_handler_disconnect (priv->last_menu, priv->last_menu_id);
      g_signal_handler_disconnect (priv->last_menu, priv->last_menu_move_id);

      priv->last_entry = NULL;
      priv->last_menu = NULL;
      priv->last_menu_id = 0;
      priv->last_menu_move_id = 0;
      priv->last_menu_button = 0;
    }

  if (entry != NULL)
    {
      if (xid > 0)
        {
          indicator_object_entry_activate_window (object, entry, xid, CurrentTime);
        }
      else
        {
          indicator_object_entry_activate (object, entry, CurrentTime);
        }

      if (GTK_IS_MENU (entry->menu))
        {
          priv->last_menu = entry->menu;
        }
      else
        {
          /* For some reason, this entry doesn't have a menu.  To simplify the
             rest of the code and to keep scrubbing fluidly, we'll create a
             stub menu for the duration of this scrub. */
          priv->last_menu = GTK_MENU (gtk_menu_new ());
          g_signal_connect (priv->last_menu, "deactivate",
                            G_CALLBACK (menu_deactivated), NULL);
          g_signal_connect (priv->last_menu, "destroy",
                            G_CALLBACK (gtk_widget_destroyed), &priv->last_menu);
        }

      GtkWidget *top_widget = gtk_widget_get_toplevel (GTK_WIDGET (priv->last_menu));

      if (GTK_IS_WINDOW (top_widget))
        {
          GtkWindow *top_win = GTK_WINDOW (top_widget);

          if (gtk_window_get_attached_to (top_win) != priv->menubar)
            gtk_window_set_attached_to (top_win, priv->menubar);
        }

      priv->last_entry = entry;
      priv->last_x = x;
      priv->last_y = y;
      priv->last_menu_button = button;
      priv->last_menu_id = g_signal_connect (priv->last_menu, "hide",
                                             G_CALLBACK (on_active_menu_hidden), self);
      priv->last_menu_move_id = g_signal_connect_after (priv->last_menu, "move-current",
                                                        G_CALLBACK (on_active_menu_move_current), self);

      gtk_menu_popup (priv->last_menu, NULL, NULL, positon_menu, self, 0, CurrentTime);
      gtk_menu_reposition (priv->last_menu);

      GdkWindow *gdkwin = gtk_widget_get_window (GTK_WIDGET (priv->last_menu));
      if (gdkwin != NULL)
        {
          gint left=0, top=0, width=0, height=0;

          gdk_window_get_geometry (gdkwin, NULL, NULL, &width, &height);
          gdk_window_get_origin (gdkwin, &left, &top);

          gchar *entry_id = get_indicator_entry_id_by_entry (entry);
          g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, entry_id,
                         left, top, width, height);
          g_free (entry_id);

          priv->last_left = left;
          priv->last_right = left + width -1;
          priv->last_top = top;
          priv->last_bottom = top + height -1;
        }
      else
        {
          priv->last_left = 0;
          priv->last_right = 0;
          priv->last_top = 0;
          priv->last_bottom = 0;
        }
    }

  /* We popdown the old one last so we don't accidently send key focus back to the
   * active application (which will make it change colour (as state changes), which
   * then looks like flickering to the user.
   */
  if (GTK_IS_MENU (last_menu))
    gtk_menu_popdown (GTK_MENU (last_menu));
}

Here is the call graph for this function:

Here is the caller graph for this function:

GVariant* panel_service_sync ( PanelService *  self)

Definition at line 1280 of file panel-service.c.

{
  GVariantBuilder b;
  GSList *i;

  g_variant_builder_init (&b, G_VARIANT_TYPE ("(a(ssssbbusbbi))"));
  g_variant_builder_open (&b, G_VARIANT_TYPE ("a(ssssbbusbbi)"));

  for (i = self->priv->indicators; i; i = i->next)
    {
      const gchar *indicator_id = g_object_get_data (G_OBJECT (i->data), "id");
      gint position;

      /* Set the sync back to neutral */
      position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (i->data), "position"));
      self->priv->timeouts[position] = SYNC_NEUTRAL;
      indicator_object_to_variant (i->data, indicator_id, &b);
    }

  g_variant_builder_close (&b);
  return g_variant_builder_end (&b);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void panel_service_sync_geometry ( PanelService *  self,
const gchar *  panel_id,
const gchar *  entry_id,
gint  x,
gint  y,
gint  width,
gint  height 
)

Definition at line 1342 of file panel-service.c.

{
  IndicatorObject      *object;
  IndicatorObjectEntry *entry;
  gboolean valid_entry = TRUE;
  PanelServicePrivate  *priv = self->priv;

  entry = get_indicator_entry_by_id (self, entry_id);

  /* If the entry we read is not valid, maybe it has already been removed
   * or unparented, so we need to make sure that the related key on the
   * entry2geometry_hash is correctly removed and the value is free'd */
  if (!entry)
    {
      IndicatorObjectEntry *invalid_entry;
      if (sscanf (entry_id, "%p", &invalid_entry) == 1)
        {
          entry = invalid_entry;
          valid_entry = FALSE;
        }
    }

  if (entry)
    {
      GHashTable *entry2geometry_hash = g_hash_table_lookup (priv->panel2entries_hash, panel_id);

      if (width < 0 || height < 0 || !valid_entry)
        {
          if (entry2geometry_hash)
            {
              if (g_hash_table_size (entry2geometry_hash) > 1)
                {
                  g_hash_table_remove (entry2geometry_hash, entry);
                }
              else
                {
                  g_hash_table_remove (priv->panel2entries_hash, panel_id);
                }
            }

          /* If the entry has been removed let's make sure that its menu is closed */
          if (valid_entry && GTK_IS_MENU (priv->last_menu) && priv->last_menu == entry->menu)
            {
              gtk_menu_popdown (entry->menu);
            }
        }
      else
        {
          GdkRectangle *geo = NULL;

          if (entry2geometry_hash == NULL)
            {
              entry2geometry_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal,
                                                           NULL, g_free);
              g_hash_table_insert (priv->panel2entries_hash, g_strdup (panel_id),
                                   entry2geometry_hash);
            }
          else
            {
              geo = g_hash_table_lookup (entry2geometry_hash, entry);
            }

          if (geo == NULL)
            {
              geo = g_new0 (GdkRectangle, 1);
              g_hash_table_insert (entry2geometry_hash, entry, geo);
            }

          /* If the current entry geometry has changed, we need to move the menu
           * accordingly to the change we recorded! */
          if (GTK_IS_MENU (priv->last_menu) && priv->last_menu == entry->menu)
            {
              GtkWidget *top_widget = gtk_widget_get_toplevel (GTK_WIDGET (priv->last_menu));

              if (GTK_IS_WINDOW (top_widget))
                {
                  GtkWindow *top_win = GTK_WINDOW (top_widget);
                  gint old_x, old_y;

                  gtk_window_get_position (top_win, &old_x, &old_y);
                  gtk_window_move (top_win, old_x - (geo->x - x), old_y - (geo->y - y));
                }
            }

          geo->x = x;
          geo->y = y;
          geo->width = width;
          geo->height = height;
        }

      if (valid_entry)
        {
          object = get_entry_parent_indicator (entry);
          g_signal_emit (self, _service_signals[GEOMETRIES_CHANGED], 0, object, entry, x, y, width, height);
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

GVariant* panel_service_sync_one ( PanelService *  self,
const gchar *  indicator_id 
)

Definition at line 1304 of file panel-service.c.

{
  GVariantBuilder b;
  GSList *i;

  g_variant_builder_init (&b, G_VARIANT_TYPE ("(a(ssssbbusbbi))"));
  g_variant_builder_open (&b, G_VARIANT_TYPE ("a(ssssbbusbbi)"));

  for (i = self->priv->indicators; i; i = i->next)
    {
      if (g_strcmp0 (indicator_id,
                     g_object_get_data (G_OBJECT (i->data), "id")) == 0)
        {
          gint position;

          /* Set the sync back to neutral */
          position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (i->data), "position"));
          self->priv->timeouts[position] = SYNC_NEUTRAL;

          if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (i->data), "remove")) != TRUE)
            {
              indicator_object_to_variant (i->data, indicator_id, &b);
            }
          else
            {
              indicator_entry_null_to_variant (indicator_id, &b);
              panel_service_actually_remove_indicator (self, i->data);
            }

          break;
        }
    }

  g_variant_builder_close (&b);
  return g_variant_builder_end (&b);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void panel_service_update_menu_keybinding ( PanelService *  self) [static]

Definition at line 480 of file panel-service.c.

{
  GConfClient *client = gconf_client_get_default ();
  gchar *binding = gconf_client_get_string (client, MENU_TOGGLE_KEYBINDING_PATH, NULL);

  KeyCode keycode = 0;
  KeySym keysym = NoSymbol;
  guint32 modifiers = 0;

  gchar *keystart = (binding) ? strrchr (binding, '>') : NULL;

  if (!keystart)
    keystart = binding;

  while (keystart && !g_ascii_isalnum (*keystart))
    keystart++;

  gchar *keyend = keystart;

  while (keyend && g_ascii_isalnum (*keyend))
    keyend++;

  if (keystart != keyend)
  {
    gchar *keystr = g_strndup (keystart, keyend-keystart);
    keysym = XStringToKeysym (keystr);
    g_free (keystr);
  }

  if (keysym != NoSymbol)
    {
      Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
      keycode = XKeysymToKeycode(dpy, keysym);

      if (g_strrstr (binding, "<Shift>"))
        {
          modifiers |= GDK_SHIFT_MASK;
        }
      if (g_strrstr (binding, "<Control>"))
        {
          modifiers |= GDK_CONTROL_MASK;
        }
      if (g_strrstr (binding, "<Alt>") || g_strrstr (binding, "<Mod1>"))
        {
          modifiers |= GDK_MOD1_MASK;
        }
      if (g_strrstr (binding, "<Super>"))
        {
          modifiers |= GDK_SUPER_MASK;
        }
    }

  self->priv->toggle_key = keycode;
  self->priv->toggle_modifiers = modifiers;

  g_free (binding);
}

Here is the caller graph for this function:

static void positon_menu ( GtkMenu *  menu,
gint *  x,
gint *  y,
gboolean *  push,
gpointer  user_data 
) [static]

Definition at line 1231 of file panel-service.c.

{
  PanelService *self = PANEL_SERVICE (user_data);
  PanelServicePrivate *priv = self->priv;

  *x = priv->last_x;
  *y = priv->last_y;
  *push = TRUE;
}

Here is the caller graph for this function:

static void sort_indicators ( PanelService *  self) [static]

Definition at line 1070 of file panel-service.c.

{
  GSList *i;
  int     k = 0;
  int     prio = 0;

  self->priv->indicators = g_slist_sort (self->priv->indicators,
                                         (GCompareFunc)indicator_compare_func);

  for (i = self->priv->indicators; i; i = i->next)
    {
      prio = name2priority(g_object_get_data (G_OBJECT (i->data), "id"), NULL);
      if (prio < 0) continue;
      g_object_set_data (G_OBJECT (i->data), "priority", GINT_TO_POINTER (prio));
      g_object_set_data (G_OBJECT (i->data), "position", GINT_TO_POINTER (k));
      self->priv->timeouts[k] = SYNC_NEUTRAL;
      k++;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

guint32 _service_signals[LAST_SIGNAL] = { 0 } [static]

Definition at line 106 of file panel-service.c.

const gchar* indicator_environment[] [static]
Initial value:
 {
  "unity",
  "unity-3d",
  "unity-panel-service",
  NULL
}

Definition at line 940 of file panel-service.c.

const gchar* indicator_order[][2] [static]
Initial value:
 {
  {"libappmenu.so", NULL},                    
  {"libapplication.so", NULL},                
  {"libprintersmenu.so", NULL},               
  {"libapplication.so", "gsd-keyboard-xkb"},  
  {"libmessaging.so", NULL},                  
  {"libpower.so", NULL},                      
  {"libapplication.so", "bluetooth-manager"}, 
  {"libnetwork.so", NULL},                    
  {"libnetworkmenu.so", NULL},                
  {"libapplication.so", "nm-applet"},         
  {"libsoundmenu.so", NULL},                  
  {"libdatetime.so", NULL},                   
  {"libsession.so", NULL},                    
  {NULL, NULL}
}

Definition at line 108 of file panel-service.c.

PanelService* static_service = NULL [static]

Definition at line 52 of file panel-service.c.

gboolean suppress_signals = FALSE [static]

Definition at line 86 of file panel-service.c.