r3938 - in trunk/src/target/OM-2007.2/applications: . openmoko-launcher openmoko-launcher/po openmoko-launcher/src
chris at sita.openmoko.org
chris at sita.openmoko.org
Thu Jan 24 13:28:11 CET 2008
Author: chris
Date: 2008-01-24 13:28:08 +0100 (Thu, 24 Jan 2008)
New Revision: 3938
Added:
trunk/src/target/OM-2007.2/applications/openmoko-launcher/
trunk/src/target/OM-2007.2/applications/openmoko-launcher/AUTHORS
trunk/src/target/OM-2007.2/applications/openmoko-launcher/ChangeLog
trunk/src/target/OM-2007.2/applications/openmoko-launcher/Makefile.am
trunk/src/target/OM-2007.2/applications/openmoko-launcher/NEWS
trunk/src/target/OM-2007.2/applications/openmoko-launcher/README
trunk/src/target/OM-2007.2/applications/openmoko-launcher/autogen.sh
trunk/src/target/OM-2007.2/applications/openmoko-launcher/configure.ac
trunk/src/target/OM-2007.2/applications/openmoko-launcher/po/
trunk/src/target/OM-2007.2/applications/openmoko-launcher/po/ChangeLog
trunk/src/target/OM-2007.2/applications/openmoko-launcher/po/LINGUAS
trunk/src/target/OM-2007.2/applications/openmoko-launcher/po/POTFILES.in
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/launcher-main.c
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/launcher.h
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
trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today.h
Log:
Check-in (completely untested, probably doesn't work yet and missing launcher)
Property changes on: trunk/src/target/OM-2007.2/applications/openmoko-launcher
___________________________________________________________________
Name: svn:externals
+ libtaku -r1898 http://svn.o-hand.com/repos/matchbox/trunk/matchbox-desktop-2/libtaku
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/AUTHORS
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/AUTHORS 2008-01-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/AUTHORS 2008-01-24 12:28:08 UTC (rev 3938)
@@ -0,0 +1 @@
+Chris Lord <chris at openedhand.com>
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/ChangeLog
===================================================================
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/Makefile.am
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/Makefile.am 2008-01-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/Makefile.am 2008-01-24 12:28:08 UTC (rev 3938)
@@ -0,0 +1,20 @@
+SUBDIRS = libtaku src po
+
+INTLTOOL_BUILT = \
+ intltool-extract \
+ intltool-merge \
+ intltool-update
+
+EXTRA_DIST = $(INTLTOOL_BUILT:=.in)
+
+DISTCLEANFILES = $(INTLTOOL_BUILT)
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = aclocal.m4 compile config.guess config.sub \
+ configure depcomp install-sh ltmain.sh \
+ Makefile.in missing config.h.in \
+ intltool-extract intltool-extract.in \
+ intltool-merge intltool-merge.in \
+ intltool-update intltool-update.in \
+ mkinstalldirs
+
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/NEWS
===================================================================
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/README
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/README 2008-01-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/README 2008-01-24 12:28:08 UTC (rev 3938)
@@ -0,0 +1,2 @@
+A simple launcher application - this is mostly code cannibalised from
+openmoko-today2.
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/autogen.sh
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/autogen.sh 2008-01-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/autogen.sh 2008-01-24 12:28:08 UTC (rev 3938)
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+PKG_NAME="openmoko-today"
+
+(test -f $srcdir/configure.ac) || {
+ echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
+ echo " top-level $PKG_NAME directory"
+ exit 1
+}
+
+which gnome-autogen.sh || {
+ echo "You need to install gnome-common from the GNOME CVS"
+ exit 1
+}
+
+REQUIRED_AUTOMAKE_VERSION=1.7 USE_GNOME2_MACROS=0 REQUIRED_GETTEXT_VERSION=0.10.36 . gnome-autogen.sh
Property changes on: trunk/src/target/OM-2007.2/applications/openmoko-launcher/autogen.sh
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/configure.ac
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/configure.ac 2008-01-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/configure.ac 2008-01-24 12:28:08 UTC (rev 3938)
@@ -0,0 +1,56 @@
+AC_PREREQ(2.53)
+AC_INIT(launcher, 0.0, http://www.openedhand.com/)
+AM_INIT_AUTOMAKE()
+AC_CONFIG_SRCDIR(src/launcher-main.c)
+AM_CONFIG_HEADER(config.h)
+AM_MAINTAINER_MODE
+
+LIBGTK_VERSION=2.6.0
+LIBMOKOUI_VERSION=0.0.5
+
+AC_ISC_POSIX
+AC_PROG_CC
+AC_PROG_CC_STDC
+AC_STDC_HEADERS
+AC_PROG_LIBTOOL
+AC_PROG_INTLTOOL([0.35.0])
+
+dnl i18n support
+GETTEXT_PACKAGE=AC_PACKAGE_NAME
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Gettext package])
+AC_SUBST(GETTEXT_PACKAGE)
+AM_GLIB_GNU_GETTEXT
+
+AC_CHECK_HEADERS([sys/inotify.h], inotify_support=yes, inotify_support=no)
+AM_CONDITIONAL(HAVE_INOTIFY, [test "$inotify_support" = "yes"])
+if test x$inotify_support = xyes; then
+ AC_DEFINE(WITH_INOTIFY, [1], [If inotify is enabled])
+fi
+
+PKG_CHECK_MODULES(MOKOUI, libmokoui2 >= $LIBMOKOUI_VERSION)
+PKG_CHECK_MODULES(GTK, gtk+-2.0 >= $LIBGTK_VERSION)
+
+AC_ARG_ENABLE(startup_notification,
+ AC_HELP_STRING([--enable-startup-notification], [enable startup notification support]),
+ enable_startup_notification=$enableval, enable_startup_notification=yes)
+
+if test x$enable_startup_notification != xno; then
+ PKG_CHECK_MODULES(SN, libstartup-notification-1.0, ,
+ AC_MSG_ERROR([*** Required Startup Notification library not installed ***]))
+ AC_DEFINE(USE_LIBSN, [1], [Has Startup Notification Support])
+fi
+
+AC_ARG_ENABLE(standalone,
+ AC_HELP_STRING([--enable-standalone], [run in a window, not as the desktop]),
+ enable_standalone=$enableval, enable_standalone=no)
+if test x$enable_standalone != xno; then
+ AC_DEFINE(STANDALONE, [1], [Run in a window])
+fi
+
+AC_OUTPUT([
+Makefile
+po/Makefile.in
+libtaku/Makefile
+src/Makefile
+])
+
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/po/ChangeLog
===================================================================
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/po/LINGUAS
===================================================================
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/po/POTFILES.in
===================================================================
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/launcher-main.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/launcher-main.c 2008-01-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/launcher-main.c 2008-01-24 12:28:08 UTC (rev 3938)
@@ -0,0 +1,109 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <libtaku/taku-table.h>
+#include <libtaku/taku-launcher-tile.h>
+#include <moko-stock.h>
+#include <moko-finger-scroll.h>
+#include "launcher.h"
+#include "today-task-manager.h"
+
+static void
+today_notebook_add_page_with_icon (GtkWidget *notebook, GtkWidget *child,
+ const gchar *icon_name, int padding)
+{
+ GtkWidget *icon = gtk_image_new_from_icon_name (icon_name,
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ GtkWidget *align = gtk_alignment_new (0.5, 0.5, 1, 1);
+
+ gtk_alignment_set_padding (GTK_ALIGNMENT (align), padding,
+ padding, padding, padding);
+ gtk_container_add (GTK_CONTAINER (align), icon);
+ gtk_widget_show_all (align);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), child, align);
+ gtk_container_child_set (GTK_CONTAINER (notebook), child,
+ "tab-expand", TRUE, NULL);
+}
+
+#ifndef STANDALONE
+static GtkWidget *window;
+
+static void
+workarea_changed (int x, int y, int w, int h)
+{
+ gtk_window_resize (GTK_WINDOW (window), w, h);
+ gtk_window_move (GTK_WINDOW (window), x, y);
+}
+#endif
+
+int
+main (int argc, char **argv)
+{
+ LauncherData data;
+
+ static GOptionEntry entries[] = {
+ { NULL }
+ };
+
+ /* Initialise */
+ bindtextdomain (GETTEXT_PACKAGE, TODAY_LOCALE_DIR);;
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ context = g_option_context_new (_(" - Today's information summary"));
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_add_group (context, gtk_get_option_group (TRUE));
+ g_option_context_parse (context, &argc, &argv, NULL);
+
+ /* init openmoko stock items */
+ moko_stock_register ();
+
+ /* Create widgets */
+ data.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (data.window), _("Home"));
+
+ /* Notebook */
+ data.notebook = gtk_notebook_new ();
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (data.notebook), GTK_POS_BOTTOM);
+ gtk_container_add (GTK_CONTAINER (data.window), data.notebook);
+ gtk_widget_show (data.notebook);
+
+ /* Add launcher page */
+ /*widget = today_launcher_page_create (&data);
+ today_notebook_add_page_with_icon (data.notebook, widget,
+ GTK_STOCK_ADD, 6);
+ gtk_widget_show (widget);*/
+
+ /* Add running tasks page */
+ widget = today_task_manager_page_create (&data);
+ today_notebook_add_page_with_icon (data.notebook, widget,
+ GTK_STOCK_EXECUTE, 6);
+ gtk_widget_show (widget);
+
+ /* Connect up signals */
+ g_signal_connect (G_OBJECT (data.window), "delete-event",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+#ifndef STANDALONE
+ x = 0; y = 0; w = 480; h = 640;
+ gtk_window_set_type_hint (GTK_WINDOW (data.window),
+ GDK_WINDOW_TYPE_HINT_DESKTOP);
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (data.window), TRUE);
+ window = data.window;
+ x_monitor_workarea (gtk_widget_get_screen (window), workarea_changed);
+#else
+ gtk_window_set_default_size (GTK_WINDOW (data.window), 480, 600);
+#endif
+
+ /* Show and start */
+ gtk_widget_show (data.window);
+
+ gtk_main ();
+
+ return 0;
+}
+
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/launcher.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/launcher.h 2008-01-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/launcher.h 2008-01-24 12:28:08 UTC (rev 3938)
@@ -0,0 +1,22 @@
+
+#ifndef LAUNCHER_H
+#define LAUNCHER_H
+
+#include <libtaku/taku-table.h>
+#include <libtaku/taku-launcher-tile.h>
+#include <gtk/gtk.h>
+
+typedef struct {
+ GtkWidget *window;
+ GtkWidget *notebook;
+
+ /* For task manager */
+ GtkWidget *root_window;
+ GtkWidget *tasks_table;
+ GtkToolItem *kill_button;
+ GtkToolItem *killall_button;
+ GtkToolItem *switch_button;
+} LauncherData;
+
+#endif
+
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-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.c 2008-01-24 12:28:08 UTC (rev 3938)
@@ -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;
+}
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-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-task-manager.h 2008-01-24 12:28:08 UTC (rev 3938)
@@ -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
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-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.c 2008-01-24 12:28:08 UTC (rev 3938)
@@ -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;
+}
+
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-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today-utils.h 2008-01-24 12:28:08 UTC (rev 3938)
@@ -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__*/
+
Added: trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today.h 2008-01-23 18:20:27 UTC (rev 3937)
+++ trunk/src/target/OM-2007.2/applications/openmoko-launcher/src/today.h 2008-01-24 12:28:08 UTC (rev 3938)
@@ -0,0 +1,10 @@
+
+#ifndef TODAY_H
+#define TODAY_H
+
+#include "launcher.h"
+
+#define TodayData LauncherData
+
+#endif
+
More information about the commitlog
mailing list