[maemo-commits] [maemo-commits] r10717 - in projects/haf/trunk/hildon-desktop: . libhildonwm src
From: subversion at stage.maemo.org subversion at stage.maemo.orgDate: Thu Mar 22 15:32:50 EET 2007
- Previous message: [maemo-commits] r10716 - in projects/haf/branches/maemo-af-desktop/python-hildondesktop: . libhildondesktop
- Next message: [maemo-commits] r10718 - in projects/haf/trunk/osso-af-startup: debian services
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Author: moimart
Date: 2007-03-22 15:32:49 +0200 (Thu, 22 Mar 2007)
New Revision: 10717
Modified:
projects/haf/trunk/hildon-desktop/ChangeLog
projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm-marshalers.list
projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm-watched-window.h
projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm.c
projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm.h
projects/haf/trunk/hildon-desktop/src/hn-app-switcher.c
Log:
* src/hn-app-switcher.c:
- Set default no of items to 3.
- Bigger main menu button.
- Added close_application_dialog dialog
* libhildonwm/hd-wm.[ch]:
- Added close_application_dialog support.
* libhildonwm/hd-wm-marshalers.list: new marshaler.
* libhildonwm/hd-wm-watched-window.h: Added missing headers.
Modified: projects/haf/trunk/hildon-desktop/ChangeLog
===================================================================
--- projects/haf/trunk/hildon-desktop/ChangeLog 2007-03-22 13:31:04 UTC (rev 10716)
+++ projects/haf/trunk/hildon-desktop/ChangeLog 2007-03-22 13:32:49 UTC (rev 10717)
@@ -1,3 +1,14 @@
+2007-03-21 Moises Martinez <moises.martinez at nokia.com>
+
+ * src/hn-app-switcher.c:
+ - Set default no of items to 3.
+ - Bigger main menu button.
+ - Added close_application_dialog dialog
+ * libhildonwm/hd-wm.[ch]:
+ - Added close_application_dialog support.
+ * libhildonwm/hd-wm-marshalers.list: new marshaler.
+ * libhildonwm/hd-wm-watched-window.h: Added missing headers.
+
2007-03-22 Lucas Rocha <lucas.rocha at nokia.com>
* libhildondesktop/hildon-home-titlebar.[ch],
Modified: projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm-marshalers.list
===================================================================
--- projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm-marshalers.list 2007-03-22 13:31:04 UTC (rev 10716)
+++ projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm-marshalers.list 2007-03-22 13:32:49 UTC (rev 10717)
@@ -1 +1,3 @@
VOID:BOOLEAN,POINTER
+BOOLEAN:UINT,POINTER
+
Modified: projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm-watched-window.h
===================================================================
--- projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm-watched-window.h 2007-03-22 13:31:04 UTC (rev 10716)
+++ projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm-watched-window.h 2007-03-22 13:32:49 UTC (rev 10717)
@@ -33,6 +33,8 @@
#include <libhildonwm/hd-wm.h>
#include <libhildonwm/hd-wm-util.h>
#include <libhildonwm/hd-wm-types.h>
+#include <sys/types.h>
+#include <signal.h>
/* For watched_window_sync(), should go in enum */
Modified: projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm.c
===================================================================
--- projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm.c 2007-03-22 13:31:04 UTC (rev 10716)
+++ projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm.c 2007-03-22 13:32:49 UTC (rev 10717)
@@ -124,6 +124,7 @@
HDWM_SHOW_A_MENU_SIGNAL,
HDWM_APPLICATION_STARTING_SIGNAL,
HDWM_FULLSCREEN,
+ HDWM_CLOSE_APP,
HDWM_SIGNALS
};
@@ -308,7 +309,157 @@
hdwm->priv->atoms);
}
-static HDWMWatchableApp*
+static gint
+hd_wm_cad_compare_items (gconstpointer a, gconstpointer b)
+{
+ HDWMCADItem *ia;
+ HDWMCADItem *ib;
+
+ ia = (HDWMCADItem *)a;
+ ib = (HDWMCADItem *)b;
+
+ return (ib->vmdata - ia->vmdata);
+}
+
+static gboolean
+hd_wm_prepare_close_application_dialog (HDWM *hdwm, HDWMCADAction action, gboolean *retval)
+{
+ GList *l,*items = NULL;
+ gint i;
+
+ for (l = hdwm->priv->applications; l; l = l->next)
+ {
+ guint32 *pid_result = NULL;
+ pid_t pid;
+ GList *p;
+ gboolean pid_exists;
+ HDWMWatchableApp *app;
+ HDWMWatchedWindow* win;
+ GdkAtom a;
+ HDEntryInfo *info;
+ HDWMCADItem *item;
+
+ info = (HDEntryInfo*)l->data;
+ win = hd_entry_info_get_window (info);
+
+ if (win == NULL)
+ {
+ gchar *title = hd_entry_info_get_title (info);
+ g_warning ("No win found for item %s",title);
+ g_free (title);
+ continue;
+ }
+
+ app = hd_wm_watched_window_get_app(win);
+
+ if (app == NULL)
+ {
+ gchar *title = hd_entry_info_get_title (info);
+ g_warning ("No app found for item %s",title);
+ g_free (title);
+ continue;
+ }
+
+ /* Skip hibernating apps */
+ if (hd_wm_watchable_app_is_hibernating (app))
+ continue;
+
+
+ /* FIXME: This is interned here since we don't want to rely on extern
+ * global structures (which are slated for removal anyway).
+ */
+ a = gdk_atom_intern ("_NET_WM_PID", FALSE);
+
+ pid_result = hd_wm_util_get_win_prop_data_and_validate (hd_wm_watched_window_get_x_win(win),
+ gdk_x11_atom_to_xatom (a),
+ XA_CARDINAL,
+ 32,
+ 0,
+ NULL);
+ if (pid_result == NULL)
+ {
+ gchar * title = hd_entry_info_get_title(info);
+ g_warning ("No pid found for item %s",title);
+ g_free (title);
+ continue;
+ }
+
+ /*
+ sanity check -- pid_t can be less than 32 bits, and has to allow
+ for a sign
+ */
+
+ if (sizeof(pid_t) <= sizeof(guint32) &&
+ pid_result[0] > (1 << (sizeof(pid_t)*8 - 1)))
+ {
+ /*
+ something is very wrong; the PID we were given does not fit into pid_t
+ */
+ g_warning ("PID (%d) out of bounds", pid_result[0]);
+ XFree (pid_result);
+ continue;
+ }
+
+
+ pid = pid_result[0];
+
+ /* If we already have the pid, skip item creation */
+ pid_exists = FALSE;
+
+ for (p = items; p != NULL; p = p->next)
+ {
+ HDWMCADItem *item = (HDWMCADItem *) p->data;
+
+ if (item->pid == pid)
+ {
+ pid_exists = TRUE;
+ break;
+ }
+ }
+
+ if (pid_exists)
+ continue;
+
+ g_debug ("%s(): %s is %s, Pid:%i, VmData: %ikB\n", __FUNCTION__, hd_wm_watchable_app_get_name(app),
+ hd_wm_watchable_app_is_hibernating(app) ? "hibernating" : "awake",
+ pid,
+ hd_wm_get_vmdata_for_pid (pid));
+
+ item = g_new0 (HDWMCADItem, 1);
+
+ item->win = win;
+ item->vmdata = hd_wm_get_vmdata_for_pid(pid);
+ item->pid = pid;
+
+ items = g_list_append(items, item);
+ }
+
+ if (g_list_length (items) == 0)
+ /* If there wasn't any items we could kill, return TRUE to try the
+ * action anyway without showing the dialog.
+ */
+ return TRUE;
+
+ /* Sort */
+ items = g_list_sort (items, hd_wm_cad_compare_items);
+
+ i = 0;
+ l = g_list_last(items);
+
+ /* Truncate to 10 items */
+ while (g_list_length (items) > 10)
+ {
+ g_free (l->data);
+ items = g_list_delete_link (items, l);
+ l = g_list_last (items);
+ }
+
+ g_signal_emit_by_name (hdwm, "close-app", action, items, retval);
+
+ return TRUE;
+}
+
+static HDWMWatchableApp *
hd_wm_x_window_is_watchable (HDWM *hdwm, Window xid)
{
HDWMWatchableApp *app;
@@ -733,6 +884,16 @@
1,
G_TYPE_BOOLEAN);
+ hdwm_signals[HDWM_CLOSE_APP] =
+ g_signal_new("close-app",
+ G_OBJECT_CLASS_TYPE(object_class),
+ G_SIGNAL_RUN_LAST,0,
+ NULL, NULL,
+ g_cclosure_user_marshal_BOOLEAN__UINT_POINTER,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_UINT, G_TYPE_POINTER);
+
g_object_class_install_property (object_class,
PROP_INIT_DBUS,
g_param_spec_boolean("init-dbus",
@@ -1114,7 +1275,12 @@
HDWM *hdwm = hd_wm_get_singleton ();
HDWMWatchedWindow *win;
guint pages_used = 0, pages_available = 0;
+ gboolean *killed_by_dialog;
+
+ killed_by_dialog = g_new0 (gboolean,1);
+ *killed_by_dialog = TRUE;
+
g_debug (" Called with '%s'", service_name);
if (service_name == NULL)
@@ -1131,17 +1297,22 @@
(pages_available > 0 && pages_available < hdwm->priv->lowmem_min_distance))
{
gboolean killed = TRUE;
-
+
if (win == NULL)
- g_debug ("%s: %d, killed = tn_close_application_dialog(CAD_ACTION_OPENING);",__FILE__,__LINE__);
+ killed = hd_wm_prepare_close_application_dialog (hdwm,CAD_ACTION_OPENING,killed_by_dialog);
else
- if (hd_wm_watched_window_is_hibernating(win))
- g_debug ("%s: %d, killed = tn_close_application_dialog(CAD_ACTION_SWITCHING);",__FILE__,__LINE__);
-
- if (!killed)
- return FALSE;
+ if (hd_wm_watched_window_is_hibernating (win))
+ killed = hd_wm_prepare_close_application_dialog (hdwm,CAD_ACTION_SWITCHING,killed_by_dialog);
+
+ if (!killed || !killed_by_dialog)
+ {
+ g_free (killed_by_dialog);
+ return FALSE;
+ }
}
+ *killed_by_dialog = TRUE;
+
/* Check how much memory we do have until the lowmem threshold */
if (!hd_wm_memory_get_limits (&pages_used, &pages_available))
@@ -1156,19 +1327,23 @@
*/
if (pages_available > 0 && pages_available < hdwm->priv->lowmem_min_distance)
{
-
gboolean killed = TRUE;
if (win == NULL)
- g_debug ("%s: %d, killed = tn_close_application_dialog(CAD_ACTION_OPENING);",__FILE__,__LINE__);
+ killed = hd_wm_prepare_close_application_dialog (hdwm,CAD_ACTION_OPENING,killed_by_dialog);
else
if (hd_wm_watched_window_is_hibernating (win))
- g_debug ("%s: %d, killed = tn_close_application_dialog(CAD_ACTION_SWITCHING);",__FILE__,__LINE__);
+ killed = hd_wm_prepare_close_application_dialog (hdwm,CAD_ACTION_SWITCHING,killed_by_dialog);
- if (!killed)
+ if (!killed || !killed_by_dialog)
+ {
+ g_free (killed_by_dialog);
return FALSE;
+ }
}
+ g_free (killed_by_dialog);
+
if (win == NULL)
{
/* We dont have a watched window for this service currently
Modified: projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm.h
===================================================================
--- projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm.h 2007-03-22 13:31:04 UTC (rev 10716)
+++ projects/haf/trunk/hildon-desktop/libhildonwm/hd-wm.h 2007-03-22 13:32:49 UTC (rev 10717)
@@ -38,6 +38,7 @@
#include <libhildonwm/hd-wm-types.h>
#include <libhildonwm/hd-entry-info.h>
#include <libhildonwm/hd-wm-watchable-app.h>
+#include <libhildonwm/hd-wm-watched-window.h>
#include <libhildonwm/hd-keys.h>
#define HN_WANT_DEBUG 0 /* Set to 1 for more verbose hn */
@@ -157,8 +158,26 @@
gchar *service;
gchar *wm_class;
gulong window_id;
-} menuitem_comp_t;
+}
+menuitem_comp_t;
+typedef struct
+{
+ HDWMWatchedWindow* win;
+ GObject *button;
+ gint vmdata;
+ guint pid;
+}
+HDWMCADItem;
+
+typedef enum
+{
+ CAD_ACTION_OPENING=0,
+ CAD_ACTION_SWITCHING,
+ CAD_ACTION_OTHER
+}
+HDWMCADAction;
+
struct HDWMLaunchBannerInfo
{
GtkWidget *parent;
Modified: projects/haf/trunk/hildon-desktop/src/hn-app-switcher.c
===================================================================
--- projects/haf/trunk/hildon-desktop/src/hn-app-switcher.c 2007-03-22 13:31:04 UTC (rev 10716)
+++ projects/haf/trunk/hildon-desktop/src/hn-app-switcher.c 2007-03-22 13:32:49 UTC (rev 10717)
@@ -112,7 +112,7 @@
#define AS_MENU_BORDER_WIDTH 20
#define AS_TIP_BORDER_WIDTH 20
#define AS_BUTTON_HEIGHT 38
-#define AS_MENU_BUTTON_HEIGHT 58
+#define AS_MENU_BUTTON_HEIGHT 116
#define AS_ROW_HEIGHT 30
#define AS_ICON_SIZE 26
#define AS_TOOLTIP_WIDTH 360
@@ -162,6 +162,9 @@
static void
queue_refresh_buttons (HNAppSwitcher *app_switcher);
+ static gboolean
+hn_app_switcher_close_application_dialog (HDWM *hdwm, HDWMCADAction action, GList *items);
+
/*
* HNAppSwitcher
*/
@@ -947,6 +950,8 @@
/* remember which button was used to press this button */
g_debug("Main menu button pressed using button %d", event->button);
+
+ /*FIXME: We will have to rewrite this */
/* hd_wm_activate (HN_TN_DEACTIVATE_KEY_FOCUS);*/
#ifndef HILDON_LIBS
if (event->button == APP_BUTTON_THUMBABLE || event->button == 2)
@@ -958,6 +963,7 @@
if (!priv->menu_button_timeout)
priv->is_thumbable = FALSE;
+
if (!priv->menu_button_timeout)
priv->menu_button_timeout = g_timeout_add (100,
(GSourceFunc)
@@ -1199,6 +1205,11 @@
G_CALLBACK (hn_app_switcher_show_menu_cb),
(gpointer)app_switcher);
+ g_signal_connect (app_switcher->hdwm,
+ "close-app",
+ G_CALLBACK (hn_app_switcher_close_application_dialog),
+ NULL);
+
g_signal_connect (app_switcher,
"notify::orientation",
G_CALLBACK (hn_app_switcher_orientation_changed_cb),
@@ -2043,7 +2054,7 @@
"Number of items",
1,
20,
- 4,
+ 3,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
}
@@ -2063,6 +2074,234 @@
hn_app_switcher_init_sound_samples (app_switcher);
}
+static void
+hn_app_switcher_cad_item_toggled (GtkToggleButton *button, gpointer user_data)
+{
+ gboolean selected;
+ GList *l;
+ GList *items;
+ GtkDialog *dialog;
+ HDWMCADItem *item;
+
+ item = NULL;
+ selected = FALSE;
+
+ items = (GList*) user_data;
+
+ for (l = items; l; l = l->next)
+ {
+ item = (HDWMCADItem *) l->data;
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (item->button)))
+ selected = TRUE;
+ }
+
+ dialog = GTK_DIALOG(gtk_widget_get_toplevel(GTK_WIDGET(item->button)));
+
+ gtk_dialog_set_response_sensitive (dialog,
+ GTK_RESPONSE_ACCEPT,
+ selected);
+}
+
+static void
+hn_app_switcher_cad_kill_selected_items (GList *items)
+{
+ GList *l;
+
+ for (l = items; l; l = l->next)
+ {
+ HDWMCADItem *item = (HDWMCADItem *) l->data;
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (item->button))
+ && item->win != NULL)
+ {
+ hd_wm_watched_window_attempt_signal_kill (item->win, SIGTERM, TRUE);
+ }
+ }
+}
+
+static gboolean
+hn_app_switcher_close_application_dialog (HDWM *hdwm, HDWMCADAction action, GList *items)
+{
+ gint response;
+ gint i;
+ gboolean retval;
+ GList *l;
+ GtkWidget *dialog;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *box;
+ GtkWidget *label;
+ GtkWidget *swin;
+ GtkWidget *check;
+ GtkRequisition req;
+
+ items = NULL;
+ check = NULL;
+ req.height = 0;
+
+ /* Creating the UI */
+ dialog = gtk_dialog_new_with_buttons ("Title"/*FIXME: HN_CAD_TITLE*/,
+ NULL,
+ GTK_DIALOG_MODAL
+ | GTK_DIALOG_DESTROY_WITH_PARENT,
+ "Ok"/*FIXME: HN_CAD_OK*/,
+ GTK_RESPONSE_ACCEPT,
+ "Cancel"/*FIXME: HN_CAD_CANCEL*/,
+ GTK_RESPONSE_CANCEL,
+ NULL);
+
+ gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
+ /* Ok is dimmed when there is nothing selected */
+ gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
+ GTK_RESPONSE_ACCEPT,
+ FALSE);
+
+ swin = GTK_WIDGET (g_object_new(GTK_TYPE_SCROLLED_WINDOW,
+ "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ "hscrollbar-policy", GTK_POLICY_NEVER,
+ NULL));
+
+ hbox = GTK_WIDGET (g_object_new(GTK_TYPE_HBOX,
+ "spacing", 12,
+ NULL));
+
+ vbox = GTK_WIDGET(g_object_new(GTK_TYPE_VBOX, NULL));
+
+ label = gtk_label_new ("label_app_list"/*FIXME: HN_CAD_LABEL_APP_LIST*/);
+
+ /* Align to top-right */
+ gtk_misc_set_alignment (GTK_MISC(label), 1, 0);
+
+ gtk_container_add (GTK_CONTAINER(hbox), label);
+ gtk_container_add (GTK_CONTAINER(hbox), vbox);
+
+ /* Collect open applications */
+ for (l = items; l; l = l->next)
+ {
+ const gchar *icon_name;
+ GtkWidget *image;
+ GtkWidget *label;
+ GdkPixbuf *icon = NULL;
+ GtkIconTheme *icon_theme;
+ HDWMWatchableApp *app;
+ HDWMCADItem *item = (HDWMCADItem *) l->data;
+
+ if (item->win == NULL)
+ continue;
+
+ app = hd_wm_watched_window_get_app (item->win);
+
+ if (app == NULL)
+ continue;
+
+ label = gtk_label_new (_(hd_wm_watchable_app_get_name (app)));
+ icon_name = hd_wm_watchable_app_get_icon_name(app);
+ icon_theme = gtk_icon_theme_get_default ();
+
+ if (icon_name)
+ icon = gtk_icon_theme_load_icon (icon_theme,
+ icon_name,
+ ICON_SIZE,
+ GTK_ICON_LOOKUP_NO_SVG,
+ NULL);
+
+ if (!icon)
+ icon = gtk_icon_theme_load_icon (icon_theme,
+ AS_MENU_DEFAULT_APP_ICON,
+ ICON_SIZE,
+ GTK_ICON_LOOKUP_NO_SVG,
+ NULL);
+
+
+ image = gtk_image_new_from_pixbuf (icon);
+ if (icon)
+ gdk_pixbuf_unref (icon);
+
+ check = gtk_check_button_new();
+ item->button = G_OBJECT (check);
+
+ box = GTK_WIDGET (g_object_new (GTK_TYPE_HBOX,
+ "spacing", 12,
+ NULL));
+
+ gtk_container_add (GTK_CONTAINER (box), image);
+ gtk_container_add (GTK_CONTAINER (box), label);
+ gtk_container_add (GTK_CONTAINER (check), box);
+
+ gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, TRUE, 0);
+
+ g_signal_connect (item->button,
+ "toggled",
+ G_CALLBACK(hn_app_switcher_cad_item_toggled),
+ items);
+ }
+
+ switch (action)
+ {
+ case CAD_ACTION_OPENING:
+ label = gtk_label_new ("opening");
+ break;
+ case CAD_ACTION_SWITCHING:
+ label = gtk_label_new ("switching");
+ break;
+ default:
+ label = gtk_label_new("Unlikely internal error happened, but feel free "
+ "to close applications anyway");
+ break;
+ }
+
+ gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
+
+ box = GTK_WIDGET(g_object_new(GTK_TYPE_VBOX,
+ "spacing", 12,
+ NULL));
+
+ gtk_box_pack_start (GTK_BOX(box), label, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX(box), gtk_hseparator_new (), FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX(box), hbox, TRUE, TRUE, 0);
+
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(swin), box);
+ gtk_container_add (GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), swin);
+
+ gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
+
+ /* ScrolledWindow won't request visibly pleasing amounts of space so we need
+ * to do it for it. We ensure that there's vertical space for the whole
+ * content or at least for 5 items (plus one for padding) at a time. We trust
+ * the dialog to not allocate so much space that it would go offscreen.
+ */
+ gtk_widget_size_request (box, &req);
+ i = req.height;
+ gtk_widget_size_request(check, &req);
+ gtk_widget_set_size_request(swin, -1, MIN(i, req.height*6));
+
+ response = gtk_dialog_run (GTK_DIALOG(dialog));
+
+ gtk_widget_hide(dialog);
+
+ switch (response)
+ {
+ case GTK_RESPONSE_ACCEPT:
+ hn_app_switcher_cad_kill_selected_items (items);
+ retval = TRUE;
+
+ break;
+ default:
+ retval = FALSE;
+ break;
+ }
+
+ gtk_widget_destroy (dialog);
+
+ /* Cleanup */
+ for (l = items; l; l = l->next)
+ {
+ if (l->data != NULL)
+ g_free (l->data);
+ }
+
+ return retval;
+}
+
GtkWidget *
hn_app_switcher_new (gint nitems)
{
- Previous message: [maemo-commits] r10716 - in projects/haf/branches/maemo-af-desktop/python-hildondesktop: . libhildondesktop
- Next message: [maemo-commits] r10718 - in projects/haf/trunk/osso-af-startup: debian services
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
