From b8b206c6e84757c6d4d36cec619a1e7c37d1eb5f Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Wed, 10 Feb 2021 13:06:05 +0100 Subject: Move source files to src --- src/indicator-object.c | 967 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 967 insertions(+) create mode 100644 src/indicator-object.c (limited to 'src/indicator-object.c') diff --git a/src/indicator-object.c b/src/indicator-object.c new file mode 100644 index 0000000..50b3078 --- /dev/null +++ b/src/indicator-object.c @@ -0,0 +1,967 @@ +/* +An object to represent loadable indicator modules to make loading +them easy and objectified. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 3.0 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License version 3.0 for more details. + +You should have received a copy of the GNU General Public +License along with this library. If not, see +. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "indicator.h" +#include "indicator-object.h" +#include "indicator-object-marshal.h" +#include "indicator-object-enum-types.h" + +/** + @ENTRY_INIT: The entry hasn't been initialized yet, so its + visibility will depend upon the inital-visibility property. + @ENTRY_VISIBLE: The entry is visible + @ENTRY_INVISIBLE: The entry is invisible +*/ +typedef enum { + ENTRY_INIT, + ENTRY_VISIBLE, + ENTRY_INVISIBLE +} +EntryVisibility; + +typedef struct _IndicatorObjectEntryPrivate { + EntryVisibility visibility; +} +IndicatorObjectEntryPrivate; + +/** + IndicatorObjectPrivate: + @module: The loaded module representing the object. Note to + subclasses: This will not be set when you're initalized. + @entry: A default entry for objects that don't need all the + fancy stuff. This works with #get_entries_default. + @gotten_entries: A check to see if the @entry has been + populated intelligently yet. + + Structure to define the memory for the private area + of the object instance. +*/ +struct _IndicatorObjectPrivate { + GModule * module; + + /* For get_entries_default */ + IndicatorObjectEntry entry; + gboolean gotten_entries; + + /* Whether or not entries are visible by default */ + gboolean default_visibility; + GHashTable * entry_privates; + + GStrv environments; +}; + +/* Signals Stuff */ +enum { + ENTRY_ADDED, + ENTRY_REMOVED, + ENTRY_MOVED, + ENTRY_SCROLLED, + MENU_SHOW, + SHOW_NOW_CHANGED, + ACCESSIBLE_DESC_UPDATE, + SECONDARY_ACTIVATE, + LAST_SIGNAL +}; + +/* Properties */ +/* Enum for the properties so that they can be quickly + found and looked up. */ +enum { + PROP_0, + PROP_GSETTINGS_SCHEMA_ID, + PROP_DEFAULT_VISIBILITY, +}; + + +static guint signals[LAST_SIGNAL] = { 0 }; + +/* GObject stuff */ +static void indicator_object_class_init (IndicatorObjectClass *klass); +static void indicator_object_init (IndicatorObject *self); +static void indicator_object_dispose (GObject *object); +static void indicator_object_finalize (GObject *object); +static void set_property (GObject*, guint prop_id, const GValue*, GParamSpec* ); +static void get_property (GObject*, guint prop_id, GValue*, GParamSpec* ); + +/* entries' visibility */ +static GList * get_entries_default (IndicatorObject*); +static GList * get_all_entries (IndicatorObject*); +static void indicator_object_entry_being_removed (IndicatorObject*, IndicatorObjectEntry*); +static void indicator_object_entry_was_added (IndicatorObject*, IndicatorObjectEntry*); +static gint indicator_object_real_get_position (IndicatorObject*); +static IndicatorObjectEntryPrivate * entry_get_private (IndicatorObject*, IndicatorObjectEntry*); + +G_DEFINE_TYPE_WITH_PRIVATE (IndicatorObject, indicator_object, G_TYPE_OBJECT); + +/* Setup the class and put the functions into the + class structure */ +static void +indicator_object_class_init (IndicatorObjectClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = indicator_object_dispose; + object_class->finalize = indicator_object_finalize; + object_class->set_property = set_property; + object_class->get_property = get_property; + + klass->get_label = NULL; + klass->get_menu = NULL; + klass->get_image = NULL; + klass->get_accessible_desc = NULL; + klass->get_entries = get_entries_default; + klass->get_location = NULL; + klass->entry_being_removed = NULL; + klass->entry_was_added = NULL; + klass->get_position = indicator_object_real_get_position; + + klass->entry_activate = NULL; + klass->entry_activate_window = NULL; + klass->entry_close = NULL; + + /** + IndicatorObject::entry-added: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + is being added. + + Signaled when a new entry is added and should + be shown by the person using this object. + */ + signals[ENTRY_ADDED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, entry_added), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); + + /** + IndicatorObject::entry-removed: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + is being removed. + + Signaled when an entry is removed and should + be removed by the person using this object. + */ + signals[ENTRY_REMOVED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, entry_removed), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); + /** + IndicatorObject::entry-moved: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + is being moved. + @arg2: The old location of the entry + @arg3: The new location of the entry + + When the order of the entries change, then this signal + is sent to tell the new location. + */ + signals[ENTRY_MOVED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, entry_moved), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_UINT_UINT, + G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_NONE); + /** + IndicatorObject::entry-scrolled: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + receives the scroll event. + @arg2: The delta of the scroll event + @arg3: The orientation of the scroll event. + + When the indicator receives a mouse scroll wheel event + from the user, this signal is emitted. + */ + signals[ENTRY_SCROLLED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, entry_scrolled), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_UINT_ENUM, + G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_UINT, + INDICATOR_OBJECT_TYPE_SCROLL_DIRECTION); + /** + IndicatorObject::secondary-activate: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + receives the secondary activate event. + @arg2: The timestamp of the event + + When the indicator receives a secondary activation event + from the user, this signal is emitted. + */ + signals[SECONDARY_ACTIVATE] = g_signal_new (INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, secondary_activate), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_UINT, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); + + /** + IndicatorObject::menu-show: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + is being shown. + @arg2: The timestamp of the event + + Used when the indicator wants to signal up the stack + that the menu should be shown. + */ + signals[MENU_SHOW] = g_signal_new (INDICATOR_OBJECT_SIGNAL_MENU_SHOW, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, menu_show), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_UINT, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); + + /** + IndicatorObject::show-now-changed: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + is changing it's state + @arg2: The state of whether the entry should be shown + + Whether the entry should be shown or not has changed so we need + to tell whoever is displaying it. + */ + signals[SHOW_NOW_CHANGED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, show_now_changed), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_BOOLEAN, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN); + + /** + IndicatorObject::accessible-desc-update:: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry whos + accessible description has been updated. + + Signaled when an indicator's accessible description + has been updated, so that the displayer of the + indicator can fetch the new description. + */ + signals[ACCESSIBLE_DESC_UPDATE] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, accessible_desc_update), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); + + /* Properties */ + + GParamSpec * pspec = g_param_spec_boolean (INDICATOR_OBJECT_DEFAULT_VISIBILITY, + "default visibility", + "Whether or not entries should initially be visible.", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_DEFAULT_VISIBILITY, pspec); +} + +/* Initialize an instance */ +static void +indicator_object_init (IndicatorObject *self) +{ + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(self); + + priv->module = NULL; + + priv->entry.parent_object = self; + priv->entry.menu = NULL; + priv->entry.label = NULL; + priv->entry.image = NULL; + priv->entry.accessible_desc = NULL; + priv->entry.name_hint = NULL; + priv->entry.parent_window = 0; + + priv->gotten_entries = FALSE; + priv->default_visibility = TRUE; + priv->entry_privates = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + + priv->environments = NULL; + + self->priv = priv; + + GObject * o = G_OBJECT(self); + /* Invoke the entry-being-removed virtual function first */ + g_signal_connect (o, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, + G_CALLBACK(indicator_object_entry_being_removed), NULL); + /* Invoke the entry-was-added virtual function last */ + g_signal_connect_after (o, INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, + G_CALLBACK(indicator_object_entry_was_added), NULL); +} + +/* Unref the objects that we're holding on to. */ +static void +indicator_object_dispose (GObject *object) +{ + /* Ensure that hidden entries are re-added so their widgetry will + be cleaned up properly by the client */ + indicator_object_set_visible (INDICATOR_OBJECT (object), TRUE); + + G_OBJECT_CLASS (indicator_object_parent_class)->dispose (object); +} + +/* A small helper function that closes a module but + in the function prototype of a GSourceFunc. */ +static gboolean +module_unref (gpointer data) +{ + if (!g_module_close((GModule *)data)) { + /* All we can do is warn. */ + g_warning("Unable to close module!"); + } + return FALSE; +} + +/* Free memory */ +static void +indicator_object_finalize (GObject *object) +{ + + IndicatorObject * obj = INDICATOR_OBJECT (object); + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(obj); + + if (priv->entry_privates != NULL) { + g_hash_table_destroy (priv->entry_privates); + priv->entry_privates = NULL; + } + + if (priv->environments != NULL) { + g_strfreev(priv->environments); + priv->environments = NULL; + } + + if (priv->module != NULL) { + /* Wow, this is convoluted. So basically we want to unref + the module which will cause the code it included to be + removed. But, since its finalize function is the function + that called this one, we can't really remove it before + it finishes being executed. So we're putting the job into + the main loop to remove it the next time it gets a chance. + Slightly non-deterministic, but should work. */ + g_idle_add(module_unref, priv->module); + priv->module = NULL; + } + + G_OBJECT_CLASS (indicator_object_parent_class)->finalize (object); + return; +} + +/** + indicator_object_new_from_file: + @file: Filename containing a loadable module + + This function builds an #IndicatorObject using the symbols + that are found in @file. The module is loaded and the + references are all kept by the object. To unload the + module the object must be destroyed. + + Return value: A valid #IndicatorObject or #NULL if error. +*/ +IndicatorObject * +indicator_object_new_from_file (const gchar * file) +{ + GObject * object = NULL; + GModule * module = NULL; + + /* Check to make sure the name exists and that the + file itself exists */ + if (file == NULL) { + g_warning("Invalid filename."); + return NULL; + } + + if (!g_file_test(file, G_FILE_TEST_EXISTS)) { + g_warning("File '%s' does not exist.", file); + return NULL; + } + + /* Grab the g_module reference, pull it in but let's + keep the symbols local to avoid conflicts. */ + module = g_module_open(file, + G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + if (module == NULL) { + g_warning("Unable to load module: %s", file); + return NULL; + } + + /* Look for the version function, error if not found. */ + get_version_t lget_version = NULL; + if (!g_module_symbol(module, INDICATOR_GET_VERSION_S, (gpointer *)(&lget_version))) { + g_warning("Unable to get the symbol for getting the version."); + return NULL; + } + + /* Check the version with the macro and make sure we're + all talking the same language. */ + if (!INDICATOR_VERSION_CHECK(lget_version())) { + g_warning("Indicator using API version '%s' we're expecting '%s'", lget_version(), INDICATOR_VERSION); + return NULL; + } + + /* The function for grabbing a label from the module + execute it, and make sure everything is a-okay */ + get_type_t lget_type = NULL; + if (!g_module_symbol(module, INDICATOR_GET_TYPE_S, (gpointer *)(&lget_type))) { + g_warning("Unable to get '" INDICATOR_GET_TYPE_S "' symbol from module: %s", file); + goto unrefandout; + } + if (lget_type == NULL) { + g_warning("Symbol '" INDICATOR_GET_TYPE_S "' is (null) in module: %s", file); + goto unrefandout; + } + + /* A this point we allocate the object, any code beyond + here needs to deallocate it if we're returning in an + error'd state. */ + object = g_object_new(lget_type(), NULL); + if (object == NULL) { + g_warning("Unable to build an object if type '%d' in module: %s", (gint)lget_type(), file); + goto unrefandout; + } + if (!INDICATOR_IS_OBJECT(object)) { + g_warning("Type '%d' in file %s is not a subclass of IndicatorObject.", (gint)lget_type(), file); + goto unrefandout; + } + + /* Now we can track the module */ + IndicatorObject * obj = INDICATOR_OBJECT(object); + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(obj); + priv->module = module; + + return obj; + + /* Error, let's drop the object and return NULL. Sad when + this happens. */ +unrefandout: + g_clear_object (&object); + g_clear_object (&module); + g_warning("Error building IndicatorObject from file: %s", file); + return NULL; +} + +/* The default get entries function uses the other single + entries in the class to create an entry structure and + put it into a list. This makes it simple for simple objects + to create the list. Small changes from the way they + previously were. */ +static GList * +get_entries_default (IndicatorObject * io) +{ + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(io); + + if (!priv->gotten_entries) { + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + priv->entry.parent_object = io; + + if (class->get_label) { + priv->entry.label = class->get_label(io); + } + + if (class->get_image) { + priv->entry.image = class->get_image(io); + } + + if (priv->entry.image == NULL && priv->entry.label == NULL) { + g_warning("IndicatorObject class does not create an image or a label. We need one of those."); + return NULL; + } + + if (class->get_menu) { + priv->entry.menu = class->get_menu(io); + } + + if (priv->entry.menu == NULL) { + g_warning("IndicatorObject class does not create a menu. We need one of those."); + return NULL; + } + + if (class->get_accessible_desc) { + priv->entry.accessible_desc = class->get_accessible_desc(io); + } + + if (priv->entry.accessible_desc == NULL) { + g_warning("IndicatorObject class does not have an accessible description."); + } + + if (class->get_name_hint) { + priv->entry.name_hint = class->get_name_hint(io); + } + + if (class->get_parent_window) { + priv->entry.parent_window = class->get_parent_window(io); + } + + priv->gotten_entries = TRUE; + } + + return g_list_append(NULL, &(priv->entry)); +} + +/* returns a list of all IndicatorObjectEntries, visible or not */ +static GList* +get_all_entries (IndicatorObject * io) +{ + GList * all_entries = NULL, *l; + + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), NULL); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->get_entries == NULL) + g_error("No get_entries function on object. It must have been deleted?!?!"); + else + { + all_entries = class->get_entries(io); + + for (l = all_entries; l; l = l->next) + { + IndicatorObjectEntry *entry = l->data; + + if (entry) + entry->parent_object = io; + } + } + + return all_entries; +} + +/* get the private structure that corresponds to a caller-specified entry */ +static IndicatorObjectEntryPrivate * +entry_get_private (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_val_if_fail (INDICATOR_IS_OBJECT(io), NULL); + g_return_val_if_fail (io->priv != NULL, NULL); + + GHashTable * h = io->priv->entry_privates; + IndicatorObjectEntryPrivate * priv = g_hash_table_lookup (h, entry); + if (priv == NULL) + { + priv = g_new0 (IndicatorObjectEntryPrivate, 1); + priv->visibility = ENTRY_INIT; + g_hash_table_insert (h, entry, priv); + } + + return priv; +} + +/** + indicator_object_get_entries: + @io: #IndicatorObject to query + + This function returns a list of visible entries. The list is built + by calling the object's #IndicatorObjectClass::get_entries + virtual function and testing each of the results for visibility. + Callers should free the GList with g_list_free(), but the entries + are owned by the IndicatorObject and should not be freed. + + Return value: (element-type IndicatorObjectEntry) (transfer container): + A list if #IndicatorObjectEntry structures or NULL on error. +*/ +GList * +indicator_object_get_entries (IndicatorObject * io) +{ + GList * l; + GList * ret = NULL; + GList * all_entries = get_all_entries (io); + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(io); + const gboolean default_visibility = priv->default_visibility; + + for (l=all_entries; l!=NULL; l=l->next) + { + gboolean show_me; + IndicatorObjectEntry * entry = l->data; + + switch (entry_get_private(io,entry)->visibility) { + case ENTRY_VISIBLE: show_me = TRUE; break; + case ENTRY_INVISIBLE: show_me = FALSE; break; + case ENTRY_INIT: show_me = default_visibility; break; + default: show_me = TRUE; g_warn_if_reached(); break; + } + + if (show_me) + ret = g_list_prepend (ret, entry); + } + + g_list_free (all_entries); + return g_list_reverse (ret); +} + +/** + indicator_object_get_location: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry to look for. + + This function looks on the class for the object and calls + it's #IndicatorObjectClass::get_location function. If the + function doesn't exist it returns zero. + + Return value: Location of the @entry in the display or + zero if no location is specified. +*/ +guint +indicator_object_get_location (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), 0); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->get_location) { + return class->get_location(io, entry); + } + + return 0; +} + +/** + indicator_object_get_show_now: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry to look for. + + This function returns whether the entry should be shown with + priority on the panel. If the object does not support checking + it assumes that its entries should never have priority. + + Return value: Whether the entry should be shown with priority. +*/ +guint +indicator_object_get_show_now (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), 0); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->get_show_now) { + return class->get_show_now(io, entry); + } + + return FALSE; +} + +/** + indicator_object_entry_activate_window: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry whose entry was shown + @windowid: ID of the window that is currently focused (or will + be very shortly) + @timestamp: The X11 timestamp of the event + + Used to signal to the indicator that the menu on an entry has + been clicked on. This can either be an activate or a showing + of the menu. Also includes a window ID so that we can know what + application is going to be getting focused soon. If there is + no override of this function, it is the same as calling + indicator_object_entry_activate and in general is preferable + if you have that information available. +*/ +void +indicator_object_entry_activate_window (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->entry_activate_window != NULL) { + return class->entry_activate_window(io, entry, windowid, timestamp); + } else { + indicator_object_entry_activate(io, entry, timestamp); + } + + return; +} + +/** + indicator_object_entry_activate: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry whose entry was shown + @timestamp: The X11 timestamp of the event + + Used to signal to the indicator that the menu on an entry has + been clicked on. This can either be an activate or a showing + of the menu. Note, this does not actually show the menu that's + left up to the reader. +*/ +void +indicator_object_entry_activate (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->entry_activate != NULL) { + return class->entry_activate(io, entry, timestamp); + } + + return; +} + +/** + indicator_object_entry_close: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry whose menu was closed + @timestamp: The X11 timestamp of the event + + Used to tell the indicator that a menu has been closed for the + entry that is specified. +*/ +void +indicator_object_entry_close (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->entry_close != NULL) { + return class->entry_close(io, entry, timestamp); + } + + return; +} + +static void +indicator_object_entry_being_removed (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + entry_get_private (io, entry)->visibility = ENTRY_INVISIBLE; + + if (entry) + entry->parent_object = NULL; + + if (class->entry_being_removed != NULL) + { + class->entry_being_removed (io, entry); + } +} + +static void +indicator_object_entry_was_added (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + entry_get_private (io, entry)->visibility = ENTRY_VISIBLE; + + if (entry) + entry->parent_object = io; + + if (class->entry_was_added != NULL) + { + class->entry_was_added (io, entry); + } +} + +static gint +indicator_object_real_get_position (IndicatorObject *io) +{ + g_return_val_if_fail (INDICATOR_IS_OBJECT (io), -1); + + return -1; +} + +/** + indicator_object_set_environment: + @io: #IndicatorObject to set on + @env: List of enviroment names to use + + Sets the names of the environment that the indicator is being + loaded into. This allows for indicators to behave differently + in different hosts if need be. +*/ +void +indicator_object_set_environment (IndicatorObject * io, GStrv env) +{ + /* FIXME: should this be a property? */ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + + if (io->priv->environments != NULL) { + g_strfreev(io->priv->environments); + io->priv->environments = NULL; + } + + io->priv->environments = g_strdupv(env); + + return; +} + +/** + indicator_object_get_environment: + @io: #IndicatorObject to get the environment from + + Gets the list of environment strings that this object is + placed into. + + Return value: (transfer none): Gets the list of strings that + represent the environment or NULL if none were given. +*/ +GStrv +indicator_object_get_environment (IndicatorObject * io) +{ + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), NULL); + return io->priv->environments; +} + +/** + indicator_object_check_environment: + @io: #IndicatorObject to check on + @env: Environment that we're looking for + + Convience function to check to see if the specified environment + @env is in our list of environments. + + Return Value: Whether we're in environment @env +*/ +gboolean +indicator_object_check_environment (IndicatorObject * io, const gchar * env) +{ + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), FALSE); + g_return_val_if_fail(env != NULL, FALSE); + + if (io->priv->environments == NULL) { + return FALSE; + } + + int i; + for (i = 0; io->priv->environments[i] != NULL; i++) { + if (g_strcmp0(env, io->priv->environments[i]) == 0) { + return TRUE; + } + } + + return FALSE; +} + +/** + indicator_object_set_visible: + @io: #IndicatorObject to check on + @visible: whether or not the entries should be visible + + Used to set all of an indicator's entries to be visible or hidden. +*/ +void +indicator_object_set_visible (IndicatorObject * io, gboolean visible) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + + GList * l; + GList * entries = get_all_entries (io); + const guint signal_id = signals[visible ? ENTRY_ADDED : ENTRY_REMOVED]; + EntryVisibility visibility = visible ? ENTRY_VISIBLE : ENTRY_INVISIBLE; + const GQuark detail = (GQuark)0; + + for (l=entries; l!=NULL; l=l->next) { + IndicatorObjectEntry *entry = l->data; + if (entry_get_private (io, entry)->visibility != visibility) + g_signal_emit(io, signal_id, detail, entry); + } + g_list_free (entries); +} + +static void +get_property (GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec) +{ + IndicatorObject * self = INDICATOR_OBJECT(object); + g_return_if_fail(self != NULL); + + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(self); + g_return_if_fail(priv != NULL); + + switch (prop_id) { + /* *********************** */ + case PROP_DEFAULT_VISIBILITY: + if (G_VALUE_HOLDS_BOOLEAN(value)) { + g_value_set_boolean(value, priv->default_visibility); + } else { + g_warning("default-visibility property requires a boolean value."); + } + break; + /* *********************** */ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec) +{ + IndicatorObject * self = INDICATOR_OBJECT(object); + g_return_if_fail (self != NULL); + + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(self); + g_return_if_fail (priv != NULL); + + + switch (prop_id) { + + /* *********************** */ + case PROP_DEFAULT_VISIBILITY: + if (G_VALUE_HOLDS_BOOLEAN(value)) { + priv->default_visibility = g_value_get_boolean (value); + } else { + g_warning("default-visibility property requires a boolean value."); + } + break; + + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +gboolean +indicator_object_entry_is_visible (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_val_if_fail (INDICATOR_IS_OBJECT (io), FALSE); + + return entry_get_private (io, entry)->visibility == ENTRY_VISIBLE; +} + +gint +indicator_object_get_position (IndicatorObject *io) +{ + g_return_val_if_fail (INDICATOR_IS_OBJECT (io), FALSE); + + return INDICATOR_OBJECT_GET_CLASS (io)->get_position (io); +} -- cgit v1.2.3