/* Giram: a simple 3D modeller * Copyright (C) 2001 DindinX * * giramcursor.c * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include #include "giramcursor.h" typedef struct _GiramBitmapCursor GiramBitmapCursor; struct _GiramBitmapCursor { guchar *bits; guchar *mask_bits; gint width, height; gint x_hot, y_hot; GdkBitmap *bitmap; GdkBitmap *mask; GdkCursor *cursor; }; #include "cursors/mouse.xbm" #include "cursors/mouse_mask.xbm" #include "cursors/zoom.xbm" #include "cursors/zoom_mask.xbm" #include "cursors/zoom_small.xbm" #include "cursors/zoom_small_mask.xbm" /* modifiers */ #include "cursors/minus.xbm" #include "cursors/minus_mask.xbm" #include "cursors/plus.xbm" #include "cursors/plus_mask.xbm" static GiramBitmapCursor giram_cursors[] = { { mouse_bits, mouse_mask_bits, mouse_width, mouse_height, mouse_x_hot, mouse_y_hot, NULL, NULL, NULL }, { zoom_bits, zoom_mask_bits, zoom_width, zoom_height, zoom_x_hot, zoom_y_hot, NULL, NULL, NULL } }; static GiramBitmapCursor giram_stock_tool_cursors[] = { { NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL }, { zoom_small_bits, zoom_small_mask_bits, zoom_small_width, zoom_small_height, 0, 0, NULL, NULL, NULL } }; static GiramBitmapCursor giram_modifier_cursors[] = { { NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL }, { plus_bits, plus_mask_bits, plus_width, plus_height, plus_x_hot, plus_y_hot, NULL, NULL, NULL }, { minus_bits, minus_mask_bits, minus_width, minus_height, minus_x_hot, minus_y_hot, NULL, NULL, NULL } }; static void create_cursor_bitmaps(GiramBitmapCursor *bmcursor) { if (bmcursor->bitmap == NULL) bmcursor->bitmap = gdk_bitmap_create_from_data(NULL, bmcursor->bits, bmcursor->width, bmcursor->height); g_return_if_fail(bmcursor->bitmap != NULL); if (bmcursor->mask == NULL) bmcursor->mask = gdk_bitmap_create_from_data(NULL, bmcursor->mask_bits, bmcursor->width, bmcursor->height); g_return_if_fail(bmcursor->mask != NULL); } GdkCursor *giram_cursor_new(GiramCursorType cursor_type, GiramToolCursorType tool_cursor, GiramCursorModifier modifier) { GdkCursor *cursor; GdkBitmap *bitmap; GdkBitmap *mask; GdkColor color; GdkColor fg, bg; static GdkGC *gc = NULL; gint width; gint height; GiramBitmapCursor *bmcursor = NULL; GiramBitmapCursor *bmmodifier = NULL; GiramBitmapCursor *bmtool = NULL; g_return_val_if_fail(cursor_type < GIRAM_LAST_CURSOR_ENTRY, NULL); if (cursor_type <= GDK_LAST_CURSOR) { return gdk_cursor_new(cursor_type); } /* allow the small tool cursor only with the standard mouse, * the small crosshair and the bad cursor */ if (cursor_type != GIRAM_MOUSE_CURSOR) { tool_cursor = GIRAM_TOOL_CURSOR_NONE; } cursor_type -= GIRAM_MOUSE_CURSOR; bmcursor = &giram_cursors[(gint)cursor_type]; /* if there are no modifiers, we can show the cursor immediately */ if (bmcursor->bitmap == NULL || bmcursor->mask == NULL) { create_cursor_bitmaps(bmcursor); } /* prepare the tool cursor */ if (tool_cursor < GIRAM_TOOL_CURSOR_NONE || tool_cursor >= GIRAM_LAST_STOCK_TOOL_CURSOR_ENTRY) { tool_cursor = GIRAM_TOOL_CURSOR_NONE; } if (tool_cursor != GIRAM_TOOL_CURSOR_NONE) { bmtool = &giram_stock_tool_cursors[(gint)tool_cursor]; if (bmtool->bitmap == NULL || bmtool->mask == NULL) { create_cursor_bitmaps(bmtool); } } /* prepare the cursor modifier */ if (modifier < GIRAM_CURSOR_MODIFIER_NONE || modifier >= GIRAM_LAST_CURSOR_MODIFIER_ENTRY) { modifier = GIRAM_CURSOR_MODIFIER_NONE; } if (modifier != GIRAM_CURSOR_MODIFIER_NONE) { bmmodifier = &giram_modifier_cursors[(gint)modifier]; if (bmmodifier->bitmap == NULL || bmmodifier->mask == NULL) { create_cursor_bitmaps(bmmodifier); } } if (gc == NULL) gc = gdk_gc_new(bmcursor->bitmap); gdk_drawable_get_size(bmcursor->bitmap, &width, &height); /* new bitmap and mask for on-the-fly cursor creation */ bitmap = gdk_pixmap_new(NULL, width, height, 1); mask = gdk_pixmap_new(NULL, width, height, 1); color.pixel = 1; gdk_gc_set_foreground(gc, &color); /* first draw the bitmap completely ... */ gdk_draw_drawable(bitmap, gc, bmcursor->bitmap, 0, 0, 0, 0, width, height); if (bmmodifier) { gdk_gc_set_clip_mask(gc, bmmodifier->bitmap); gdk_draw_drawable(bitmap, gc, bmmodifier->bitmap, 0, 0, 0, 0, width, height); gdk_gc_set_clip_mask(gc, NULL); } if (bmtool) { gdk_gc_set_clip_mask(gc, bmtool->bitmap); gdk_draw_drawable(bitmap, gc, bmtool->bitmap, 0, 0, 0, 0, width, height); gdk_gc_set_clip_mask(gc, NULL); } /* ... then the mask */ gdk_draw_drawable(mask, gc, bmcursor->mask, 0, 0, 0, 0, width, height); if (bmmodifier) { gdk_gc_set_clip_mask(gc, bmmodifier->mask); gdk_draw_drawable(mask, gc, bmmodifier->mask, 0, 0, 0, 0, width, height); gdk_gc_set_clip_mask(gc, NULL); } if (bmtool) { gdk_gc_set_clip_mask(gc, bmtool->mask); gdk_draw_drawable(mask, gc, bmtool->mask, 0, 0, 0, 0, width, height); gdk_gc_set_clip_mask(gc, NULL); } /* should have a way to configure the mouse colors */ gdk_color_parse("#FFFFFF", &bg); gdk_color_parse("#000000", &fg); cursor = gdk_cursor_new_from_pixmap(bitmap, mask, &fg, &bg, bmcursor->x_hot, bmcursor->y_hot); g_object_unref(bitmap); g_object_unref(mask); return cursor; }