[maemo-commits] [maemo-commits] r10717 - in projects/haf/trunk/hildon-desktop: . libhildonwm src

From: subversion at stage.maemo.org subversion at stage.maemo.org
Date: Thu Mar 22 15:32:50 EET 2007
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)
 {


More information about the maemo-commits mailing list