diff options
author | Marco Pesenti Gritti <marco@localhost.localdomain> | 2007-04-19 17:16:09 (GMT) |
---|---|---|
committer | Marco Pesenti Gritti <marco@localhost.localdomain> | 2007-04-19 17:16:09 (GMT) |
commit | 855f8560b1398e6587ef315b1f361c223965b0f7 (patch) | |
tree | c21c37b826a31e0e9090c595d65885eb2218bcfc /cursor | |
parent | 2ebd40e9ab0d2d74bb29d0b8b3b23064653e295a (diff) |
Cleanup directory structure and rename olpc to sugar
Diffstat (limited to 'cursor')
24 files changed, 1901 insertions, 0 deletions
diff --git a/cursor/Makefile.am b/cursor/Makefile.am new file mode 100644 index 0000000..5f0148f --- /dev/null +++ b/cursor/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = cursorthemegen sugar diff --git a/cursor/cursorthemegen/ChangeLog b/cursor/cursorthemegen/ChangeLog new file mode 100644 index 0000000..40bcc7e --- /dev/null +++ b/cursor/cursorthemegen/ChangeLog @@ -0,0 +1,48 @@ +2003-08-06 Alexander Larsson <alexl@redhat.com> + + * main.c (cursor_get_image): + Define variables at top of function. + +2003-02-22 Matt Wilson <msw@redhat.com> + + * main.c (cursor_source_find_image): use tmp_list = + tmp_list->next;, not tmp_list = tmp_list++; + (cursor_add_source): convert missing frames into warnings + (cursor_theme_write_cursor): skip frames of size -1 (they're + missing cursor files) + +Tue Feb 4 14:52:27 2003 Owen Taylor <otaylor@redhat.com> + + * main.c (cursor_theme_check_alias): Add a warning if + the alias is defined but missing in the image. (#83252) + +2003-01-17 Havoc Pennington <hp@redhat.com> + + * Makefile.am (cursorthemegen_SOURCES): fix distcheck + +Thu Jan 16 15:25:47 2003 Owen Taylor <otaylor@redhat.com> + + * README: Add, add some docs. + + * main.c themefile.c cursortheme.h: Put under MIT-style + license. + + * Makefile.am generic.cursortheme sample.cursortheme: + Rename generic.cursortheme => sample.cursortheme + +Wed Jan 15 23:48:39 2003 Owen Taylor <otaylor@redhat.com> + + * main.c themefile.c: Use a hash table instead of a + list of cursors. + + * themefile.c generic.cursortheme: Remove <sources> element, + put <source> elements directly under <theme> node. + + * themefile.c generic.cursortheme: Rename <rows> element to + <layout>. + +Wed Jan 15 18:25:24 2003 Owen Taylor <otaylor@redhat.com> + + * Import sources into CVS, start ChangeLog + + diff --git a/cursor/cursorthemegen/Makefile.am b/cursor/cursorthemegen/Makefile.am new file mode 100644 index 0000000..3ef188d --- /dev/null +++ b/cursor/cursorthemegen/Makefile.am @@ -0,0 +1,11 @@ +INCLUDES = $(GDK_PIXBUF2_CFLAGS) + +noinst_PROGRAMS = cursorthemegen + +cursorthemegen_LDADD = $(GDK_PIXBUF2_LIBS) +cursorthemegen_SOURCES = \ + cursortheme.h \ + themefile.c \ + main.c + +EXTRA_DIST = sample.cursortheme diff --git a/cursor/cursorthemegen/README b/cursor/cursorthemegen/README new file mode 100644 index 0000000..e43a7c1 --- /dev/null +++ b/cursor/cursorthemegen/README @@ -0,0 +1,186 @@ +Introduction +============ + +cursorthemegen is a utility for generating libXcursor +cursor themes. + +The inputs to cursorthemegen are conceptually: + + A) A set of multi-layer images, one for each + size. + B) A XML theme description file + +Each image contains all the cursors arranged in +a grid; the layers are: + + - A layer with a dot for the hotspot of each cursor + - The main image or first animation frame for multi-frame + animated cursors + - The second animation frame for multi-frame animated cursors + - ... + +In practice, since loading of multilayer images is not +supported by standard image libraries, each layer is +input as a separate image file. + +The cursor theme file contains information about the +source images to read, the location of each named +cursor within the grid, and a set of aliases from +names to other names. + + +Invocation +========== + +cursorthemegen takes two arguments: + + cursorthemegen THEMEFILE OUTPUTDIR + +cursorthemegen reads in THEMEFILE, compiles a cursor +theme from it, creates the OUTPUTDIR directory and +writes the result in it. The OUTPUTDIR directory must +not already exist. + + +Theme file format +================= + +The tags in the Theme file format are: + +<theme>: The toplevel element. There must be + exactly one of these. + + Attributes: + name: The name of the theme. Required. + + Child elements: + <alias>, <layout>, <source> + +<alias>: The alias element defines an alias of + one cursor name to another cursor. + + Attributes: + name: The name of the alias. Required. + target: The name cursor (or alias) to which the + alias points. Required. + + Child elements: + None + +<source>: Defines a multilayer source + + Attributes: + size: The nominal size of the cursors in the + this source. This is used when selecting a + cursor. Required. + + gridsize: The size of the grid used for this + source. Defaults to the same as 'size'. + Optional. + + Child elements: + <image> + +<image>: One layer in a multilayer source + + Attributes: + file: The filename to get the image from. Required. + use: Either an integer indicating what animation + frame this is (0, 1, ...) or "hotspot" to + indicate that this frame contains hotspots. Required. + + Child elements: + None + +<layout>: Defines the layout of cursors within the grid. + + Attributes: + None + + Child elements: + <row> + +<row>: Defines one row of cursors within the grid + + Attributes: + None + + Child elements: + <cursor> + +<cursor>: Defines a single cursor. If there are no + child <frame> elements, it is assumed to be a non-animated + cursor with a single frame in it. Otherwise, one + or more frames is specified with child <frame> elements. + + Attributes: + name: The name of the cursor. Required. + + Child elements: + <frame> + +<frame>: Defines one frame of a multiframe cursor. + + Attributes: + delay: The delay before the next frame is shown in + milliseconds. Optional. (If you don't specify the delays + for a multiframe animation, the result is undefined.) + + Child elements: + None + +Note that cursorthemegen doesn't actually use a full +XML parser, but the XML-subset GMarkup parser from +GLib, so some less common XML constructs may not work. + + +Makefile example +================ + +Makefile rules for generating and installing a theme +look like: + +bluecurve_images = \ + Bluecurve-1-24.png \ + Bluecurve-2-24.png \ + Bluecurve-hotspot-24.png + +Bluecurve.stamp: $(bluecurve_images) Bluecurve.cursortheme + rm -rf Bluecurve && \ + $(THEMEGEN) Bluecurve.cursortheme Bluecurve && \ + touch Bluecurve.stamp + +install: + rm -rf $(datadir)/icons/Bluecurve/cursors + mkdir -p $(datadir)/icons/Bluecurve/cursors + for i in `cd Bluecurve && echo *` ; do \ + if test -L Bluecurve/$$i ; then \ + cp -d Bluecurve/$$i $(datadir)/icons/Bluecurve/cursors/$$i ; \ + else \ + install -m 0644 Bluecurve/$$i $(datadir)/icons/Bluecurve/cursors/$$i ; \ + fi ; \ + done + + +License +======= + +Copyright © 2003 Red Hat, Inc. + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of Red Hat not be used in advertising or +publicity pertaining to distribution of the software without specific, +written prior permission. Red Hat makes no representations about the +suitability of this software for any purpose. It is provided "as is" +without express or implied warranty. + +RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT +BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + diff --git a/cursor/cursorthemegen/cursortheme.h b/cursor/cursorthemegen/cursortheme.h new file mode 100644 index 0000000..78f14fc --- /dev/null +++ b/cursor/cursorthemegen/cursortheme.h @@ -0,0 +1,92 @@ +/* + * Copyright © 2003 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + */ +#ifndef __CURSORTHEME_H__ +#define __CURSORTHEME_H__ + +#include <gdk-pixbuf/gdk-pixbuf.h> + +G_BEGIN_DECLS + +typedef struct _Cursor Cursor; +typedef struct _CursorAlias CursorAlias; +typedef struct _CursorFrame CursorFrame; +typedef struct _CursorFrameConfig CursorFrameConfig; +typedef struct _CursorImage CursorImage; +typedef struct _CursorSource CursorSource; +typedef struct _CursorTheme CursorTheme; + +struct _Cursor +{ + char *name; + int row; + int column; + GSList *frame_configs; + GSList *frames; +}; + +struct _CursorAlias +{ + char *name; + char *target; +}; + +struct _CursorFrameConfig +{ + int delay; +}; + +struct _CursorFrame +{ + int size; + int hot_x; + int hot_y; + int delay; + GdkPixbuf *image; +}; + +struct _CursorImage +{ + int use; /* Frame number or -1 for hotspot */ + GdkPixbuf *image; +}; + +struct _CursorSource +{ + int size; + int gridsize; + GSList *images; +}; + +struct _CursorTheme +{ + char *name; + GSList *sources; + GHashTable *cursors; + GHashTable *aliases; +}; + +CursorTheme *cursor_theme_read (const char *filename); + +G_END_DECLS + +#endif /* __CURSORTHEME_H__ */ diff --git a/cursor/cursorthemegen/main.c b/cursor/cursorthemegen/main.c new file mode 100644 index 0000000..fa1d3d1 --- /dev/null +++ b/cursor/cursorthemegen/main.c @@ -0,0 +1,615 @@ +/* + * Copyright © 2003 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + */ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "cursortheme.h" + +static CursorImage * +cursor_source_find_image (CursorSource *source, + int use) +{ + GSList *tmp_list; + + for (tmp_list = source->images; tmp_list; tmp_list = tmp_list->next) + { + CursorImage *image = tmp_list->data; + + if (image->use == use) + return image; + } + + return NULL; +} + +static gboolean +cursor_find_hotspot (Cursor *cursor, + CursorSource *source, + int *hot_x, + int *hot_y) +{ + CursorImage *image; + int x = cursor->column * source->gridsize; + int y = cursor->row * source->gridsize; + + *hot_x = -1; + *hot_y = -1; + + image = cursor_source_find_image (source, -1); + if (!image) + { + g_printerr ("Source at size %d doesn't have a hotspot image\n", + source->size); + return FALSE; + } + + if (!gdk_pixbuf_get_has_alpha (image->image) || + gdk_pixbuf_get_colorspace (image->image) != GDK_COLORSPACE_RGB) + { + g_printerr ("Invalid format for hotspot file\n"); + return FALSE; + } + + if (x + source->gridsize <= gdk_pixbuf_get_width (image->image) && + y + source->gridsize <= gdk_pixbuf_get_height (image->image)) + { + int rowstride; + guchar *pixels; + int i, j; + + rowstride = gdk_pixbuf_get_rowstride (image->image); + pixels = gdk_pixbuf_get_pixels (image->image) + y * rowstride + x * 4; + for (j = 0; j < source->gridsize; j++) + { + for (i = 0; i < source->gridsize; i++) + { + if (pixels[4*i + 3] > 0x80) + { + if (*hot_x >=0 || *hot_y >= 0) + { + g_printerr ("Multiple hotspots for cursor %s at size %d\n", + cursor->name, source->size); + return FALSE; + } + *hot_x = i; + *hot_y = j; + } + } + pixels += rowstride; + } + } + + if (*hot_x == -1 || *hot_y == -1) + { + g_printerr ("Cannot find hotspot for cursor %s at size %d\n", + cursor->name, source->size); + return FALSE; + } + + return TRUE; +} + +static gboolean +cursor_is_present (Cursor *cursor, + CursorSource *source, + int frame) +{ + CursorImage *image = cursor_source_find_image (source, frame); + int x = cursor->column * source->gridsize; + int y = cursor->row * source->gridsize; + int i, j; + + const guchar *pixels; + int rowstride; + int n_channels; + + if (!image) + return FALSE; + + if (gdk_pixbuf_get_colorspace (image->image) != GDK_COLORSPACE_RGB) + { + g_printerr ("Invalid format for image file\n"); + return FALSE; + } + + if (x + source->gridsize > gdk_pixbuf_get_width (image->image) || + y + source->gridsize > gdk_pixbuf_get_height (image->image)) + return FALSE; + + rowstride = gdk_pixbuf_get_rowstride (image->image); + n_channels = gdk_pixbuf_get_n_channels (image->image); + + if (n_channels == 3) + return TRUE; + + pixels = gdk_pixbuf_get_pixels (image->image) + y * rowstride + x * 4; + + for (j = 0; j < source->gridsize; j++) + { + for (i = 0; i < source->gridsize; i++) + { + if (pixels[4*i + 3] != 0) + return TRUE; + } + pixels += rowstride; + } + + return FALSE; +} + +static void +cursor_frame_find_bounds (Cursor *cursor, + CursorFrame *frame, + CursorSource *source, + int frame_index, + int *x, + int *y, + int *width, + int *height) +{ + CursorImage *image = cursor_source_find_image (source, frame_index); + int start_x = cursor->column * source->gridsize; + int start_y = cursor->row * source->gridsize; + int i, j; + + const guchar *pixels; + int rowstride; + int n_channels; + + rowstride = gdk_pixbuf_get_rowstride (image->image); + n_channels = gdk_pixbuf_get_n_channels (image->image); + + if (n_channels == 3) + { + *x = start_x; + *y = start_x; + *width = source->gridsize; + *height = source->gridsize; + + return; + } + else + { + int min_x = start_x + frame->hot_x; + int max_x = start_x + frame->hot_x + 1; + int min_y = start_y + frame->hot_y; + int max_y = start_y + frame->hot_y + 1; + + pixels = gdk_pixbuf_get_pixels (image->image) + start_y * rowstride + start_x * 4; + + for (j = 0; j < source->gridsize; j++) + { + for (i = 0; i < source->gridsize; i++) + { + if (pixels[4*i + 3] != 0) + { + if (start_x + i < min_x) + min_x = start_x + i; + if (start_x + i >= max_x) + max_x = start_x + i + 1; + if (start_y + j < min_y) + min_y = start_y + j; + if (start_y + j >= max_y) + max_y = start_y + j + 1; + } + } + + pixels += rowstride; + } + + *x = min_x; + *y = min_y; + *width = max_x - min_x; + *height = max_y - min_y; + } +} + +static void +cursor_get_image (Cursor *cursor, + CursorFrame *frame, + CursorSource *source, + int frame_index, + int x, + int y, + int width, + int height) +{ + CursorImage *image = cursor_source_find_image (source, frame_index); + GdkPixbuf *tmp_pixbuf; + + /*cursor_frame_find_bounds (cursor, frame, source, frame_index, + &x, &y, &width, &height); +*/ + tmp_pixbuf = gdk_pixbuf_new_subpixbuf (image->image, + x, y, width, height); + + frame->hot_x -= x - cursor->column * source->gridsize; + frame->hot_y -= y - cursor->row * source->gridsize; + + frame->image = gdk_pixbuf_copy (tmp_pixbuf); + g_object_unref (tmp_pixbuf); +} + +static gboolean +cursor_add_source (Cursor *cursor, + CursorSource *source) +{ + GSList *tmp_list; + int hot_x, hot_y; + int i; + int x, y, x2, y2, height, width; + + /* If the first frame is missing we silently treat + * it as OK + */ + if (!cursor_is_present (cursor, source, 0)) + return TRUE; + + if (!cursor_find_hotspot (cursor, source, &hot_x, &hot_y)) + return FALSE; + + /* generate a single hight width for all cursors in a + given animation*/ + + for (tmp_list = cursor->frame_configs, i = 0; + tmp_list; + tmp_list = tmp_list->next, i++) + { + CursorFrameConfig *frame_config = tmp_list->data; + CursorFrame *frame; + int tx, ty, tx2, ty2, twidth, theight; + + if (i != 0 && !cursor_is_present (cursor, source, i)) + continue; + + frame = g_new0 (CursorFrame, 1); + frame->size = source->size; + frame->hot_x = hot_x; + frame->hot_y = hot_y; + frame->delay = frame_config->delay; + + cursor_frame_find_bounds (cursor, frame, source, i, + &tx, &ty, &twidth, &theight); + + tx2 = tx + twidth; + ty2 = ty + theight; + + if (i == 0) + { + x = tx; + y = ty; + x2 = tx2; + y2 = ty2; + } + else + { + if (tx < x) + x = tx; + + if (ty < y) + y = ty; + + if (tx2 > x2) + x2 = tx2; + + if (ty2 > y2) + y2 = ty2; + } + + g_free (frame); + } + + width = x2 - x; + height = y2 - y; + + for (tmp_list = cursor->frame_configs, i = 0; + tmp_list; + tmp_list = tmp_list->next, i++) + { + CursorFrameConfig *frame_config = tmp_list->data; + CursorFrame *frame; + + if (i != 0 && !cursor_is_present (cursor, source, i)) + { + g_printerr ("Frame %d missing for cursor '%s' at size %d\n", + i, cursor->name, source->size); + frame = g_new0 (CursorFrame, 1); + frame->size = -1; + cursor->frames = g_slist_append (cursor->frames, frame); + continue; + } + + frame = g_new0 (CursorFrame, 1); + frame->size = source->size; + frame->hot_x = hot_x; + frame->hot_y = hot_y; + frame->delay = frame_config->delay; + + cursor_get_image (cursor, frame, source, i, x, y, width, height); + + cursor->frames = g_slist_append (cursor->frames, frame); + } + + return TRUE; +} + +static gboolean +cursor_theme_read_cursor (CursorTheme *theme, + Cursor *cursor) +{ + GSList *tmp_list; + + for (tmp_list = theme->sources; tmp_list; tmp_list = tmp_list->next) + { + if (!cursor_add_source (cursor, tmp_list->data)) + return FALSE; + } + + return TRUE; +} + +static void +cursor_theme_write_cursor (CursorTheme *theme, + Cursor *cursor) +{ + GSList *tmp_list; + char *config_filename; + char *command; + FILE *config_file; + GError *error = NULL; + int status; + int i; + + if (g_hash_table_lookup (theme->aliases, cursor->name)) + { + g_printerr ("Warning: cursor '%s' overridden by alias\n", cursor->name); + return; + } + + if (!cursor->frames) + return; + + config_filename = g_strconcat (cursor->name, ".cfg", NULL); + config_file = fopen (config_filename, "w"); + + if (!config_file) + { + g_printerr ("Cannot open config file '%s'\n", config_filename); + return; + } + + for (tmp_list = cursor->frames, i = 0; tmp_list; tmp_list = tmp_list->next, i++) + { + CursorFrame *frame = tmp_list->data; + char *filename; + + if (frame->size == -1) + continue; + filename = g_strdup_printf ("%s-%d.png", cursor->name, i); + if (gdk_pixbuf_save (frame->image, filename, "png", &error, NULL)) + { + if (frame->delay > 0) + fprintf (config_file, "%d %d %d %s %d\n", + frame->size, frame->hot_x, frame->hot_y, filename, frame->delay); + else + fprintf (config_file, "%d %d %d %s\n", + frame->size, frame->hot_x, frame->hot_y, filename); + } + else + { + g_printerr ("Error saving image file: %s\n", error->message); + g_error_free (error); + } + g_free (filename); + } + + fclose (config_file); + + command = g_strdup_printf ("sh -c 'xcursorgen %s > %s'\n", + config_filename, cursor->name); + if (!g_spawn_command_line_sync (command, NULL, NULL, &status, &error)) + { + g_printerr ("Error running xcursorgen for %s: %s\n", + cursor->name, error->message); + g_error_free (error); + } + else if (status) + { + g_printerr ("Error running xcursorgen for %s\n", + cursor->name); + } + else + { + /* Only delete temporary files if no error occurred + */ + unlink (config_filename); + g_free (config_filename); + + for (tmp_list = cursor->frames, i = 0; tmp_list; tmp_list = tmp_list->next, i++) + { + char *filename; + + filename = g_strdup_printf ("%s-%d.png", cursor->name, i); + unlink (filename); + g_free (filename); + } + } +} + +static const char * +cursor_theme_check_alias (CursorTheme *theme, + CursorAlias *alias) +{ + /* Dereference, using tortoise-and-hare checkign for circular aliases + */ + CursorAlias *tortoise = alias; + CursorAlias *hare = alias; + Cursor *target; + + while (TRUE) + { + CursorAlias *next; + + next = g_hash_table_lookup (theme->aliases, hare->target); + if (!next) + break; + hare = next; + + if (hare == tortoise) + goto found_loop; + + next = g_hash_table_lookup (theme->aliases, hare->target); + if (!next) + break; + hare = next; + + if (hare == tortoise) + goto found_loop; + + tortoise = g_hash_table_lookup (theme->aliases, tortoise->target); + } + + target = g_hash_table_lookup (theme->cursors, hare->target); + + if (!target || !target->frames) + { + g_printerr ("Cursor '%s', which is the target of alias '%s', is not in theme\n", + hare->target, alias->name); + return NULL; + } + + return hare->target; + + found_loop: + g_printerr ("Circular looop detected when dereferencing alias '%s'\n", + alias->name); + return NULL; +} + +static void +cursor_theme_write_alias (CursorTheme *theme, + CursorAlias *alias) +{ + const char *target = cursor_theme_check_alias (theme, alias); + if (!target) + return; + + if (symlink (target, alias->name) < 0) + { + g_printerr ("Error creating symlink for alias '%s' to '%s': %s\n", + alias->name, target, g_strerror (errno)); + } +} + +static void +write_cursor_foreach (gpointer key, + gpointer value, + gpointer data) +{ + cursor_theme_write_cursor (data, value); +} + +static void +write_alias_foreach (gpointer key, + gpointer value, + gpointer data) +{ + cursor_theme_write_alias (data, value); +} + +static gboolean +cursor_theme_write (CursorTheme *theme, + const char *output_dir) +{ + char *curdir; + + if (mkdir (output_dir, 0755) < 0 && errno != EEXIST) + { + g_printerr ("Error creating output directory '%s'\n: %s", + output_dir, g_strerror (errno)); + return FALSE; + } + + curdir = g_get_current_dir (); + if (chdir (output_dir) < 0) + { + g_printerr ("Could not change to output directory '%s'\n", output_dir); + return FALSE; + } + + g_hash_table_foreach (theme->cursors, + write_cursor_foreach, + theme); + + g_hash_table_foreach (theme->aliases, + write_alias_foreach, + theme); + + chdir (curdir); + + return TRUE; +} + +void +usage (void) +{ + g_printerr ("Usage: cursorthemegen CONFIG_FILE OUTPUT_DIR\n"); + exit (1); +} + +static void +read_cursor_foreach (gpointer key, + gpointer value, + gpointer data) +{ + if (!cursor_theme_read_cursor (data, value)) + exit (1); +} + +int +main (int argc, char **argv) +{ + CursorTheme *theme; + + g_type_init (); + + if (argc != 3) + usage (); + + theme = cursor_theme_read (argv[1]); + if (!theme) + exit (1); + + g_hash_table_foreach (theme->cursors, + read_cursor_foreach, + theme); + + if (!cursor_theme_write (theme, argv[2])) + exit (1); + + return 0; +} diff --git a/cursor/cursorthemegen/sample.cursortheme b/cursor/cursorthemegen/sample.cursortheme new file mode 100644 index 0000000..e288b42 --- /dev/null +++ b/cursor/cursorthemegen/sample.cursortheme @@ -0,0 +1,148 @@ +<theme name="Bluecurve"> + <source size="48"> + <image file="Bluecurve-1-48.png" use="0"/> + <image file="Bluecurve-2-48.png" use="1"/ > + <image file="Bluecurve-hotspot-48.png" use="hotspot"/> + </source> + <layout> + <row> + <cursor name="X_cursor"/> + <cursor name="arrow"/> + <cursor name="based_arrow_down"/> + <cursor name="based_arrow_up"/> + <cursor name="boat"/> + <cursor name="bogosity"/> + <cursor name="bottom_left_corner"/> + <cursor name="bottom_right_corner"/> + </row><row> + <cursor name="bottom_side"/> + <cursor name="bottom_tee"/> + <cursor name="box_spiral"/> + <cursor name="center_ptr"/> + <cursor name="circle"/> + <cursor name="clock"/> + <cursor name="coffee_mug"/> + <cursor name="cross"/> + </row><row> + <cursor name="cross_reverse"/> + <cursor name="crosshair"/> + <cursor name="diamond_cross"/> + <cursor name="dot"/> + <cursor name="dotbox"/> + <cursor name="double_arrow"/> + <cursor name="draft_large"/> + <cursor name="draft_small"/> + </row><row> + <cursor name="draped_box"/> + <cursor name="exchange"/> + <cursor name="fleur"/> + <cursor name="gobbler"/> + <cursor name="gumby"/> + <cursor name="hand1"/> + <cursor name="hand2"/> + <cursor name="heart"/> + </row><row> + <cursor name="icon"/> + <cursor name="iron_cross"/> + <cursor name="left_ptr"/> + <cursor name="left_side"/> + <cursor name="left_tee"/> + <cursor name="leftbutton"/> + <cursor name="ll_angle"/> + <cursor name="lr_angle"/> + </row><row> + <cursor name="man"/> + <cursor name="middlebutton"/> + <cursor name="mouse"/> + <cursor name="pencil"/> + <cursor name="pirate"/> + <cursor name="plus"/> + <cursor name="question_arrow"/> + <cursor name="right_ptr"/> + </row><row> + <cursor name="right_side"/> + <cursor name="right_tee"/> + <cursor name="rightbutton"/> + <cursor name="rtl_logo"/> + <cursor name="sailboat"/> + <cursor name="sb_down_arrow"/> + <cursor name="sb_h_double_arrow"/> + <cursor name="sb_left_arrow"/> + </row><row> + <cursor name="sb_right_arrow"/> + <cursor name="sb_up_arrow"/> + <cursor name="sb_v_double_arrow"/> + <cursor name="shuttle"/> + <cursor name="sizing"/> + <cursor name="spider"/> + <cursor name="spraycan"/> + <cursor name="star"/> + </row><row> + <cursor name="target"/> + <cursor name="tcross"/> + <cursor name="top_left_arrow"/> + <cursor name="top_left_corner"/> + <cursor name="top_right_corner"/> + <cursor name="top_side"/> + <cursor name="top_tee"/> + <cursor name="trek"/> + </row><row> + <cursor name="ul_angle"/> + <cursor name="umbella"/> + <cursor name="ur_angle"/> + <cursor name="watch"/> + <cursor name="xterm"/> + <cursor name="left_ptr_watch"> + <frame delay="500"/> + <frame delay="500"/> + </cursor> + </row> + </layout> +<!-- + The number of cursors in the WhiteGlass theme distributed with XFree86 + are reduced using the following aliases: + + <alias name="arrow" target="right_ptr"/> + <alias name="cross_reverse" target="cross"/> + <alias name="crosshair" target="cross"/> + <alias name="draft_large" target="right_ptr"/> + <alias name="draft_small" target="right_ptr"/> + <alias name="plus" target="cross"/> + <alias name="tcross" target="cross"/> + <alias name="top_left_arrow" target="top_left_arrow"/> + --> + +<!-- + Aliases can also be used to provide cursors to be used in place + of particular legacy cursor shapes; whenever libXcursor is + asked to create a bitmap cursor, it creates a hash value + from the cursor shape, and tries using that as a cursor + name. Setting the environment variable XCURSOR_DISCOVER will + log this process, which is useful for finding out the hash values. + + The following maps the mozilla pointer-while-waiting cursor to + left_ptr_watch. +--> + <!-- moz_spinning (left_ptr with watch) --> + <alias name="08e8e1c95fe2fc01f976f1e063a24ccd" target="left_ptr_watch"/> + +<!-- + More mozilla hash values that could be aliased: + + moz_alias 0876e1c15ff2fc01f906f1c363074c0f (left_ptr with small arrow) + moz_copy 08ffe1cb5fe6fc01f906f1c063814ccf (left_ptr with plus) + moz_hand_grabbing 208530c400c041818281048008011002 (closed hand) + moz_hand_grab 5aca4d189052212118709018842178c0 (open hand) + moz_menu 08ffe1e65f80fcfdf9fff11263e74c48 (left_ptr with menu) */ + moz_question_arrow 5c6cd98b3f3ebcb1f9c7f1c204630408 (left_ptr with ?) + + GTK+ toolkit cursors: + + DND copy 1081e37283d90000800003c07f3ef6bf + DND move 9081237383d90e509aa00f00170e968f + DND link 3085a0e285430894940527032f8b26df + DND no drop 1001208387f90000800003000700f6ff + + Eye dropper 90b3018312820b127e5a0b7c8034a301 +--> +</theme> diff --git a/cursor/cursorthemegen/themefile.c b/cursor/cursorthemegen/themefile.c new file mode 100644 index 0000000..a8a703f --- /dev/null +++ b/cursor/cursorthemegen/themefile.c @@ -0,0 +1,609 @@ +/* + * Copyright © 2003 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + */ +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +#include "cursortheme.h" + +typedef struct _ParseData ParseData; + +typedef enum { + OUTSIDE, + IN_THEME, + IN_SOURCE, + IN_IMAGE, + IN_ALIAS, + IN_LAYOUT, + IN_ROW, + IN_CURSOR, + IN_FRAME +} ParseState; + +struct _ParseData { + CursorTheme *theme; + ParseState state; + gboolean seen_theme; + gboolean seen_layout; + int row; + int column; + Cursor *current_cursor; +}; + +static gboolean +expect_tag (GMarkupParseContext *context, + const gchar *element_name, + const gchar *expected_name, /* Null for expected empty */ + GError **error) +{ + if (!expected_name || strcmp (element_name, expected_name) != 0) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Unexpected tag '%s'", + element_name); + return FALSE; + } + return TRUE; +} + +static gboolean +extract_attrs (GMarkupParseContext *context, + const gchar **attribute_names, + const gchar **attribute_values, + GError **error, + ...) +{ + va_list vap; + const char *name; + gboolean *attr_map; + gboolean nattrs = 0; + int i; + + for (i = 0; attribute_names[i]; i++) + nattrs++; + + attr_map = g_new0 (gboolean, nattrs); + + va_start (vap, error); + name = va_arg (vap, const char *); + while (name) + { + gboolean mandatory = va_arg (vap, gboolean); + const char **loc = va_arg (vap, const char **); + gboolean found = FALSE; + + for (i = 0; attribute_names[i]; i++) + { + if (!attr_map[i] && strcmp (attribute_names[i], name) == 0) + { + if (found) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Duplicate attribute '%s'", name); + return FALSE; + } + + *loc = attribute_values[i]; + found = TRUE; + attr_map[i] = TRUE; + } + } + + if (!found && mandatory) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Missing attribute '%s'", name); + return FALSE; + } + + name = va_arg (vap, const char *); + } + + for (i = 0; i < nattrs; i++) + if (!attr_map[i]) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, + "Unknown attribute '%s'", attribute_names[i]); + return FALSE; + } + + return TRUE; +} + +static gboolean +get_int (const char *str, + int *result) +{ + long val; + char *p; + + val = strtol (str, &p, 0); + if (*str == '\0' || *p != '\0' || + val < G_MININT || val > G_MAXINT) + return FALSE; + + *result = val; + + return TRUE; +} + +static void +add_source (ParseData *parse_data, + int size, + int gridsize) +{ + CursorSource *source = g_new0 (CursorSource, 1); + source->size = size; + source->gridsize = gridsize; + parse_data->theme->sources = g_slist_prepend (parse_data->theme->sources, source); +} + +static void +add_alias (ParseData *parse_data, + const char *name, + const char *target) +{ + CursorAlias *alias = g_new0 (CursorAlias, 1); + alias->name = g_strdup (name); + alias->target = g_strdup (target); + + g_hash_table_insert (parse_data->theme->aliases, alias->name, alias); +} + +static gboolean +add_image (ParseData *parse_data, + const char *file, + int use, + GError **error) +{ + GdkPixbuf *pixbuf; + CursorSource *source; + CursorImage *image; + + pixbuf = gdk_pixbuf_new_from_file (file, error); + if (!pixbuf) + return FALSE; + + source = parse_data->theme->sources->data; + image = g_new0 (CursorImage, 1); + image->image = pixbuf; + image->use = use; + source->images = g_slist_prepend (source->images, image); + + return TRUE; +} + +static void +add_cursor (ParseData *parse_data, + const char *name) +{ + Cursor *cursor = g_new0 (Cursor, 1); + cursor->name = g_strdup (name); + cursor->row = parse_data->row; + cursor->column = parse_data->column; + parse_data->current_cursor = cursor; + g_hash_table_insert (parse_data->theme->cursors, cursor->name, cursor); +} + +static void +add_frame_config (ParseData *parse_data, + int delay) +{ + Cursor *cursor = parse_data->current_cursor; + CursorFrameConfig *frame_config = g_new0 (CursorFrameConfig, 1); + frame_config->delay = delay; + cursor->frame_configs = g_slist_prepend (cursor->frame_configs, frame_config); +} + +/* Called for open tags <foo bar="baz"> */ +static void +cursor_theme_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + ParseData *parse_data = user_data; + + switch (parse_data->state) + { + case OUTSIDE: + { + const char *name; + + if (!expect_tag (context, element_name, "theme", error)) + return; + if (parse_data->seen_theme) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Multiple occurrences of <theme>"); + return; + } + parse_data->seen_theme = TRUE; + parse_data->state = IN_THEME; + + if (!extract_attrs (context, attribute_names, attribute_values, error, + "name", TRUE, &name, + NULL)) + return; + + parse_data->theme->name = g_strdup (name); + } + break; + case IN_THEME: + if (strcmp (element_name, "source") == 0) + { + const char *size_str; + const char *gridsize_str; + int size, gridsize; + + parse_data->state = IN_SOURCE; + + if (!extract_attrs (context, attribute_names, attribute_values, error, + "size", TRUE, &size_str, + "gridsize", FALSE, &gridsize_str, + NULL)) + return; + + if (!get_int (size_str, &size) || size < 0) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Invalid size %s", size_str); + return; + } + + if (gridsize_str) + { + if (!get_int (gridsize_str, &gridsize) || size < 0) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Invalid size %s", size_str); + return; + } + } + else + gridsize = size; + + add_source (parse_data, size, gridsize); + } + else if (strcmp (element_name, "alias") == 0) + { + const char *name; + const char *target; + + parse_data->state = IN_ALIAS; + + if (!extract_attrs (context, attribute_names, attribute_values, error, + "name", TRUE, &name, + "target", FALSE, &target, + NULL)) + return; + + add_alias (parse_data, name, target); + } + else if (strcmp (element_name, "layout") == 0) + { + if (parse_data->seen_layout) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Multiple occurrences of <layout>"); + return; + } + parse_data->seen_layout = TRUE; + parse_data->state = IN_LAYOUT; + + if (!extract_attrs (context, attribute_names, attribute_values, error, + NULL)) + return; + } + else + expect_tag (context, element_name, NULL, error); + break; + case IN_SOURCE: + { + const char *file; + const char *use_str; + int use; + + if (!expect_tag (context, element_name, "image", error)) + return; + parse_data->state = IN_IMAGE; + + if (!extract_attrs (context, attribute_names, attribute_values, error, + "file", TRUE, &file, + "use", TRUE, &use_str, + NULL)) + return; + + if (strcmp (use_str, "hotspot") == 0) + use = -1; + else + { + if (!get_int (use_str, &use) || use < 0) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Invalid use value %s", use_str); + return; + } + } + + add_image (parse_data, file, use, error); + } + + break; + case IN_LAYOUT: + if (!expect_tag (context, element_name, "row", error)) + return; + parse_data->state = IN_ROW; + parse_data->column = 0; + break; + case IN_ROW: + { + const char *name; + + if (!expect_tag (context, element_name, "cursor", error)) + return; + parse_data->state = IN_CURSOR; + + if (!extract_attrs (context, attribute_names, attribute_values, error, + "name", TRUE, &name, + NULL)) + return; + + add_cursor (parse_data, name); + } + break; + case IN_CURSOR: + { + const char *delay_str = NULL; + int delay = -1; + + if (!expect_tag (context, element_name, "frame", error)) + return; + parse_data->state = IN_FRAME; + + if (!extract_attrs (context, attribute_names, attribute_values, error, + "delay", FALSE, &delay_str, + NULL)) + return; + + if (delay_str) + { + if (!get_int (delay_str, &delay) || delay < 0) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Invalid delay value '%s'", delay_str); + return; + } + } + + add_frame_config (parse_data, delay); + } + break; + case IN_ALIAS: + case IN_IMAGE: + case IN_FRAME: + expect_tag (context, element_name, NULL, error); + break; + } +} + +/* Called for close tags </foo> */ +static void +cursor_theme_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + ParseData *parse_data = user_data; + + switch (parse_data->state) + { + case OUTSIDE: + g_assert_not_reached (); + break; + case IN_THEME: + parse_data->state = OUTSIDE; + parse_data->theme->sources = g_slist_reverse (parse_data->theme->sources); + break; + case IN_SOURCE: + { + CursorSource *source = parse_data->theme->sources->data; + source->images = g_slist_reverse (source->images); + parse_data->state = IN_THEME; + } + break; + case IN_ALIAS: + parse_data->state = IN_THEME; + break; + case IN_IMAGE: + parse_data->state = IN_SOURCE; + break; + case IN_LAYOUT: + parse_data->state = IN_THEME; + break; + case IN_ROW: + parse_data->state = IN_LAYOUT; + parse_data->row++; + break; + case IN_CURSOR: + { + Cursor *cursor = parse_data->current_cursor; + if (!cursor->frame_configs) + add_frame_config (parse_data, -1); + cursor->frame_configs = g_slist_reverse (cursor->frame_configs); + parse_data->state = IN_ROW; + parse_data->column++; + parse_data->current_cursor = NULL; + } + break; + case IN_FRAME: + parse_data->state = IN_CURSOR; + break; + } +} + +/* Called for character data */ +/* text is not nul-terminated */ +static void +cursor_theme_text (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + int i; + + for (i = 0; i < text_len; i++) + if (!g_ascii_isspace (text[i])) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Unexpected text in theme file"); + return; + } +} + +/* Called for strings that should be re-saved verbatim in this same + * position, but are not otherwise interpretable. At the moment + * this includes comments and processing instructions. + */ +/* text is not nul-terminated. */ +static void +cursor_theme_passthrough (GMarkupParseContext *context, + const gchar *passthrough_text, + gsize text_len, + gpointer user_data, + GError **error) +{ + /* do nothing */ +} + +/* Called on error, including one set by other + * methods in the vtable. The GError should not be freed. + */ +static void +cursor_theme_error (GMarkupParseContext *context, + GError *error, + gpointer user_data) +{ +} + +static GMarkupParser cursor_theme_parse = { + cursor_theme_start_element, + cursor_theme_end_element, + cursor_theme_text, + cursor_theme_passthrough, + cursor_theme_error +}; + +static void +cursor_theme_free (CursorTheme *theme) +{ +} + +CursorTheme * +cursor_theme_read (const char *filename) +{ + ParseData parse_data; + GMarkupParseContext *context; + GError *error = NULL; + char *text; + gboolean have_error = FALSE; + size_t len; + + if (!g_file_get_contents (filename, &text, &len, &error)) + { + g_printerr ("Cannot read theme definition file: %s\n", error->message); + g_error_free (error); + return NULL; + } + + parse_data.theme = g_new0 (CursorTheme, 1); + parse_data.theme->cursors = g_hash_table_new (g_str_hash, g_str_equal); + parse_data.theme->aliases = g_hash_table_new (g_str_hash, g_str_equal); + + parse_data.state = OUTSIDE; + parse_data.seen_theme = FALSE; + parse_data.seen_layout = FALSE; + parse_data.row = 0; + parse_data.column = 0; + + context = g_markup_parse_context_new (&cursor_theme_parse, 0, + &parse_data, NULL); + + if (!g_markup_parse_context_parse (context, text, len, &error) || + !g_markup_parse_context_end_parse (context, &error)) + { + g_printerr ("Error parsing theme definition file: %s\n", error->message); + have_error = TRUE; + g_error_free (error); + } + else if (!parse_data.seen_theme) + { + g_printerr ("Did not find <theme> element in theme file\n"); + have_error = TRUE; + } + else if (!parse_data.seen_layout) + { + g_printerr ("Did not find <layout> element in theme file\n"); + have_error = TRUE; + } + else if (!parse_data.theme->sources) + { + g_printerr ("No <source> element in theme file\n"); + have_error = TRUE; + } + + g_markup_parse_context_free (context); + + if (!have_error) + return parse_data.theme; + else + { + cursor_theme_free (parse_data.theme); + return NULL; + } +} diff --git a/cursor/sugar/ChangeLog b/cursor/sugar/ChangeLog new file mode 100644 index 0000000..ac10780 --- /dev/null +++ b/cursor/sugar/ChangeLog @@ -0,0 +1,9 @@ +2003-01-17 Havoc Pennington <hp@redhat.com> + + * Makefile.am (EXTRA_DIST): fix distcheck + +Thu Jan 16 14:56:26 2003 Owen Taylor <otaylor@redhat.com> + + * Bluecurve.cursortheme: Conform to new syntax, + add aliases. + diff --git a/cursor/sugar/Makefile.am b/cursor/sugar/Makefile.am new file mode 100644 index 0000000..fb86ae2 --- /dev/null +++ b/cursor/sugar/Makefile.am @@ -0,0 +1,40 @@ +THEMEGEN = $(top_builddir)/art/cursor/cursorthemegen/cursorthemegen +THEME_DIR = $(top_builddir)/art/cursor/sugar/theme + +all-local: sugar.stamp + +sugar_images = \ + sugar-0.png \ + sugar-1.png \ + sugar-2.png \ + sugar-3.png \ + sugar-4.png \ + sugar-5.png \ + sugar-6.png \ + sugar-7.png \ + sugar-8.png \ + sugar-9.png \ + sugar-10.png \ + sugar-11.png \ + sugar-hotspots.png + +sugar.stamp: $(sugar_images) $(THEMEGEN) sugar.cursortheme + rm -rf sugar && \ + BDIR=`pwd` && cd $(srcdir) && \ + $$BDIR/$(THEMEGEN) sugar.cursortheme $$BDIR/theme && \ + cd $$BDIR && touch sugar.stamp + +clean-local: + rm -rf $(THEME_DIR) + rm -rf $(top_builddir)/art/cursor/sugar/sugar.stamp + +install-data-local: + $(mkinstalldirs) $(DESTDIR)$(datadir)/icons/sugar/cursors/ + for i in `cd $(THEME_DIR) && echo *` ; do \ + $(INSTALL) $(THEME_DIR)/$$i $(DESTDIR)$(datadir)/icons/sugar/cursors/$$i ; \ + done + +uninstall-local: + rm -rf $(DESTDIR)$(datadir)/icons/sugar/cursors + +EXTRA_DIST=$(sugar_images) sugar.cursortheme diff --git a/cursor/sugar/olpc-hotspots.png b/cursor/sugar/olpc-hotspots.png Binary files differnew file mode 100644 index 0000000..6fefa39 --- /dev/null +++ b/cursor/sugar/olpc-hotspots.png diff --git a/cursor/sugar/olpc.cursortheme b/cursor/sugar/olpc.cursortheme new file mode 100644 index 0000000..402ba6e --- /dev/null +++ b/cursor/sugar/olpc.cursortheme @@ -0,0 +1,142 @@ +<theme name="OLPC"> + <source size="48" gridsize="48"> + <image file="olpc-0.png" use="0"/> + <image file="olpc-1.png" use="1"/> + <image file="olpc-2.png" use="2"/> + <image file="olpc-3.png" use="3"/> + <image file="olpc-4.png" use="4"/> + <image file="olpc-5.png" use="5"/> + <image file="olpc-6.png" use="6"/> + <image file="olpc-7.png" use="7"/> + <image file="olpc-8.png" use="8"/> + <image file="olpc-9.png" use="9"/> + <image file="olpc-10.png" use="10"/> + <image file="olpc-11.png" use="11"/> + + <image file="olpc-hotspots.png" use="hotspot"/> + </source> + + <alias name="top_left_arrow" target="left_ptr"/> + + <alias name="top_right_arrow" target="right_ptr"/> + <alias name="arrow" target="right_ptr"/> + <alias name="draft_small" target="right_ptr"/> + <alias name="draft_large" target="right_ptr"/> + + <alias name="close" target="pirate"/> + <alias name="destroy" target="pirate"/> + + <alias name="right_side" target="left_side"/> + <alias name="bottom_side" target="top_side"/> + <alias name="double_arrow" target="top_side"/> + <alias name="top_right_corner" target="bottom_left_corner"/> + <alias name="top_left_corner" target="bottom_right_corner"/> + + <layout> + <row> + <cursor name="left_ptr"/> + <cursor name="center_ptr"/> + <cursor name="right_ptr"/> + <cursor name="exchange"/> + <cursor name="plus"/> + <cursor name="minus"/> + </row><row> + <cursor name="question_arrow"/> + <cursor name="link"/> + <cursor name="unavailable"/> + <cursor name="pirate"/> + <cursor name="left_ptr_watch"> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + </cursor> + <cursor name="left_ptr_modify"/> + </row><row> + <cursor name="busy"> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + <frame delay="60"/> + </cursor> + <cursor name="circle"/> + <cursor name="hand1"/> + <cursor name="hand2"/> + <cursor name="hand_open"/> + <cursor name="hand_closed"/> + </row><row> + <cursor name="sb_left_arrow"/> + <cursor name="sb_right_arrow"/> + <cursor name="sb_up_arrow"/> + <cursor name="sb_down_arrow"/> + <cursor name="sb_v_double_arrow"/> + <cursor name="sb_h_double_arrow"/> + </row><row> + <cursor name="bottom_right_corner"/> + <cursor name="bottom_left_corner"/> + <cursor name="top_side"/> + <cursor name="right_side"/> + <cursor name="fleur"/> + <cursor name="xterm"/> + </row><row> + <cursor name="crosshair"/> + <cursor name="pencil"/> + </row> + </layout> + +<!-- + Aliases can also be used to provide cursors to be used in place + of particular legacy cursor shapes; whenever libXcursor is + asked to create a bitmap cursor, it creates a hash value + from the cursor shape, and tries using that as a cursor + name. Setting the environment variable XCURSOR_DISCOVER will + log this process, which is useful for finding out the hash values. + + The following maps the mozilla pointer-while-waiting cursor to + left_ptr_watch. +--> + + <!-- moz_spinning (left_ptr with watch) --> + <alias name="08e8e1c95fe2fc01f976f1e063a24ccd" target="left_ptr_watch"/> + + <!-- moz_question_arrow (left_ptr with question) --> + <alias name="5c6cd98b3f3ebcb1f9c7f1c204630408" target="question_arrow"/> + +<!-- + More mozilla hash values that could be aliased: + + moz_alias 0876e1c15ff2fc01f906f1c363074c0f (left_ptr with small arrow) + moz_copy 08ffe1cb5fe6fc01f906f1c063814ccf (left_ptr with plus) + moz_hand_grabbing 208530c400c041818281048008011002 (closed hand) + moz_hand_grab 5aca4d189052212118709018842178c0 (open hand) + moz_menu 08ffe1e65f80fcfdf9fff11263e74c48 (left_ptr with menu) */ + moz_question_arrow 5c6cd98b3f3ebcb1f9c7f1c204630408 (left_ptr with ?) + + GTK+ toolkit cursors: +--> + + <alias name="1081e37283d90000800003c07f3ef6bf" target="dnd_copy"/> + <alias name="9081237383d90e509aa00f00170e968f" target="dnd_move"/> + <alias name="3085a0e285430894940527032f8b26df" target="dnd_link"/> + <alias name="1001208387f90000800003000700f6ff" target="dnd_none"/> + + <alias name="90b3018312820b127e5a0b7c8034a301" target="color-picker"/> + + <alias name="watch" target="left_ptr_watch"/> +</theme> diff --git a/cursor/sugar/sugar-0.png b/cursor/sugar/sugar-0.png Binary files differnew file mode 100644 index 0000000..5e56564 --- /dev/null +++ b/cursor/sugar/sugar-0.png diff --git a/cursor/sugar/sugar-1.png b/cursor/sugar/sugar-1.png Binary files differnew file mode 100644 index 0000000..340bbf7 --- /dev/null +++ b/cursor/sugar/sugar-1.png diff --git a/cursor/sugar/sugar-10.png b/cursor/sugar/sugar-10.png Binary files differnew file mode 100644 index 0000000..1d2991b --- /dev/null +++ b/cursor/sugar/sugar-10.png diff --git a/cursor/sugar/sugar-11.png b/cursor/sugar/sugar-11.png Binary files differnew file mode 100644 index 0000000..02719c1 --- /dev/null +++ b/cursor/sugar/sugar-11.png diff --git a/cursor/sugar/sugar-2.png b/cursor/sugar/sugar-2.png Binary files differnew file mode 100644 index 0000000..9e69567 --- /dev/null +++ b/cursor/sugar/sugar-2.png diff --git a/cursor/sugar/sugar-3.png b/cursor/sugar/sugar-3.png Binary files differnew file mode 100644 index 0000000..bedc3b1 --- /dev/null +++ b/cursor/sugar/sugar-3.png diff --git a/cursor/sugar/sugar-4.png b/cursor/sugar/sugar-4.png Binary files differnew file mode 100644 index 0000000..1f65d44 --- /dev/null +++ b/cursor/sugar/sugar-4.png diff --git a/cursor/sugar/sugar-5.png b/cursor/sugar/sugar-5.png Binary files differnew file mode 100644 index 0000000..22b6eba --- /dev/null +++ b/cursor/sugar/sugar-5.png diff --git a/cursor/sugar/sugar-6.png b/cursor/sugar/sugar-6.png Binary files differnew file mode 100644 index 0000000..7f5d49e --- /dev/null +++ b/cursor/sugar/sugar-6.png diff --git a/cursor/sugar/sugar-7.png b/cursor/sugar/sugar-7.png Binary files differnew file mode 100644 index 0000000..32ec0e0 --- /dev/null +++ b/cursor/sugar/sugar-7.png diff --git a/cursor/sugar/sugar-8.png b/cursor/sugar/sugar-8.png Binary files differnew file mode 100644 index 0000000..1dd0eea --- /dev/null +++ b/cursor/sugar/sugar-8.png diff --git a/cursor/sugar/sugar-9.png b/cursor/sugar/sugar-9.png Binary files differnew file mode 100644 index 0000000..1e57153 --- /dev/null +++ b/cursor/sugar/sugar-9.png |