r3942 - trunk/src/target/OM-2007.2/applications/openmoko-launcher/src
chris at sita.openmoko.org
chris at sita.openmoko.org
Thu Jan 24 15:26:26 CET 2008
Author: chris
Date: 2008-01-24 15:26:24 +0100 (Thu, 24 Jan 2008)
New Revision: 3942
Added:
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.c
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.h
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.c
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.h
Removed:
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.c
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.h
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.c
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.h
Log:
You can't svn:externals files :(
Deleted: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.c 2008-01-24 14:20:46 UTC (rev 3941)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.c 2008-01-24 14:26:24 UTC (rev 3942)
@@ -1,821 +0,0 @@
-
-#include <string.h>
-#include <moko-stock.h>
-#include <moko-finger-scroll.h>
-#include <libtaku/taku-table.h>
-#include <gdk/gdkx.h>
-#include <X11/Xatom.h>
-#include <glib/gi18n.h>
-#include "today-task-manager.h"
-#include "today-utils.h"
-
-#define DEFAULT_WINDOW_ICON_NAME "gnome-fs-executable"
-
-/* NOTE: Lots of this code taken from windowselector applet in
- * matchbox-panel-2.
- */
-
-enum {
- _NET_CLIENT_LIST,
- UTF8_STRING,
- _NET_WM_VISIBLE_NAME,
- _NET_WM_NAME,
- _NET_WM_ICON,
- _NET_WM_WINDOW_TYPE,
- _NET_CLOSE_WINDOW,
- _NET_ACTIVE_WINDOW,
- N_ATOMS
-};
-
-static gboolean hidden = TRUE;
-static Atom atoms[N_ATOMS];
-static GtkIconSize icon_size;
-
-static GdkFilterReturn
-filter_func (GdkXEvent *xevent, GdkEvent *event, TodayData *data);
-
-/* Retrieves the UTF-8 property @atom from @window */
-static char *
-get_utf8_property (TodayData *data, Window window, Atom atom)
-{
- GdkDisplay *display;
- Atom type;
- int format, result;
- gulong nitems, bytes_after;
- guchar *val;
- char *ret;
-
- display = gtk_widget_get_display (GTK_WIDGET (data->tasks_table));
-
- type = None;
- val = NULL;
-
- gdk_error_trap_push ();
- result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
- window,
- atom,
- 0,
- G_MAXLONG,
- False,
- atoms[UTF8_STRING],
- &type,
- &format,
- &nitems,
- &bytes_after,
- (gpointer) &val);
- gdk_flush ();
- if (gdk_error_trap_pop () || result != Success)
- return NULL;
-
- if (type != atoms[UTF8_STRING] || format != 8 || nitems == 0) {
- if (val)
- XFree (val);
-
- return NULL;
- }
-
- if (!g_utf8_validate ((char *) val, nitems, NULL)) {
- g_warning ("Invalid UTF-8 in window title");
-
- XFree (val);
-
- return NULL;
- }
-
- ret = g_strndup ((char *) val, nitems);
-
- XFree (val);
-
- return ret;
-}
-
-/* Retrieves the text property @atom from @window */
-static char *
-get_text_property (TodayData *data, Window window, Atom atom)
-{
- GdkDisplay *display;
- XTextProperty text;
- char *ret, **list;
- int result, count;
-
- display = gtk_widget_get_display (GTK_WIDGET (data->tasks_table));
-
- gdk_error_trap_push ();
- result = XGetTextProperty (GDK_DISPLAY_XDISPLAY (display),
- window,
- &text,
- atom);
- gdk_flush ();
- if (gdk_error_trap_pop () || result == 0)
- return NULL;
-
- count = gdk_text_property_to_utf8_list
- (gdk_x11_xatom_to_atom (text.encoding),
- text.format,
- text.value,
- text.nitems,
- &list);
- if (count > 0) {
- int i;
-
- ret = list[0];
-
- for (i = 1; i < count; i++)
- g_free (list[i]);
- g_free (list);
- } else
- ret = NULL;
-
- if (text.value)
- XFree (text.value);
-
- return ret;
-}
-
-/* Retrieves the name for @window */
-static char *
-window_get_name (TodayData *data, Window window)
-{
- char *name;
-
- name = get_utf8_property (data,
- window,
- atoms[_NET_WM_VISIBLE_NAME]);
- if (name == NULL) {
- name = get_utf8_property (data,
- window,
- atoms[_NET_WM_NAME]);
- } if (name == NULL) {
- name = get_text_property (data,
- window,
- XA_WM_NAME);
- } if (name == NULL) {
- name = g_strdup (_("(untitled)"));
- }
-
- return name;
-}
-
-/* Retrieves the icon for @window */
-static GdkPixbuf *
-window_get_icon (TodayData *tdata, Window window)
-{
- GdkPixbuf *pixbuf;
- GdkDisplay *display;
- Atom type;
- int format, result;
- int ideal_width, ideal_height, ideal_size;
- int best_width, best_height, best_size;
- int i, npixels, ip;
- gulong nitems, bytes_after, *data, *datap, *best_data;
- GtkSettings *settings;
- guchar *pixdata;
-
- /* First, we read the contents of the _NET_WM_ICON property */
- display = gtk_widget_get_display (GTK_WIDGET (tdata->tasks_table));
-
- type = 0;
-
- gdk_error_trap_push ();
- result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
- window,
- atoms[_NET_WM_ICON],
- 0,
- G_MAXLONG,
- False,
- XA_CARDINAL,
- &type,
- &format,
- &nitems,
- &bytes_after,
- (gpointer) &data);
- gdk_flush ();
- if (gdk_error_trap_pop () || result != Success)
- return NULL;
-
- if (type != XA_CARDINAL || nitems < 3) {
- XFree (data);
-
- return NULL;
- }
-
- /* Got it. Now what size icon are we looking for? */
- settings = gtk_widget_get_settings (GTK_WIDGET (tdata->tasks_table));
- gtk_icon_size_lookup_for_settings (settings,
- icon_size,
- &ideal_width,
- &ideal_height);
-
- ideal_size = (ideal_width + ideal_height) / 2;
-
- /* Try to find the closest match */
- best_data = NULL;
- best_width = best_height = best_size = 0;
-
- datap = data;
- while (nitems > 0) {
- int cur_width, cur_height, cur_size;
- gboolean replace;
-
- if (nitems < 3)
- break;
-
- cur_width = datap[0];
- cur_height = datap[1];
- cur_size = (cur_width + cur_height) / 2;
-
- if (nitems < (2 + cur_width * cur_height))
- break;
-
- if (!best_data) {
- replace = TRUE;
- } else {
- /* Always prefer bigger to smaller */
- if (best_size < ideal_size &&
- cur_size > best_size)
- replace = TRUE;
- /* Prefer smaller bigger */
- else if (best_size > ideal_size &&
- cur_size >= ideal_size &&
- cur_size < best_size)
- replace = TRUE;
- else
- replace = FALSE;
- }
-
- if (replace) {
- best_data = datap + 2;
- best_width = cur_width;
- best_height = cur_height;
- best_size = cur_size;
- }
-
- datap += (2 + cur_width * cur_height);
- nitems -= (2 + cur_width * cur_height);
- }
-
- if (!best_data) {
- XFree (data);
-
- return NULL;
- }
-
- /* Got it. Load it into a pixbuf. */
- npixels = best_width * best_height;
- pixdata = g_new (guchar, npixels * 4);
-
- for (i = 0, ip = 0; i < npixels; i++) {
- /* red */
- pixdata[ip] = (best_data[i] >> 16) & 0xff;
- ip++;
-
- /* green */
- pixdata[ip] = (best_data[i] >> 8) & 0xff;
- ip++;
-
- /* blue */
- pixdata[ip] = best_data[i] & 0xff;
- ip++;
-
- /* alpha */
- pixdata[ip] = best_data[i] >> 24;
- ip++;
- }
-
- pixbuf = gdk_pixbuf_new_from_data (pixdata,
- GDK_COLORSPACE_RGB,
- TRUE,
- 8,
- best_width,
- best_height,
- best_width * 4,
- (GdkPixbufDestroyNotify) g_free,
- NULL);
-
- /* Scale if necessary */
- if (best_width != ideal_width &&
- best_height != ideal_height) {
- GdkPixbuf *scaled;
-
- scaled = gdk_pixbuf_scale_simple (pixbuf,
- ideal_width,
- ideal_height,
- GDK_INTERP_BILINEAR);
- g_object_unref (pixbuf);
-
- pixbuf = scaled;
- }
-
- /* Cleanup */
- XFree (data);
-
- /* Return */
- return pixbuf;
-}
-
-static void
-today_task_manager_free_tasks (TodayData *data)
-{
- GList *c, *children;
-
- /* Free window list */
- children = gtk_container_get_children (
- GTK_CONTAINER (data->tasks_table));
-
- for (c = children; c; c = c->next) {
- GtkWidget *child = GTK_WIDGET (c->data);
- if (TAKU_IS_TILE (child))
- gtk_container_remove (GTK_CONTAINER (
- data->tasks_table), child);
- }
-}
-
-static void
-today_task_manager_populate_tasks (TodayData *data)
-{
- GdkDisplay *display;
- GdkScreen *screen;
- GdkWindow *current;
- Atom type;
- int format, result, i;
- gulong nitems, bytes_after;
- Window *windows;
-
- /* Empty list */
- today_task_manager_free_tasks (data);
-
- /* Return if our main window has gone (e.g. on quit) */
- if ((!data->window) || (!data->window->window)) return;
-
- /* Retrieve list of app windows from root window */
- display = gtk_widget_get_display (data->tasks_table);
- screen = gtk_widget_get_screen (data->tasks_table);
-
- type = None;
-
- gdk_error_trap_push ();
- result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
- GDK_WINDOW_XWINDOW (data->root_window),
- atoms[_NET_CLIENT_LIST],
- 0,
- G_MAXLONG,
- False,
- XA_WINDOW,
- &type,
- &format,
- &nitems,
- &bytes_after,
- (gpointer) &windows);
- gdk_flush ();
- if (gdk_error_trap_pop () || result != Success)
- return;
-
- if (type != XA_WINDOW) {
- XFree (windows);
-
- return;
- }
-
- /* Load into menu */
- current = gdk_screen_get_active_window (screen);
- for (i = 0; i < nitems; i++) {
- char *name;
- GtkWidget *task_tile;
- GdkPixbuf *icon;
- GdkWindow *window;
-
- if (current && GDK_WINDOW_XID (current) == windows[i]) continue;
- if (GDK_WINDOW_XID (data->window->window) == windows[i])
- continue;
-
- if (!(window = gdk_window_foreign_new_for_display (
- display, windows[i]))) continue;
-
- gdk_error_trap_push ();
- if (gdk_window_get_type_hint (window) !=
- GDK_WINDOW_TYPE_HINT_NORMAL) {
- gdk_flush ();
- gdk_error_trap_pop ();
- continue;
- }
- gdk_flush ();
- if (gdk_error_trap_pop ()) continue;
-
- name = window_get_name (data, windows[i]);
- task_tile = taku_icon_tile_new ();
- taku_icon_tile_set_primary (TAKU_ICON_TILE (task_tile), name);
- g_free (name);
- taku_icon_tile_set_secondary (TAKU_ICON_TILE (task_tile), "");
-
- icon = window_get_icon (data, windows[i]);
- if (icon) {
- taku_icon_tile_set_pixbuf (
- TAKU_ICON_TILE (task_tile), icon);
- g_object_unref (icon);
- } else {
- taku_icon_tile_set_icon_name (
- TAKU_ICON_TILE (task_tile),
- DEFAULT_WINDOW_ICON_NAME);
- }
-
- g_object_set_data (G_OBJECT (task_tile),
- "window",
- GUINT_TO_POINTER (windows[i]));
-
- /*g_signal_connect (task_tile,
- "activate",
- G_CALLBACK (window_menu_item_activate_cb),
- applet);*/
-
- gtk_container_add (GTK_CONTAINER (data->tasks_table),
- task_tile);
- gtk_widget_show (task_tile);
- }
- if (current) g_object_unref (current);
-
- /* If no windows were found, insert an insensitive "No tasks" item */
- if (nitems == 0) {
- GtkWidget *task_tile;
-
- task_tile = taku_icon_tile_new ();
- taku_icon_tile_set_primary (TAKU_ICON_TILE (task_tile),
- _("No active tasks"));
-
- gtk_widget_set_sensitive (task_tile, FALSE);
-
- gtk_container_add (GTK_CONTAINER (data->tasks_table),
- task_tile);
- gtk_widget_show (task_tile);
-
- gtk_widget_set_sensitive (
- GTK_WIDGET (data->killall_button), FALSE);
- } else {
- gtk_widget_set_sensitive (
- GTK_WIDGET (data->killall_button), TRUE);
- }
-
- /* Cleanup */
- XFree (windows);
-}
-
-static void
-set_focus_cb (GtkWindow *window, GtkWidget *widget, TodayData *data)
-{
- gtk_widget_set_sensitive (GTK_WIDGET (data->kill_button),
- TAKU_IS_TILE (widget));
- gtk_widget_set_sensitive (GTK_WIDGET (data->switch_button),
- TAKU_IS_TILE (widget));
-}
-
-static void
-page_shown (TodayData *data)
-{
- today_task_manager_populate_tasks (data);
- g_signal_connect (data->window, "set-focus",
- G_CALLBACK (set_focus_cb), data);
-}
-
-static void
-page_hidden (TodayData *data)
-{
- today_task_manager_free_tasks (data);
- g_signal_handlers_disconnect_by_func (data->window, set_focus_cb, data);
-}
-
-static void
-today_task_manager_notify_visible_cb (GObject *gobject,
- GParamSpec *arg1,
- TodayData *data)
-{
- if ((!hidden) && (!GTK_WIDGET_VISIBLE (gobject))) {
- hidden = TRUE;
- page_hidden (data);
- }
-}
-
-static gboolean
-today_task_manager_visibility_notify_event_cb (GtkWidget *widget,
- GdkEventVisibility *event,
- TodayData *data)
-{
- if (((event->state == GDK_VISIBILITY_PARTIAL) ||
- (event->state == GDK_VISIBILITY_UNOBSCURED)) && (hidden)) {
- hidden = FALSE;
- page_shown (data);
- } else if ((event->state == GDK_VISIBILITY_FULLY_OBSCURED) &&
- (!hidden)) {
- hidden = TRUE;
- page_hidden (data);
- }
-
- return FALSE;
-}
-
-static void
-today_task_manager_unmap_cb (GtkWidget *widget, TodayData *data)
-{
- if (!hidden) {
- hidden = TRUE;
- page_hidden (data);
- }
-}
-
-static void
-screen_changed_cb (GtkWidget *button, GdkScreen *old_screen, TodayData *data)
-{
- GdkScreen *screen;
- GdkDisplay *display;
- GdkEventMask events;
-
- if (data->root_window) {
- gdk_window_remove_filter (data->root_window,
- (GdkFilterFunc) filter_func,
- data);
- }
-
- screen = gtk_widget_get_screen (data->tasks_table);
- display = gdk_screen_get_display (screen);
-
- /* Get atoms */
- atoms[_NET_CLIENT_LIST] =
- gdk_x11_get_xatom_by_name_for_display
- (display, "_NET_CLIENT_LIST");
- atoms[UTF8_STRING] =
- gdk_x11_get_xatom_by_name_for_display
- (display, "UTF8_STRING");
- atoms[_NET_WM_NAME] =
- gdk_x11_get_xatom_by_name_for_display
- (display, "_NET_WM_NAME");
- atoms[_NET_WM_VISIBLE_NAME] =
- gdk_x11_get_xatom_by_name_for_display
- (display, "_NET_WM_VISIBLE_NAME");
- atoms[_NET_WM_ICON] =
- gdk_x11_get_xatom_by_name_for_display
- (display, "_NET_WM_ICON");
- atoms[_NET_WM_WINDOW_TYPE] =
- gdk_x11_get_xatom_by_name_for_display
- (display, "_NET_WM_WINDOW_TYPE");
- atoms[_NET_CLOSE_WINDOW] =
- gdk_x11_get_xatom_by_name_for_display
- (display, "_NET_CLOSE_WINDOW");
- atoms[_NET_ACTIVE_WINDOW] =
- gdk_x11_get_xatom_by_name_for_display
- (display, "_NET_ACTIVE_WINDOW");
-
- /* Get root window */
- data->root_window = gdk_screen_get_root_window (screen);
-
- /* Watch _NET_CLIENT_LIST */
- events = gdk_window_get_events (data->root_window);
- if ((events & GDK_PROPERTY_CHANGE_MASK) == 0) {
- gdk_window_set_events (data->root_window,
- events & GDK_PROPERTY_CHANGE_MASK);
- }
-
- gdk_window_add_filter (data->root_window,
- (GdkFilterFunc) filter_func,
- data);
-
- /* Rebuild list if around */
- if (!hidden) today_task_manager_populate_tasks (data);
-}
-
-/* Something happened on the root window */
-static GdkFilterReturn
-filter_func (GdkXEvent *xevent, GdkEvent *event, TodayData *data)
-{
- XEvent *xev;
-
- xev = (XEvent *) xevent;
-
- if (xev->type == PropertyNotify) {
- if (xev->xproperty.atom ==
- atoms[_NET_CLIENT_LIST]) {
- /* _NET_CLIENT_LIST changed.
- * Rebuild menu if around. */
- if (!hidden)
- today_task_manager_populate_tasks (data);
- }
- }
-
- return GDK_FILTER_CONTINUE;
-}
-
-static void
-today_task_manager_kill (TodayData *data, GdkWindow *window)
-{
- /* NOTE: See
- * http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2506711
- */
- if (GDK_IS_WINDOW (window)) {
- XEvent ev;
- memset(&ev, 0, sizeof(ev));
-
- ev.xclient.type = ClientMessage;
- ev.xclient.window = GDK_WINDOW_XID (window);
- ev.xclient.message_type = atoms[_NET_CLOSE_WINDOW];
- ev.xclient.format = 32;
- ev.xclient.data.l[0] = CurrentTime;
- ev.xclient.data.l[1] = GDK_WINDOW_XID (data->root_window);
-
- gdk_error_trap_push();
- XSendEvent (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (data->root_window), False,
- SubstructureRedirectMask, &ev);
-
- XSync(GDK_DISPLAY(),FALSE);
- gdk_flush ();
- gdk_error_trap_pop ();
-
- /* The following code looks equivalent to me, but isn't.. */
- /*GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);
- ((GdkEventAny *)event)->window = g_object_ref (window);
- ((GdkEventAny *)event)->send_event = TRUE;
- ((GdkEventClient *)event)->message_type =
- gdk_x11_xatom_to_atom (atoms[_NET_CLOSE_WINDOW]);
- ((GdkEventClient *)event)->data_format = 32;
- ((GdkEventClient *)event)->data.l[0] = GDK_CURRENT_TIME;
- ((GdkEventClient *)event)->data.l[1] = GDK_WINDOW_XID (
- data->root_window);
-
- gdk_event_send_client_message (event,
- GDK_WINDOW_XID (data->root_window));
- gdk_event_free (event);*/
- }
-}
-
-static void
-today_task_manager_kill_clicked_cb (GtkToolButton *widget, TodayData *data)
-{
- GdkWindow *window;
- GdkDisplay *display;
- Window xid;
- GtkWidget *tile = gtk_window_get_focus (GTK_WINDOW (data->window));
-
- if (!TAKU_IS_ICON_TILE (tile)) return;
-
- display = gtk_widget_get_display (data->tasks_table);
- xid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (tile), "window"));
-
- gdk_error_trap_push ();
- window = gdk_window_foreign_new_for_display (display, xid);
- gdk_flush ();
- gdk_error_trap_pop ();
-
- if (window) today_task_manager_kill (data, window);
-}
-
-static void
-today_task_manager_raise_clicked_cb (GtkToolButton *widget, TodayData *data)
-{
- XEvent ev;
- GdkWindow *window;
- GdkDisplay *display;
- Window xid;
- GtkWidget *tile = gtk_window_get_focus (GTK_WINDOW (data->window));
-
- if (!TAKU_IS_ICON_TILE (tile)) return;
-
- display = gtk_widget_get_display (data->tasks_table);
- xid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (tile), "window"));
- window = gdk_window_foreign_new_for_display (display, xid);
-
- /* NOTE: gdk_window_raise doesn't work? */
- /*gdk_window_raise (window);*/
-
- /* Send a _NET_ACTIVE_WINDOW message */
- /* See
- * http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2506353
- */
- memset(&ev, 0, sizeof(ev));
-
- ev.xclient.type = ClientMessage;
- ev.xclient.window = GDK_WINDOW_XID (window);
- ev.xclient.message_type = atoms[_NET_ACTIVE_WINDOW];
- ev.xclient.format = 32;
- ev.xclient.data.l[0] = 1;
- ev.xclient.data.l[1] = CurrentTime;
- ev.xclient.data.l[2] = GDK_WINDOW_XID (data->root_window);
-
- gdk_error_trap_push();
- XSendEvent (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (data->root_window), False,
- SubstructureRedirectMask, &ev);
-
- XSync(GDK_DISPLAY(),FALSE);
- gdk_flush ();
- gdk_error_trap_pop();
-}
-
-static void
-today_task_manager_killall_clicked_cb (GtkToolButton *widget, TodayData *data)
-{
- GList *c, *children;
- GdkDisplay *display;
- GtkWidget *dialog;
- gint response;
-
- /* Confirmation dialog first */
- dialog = gtk_message_dialog_new (GTK_WINDOW (data->window),
- GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
- "Are you sure you want to close all applications?");
- response = gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-
- if (response != GTK_RESPONSE_YES) return;
-
- display = gtk_widget_get_display (data->tasks_table);
-
- /* Kill all windows */
- children = gtk_container_get_children (
- GTK_CONTAINER (data->tasks_table));
-
- for (c = children; c; c = c->next) {
- GdkWindow *window;
- Window xid;
- GtkWidget *child = GTK_WIDGET (c->data);
-
- if (!TAKU_IS_ICON_TILE (child)) continue;
-
- xid = GPOINTER_TO_UINT (g_object_get_data (
- G_OBJECT (child), "window"));
- window = gdk_window_foreign_new_for_display (display, xid);
-
- today_task_manager_kill (data, window);
- }
-}
-
-GtkWidget *
-today_task_manager_page_create (TodayData *data)
-{
- GtkWidget *vbox, *toolbar, *viewport, *scroll;
-
- icon_size = gtk_icon_size_from_name ("taku-icon");
- if (icon_size == GTK_ICON_SIZE_INVALID) {
- icon_size = GTK_ICON_SIZE_BUTTON;
- }
-
- vbox = gtk_vbox_new (FALSE, 0);
-
- /* Create toolbar */
- toolbar = gtk_toolbar_new ();
- gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0);
-
- /* Kill all apps button */
- data->kill_button = gtk_tool_button_new_from_stock (
- MOKO_STOCK_FOLDER_DELETE);
- gtk_tool_item_set_expand (data->kill_button, TRUE);
- gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->kill_button, 0);
- gtk_toolbar_insert (GTK_TOOLBAR (toolbar),
- gtk_separator_tool_item_new (), 0);
- g_signal_connect (data->kill_button, "clicked",
- G_CALLBACK (today_task_manager_killall_clicked_cb), data);
-
- /* Switch to app button */
- data->switch_button = gtk_tool_button_new_from_stock (GTK_STOCK_JUMP_TO);
- gtk_tool_item_set_expand (data->switch_button, TRUE);
- gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->switch_button, 0);
- gtk_toolbar_insert (GTK_TOOLBAR (toolbar),
- gtk_separator_tool_item_new (), 0);
- g_signal_connect (data->switch_button, "clicked",
- G_CALLBACK (today_task_manager_raise_clicked_cb), data);
-
- /* Kill app button */
- data->killall_button = gtk_tool_button_new_from_stock (GTK_STOCK_DELETE);
- gtk_tool_item_set_expand (data->killall_button, TRUE);
- gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->killall_button, 0);
- g_signal_connect (data->killall_button, "clicked",
- G_CALLBACK (today_task_manager_kill_clicked_cb), data);
-
- /* Viewport / tasks table */
- viewport = gtk_viewport_new (NULL, NULL);
- gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport),
- GTK_SHADOW_NONE);
-
- data->tasks_table = taku_table_new ();
- gtk_container_add (GTK_CONTAINER (viewport), data->tasks_table);
- gtk_widget_show (data->tasks_table);
-
- scroll = moko_finger_scroll_new ();
- gtk_container_add (GTK_CONTAINER (scroll), viewport);
- gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
- gtk_widget_show (viewport);
- gtk_widget_show (scroll);
-
- gtk_widget_show_all (toolbar);
-
- data->root_window = NULL;
-
- gtk_widget_add_events (viewport, GDK_VISIBILITY_NOTIFY_MASK);
- g_signal_connect (G_OBJECT (viewport), "visibility-notify-event",
- G_CALLBACK (today_task_manager_visibility_notify_event_cb),
- data);
- g_signal_connect (G_OBJECT (data->tasks_table), "notify::visible",
- G_CALLBACK (today_task_manager_notify_visible_cb), data);
- g_signal_connect (G_OBJECT (data->tasks_table), "screen-changed",
- G_CALLBACK (screen_changed_cb), data);
- g_signal_connect (G_OBJECT (vbox), "unmap",
- G_CALLBACK (today_task_manager_unmap_cb), data);
-
- return vbox;
-}
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.c 2008-01-24 14:20:46 UTC (rev 3941)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.c 2008-01-24 14:26:24 UTC (rev 3942)
@@ -0,0 +1,821 @@
+
+#include <string.h>
+#include <moko-stock.h>
+#include <moko-finger-scroll.h>
+#include <libtaku/taku-table.h>
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+#include <glib/gi18n.h>
+#include "today-task-manager.h"
+#include "today-utils.h"
+
+#define DEFAULT_WINDOW_ICON_NAME "gnome-fs-executable"
+
+/* NOTE: Lots of this code taken from windowselector applet in
+ * matchbox-panel-2.
+ */
+
+enum {
+ _NET_CLIENT_LIST,
+ UTF8_STRING,
+ _NET_WM_VISIBLE_NAME,
+ _NET_WM_NAME,
+ _NET_WM_ICON,
+ _NET_WM_WINDOW_TYPE,
+ _NET_CLOSE_WINDOW,
+ _NET_ACTIVE_WINDOW,
+ N_ATOMS
+};
+
+static gboolean hidden = TRUE;
+static Atom atoms[N_ATOMS];
+static GtkIconSize icon_size;
+
+static GdkFilterReturn
+filter_func (GdkXEvent *xevent, GdkEvent *event, TodayData *data);
+
+/* Retrieves the UTF-8 property @atom from @window */
+static char *
+get_utf8_property (TodayData *data, Window window, Atom atom)
+{
+ GdkDisplay *display;
+ Atom type;
+ int format, result;
+ gulong nitems, bytes_after;
+ guchar *val;
+ char *ret;
+
+ display = gtk_widget_get_display (GTK_WIDGET (data->tasks_table));
+
+ type = None;
+ val = NULL;
+
+ gdk_error_trap_push ();
+ result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
+ window,
+ atom,
+ 0,
+ G_MAXLONG,
+ False,
+ atoms[UTF8_STRING],
+ &type,
+ &format,
+ &nitems,
+ &bytes_after,
+ (gpointer) &val);
+ gdk_flush ();
+ if (gdk_error_trap_pop () || result != Success)
+ return NULL;
+
+ if (type != atoms[UTF8_STRING] || format != 8 || nitems == 0) {
+ if (val)
+ XFree (val);
+
+ return NULL;
+ }
+
+ if (!g_utf8_validate ((char *) val, nitems, NULL)) {
+ g_warning ("Invalid UTF-8 in window title");
+
+ XFree (val);
+
+ return NULL;
+ }
+
+ ret = g_strndup ((char *) val, nitems);
+
+ XFree (val);
+
+ return ret;
+}
+
+/* Retrieves the text property @atom from @window */
+static char *
+get_text_property (TodayData *data, Window window, Atom atom)
+{
+ GdkDisplay *display;
+ XTextProperty text;
+ char *ret, **list;
+ int result, count;
+
+ display = gtk_widget_get_display (GTK_WIDGET (data->tasks_table));
+
+ gdk_error_trap_push ();
+ result = XGetTextProperty (GDK_DISPLAY_XDISPLAY (display),
+ window,
+ &text,
+ atom);
+ gdk_flush ();
+ if (gdk_error_trap_pop () || result == 0)
+ return NULL;
+
+ count = gdk_text_property_to_utf8_list
+ (gdk_x11_xatom_to_atom (text.encoding),
+ text.format,
+ text.value,
+ text.nitems,
+ &list);
+ if (count > 0) {
+ int i;
+
+ ret = list[0];
+
+ for (i = 1; i < count; i++)
+ g_free (list[i]);
+ g_free (list);
+ } else
+ ret = NULL;
+
+ if (text.value)
+ XFree (text.value);
+
+ return ret;
+}
+
+/* Retrieves the name for @window */
+static char *
+window_get_name (TodayData *data, Window window)
+{
+ char *name;
+
+ name = get_utf8_property (data,
+ window,
+ atoms[_NET_WM_VISIBLE_NAME]);
+ if (name == NULL) {
+ name = get_utf8_property (data,
+ window,
+ atoms[_NET_WM_NAME]);
+ } if (name == NULL) {
+ name = get_text_property (data,
+ window,
+ XA_WM_NAME);
+ } if (name == NULL) {
+ name = g_strdup (_("(untitled)"));
+ }
+
+ return name;
+}
+
+/* Retrieves the icon for @window */
+static GdkPixbuf *
+window_get_icon (TodayData *tdata, Window window)
+{
+ GdkPixbuf *pixbuf;
+ GdkDisplay *display;
+ Atom type;
+ int format, result;
+ int ideal_width, ideal_height, ideal_size;
+ int best_width, best_height, best_size;
+ int i, npixels, ip;
+ gulong nitems, bytes_after, *data, *datap, *best_data;
+ GtkSettings *settings;
+ guchar *pixdata;
+
+ /* First, we read the contents of the _NET_WM_ICON property */
+ display = gtk_widget_get_display (GTK_WIDGET (tdata->tasks_table));
+
+ type = 0;
+
+ gdk_error_trap_push ();
+ result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
+ window,
+ atoms[_NET_WM_ICON],
+ 0,
+ G_MAXLONG,
+ False,
+ XA_CARDINAL,
+ &type,
+ &format,
+ &nitems,
+ &bytes_after,
+ (gpointer) &data);
+ gdk_flush ();
+ if (gdk_error_trap_pop () || result != Success)
+ return NULL;
+
+ if (type != XA_CARDINAL || nitems < 3) {
+ XFree (data);
+
+ return NULL;
+ }
+
+ /* Got it. Now what size icon are we looking for? */
+ settings = gtk_widget_get_settings (GTK_WIDGET (tdata->tasks_table));
+ gtk_icon_size_lookup_for_settings (settings,
+ icon_size,
+ &ideal_width,
+ &ideal_height);
+
+ ideal_size = (ideal_width + ideal_height) / 2;
+
+ /* Try to find the closest match */
+ best_data = NULL;
+ best_width = best_height = best_size = 0;
+
+ datap = data;
+ while (nitems > 0) {
+ int cur_width, cur_height, cur_size;
+ gboolean replace;
+
+ if (nitems < 3)
+ break;
+
+ cur_width = datap[0];
+ cur_height = datap[1];
+ cur_size = (cur_width + cur_height) / 2;
+
+ if (nitems < (2 + cur_width * cur_height))
+ break;
+
+ if (!best_data) {
+ replace = TRUE;
+ } else {
+ /* Always prefer bigger to smaller */
+ if (best_size < ideal_size &&
+ cur_size > best_size)
+ replace = TRUE;
+ /* Prefer smaller bigger */
+ else if (best_size > ideal_size &&
+ cur_size >= ideal_size &&
+ cur_size < best_size)
+ replace = TRUE;
+ else
+ replace = FALSE;
+ }
+
+ if (replace) {
+ best_data = datap + 2;
+ best_width = cur_width;
+ best_height = cur_height;
+ best_size = cur_size;
+ }
+
+ datap += (2 + cur_width * cur_height);
+ nitems -= (2 + cur_width * cur_height);
+ }
+
+ if (!best_data) {
+ XFree (data);
+
+ return NULL;
+ }
+
+ /* Got it. Load it into a pixbuf. */
+ npixels = best_width * best_height;
+ pixdata = g_new (guchar, npixels * 4);
+
+ for (i = 0, ip = 0; i < npixels; i++) {
+ /* red */
+ pixdata[ip] = (best_data[i] >> 16) & 0xff;
+ ip++;
+
+ /* green */
+ pixdata[ip] = (best_data[i] >> 8) & 0xff;
+ ip++;
+
+ /* blue */
+ pixdata[ip] = best_data[i] & 0xff;
+ ip++;
+
+ /* alpha */
+ pixdata[ip] = best_data[i] >> 24;
+ ip++;
+ }
+
+ pixbuf = gdk_pixbuf_new_from_data (pixdata,
+ GDK_COLORSPACE_RGB,
+ TRUE,
+ 8,
+ best_width,
+ best_height,
+ best_width * 4,
+ (GdkPixbufDestroyNotify) g_free,
+ NULL);
+
+ /* Scale if necessary */
+ if (best_width != ideal_width &&
+ best_height != ideal_height) {
+ GdkPixbuf *scaled;
+
+ scaled = gdk_pixbuf_scale_simple (pixbuf,
+ ideal_width,
+ ideal_height,
+ GDK_INTERP_BILINEAR);
+ g_object_unref (pixbuf);
+
+ pixbuf = scaled;
+ }
+
+ /* Cleanup */
+ XFree (data);
+
+ /* Return */
+ return pixbuf;
+}
+
+static void
+today_task_manager_free_tasks (TodayData *data)
+{
+ GList *c, *children;
+
+ /* Free window list */
+ children = gtk_container_get_children (
+ GTK_CONTAINER (data->tasks_table));
+
+ for (c = children; c; c = c->next) {
+ GtkWidget *child = GTK_WIDGET (c->data);
+ if (TAKU_IS_TILE (child))
+ gtk_container_remove (GTK_CONTAINER (
+ data->tasks_table), child);
+ }
+}
+
+static void
+today_task_manager_populate_tasks (TodayData *data)
+{
+ GdkDisplay *display;
+ GdkScreen *screen;
+ GdkWindow *current;
+ Atom type;
+ int format, result, i;
+ gulong nitems, bytes_after;
+ Window *windows;
+
+ /* Empty list */
+ today_task_manager_free_tasks (data);
+
+ /* Return if our main window has gone (e.g. on quit) */
+ if ((!data->window) || (!data->window->window)) return;
+
+ /* Retrieve list of app windows from root window */
+ display = gtk_widget_get_display (data->tasks_table);
+ screen = gtk_widget_get_screen (data->tasks_table);
+
+ type = None;
+
+ gdk_error_trap_push ();
+ result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
+ GDK_WINDOW_XWINDOW (data->root_window),
+ atoms[_NET_CLIENT_LIST],
+ 0,
+ G_MAXLONG,
+ False,
+ XA_WINDOW,
+ &type,
+ &format,
+ &nitems,
+ &bytes_after,
+ (gpointer) &windows);
+ gdk_flush ();
+ if (gdk_error_trap_pop () || result != Success)
+ return;
+
+ if (type != XA_WINDOW) {
+ XFree (windows);
+
+ return;
+ }
+
+ /* Load into menu */
+ current = gdk_screen_get_active_window (screen);
+ for (i = 0; i < nitems; i++) {
+ char *name;
+ GtkWidget *task_tile;
+ GdkPixbuf *icon;
+ GdkWindow *window;
+
+ if (current && GDK_WINDOW_XID (current) == windows[i]) continue;
+ if (GDK_WINDOW_XID (data->window->window) == windows[i])
+ continue;
+
+ if (!(window = gdk_window_foreign_new_for_display (
+ display, windows[i]))) continue;
+
+ gdk_error_trap_push ();
+ if (gdk_window_get_type_hint (window) !=
+ GDK_WINDOW_TYPE_HINT_NORMAL) {
+ gdk_flush ();
+ gdk_error_trap_pop ();
+ continue;
+ }
+ gdk_flush ();
+ if (gdk_error_trap_pop ()) continue;
+
+ name = window_get_name (data, windows[i]);
+ task_tile = taku_icon_tile_new ();
+ taku_icon_tile_set_primary (TAKU_ICON_TILE (task_tile), name);
+ g_free (name);
+ taku_icon_tile_set_secondary (TAKU_ICON_TILE (task_tile), "");
+
+ icon = window_get_icon (data, windows[i]);
+ if (icon) {
+ taku_icon_tile_set_pixbuf (
+ TAKU_ICON_TILE (task_tile), icon);
+ g_object_unref (icon);
+ } else {
+ taku_icon_tile_set_icon_name (
+ TAKU_ICON_TILE (task_tile),
+ DEFAULT_WINDOW_ICON_NAME);
+ }
+
+ g_object_set_data (G_OBJECT (task_tile),
+ "window",
+ GUINT_TO_POINTER (windows[i]));
+
+ /*g_signal_connect (task_tile,
+ "activate",
+ G_CALLBACK (window_menu_item_activate_cb),
+ applet);*/
+
+ gtk_container_add (GTK_CONTAINER (data->tasks_table),
+ task_tile);
+ gtk_widget_show (task_tile);
+ }
+ if (current) g_object_unref (current);
+
+ /* If no windows were found, insert an insensitive "No tasks" item */
+ if (nitems == 0) {
+ GtkWidget *task_tile;
+
+ task_tile = taku_icon_tile_new ();
+ taku_icon_tile_set_primary (TAKU_ICON_TILE (task_tile),
+ _("No active tasks"));
+
+ gtk_widget_set_sensitive (task_tile, FALSE);
+
+ gtk_container_add (GTK_CONTAINER (data->tasks_table),
+ task_tile);
+ gtk_widget_show (task_tile);
+
+ gtk_widget_set_sensitive (
+ GTK_WIDGET (data->killall_button), FALSE);
+ } else {
+ gtk_widget_set_sensitive (
+ GTK_WIDGET (data->killall_button), TRUE);
+ }
+
+ /* Cleanup */
+ XFree (windows);
+}
+
+static void
+set_focus_cb (GtkWindow *window, GtkWidget *widget, TodayData *data)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (data->kill_button),
+ TAKU_IS_TILE (widget));
+ gtk_widget_set_sensitive (GTK_WIDGET (data->switch_button),
+ TAKU_IS_TILE (widget));
+}
+
+static void
+page_shown (TodayData *data)
+{
+ today_task_manager_populate_tasks (data);
+ g_signal_connect (data->window, "set-focus",
+ G_CALLBACK (set_focus_cb), data);
+}
+
+static void
+page_hidden (TodayData *data)
+{
+ today_task_manager_free_tasks (data);
+ g_signal_handlers_disconnect_by_func (data->window, set_focus_cb, data);
+}
+
+static void
+today_task_manager_notify_visible_cb (GObject *gobject,
+ GParamSpec *arg1,
+ TodayData *data)
+{
+ if ((!hidden) && (!GTK_WIDGET_VISIBLE (gobject))) {
+ hidden = TRUE;
+ page_hidden (data);
+ }
+}
+
+static gboolean
+today_task_manager_visibility_notify_event_cb (GtkWidget *widget,
+ GdkEventVisibility *event,
+ TodayData *data)
+{
+ if (((event->state == GDK_VISIBILITY_PARTIAL) ||
+ (event->state == GDK_VISIBILITY_UNOBSCURED)) && (hidden)) {
+ hidden = FALSE;
+ page_shown (data);
+ } else if ((event->state == GDK_VISIBILITY_FULLY_OBSCURED) &&
+ (!hidden)) {
+ hidden = TRUE;
+ page_hidden (data);
+ }
+
+ return FALSE;
+}
+
+static void
+today_task_manager_unmap_cb (GtkWidget *widget, TodayData *data)
+{
+ if (!hidden) {
+ hidden = TRUE;
+ page_hidden (data);
+ }
+}
+
+static void
+screen_changed_cb (GtkWidget *button, GdkScreen *old_screen, TodayData *data)
+{
+ GdkScreen *screen;
+ GdkDisplay *display;
+ GdkEventMask events;
+
+ if (data->root_window) {
+ gdk_window_remove_filter (data->root_window,
+ (GdkFilterFunc) filter_func,
+ data);
+ }
+
+ screen = gtk_widget_get_screen (data->tasks_table);
+ display = gdk_screen_get_display (screen);
+
+ /* Get atoms */
+ atoms[_NET_CLIENT_LIST] =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_NET_CLIENT_LIST");
+ atoms[UTF8_STRING] =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "UTF8_STRING");
+ atoms[_NET_WM_NAME] =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_NET_WM_NAME");
+ atoms[_NET_WM_VISIBLE_NAME] =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_NET_WM_VISIBLE_NAME");
+ atoms[_NET_WM_ICON] =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_NET_WM_ICON");
+ atoms[_NET_WM_WINDOW_TYPE] =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_NET_WM_WINDOW_TYPE");
+ atoms[_NET_CLOSE_WINDOW] =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_NET_CLOSE_WINDOW");
+ atoms[_NET_ACTIVE_WINDOW] =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_NET_ACTIVE_WINDOW");
+
+ /* Get root window */
+ data->root_window = gdk_screen_get_root_window (screen);
+
+ /* Watch _NET_CLIENT_LIST */
+ events = gdk_window_get_events (data->root_window);
+ if ((events & GDK_PROPERTY_CHANGE_MASK) == 0) {
+ gdk_window_set_events (data->root_window,
+ events & GDK_PROPERTY_CHANGE_MASK);
+ }
+
+ gdk_window_add_filter (data->root_window,
+ (GdkFilterFunc) filter_func,
+ data);
+
+ /* Rebuild list if around */
+ if (!hidden) today_task_manager_populate_tasks (data);
+}
+
+/* Something happened on the root window */
+static GdkFilterReturn
+filter_func (GdkXEvent *xevent, GdkEvent *event, TodayData *data)
+{
+ XEvent *xev;
+
+ xev = (XEvent *) xevent;
+
+ if (xev->type == PropertyNotify) {
+ if (xev->xproperty.atom ==
+ atoms[_NET_CLIENT_LIST]) {
+ /* _NET_CLIENT_LIST changed.
+ * Rebuild menu if around. */
+ if (!hidden)
+ today_task_manager_populate_tasks (data);
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+today_task_manager_kill (TodayData *data, GdkWindow *window)
+{
+ /* NOTE: See
+ * http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2506711
+ */
+ if (GDK_IS_WINDOW (window)) {
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = GDK_WINDOW_XID (window);
+ ev.xclient.message_type = atoms[_NET_CLOSE_WINDOW];
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = CurrentTime;
+ ev.xclient.data.l[1] = GDK_WINDOW_XID (data->root_window);
+
+ gdk_error_trap_push();
+ XSendEvent (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (data->root_window), False,
+ SubstructureRedirectMask, &ev);
+
+ XSync(GDK_DISPLAY(),FALSE);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+
+ /* The following code looks equivalent to me, but isn't.. */
+ /*GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);
+ ((GdkEventAny *)event)->window = g_object_ref (window);
+ ((GdkEventAny *)event)->send_event = TRUE;
+ ((GdkEventClient *)event)->message_type =
+ gdk_x11_xatom_to_atom (atoms[_NET_CLOSE_WINDOW]);
+ ((GdkEventClient *)event)->data_format = 32;
+ ((GdkEventClient *)event)->data.l[0] = GDK_CURRENT_TIME;
+ ((GdkEventClient *)event)->data.l[1] = GDK_WINDOW_XID (
+ data->root_window);
+
+ gdk_event_send_client_message (event,
+ GDK_WINDOW_XID (data->root_window));
+ gdk_event_free (event);*/
+ }
+}
+
+static void
+today_task_manager_kill_clicked_cb (GtkToolButton *widget, TodayData *data)
+{
+ GdkWindow *window;
+ GdkDisplay *display;
+ Window xid;
+ GtkWidget *tile = gtk_window_get_focus (GTK_WINDOW (data->window));
+
+ if (!TAKU_IS_ICON_TILE (tile)) return;
+
+ display = gtk_widget_get_display (data->tasks_table);
+ xid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (tile), "window"));
+
+ gdk_error_trap_push ();
+ window = gdk_window_foreign_new_for_display (display, xid);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+
+ if (window) today_task_manager_kill (data, window);
+}
+
+static void
+today_task_manager_raise_clicked_cb (GtkToolButton *widget, TodayData *data)
+{
+ XEvent ev;
+ GdkWindow *window;
+ GdkDisplay *display;
+ Window xid;
+ GtkWidget *tile = gtk_window_get_focus (GTK_WINDOW (data->window));
+
+ if (!TAKU_IS_ICON_TILE (tile)) return;
+
+ display = gtk_widget_get_display (data->tasks_table);
+ xid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (tile), "window"));
+ window = gdk_window_foreign_new_for_display (display, xid);
+
+ /* NOTE: gdk_window_raise doesn't work? */
+ /*gdk_window_raise (window);*/
+
+ /* Send a _NET_ACTIVE_WINDOW message */
+ /* See
+ * http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2506353
+ */
+ memset(&ev, 0, sizeof(ev));
+
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = GDK_WINDOW_XID (window);
+ ev.xclient.message_type = atoms[_NET_ACTIVE_WINDOW];
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = 1;
+ ev.xclient.data.l[1] = CurrentTime;
+ ev.xclient.data.l[2] = GDK_WINDOW_XID (data->root_window);
+
+ gdk_error_trap_push();
+ XSendEvent (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (data->root_window), False,
+ SubstructureRedirectMask, &ev);
+
+ XSync(GDK_DISPLAY(),FALSE);
+ gdk_flush ();
+ gdk_error_trap_pop();
+}
+
+static void
+today_task_manager_killall_clicked_cb (GtkToolButton *widget, TodayData *data)
+{
+ GList *c, *children;
+ GdkDisplay *display;
+ GtkWidget *dialog;
+ gint response;
+
+ /* Confirmation dialog first */
+ dialog = gtk_message_dialog_new (GTK_WINDOW (data->window),
+ GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+ "Are you sure you want to close all applications?");
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ if (response != GTK_RESPONSE_YES) return;
+
+ display = gtk_widget_get_display (data->tasks_table);
+
+ /* Kill all windows */
+ children = gtk_container_get_children (
+ GTK_CONTAINER (data->tasks_table));
+
+ for (c = children; c; c = c->next) {
+ GdkWindow *window;
+ Window xid;
+ GtkWidget *child = GTK_WIDGET (c->data);
+
+ if (!TAKU_IS_ICON_TILE (child)) continue;
+
+ xid = GPOINTER_TO_UINT (g_object_get_data (
+ G_OBJECT (child), "window"));
+ window = gdk_window_foreign_new_for_display (display, xid);
+
+ today_task_manager_kill (data, window);
+ }
+}
+
+GtkWidget *
+today_task_manager_page_create (TodayData *data)
+{
+ GtkWidget *vbox, *toolbar, *viewport, *scroll;
+
+ icon_size = gtk_icon_size_from_name ("taku-icon");
+ if (icon_size == GTK_ICON_SIZE_INVALID) {
+ icon_size = GTK_ICON_SIZE_BUTTON;
+ }
+
+ vbox = gtk_vbox_new (FALSE, 0);
+
+ /* Create toolbar */
+ toolbar = gtk_toolbar_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0);
+
+ /* Kill all apps button */
+ data->kill_button = gtk_tool_button_new_from_stock (
+ MOKO_STOCK_FOLDER_DELETE);
+ gtk_tool_item_set_expand (data->kill_button, TRUE);
+ gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->kill_button, 0);
+ gtk_toolbar_insert (GTK_TOOLBAR (toolbar),
+ gtk_separator_tool_item_new (), 0);
+ g_signal_connect (data->kill_button, "clicked",
+ G_CALLBACK (today_task_manager_killall_clicked_cb), data);
+
+ /* Switch to app button */
+ data->switch_button = gtk_tool_button_new_from_stock (GTK_STOCK_JUMP_TO);
+ gtk_tool_item_set_expand (data->switch_button, TRUE);
+ gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->switch_button, 0);
+ gtk_toolbar_insert (GTK_TOOLBAR (toolbar),
+ gtk_separator_tool_item_new (), 0);
+ g_signal_connect (data->switch_button, "clicked",
+ G_CALLBACK (today_task_manager_raise_clicked_cb), data);
+
+ /* Kill app button */
+ data->killall_button = gtk_tool_button_new_from_stock (GTK_STOCK_DELETE);
+ gtk_tool_item_set_expand (data->killall_button, TRUE);
+ gtk_toolbar_insert (GTK_TOOLBAR (toolbar), data->killall_button, 0);
+ g_signal_connect (data->killall_button, "clicked",
+ G_CALLBACK (today_task_manager_kill_clicked_cb), data);
+
+ /* Viewport / tasks table */
+ viewport = gtk_viewport_new (NULL, NULL);
+ gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport),
+ GTK_SHADOW_NONE);
+
+ data->tasks_table = taku_table_new ();
+ gtk_container_add (GTK_CONTAINER (viewport), data->tasks_table);
+ gtk_widget_show (data->tasks_table);
+
+ scroll = moko_finger_scroll_new ();
+ gtk_container_add (GTK_CONTAINER (scroll), viewport);
+ gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
+ gtk_widget_show (viewport);
+ gtk_widget_show (scroll);
+
+ gtk_widget_show_all (toolbar);
+
+ data->root_window = NULL;
+
+ gtk_widget_add_events (viewport, GDK_VISIBILITY_NOTIFY_MASK);
+ g_signal_connect (G_OBJECT (viewport), "visibility-notify-event",
+ G_CALLBACK (today_task_manager_visibility_notify_event_cb),
+ data);
+ g_signal_connect (G_OBJECT (data->tasks_table), "notify::visible",
+ G_CALLBACK (today_task_manager_notify_visible_cb), data);
+ g_signal_connect (G_OBJECT (data->tasks_table), "screen-changed",
+ G_CALLBACK (screen_changed_cb), data);
+ g_signal_connect (G_OBJECT (vbox), "unmap",
+ G_CALLBACK (today_task_manager_unmap_cb), data);
+
+ return vbox;
+}
Deleted: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.h 2008-01-24 14:20:46 UTC (rev 3941)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.h 2008-01-24 14:26:24 UTC (rev 3942)
@@ -1,9 +0,0 @@
-#ifndef TODAY_TASK_MANAGER_H
-#define TODAY_TASK_MANAGER_H
-
-#include <gtk/gtk.h>
-#include "today.h"
-
-GtkWidget *today_task_manager_page_create (TodayData *data);
-
-#endif
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.h 2008-01-24 14:20:46 UTC (rev 3941)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.h 2008-01-24 14:26:24 UTC (rev 3942)
@@ -0,0 +1,9 @@
+#ifndef TODAY_TASK_MANAGER_H
+#define TODAY_TASK_MANAGER_H
+
+#include <gtk/gtk.h>
+#include "today.h"
+
+GtkWidget *today_task_manager_page_create (TodayData *data);
+
+#endif
Deleted: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.c 2008-01-24 14:20:46 UTC (rev 3941)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.c 2008-01-24 14:26:24 UTC (rev 3942)
@@ -1,37 +0,0 @@
-/*
- * Today - At a glance view of date, time, calender events, todo items and
- * other images.
- *
- * Copyright (C) 2007 by OpenMoko, Inc.
- * Written by OpenedHand Ltd <info at openedhand.com>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <string.h>
-#include <gtk/gtk.h>
-#include "today-utils.h"
-
-GtkToolItem *
-today_toolbutton_new (const gchar *icon_name)
-{
- GtkWidget *icon = gtk_image_new_from_icon_name (icon_name,
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- GtkToolItem *button = gtk_tool_button_new (icon, NULL);
- gtk_tool_item_set_expand (button, TRUE);
- return button;
-}
-
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.c 2008-01-24 14:20:46 UTC (rev 3941)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.c 2008-01-24 14:26:24 UTC (rev 3942)
@@ -0,0 +1,37 @@
+/*
+ * Today - At a glance view of date, time, calender events, todo items and
+ * other images.
+ *
+ * Copyright (C) 2007 by OpenMoko, Inc.
+ * Written by OpenedHand Ltd <info at openedhand.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include "today-utils.h"
+
+GtkToolItem *
+today_toolbutton_new (const gchar *icon_name)
+{
+ GtkWidget *icon = gtk_image_new_from_icon_name (icon_name,
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ GtkToolItem *button = gtk_tool_button_new (icon, NULL);
+ gtk_tool_item_set_expand (button, TRUE);
+ return button;
+}
+
Deleted: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.h 2008-01-24 14:20:46 UTC (rev 3941)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.h 2008-01-24 14:26:24 UTC (rev 3942)
@@ -1,32 +0,0 @@
-/*
- * Today - At a glance view of date, time, calender events, todo items and
- * other images.
- *
- * Copyright (C) 2007 by OpenMoko, Inc.
- * Written by OpenedHand Ltd <info at openedhand.com>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef __TODAY_UTILS_H__
-#define __TODAY_UTILS_H__
-
-#include <glib.h>
-#include <gtk/gtk.h>
-
-GtkToolItem *today_toolbutton_new (const gchar *icon_name);
-
-#endif /*__TODAY_UTILS_H__*/
-
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.h 2008-01-24 14:20:46 UTC (rev 3941)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.h 2008-01-24 14:26:24 UTC (rev 3942)
@@ -0,0 +1,32 @@
+/*
+ * Today - At a glance view of date, time, calender events, todo items and
+ * other images.
+ *
+ * Copyright (C) 2007 by OpenMoko, Inc.
+ * Written by OpenedHand Ltd <info at openedhand.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __TODAY_UTILS_H__
+#define __TODAY_UTILS_H__
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+GtkToolItem *today_toolbutton_new (const gchar *icon_name);
+
+#endif /*__TODAY_UTILS_H__*/
+
More information about the commitlog
mailing list