[maemo-commits] [maemo-commits] r9127 - in projects/haf/branches/maemo-af-desktop/hildon-desktop: . data src
From: subversion at stage.maemo.org subversion at stage.maemo.orgDate: Tue Jan 16 16:47:57 EET 2007
- Previous message: [maemo-commits] r9126 - in projects/haf/trunk/osso-af-startup: debian services
- Next message: [maemo-commits] r9128 - in projects/haf/trunk/osso-af-startup: debian top-scripts
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Author: lucasr Date: 2007-01-16 16:47:55 +0200 (Tue, 16 Jan 2007) New Revision: 9127 Added: projects/haf/branches/maemo-af-desktop/hildon-desktop/data/others-button.desktop.in projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hn-others-button.c projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hn-others-button.h Modified: projects/haf/branches/maemo-af-desktop/hildon-desktop/ChangeLog projects/haf/branches/maemo-af-desktop/hildon-desktop/configure.ac projects/haf/branches/maemo-af-desktop/hildon-desktop/data/Makefile.am projects/haf/branches/maemo-af-desktop/hildon-desktop/src/Makefile.am projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hd-plugin-loader-builtin.c Log: 2007-01-16 Lucas Rocha <lucas.rocha at nokia.com> * configure.ac, src/Makefile.am, src/hn-others-button.[ch]: others menu button ported to hildon-desktop. * src/hd-plugin-loader-builtin.c: added others menu support. * data/others-button.desktop.in: others menu button plugin desktop file. Modified: projects/haf/branches/maemo-af-desktop/hildon-desktop/ChangeLog =================================================================== --- projects/haf/branches/maemo-af-desktop/hildon-desktop/ChangeLog 2007-01-16 14:39:18 UTC (rev 9126) +++ projects/haf/branches/maemo-af-desktop/hildon-desktop/ChangeLog 2007-01-16 14:47:55 UTC (rev 9127) @@ -1,3 +1,11 @@ +2007-01-16 Lucas Rocha <lucas.rocha at nokia.com> + + * configure.ac, src/Makefile.am, src/hn-others-button.[ch]: others menu + button ported to hildon-desktop. + * src/hd-plugin-loader-builtin.c: added others menu support. + * data/others-button.desktop.in: others menu button plugin desktop + file. + 2007-01-11 Johan Bilien <johan.bilien at nokia.com> * src/hd-home-background.[ch]: Modified: projects/haf/branches/maemo-af-desktop/hildon-desktop/configure.ac =================================================================== --- projects/haf/branches/maemo-af-desktop/hildon-desktop/configure.ac 2007-01-16 14:39:18 UTC (rev 9126) +++ projects/haf/branches/maemo-af-desktop/hildon-desktop/configure.ac 2007-01-16 14:47:55 UTC (rev 9127) @@ -190,4 +190,5 @@ background-manager/background-manager-dbus.h data/Makefile data/app-switcher.desktop +data/others-button.desktop ]) Modified: projects/haf/branches/maemo-af-desktop/hildon-desktop/data/Makefile.am =================================================================== --- projects/haf/branches/maemo-af-desktop/hildon-desktop/data/Makefile.am 2007-01-16 14:39:18 UTC (rev 9126) +++ projects/haf/branches/maemo-af-desktop/hildon-desktop/data/Makefile.am 2007-01-16 14:47:55 UTC (rev 9127) @@ -6,6 +6,7 @@ home-background.conf hildonnavigatordesktopentry_DATA = \ - app-switcher.desktop + app-switcher.desktop \ + others-button.desktop CLEANFILES = *~ Added: projects/haf/branches/maemo-af-desktop/hildon-desktop/data/others-button.desktop.in =================================================================== --- projects/haf/branches/maemo-af-desktop/hildon-desktop/data/others-button.desktop.in 2007-01-16 14:39:18 UTC (rev 9126) +++ projects/haf/branches/maemo-af-desktop/hildon-desktop/data/others-button.desktop.in 2007-01-16 14:47:55 UTC (rev 9127) @@ -0,0 +1,4 @@ +[Desktop Entry] +Name=Other Menu Button +Type=builtin +X-Path=othersbutton Modified: projects/haf/branches/maemo-af-desktop/hildon-desktop/src/Makefile.am =================================================================== --- projects/haf/branches/maemo-af-desktop/hildon-desktop/src/Makefile.am 2007-01-16 14:39:18 UTC (rev 9126) +++ projects/haf/branches/maemo-af-desktop/hildon-desktop/src/Makefile.am 2007-01-16 14:47:55 UTC (rev 9127) @@ -16,6 +16,7 @@ -I$(top_srcdir) \ -DLOCALEDIR=\"$(localedir)\" \ -DDATADIR=\"$(datadir)\" \ + -DHD_DESKTOP_ENTRY_PATH=\"$(hildondesktopentrydir)\" \ -DHD_DESKTOP_CONFIG_PATH=\"$(hildondesktopconfdir)\" \ -DHD_DESKTOP_MODULE_PATH=\"$(hildondesktoplibdir)\" \ -DHD_DESKTOP_BACKGROUNDS_PATH=\"$(hildondesktopbackgroundsdir)\" \ @@ -52,9 +53,9 @@ HOME_SOURCES = \ hd-home-window.c \ hd-home-window.h \ - hd-home-background-dialog.c \ - hd-home-background-dialog.h \ - hd-home-background.c \ + hd-home-background-dialog.c \ + hd-home-background-dialog.h \ + hd-home-background.c \ hd-home-background.h APP_SWITCHER_SOURCES = \ @@ -71,10 +72,15 @@ hn-app-tooltip.c \ hn-app-tooltip.h +OTHERS_BUTTON_SOURCES = \ + hn-others-button.c \ + hn-others-button.h + hildon_desktop_SOURCES = \ $(PLUGIN_MANAGER_SOURCES) \ $(HOME_SOURCES) \ $(APP_SWITCHER_SOURCES) \ + $(OTHERS_BUTTON_SOURCES) \ hd-desktop.c \ hd-desktop.h \ hd-select-plugins-dialog.c \ Modified: projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hd-plugin-loader-builtin.c =================================================================== --- projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hd-plugin-loader-builtin.c 2007-01-16 14:39:18 UTC (rev 9126) +++ projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hd-plugin-loader-builtin.c 2007-01-16 14:47:55 UTC (rev 9127) @@ -29,13 +29,15 @@ #include "hd-plugin-loader-builtin.h" #include "hd-config.h" #include "hn-app-switcher.h" +#include "hn-others-button.h" #define HD_PLUGIN_LOADER_BUILTIN_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HD_TYPE_PLUGIN_LOADER_BUILTIN, HDPluginLoaderBuiltinPrivate)) G_DEFINE_TYPE (HDPluginLoaderBuiltin, hd_plugin_loader_builtin, HD_TYPE_PLUGIN_LOADER); -#define HD_PLUGIN_LOADER_BUILTIN_APP_SWITCHER "appswitcher" +#define HD_PLUGIN_LOADER_BUILTIN_APP_SWITCHER "appswitcher" +#define HD_PLUGIN_LOADER_BUILTIN_OTHERS_BUTTON "othersbutton" static GList * hd_plugin_loader_builtin_load (HDPluginLoader *loader, GError **error) @@ -64,7 +66,7 @@ HD_PLUGIN_CONFIG_GROUP, HD_PLUGIN_CONFIG_KEY_PATH, &keyfile_error); - g_debug ("path %s",path); + if (keyfile_error) { g_propagate_error (error, keyfile_error); @@ -78,7 +80,13 @@ objects = g_list_append (objects, object); } + else if (!g_ascii_strcasecmp (path, HD_PLUGIN_LOADER_BUILTIN_OTHERS_BUTTON)) + { + GObject *object = g_object_new (HN_TYPE_OTHERS_BUTTON, NULL); + objects = g_list_append (objects, object); + } + g_free (path); return objects; Added: projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hn-others-button.c =================================================================== --- projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hn-others-button.c 2007-01-16 14:39:18 UTC (rev 9126) +++ projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hn-others-button.c 2007-01-16 14:47:55 UTC (rev 9127) @@ -0,0 +1,1020 @@ +/* -*- mode:C; c-file-style:"gnu"; -*- */ +/* + * This file is part of maemo-af-desktop + * + * Copyright (C) 2006 Nokia Corporation. + * + * Contact: Karoliina Salminen <karoliina.t.salminen at nokia.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <errno.h> +#include <sys/resource.h> +#include <string.h> + +#include <glib.h> +#include <glib/gstdio.h> +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> +#include <gdk/gdkx.h> + +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> + +#include <hildon-base-lib/hildon-base-dnotify.h> +#include <hildon-widgets/hildon-finger.h> +#include <libhildondesktop/libhildonmenu.h> +#include <libhildondesktop/hildon-thumb-menu-item.h> +#include <libhildonwm/hd-wm.h> +#include <libosso.h> + +#include "hn-others-button.h" +#include "hn-app-switcher.h" + +#define HN_OTHERS_BUTTON_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HN_TYPE_OTHERS_BUTTON, HNOthersButtonPrivate)) + +G_DEFINE_TYPE (HNOthersButton, hn_others_button, TASKNAVIGATOR_TYPE_ITEM); + +#define NAVIGATOR_BUTTON_THREE "hildon-navigator-button-three" +#define NAVIGATOR_MENU_NAME "menu_from_navigator" + +#define OTHERS_MENU_ICON_NAME "qgn_grid_tasknavigator_others" +#define OTHERS_MENU_ICON_SIZE 64 + +#define MENU_ITEM_DEFAULT_ICON "" +#define MENU_ITEM_SUBMENU_ICON "qgn_list_gene_fldr_cls" +#define MENU_ITEM_SUBMENU_ICON_DIMMED "qgn_list_gene_nonreadable_fldr" +#define MENU_ITEM_DEFAULT_APP_ICON "qgn_list_gene_default_app" +#define MENU_ITEM_ICON_SIZE 26 +#define MENU_ITEM_THUMB_ICON_SIZE 64 + +#define MENU_ITEM_EMPTY_SUBMENU_STRING _( "tana_li_of_noapps" ) + +#define BORDER_WIDTH 7 +#define BUTTON_HEIGHT 90 + +#define MENU_Y_POS 180 +#define MENU_MAX_WIDTH 360 + +#define WORKAREA_ATOM "_NET_WORKAREA" + +#define MENU_ITEM_N_ITEMS(n) dngettext("hildon-fm", "sfil_li_folder_contents_item", "sfil_li_folder_contents_items", n) + +struct _HNOthersButtonPrivate +{ + GtkWidget *button; + guint collapse_id; + gboolean thumb_pressed; + guint dnotify_update_timeout; +}; + +static void hn_others_button_create_menu (HNOthersButton *button); +static void hn_others_button_button_toggled (GtkWidget *widget, HNOthersButton *button); +static gboolean hn_others_button_key_press (GtkWidget* widget, GdkEventKey *event, HNOthersButton *button); +static gboolean hn_others_button_button_press (GtkWidget *widget, GdkEventButton *event, HNOthersButton *button); +static gboolean hn_others_button_button_release(GtkWidget *widget, GdkEventButton *event, HNOthersButton *button); + +static void +hn_others_button_finalize (GObject *gobject) +{ + HNOthersButton *button = HN_OTHERS_BUTTON (gobject); + + if (button->priv->collapse_id) + g_source_remove (button->priv->collapse_id); + + if (button->priv->dnotify_update_timeout) + g_source_remove (button->priv->dnotify_update_timeout); + + if (TASKNAVIGATOR_ITEM (button)->menu) + gtk_widget_destroy (GTK_WIDGET (TASKNAVIGATOR_ITEM (button)->menu)); + + G_OBJECT_CLASS (hn_others_button_parent_class)->finalize (gobject); +} + +static void +hn_others_button_class_init (HNOthersButtonClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = hn_others_button_finalize; + + g_type_class_add_private (gobject_class, sizeof (HNOthersButtonPrivate)); +} + +static void +hn_others_button_init (HNOthersButton *button) +{ + HDWM *hdwm; + GtkWidget *icon; + + HNOthersButtonPrivate *priv = HN_OTHERS_BUTTON_GET_PRIVATE (button); + + button->priv = priv; + + gtk_widget_set_name (GTK_WIDGET(button), NAVIGATOR_BUTTON_THREE); + + gtk_widget_set_extension_events (GTK_WIDGET (button), + GDK_EXTENSION_EVENTS_ALL); + + priv->button = gtk_toggle_button_new (); + + icon = gtk_image_new_from_pixbuf (get_icon (OTHERS_MENU_ICON_NAME, + OTHERS_MENU_ICON_SIZE)); + + if (icon) + { + gtk_container_add (GTK_CONTAINER (priv->button), icon); + } + + gtk_widget_set_size_request (priv->button, 80, 80); + + gtk_widget_show_all (priv->button); + + hdwm = hd_wm_get_singleton (); + hd_wm_set_others_menu_button (hdwm, priv->button); + + g_signal_connect (G_OBJECT (priv->button), + "button-press-event", + G_CALLBACK (hn_others_button_button_press), + button); + + g_signal_connect (G_OBJECT (priv->button), + "button-release-event", + G_CALLBACK (hn_others_button_button_release), + button); + + g_signal_connect (G_OBJECT (priv->button), + "toggled", + G_CALLBACK (hn_others_button_button_toggled), + button); + + g_signal_connect (G_OBJECT (priv->button), + "key-press-event", + G_CALLBACK (hn_others_button_key_press), + button); + + priv->collapse_id = 0; + priv->thumb_pressed = FALSE; + priv->dnotify_update_timeout = 0; + + TASKNAVIGATOR_ITEM (button)->menu = NULL; + + gtk_container_add (GTK_CONTAINER (button), priv->button); +} + +GtkWidget * +hn_others_button_new () +{ + HNOthersButton *button; + + button = g_object_new (HN_TYPE_OTHERS_BUTTON, NULL); + + return GTK_WIDGET (button); +} + +static void +hn_others_menu_size_request(GtkWidget *menu, + GtkRequisition *req, + gpointer data) +{ + if (req->width > MENU_MAX_WIDTH) + { + gtk_widget_set_size_request (GTK_WIDGET (menu), MENU_MAX_WIDTH, -1); + } +} + +static gboolean +hn_others_menu_deactivate (GtkWidget *menu, HNOthersButton *button) +{ + g_return_val_if_fail (button, FALSE); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button->priv->button), + FALSE); + + return TRUE; +} + +static gboolean +hn_others_menu_key_press(GtkWidget *menu, + GdkEventKey *event, + HNOthersButton *button) +{ + HDWM *hdwm = hd_wm_get_singleton (); + + if (event->keyval == GDK_Left || + event->keyval == GDK_KP_Left || + event->keyval == GDK_Escape) + { + gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu)); + + if (event->keyval == GDK_Escape) + { + /* pass focus to the last active application */ + hd_wm_focus_active_window (hdwm); + } + else + { + hd_wm_activate (HD_TN_ACTIVATE_KEY_FOCUS); + gtk_widget_grab_focus (GTK_WIDGET (button->priv->button)); + } + + return TRUE; + } + + return FALSE; +} + +static void +hn_others_menu_activate_item (GtkMenuItem *item, HNOthersButton *button) +{ + gchar *service_field; + gchar *exec_field; + gchar *program = NULL; + GError *error = NULL; + + g_return_if_fail (button); + + if ((service_field = g_object_get_data (G_OBJECT (item), + DESKTOP_ENTRY_SERVICE_FIELD))) + { + /* Launch the app or if it's already running move it to the top */ + hd_wm_top_service (service_field); + } + else + { + /* No way to track hibernation (if any), so call the dialog + unconditionally when in lowmem state */ + if (hd_wm_is_lowmem_situation ()) + { + /* + if (!tn_close_application_dialog (CAD_ACTION_OPENING)) + { + return; + } + */ + } + + exec_field = g_object_get_data (G_OBJECT (item), + DESKTOP_ENTRY_EXEC_FIELD); + + if(exec_field) + { + gchar * space = strchr(exec_field, ' '); + + if(space) + { + gchar *cmd = g_strdup (exec_field); + cmd[space - exec_field] = 0; + + gchar *exc = g_find_program_in_path (cmd); + + program = g_strconcat (exc, space, NULL); + + g_free (exc); + g_free (cmd); + } + else + { + program = g_find_program_in_path (exec_field); + } + } + + if (program) + { + gint argc; + gchar **argv; + GPid child_pid; + + if (g_shell_parse_argv (program, &argc, &argv, &error)) + { + g_spawn_async ( + /* Child's current working directory, + or NULL to inherit parent's */ + NULL, + /* Child's argument vector. [0] is the path of + the program to execute */ + argv, + /* Child's environment, or NULL to inherit + parent's */ + NULL, + /* Flags from GSpawnFlags */ + 0, + /* Function to run in the child just before + exec() */ + NULL, + /* User data for child_setup */ + NULL, + /* Return location for child process ID or NULL */ + &child_pid, + /* Return location for error */ + &error); + } + + if (error) + { + g_error ("Others_menu_activate_item: failed to execute %s: %s.", + exec_field, + error->message); + + g_clear_error (&error); + } + else + { + int priority; + errno = 0; + + /* If the child process inherited desktop's high priority, + * give child default priority */ + priority = getpriority (PRIO_PROCESS, child_pid); + + if (!errno && priority < 0) + { + setpriority (PRIO_PROCESS, child_pid, 0); + } + } + } + else + { + /* We don't have the service name and we don't + * have a path to the executable so it would be + * quite difficult to launch the app. + */ + g_error ("hn_others_menu_activate_item: " + "both service name and binary path missing. " + "Unable to launch."); + } + } + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button->priv->button), + FALSE); + + g_free(program); +} + +static void +hn_others_menu_get_items (GtkMenu *menu, + HNOthersButton *button, + GtkTreeModel *model, + GtkTreeIter *iter) +{ + GtkMenu *submenu = NULL; + + GtkWidget *menu_item = NULL; + + gchar *item_name = NULL; + gchar *item_comment = NULL; + GdkPixbuf *item_icon = NULL; + GdkPixbuf *item_thumb_icon = NULL; + gchar *item_exec = NULL; + gchar *item_service = NULL; + gchar *item_desktop_id = NULL; + gchar *item_text_domain = NULL; + GtkTreeIter child_iter; + gint children; + gboolean my_iterator = FALSE; + + g_return_if_fail (menu); + + if (!model) + { + GtkTreeIter iter0; + + model = get_menu_contents(); + iter = g_malloc0 (sizeof (GtkTreeIter)); + my_iterator = TRUE; + + /* Get the top level iterator. */ + if (!gtk_tree_model_get_iter_first(model, &iter0) || + !gtk_tree_model_iter_children(model, iter, &iter0)) + { + g_object_unref (G_OBJECT (model)); + return; + } + } + else + { + g_object_ref (G_OBJECT (model)); + } + + /* Loop! */ + do { + item_name = NULL; + item_icon = NULL; + item_thumb_icon = NULL; + item_exec = NULL; + item_service = NULL; + item_desktop_id = NULL; + item_text_domain = NULL; + + gtk_tree_model_get (model, iter, + TREE_MODEL_NAME, &item_name, + TREE_MODEL_ICON, &item_icon, + TREE_MODEL_THUMB_ICON, &item_thumb_icon, + TREE_MODEL_EXEC, &item_exec, + TREE_MODEL_SERVICE, &item_service, + TREE_MODEL_DESKTOP_ID, &item_desktop_id, + TREE_MODEL_COMMENT, &item_comment, + TREE_MODEL_TEXT_DOMAIN, &item_text_domain, + -1); + + children = 0; + + /* If the item has children. */ + if (gtk_tree_model_iter_children (model, &child_iter, iter)) + { + gchar *child_string = NULL; + + /* It's a submenu */ + submenu = GTK_MENU (gtk_menu_new ()); + + gtk_widget_set_name (GTK_WIDGET (submenu), + NAVIGATOR_MENU_NAME); + + /* Create a menu item and add it to the menu. */ + children = gtk_tree_model_iter_n_children (model, iter); + child_string = g_strdup_printf(MENU_ITEM_N_ITEMS (children), children); + + menu_item = hildon_thumb_menu_item_new_with_labels ( + (item_text_domain && *item_text_domain) ? + dgettext(item_text_domain, item_name): + _(item_name), + NULL, + child_string); + + g_free(child_string); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + GTK_WIDGET (menu_item)); + + /* Add the submenu icon */ + if (item_icon && item_thumb_icon) + { + hildon_thumb_menu_item_set_images ( + HILDON_THUMB_MENU_ITEM (menu_item), + gtk_image_new_from_pixbuf (item_icon), + gtk_image_new_from_pixbuf (item_thumb_icon)); + } + + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), + GTK_WIDGET (submenu)); + + /* Recurse! */ + hn_others_menu_get_items(submenu, button, model, &child_iter); + } + else if ( !item_desktop_id || strlen( item_desktop_id ) == 0 ) + { + /* Empty submenu. Skip "Extras" */ + if (strcmp (item_name, "tana_fi_extras") != 0) + { + gchar *child_string; + submenu = GTK_MENU(gtk_menu_new()); + + gtk_widget_set_name (GTK_WIDGET(submenu), + NAVIGATOR_MENU_NAME); + + /* Create a menu item and add it to the menu. + */ + child_string = g_strdup_printf(MENU_ITEM_N_ITEMS(children), children); + menu_item = hildon_thumb_menu_item_new_with_labels ( + (item_text_domain && *item_text_domain)? + dgettext(item_text_domain, item_name): + _(item_name), + NULL, + child_string); + + g_free(child_string); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + GTK_WIDGET (menu_item)); + + /* Add the submenu icon */ + if (item_icon) + { + hildon_thumb_menu_item_set_images( + HILDON_THUMB_MENU_ITEM(menu_item), + gtk_image_new_from_pixbuf(item_icon), + gtk_image_new_from_pixbuf(item_thumb_icon)); + } + + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), + GTK_WIDGET (submenu)); + + /* Create a menu item and add it to the menu. */ + GtkWidget *submenu_item = + gtk_image_menu_item_new_with_label (MENU_ITEM_EMPTY_SUBMENU_STRING); + + gtk_widget_set_sensitive (submenu_item, FALSE); + + gtk_menu_shell_append (GTK_MENU_SHELL (submenu), + GTK_WIDGET (submenu_item)); + + } + } + else if (strcmp(item_desktop_id, SEPARATOR_STRING) == 0) + { + /* Separator */ + menu_item = gtk_separator_menu_item_new(); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + GTK_WIDGET (menu_item)); + + } + else + { + /* Application */ + menu_item = hildon_thumb_menu_item_new_with_labels ( + (item_text_domain && *item_text_domain)? + dgettext(item_text_domain, item_name): + _(item_name), + NULL, + /* work around strange behaviour of gettext for + * empty strings + */ + (item_comment && *item_comment)?_(item_comment):""); + + if (!item_icon) + { + item_icon = get_icon (MENU_ITEM_DEFAULT_APP_ICON, + MENU_ITEM_ICON_SIZE); + } + + if (!item_thumb_icon) + { + item_thumb_icon = get_icon (MENU_ITEM_DEFAULT_APP_ICON, + MENU_ITEM_THUMB_ICON_SIZE); + } + + if (item_icon && item_thumb_icon) + { + hildon_thumb_menu_item_set_images ( + HILDON_THUMB_MENU_ITEM (menu_item), + gtk_image_new_from_pixbuf (item_icon), + gtk_image_new_from_pixbuf (item_thumb_icon)); + } + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + GTK_WIDGET (menu_item)); + + g_object_set_data_full (G_OBJECT (menu_item), + DESKTOP_ENTRY_EXEC_FIELD, + g_strdup (item_exec), + g_free); + + g_object_set_data_full (G_OBJECT(menu_item), + DESKTOP_ENTRY_SERVICE_FIELD, + g_strdup (item_service), + g_free); + + /* Connect the signal and callback */ + g_signal_connect (G_OBJECT (menu_item), + "activate", + G_CALLBACK (hn_others_menu_activate_item), + button); + } + + g_free (item_name); + + if (item_icon) + g_object_unref (G_OBJECT (item_icon)); + + if (item_thumb_icon) + g_object_unref (G_OBJECT (item_thumb_icon)); + + g_free (item_exec); + g_free (item_service); + g_free (item_desktop_id); + g_free (item_comment); + g_free (item_text_domain); + + } while (gtk_tree_model_iter_next(model, iter)); + + + if (my_iterator) + { + gtk_tree_iter_free (iter); + + g_debug ("ref count remaining on model %d (should be 1)", + G_OBJECT (model)->ref_count); + } + + g_object_unref (G_OBJECT (model)); +} + +static void +hn_others_menu_populate (HNOthersButton *button) +{ + hn_others_menu_get_items (TASKNAVIGATOR_ITEM (button)->menu, + button, + NULL, + NULL); + + gtk_widget_show_all (GTK_WIDGET (TASKNAVIGATOR_ITEM (button)->menu)); +} + +static void +hn_others_button_create_menu (HNOthersButton *button) +{ + GtkWidget * menu; + + g_return_if_fail (button); + + /* Create the menu shell, and connect callbacks */ + menu = gtk_menu_new (); + + gtk_widget_set_name (menu, NAVIGATOR_MENU_NAME); + + g_signal_connect (G_OBJECT (menu), + "size-request", + G_CALLBACK (hn_others_menu_size_request), + button); + + g_signal_connect (G_OBJECT (menu), + "deactivate", + G_CALLBACK (hn_others_menu_deactivate), + button); + + g_signal_connect (G_OBJECT (menu), + "key-press-event", + G_CALLBACK (hn_others_menu_key_press), + button); + + g_signal_connect (G_OBJECT (menu), + "button-release-event", + G_CALLBACK (hn_app_switcher_menu_button_release_cb), + NULL); + + if (TASKNAVIGATOR_ITEM (button)->menu) + { + /* Destroy the previous version of the menu */ + g_debug ("Destroying previous menu... "); + gtk_widget_destroy (GTK_WIDGET (TASKNAVIGATOR_ITEM (button)->menu)); + g_debug ("done."); + } + + TASKNAVIGATOR_ITEM (button)->menu = GTK_MENU (menu); + + /* Now populate the menu */ + hn_others_menu_populate (button); +} + +static void +hn_others_button_get_workarea (GtkAllocation *allocation) +{ + unsigned long n; + unsigned long extra; + int format; + int status; + Atom property = XInternAtom (GDK_DISPLAY (), WORKAREA_ATOM, FALSE); + Atom realType; + + /* This is needed to get rid of the punned type-pointer + breaks strict aliasing warning*/ + union + { + unsigned char *char_value; + int *int_value; + } value; + + status = XGetWindowProperty (GDK_DISPLAY (), + GDK_ROOT_WINDOW (), + property, + 0L, + 4L, + 0, + XA_CARDINAL, + &realType, + &format, + &n, + &extra, + (unsigned char **) &value.char_value); + + if (status == Success && + realType == XA_CARDINAL && + format == 32 && + n == 4 && + value.char_value != NULL) + { + allocation->x = value.int_value[0]; + allocation->y = value.int_value[1]; + allocation->width = value.int_value[2]; + allocation->height = value.int_value[3]; + } + else + { + allocation->x = 0; + allocation->y = 0; + allocation->width = 0; + allocation->height = 0; + } + + if (value.char_value) + { + XFree(value.char_value); + } +} + +static void +hn_others_button_get_menu_position (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + GtkWidget *button) +{ + GtkRequisition req; + GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(menu)); + int menu_height = 0; + int main_height = 0; + GtkAllocation workarea = { 0, 0, 0, 0 }; + + hn_others_button_get_workarea (&workarea); + + gtk_widget_size_request (GTK_WIDGET (menu), &req); + + menu_height = req.height; + main_height = gdk_screen_get_height (screen); + + *push_in = FALSE; + *x = workarea.x; + + if (main_height - button->allocation.y < menu_height) + { + *y = MAX(0, ((main_height - menu_height) / 2)); + } + else + { + *y = button->allocation.y; + } +} + +static void +hn_others_button_menu_show (HNOthersButton * button) +{ + g_return_if_fail (button); + + if (!TASKNAVIGATOR_ITEM (button)->menu) + hn_others_button_create_menu (button); + + gtk_menu_popup (TASKNAVIGATOR_ITEM (button)->menu, + NULL, + NULL, + (GtkMenuPositionFunc) hn_others_button_get_menu_position, + button, + 1, + gtk_get_current_event_time ()); + + gtk_menu_shell_select_first (GTK_MENU_SHELL (TASKNAVIGATOR_ITEM (button)->menu), + TRUE); +} + +static void +hn_others_button_button_toggled (GtkWidget *widget, HNOthersButton *button) +{ + if (button->priv->collapse_id) + return; + + if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) + { + g_debug ("button not active -- not showing menu"); + return; + } + + g_debug ("showing menu"); + + hn_others_button_menu_show (button); +} + +static gboolean +hn_others_button_key_press (GtkWidget *widget, + GdkEventKey *event, + HNOthersButton *button) +{ + g_return_val_if_fail (button, FALSE); + + if (event->keyval == GDK_Right || + event->keyval == GDK_KP_Enter) + { + hn_others_button_menu_show (button); + return TRUE; + } + else if (event->keyval == GDK_Left || + event->keyval == GDK_KP_Left) + { + hd_wm_activate (HD_TN_ACTIVATE_LAST_APP_WINDOW); + } + + return FALSE; +} + +static gboolean +hn_others_button_button_press (GtkWidget *widget, + GdkEventButton *event, + HNOthersButton *button) +{ + /* Eat all press events to stabilize the behaviour */ + g_debug ("swallowing button-press-event"); + + return TRUE; +} + +/* Since we'll get hundred press events when thumbing the button, we'll need to + * wait for a moment until reacting + */ +static gboolean +hn_others_button_press_collapser (HNOthersButton *button) +{ + g_return_val_if_fail (button, FALSE); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button->priv->button))) + { + g_debug ("deactivating menu"); + gtk_menu_shell_deactivate (GTK_MENU_SHELL (TASKNAVIGATOR_ITEM (button)->menu)); + button->priv->collapse_id = 0; + button->priv->thumb_pressed = FALSE; + + return FALSE; + } + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); + + if (!TASKNAVIGATOR_ITEM (button)->menu) + hn_others_button_create_menu (button); + + if (button->priv->thumb_pressed) + { + hildon_menu_set_thumb_mode (TASKNAVIGATOR_ITEM (button)->menu, TRUE); + } + else + { + hildon_menu_set_thumb_mode(TASKNAVIGATOR_ITEM (button)->menu, FALSE); + } + + hn_others_button_menu_show (button); + + button->priv->collapse_id = 0; + button->priv->thumb_pressed = FALSE; + + return FALSE; +} + +static gboolean +hn_others_button_button_release (GtkWidget *widget, + GdkEventButton *event, + HNOthersButton *button) +{ + /* This has to be done in the release handler, not the press handler, + * otherwise the button gets toggled when there is no corresponding release + * event, or worse, before the release event arrives (in which case, the + * release event is passed to the open menu). + */ + if (button->priv->collapse_id <= 0) + { + hd_wm_activate (HD_TN_DEACTIVATE_KEY_FOCUS); + + button->priv->collapse_id = + g_timeout_add (100, + (GSourceFunc) hn_others_button_press_collapser, + button); + } + + if (hildon_button_event_is_finger (event)) + button->priv->thumb_pressed = TRUE; + + return TRUE; +} + +/* Dnotify dispatches large number of events when a file is modified -- + we use a 1s timeout to wait for the flurry to pass, and then do our stuff */ +static gboolean +hn_others_button_menu_changed (HNOthersButton *button) +{ + g_return_val_if_fail (button, FALSE); + + g_debug ("Creating menu"); + + button->priv->dnotify_update_timeout = 0; + + hn_others_button_create_menu (button); + + return FALSE; +} + +static void +hn_others_button_dnotify_handler (char *path, gpointer data) +{ + HNOthersButton * button = HN_OTHERS_BUTTON (data); + + if (!button->priv->dnotify_update_timeout) + { + button->priv->dnotify_update_timeout = + g_timeout_add (1000, + (GSourceFunc)hn_others_button_menu_changed, + button); + } +} + +void +hn_others_button_dnotify_register (HNOthersButton * button) +{ + const gchar *home_dir; + gchar *dir; + gchar *file = NULL; + gchar *conf_file; + + home_dir = getenv ("HOME"); + + conf_file = g_build_filename (home_dir, USER_MENU_FILE, NULL); + + /* We copy SYSTEMWIDE_MENU_FILE to always track the changes */ + if (!g_file_test (conf_file, G_FILE_TEST_EXISTS)) + if (g_file_get_contents (SYSTEMWIDE_MENU_FILE, &file, NULL, NULL)) + { + g_debug ("I couldn't get contents"); + g_file_set_contents (USER_MENU_FILE, file, -1, NULL); + } + + g_free (file); + + /* Watch systemwide menu conf */ + dir = g_path_get_dirname (SYSTEMWIDE_MENU_FILE); + + if (hildon_dnotify_set_cb ( + (hildon_dnotify_cb_f *) hn_others_button_dnotify_handler, + dir, button) != HILDON_OK) + { + g_error ("Others_menu_initialize_menu: " + "failed setting dnotify callback " + "for systemwide menu conf." ); + } + + g_free (dir); + + /* Watch user specific menu conf */ + if (home_dir && *home_dir) + { + /* Have to get the directory from the path because the USER_MENU_FILE + define might contain directory (it does, in fact). */ + dir = g_path_get_dirname (conf_file); + + g_mkdir (dir, 0755); + + if (dir && *dir) + { + if (hildon_dnotify_set_cb ( + (hildon_dnotify_cb_f *) hn_others_button_dnotify_handler, + dir, button) != HILDON_OK) + { + g_error ("Others_menu_initialize_menu: " + "failed setting dnotify callback " + "for user spesific menu conf." ); + } + } + else + { + g_error ("Others_menu_initialize_menu: " + "failed to create directory '%s'", dir); + } + + g_free (dir); + } + + g_free (conf_file); + + /* Monitor the .desktop directories, so we can regenerate the menu + * when a new application is installed */ + if (hildon_dnotify_set_cb ( + (hildon_dnotify_cb_f *) hn_others_button_dnotify_handler, + HD_DESKTOP_ENTRY_PATH, button) != HILDON_OK) + { + g_error ("Others_menu_initialize_menu: " + "failed setting dnotify callback " + "for .desktop directory." ); + } +} + +void +hn_others_button_close_menu (HNOthersButton *button) +{ + g_return_if_fail (button && HN_IS_OTHERS_BUTTON (button)); + g_return_if_fail (TASKNAVIGATOR_ITEM (button)->menu != NULL); + + gtk_menu_popdown (TASKNAVIGATOR_ITEM (button)->menu); +} Added: projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hn-others-button.h =================================================================== --- projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hn-others-button.h 2007-01-16 14:39:18 UTC (rev 9126) +++ projects/haf/branches/maemo-af-desktop/hildon-desktop/src/hn-others-button.h 2007-01-16 14:47:55 UTC (rev 9127) @@ -0,0 +1,69 @@ +/* -*- mode:C; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This file is part of maemo-af-desktop + * + * Copyright (C) 2006 Nokia Corporation. + * + * Contact: Karoliina Salminen <karoliina.t.salminen at nokia.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HN_OTHERS_BUTTON_H__ +#define __HN_OTHERS_BUTTON_H__ + +#include <glib.h> +#include <glib-object.h> +#include <libhildonwm/hd-wm.h> +#include <libhildondesktop/libhildondesktop.h> + +G_BEGIN_DECLS + +typedef struct _HNOthersButton HNOthersButton; +typedef struct _HNOthersButtonClass HNOthersButtonClass; +typedef struct _HNOthersButtonPrivate HNOthersButtonPrivate; + +#define HN_TYPE_OTHERS_BUTTON (hn_others_button_get_type ()) +#define HN_OTHERS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HN_TYPE_OTHERS_BUTTON, HNOthersButton)) +#define HN_IS_OTHERS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HN_TYPE_OTHERS_BUTTON)) +#define HN_OTHERS_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HN_TYPE_OTHERS_BUTTON, HNOthersButtonClass)) +#define HN_IS_OTHERS_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HN_TYPE_OTHERS_BUTTON)) +#define HN_OTHERS_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HN_TYPE_OTHERS_BUTTON, HNOthersButtonClass)) + +struct _HNOthersButton +{ + TaskNavigatorItem parent_instance; + + HNOthersButtonPrivate *priv; +}; + +struct _HNOthersButtonClass +{ + TaskNavigatorItemClass parent_class; +}; + +GType hn_others_button_get_type (void); + +GtkWidget *hn_others_button_new (void); + +void hn_others_button_dnotify_register (HNOthersButton *button); + +void hn_others_button_close_menu (HNOthersButton *button); + +G_END_DECLS + +#endif /* __HN_OTHERS_BUTTON_H__ */
- Previous message: [maemo-commits] r9126 - in projects/haf/trunk/osso-af-startup: debian services
- Next message: [maemo-commits] r9128 - in projects/haf/trunk/osso-af-startup: debian top-scripts
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]