[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 ]