diff options
Diffstat (limited to 'mate-panel/nothing.cP')
-rw-r--r-- | mate-panel/nothing.cP | 1568 |
1 files changed, 1568 insertions, 0 deletions
diff --git a/mate-panel/nothing.cP b/mate-panel/nothing.cP new file mode 100644 index 00000000..4ce1f246 --- /dev/null +++ b/mate-panel/nothing.cP @@ -0,0 +1,1568 @@ +#include <string.h> +#include <math.h> +#include <unistd.h> + +#include <X11/Xlib.h> +#include <cairo.h> +#include <gdk/gdkkeysyms.h> +#include <canberra-gtk.h> + +#ifdef CA_CHECK_VERSION +#if CA_CHECK_VERSION(0, 13) +#define HAVE_CANBERRA_GTK_MULTIHEAD_SAFE +#endif +#endif + +#include "panel-util.h" +#include "nothing.h" + +static void +pixbuf_reverse (GdkPixbuf *gp) +{ + guchar *pixels = gdk_pixbuf_get_pixels (gp); + int rs = gdk_pixbuf_get_rowstride (gp); + int w = gdk_pixbuf_get_width (gp); + int h = gdk_pixbuf_get_height (gp); + int x, y; +#define DOSWAP(x,y) tmp = x; x = y; y = tmp; + for (y = 0; y < h; y++, pixels += rs) { + guchar *p = pixels; + guchar *p2 = pixels + w*4 - 4; + for (x = 0; x < w/2; x++, p+=4, p2-=4) { + guchar tmp; + DOSWAP (p[0], p2[0]); + DOSWAP (p[1], p2[1]); + DOSWAP (p[2], p2[2]); + DOSWAP (p[3], p2[3]); + } + } +#undef DOSWAP +} + +/* This unsea's the phsh */ +/*code snippet, not to be compiled separately*/ +static gboolean goat_loaded=FALSE; +static int goat_frame=0; +static GdkPixmap *goat_pix[2] = {NULL,NULL}; +static GdkPixmap *goat_pix_rev[2] = {NULL,NULL}; +static GtkWidget *goat_darea = NULL; +static int goat_width = 0,goat_height = 0; +static int goat_timeout = 0; +static int goat_x = -1, goat_y = -1; +static int goat_accx = -1, goat_accy = -1; + +static void +destroy_egg(GtkWidget *widget, gpointer data) +{ + int i; + goat_loaded = FALSE; + if(goat_timeout) { + g_source_remove(goat_timeout); + goat_timeout = 0; + } + for (i = 0; i < 2; i++) { + if (goat_pix[i] != NULL) + g_object_unref (G_OBJECT (goat_pix[i])); + goat_pix[i] = NULL; + if (goat_pix_rev[i] != NULL) + g_object_unref (G_OBJECT (goat_pix_rev[i])); + goat_pix_rev[i] = NULL; + } + goat_x = goat_y = -1; +} + +static int +goat_timeout_func(gpointer data) +{ + GtkAllocation allocation; + cairo_t *cr; + int real_goat_frame; + gboolean sound = FALSE; + int old_x; + int old_y; + + if(!gtk_widget_get_realized(goat_darea) || + !gtk_widget_is_drawable(goat_darea)) + return TRUE; + + if (!goat_pix[0] || !goat_pix[1]) { + destroy_egg (NULL, NULL); + return FALSE; + } + + gtk_widget_get_allocation (goat_darea, &allocation); + cr = gdk_cairo_create (gtk_widget_get_window (goat_darea)); + + if(goat_x == -1) { + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + + goat_x = 2; + goat_y = 2; + goat_accx = g_random_int()%4 +3; + goat_accy = g_random_int()%4 +3; + } + + old_x = goat_x; + old_y = goat_y; + goat_x += goat_accx; + goat_y += goat_accy; + + + if(goat_x>allocation.width-2-goat_width) { + goat_accx = -(g_random_int()%4 +3); + goat_x = allocation.width-2-goat_width; + sound = TRUE; + } else if(goat_x<2) { + goat_accx = g_random_int()%4 +3; + goat_x = 2; + sound = TRUE; + } + if(goat_y>allocation.height-2-goat_height) { + goat_accy = -(g_random_int()%4 +3); + goat_y = allocation.height-2-goat_height; + sound = TRUE; + } else if(goat_y<2) { + goat_accy = g_random_int()%4 +3; + goat_y = 2; + sound = TRUE; + } + + if (sound) { +#ifdef HAVE_CANBERRA_GTK_MULTIHEAD_SAFE + ca_context_cancel (ca_gtk_context_get_for_screen (gtk_widget_get_screen (goat_darea)), 42); +#else + ca_context_cancel (ca_gtk_context_get (), 42); +#endif + ca_gtk_play_for_widget (goat_darea, 42, + CA_PROP_EVENT_ID, "bell-window-system", + CA_PROP_EVENT_DESCRIPTION, "Ouch! This box is small!", + NULL); + } + + real_goat_frame = goat_frame/2; + + cairo_rectangle (cr, MIN(old_x, goat_x), MIN(old_y, goat_y), + goat_width + ABS(goat_x-old_x) + 6, + goat_height + ABS(goat_y-old_y) + 6); + + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + + gdk_cairo_set_source_pixmap (cr, + goat_accx<0?goat_pix[real_goat_frame]: + goat_pix_rev[real_goat_frame], + goat_x,goat_y); + + cairo_paint (cr); + + if(++goat_frame == 4) + goat_frame = 0; + + cairo_destroy (cr); + + return TRUE; +} + +static int +goat_expose(GtkWidget *widget, GdkEventExpose *event) +{ + cairo_t *cr; + + if(!gtk_widget_is_drawable(widget)) + return FALSE; + + cr = gdk_cairo_create (gtk_widget_get_window (goat_darea)); + + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + + cairo_destroy (cr); + + return FALSE; +} + +static void +goat_realize(GtkWidget *widget) +{ + GdkWindow *window; + int frame; + char *files[] = { + "mate-gegl2.png", + "mate-gegl2-2.png" + }; + if(goat_pix[0]) + return; + window = gtk_widget_get_window (widget); + for(frame=0;frame<2;frame++) { + GdkPixbuf *pb; + char *file; + int width; + int height; + cairo_t *cr; + cairo_matrix_t matrix; + cairo_pattern_t *pattern; + + file = g_strdup_printf ("%s/%s", ICONDIR, files[frame]); + if(!file) + return; + pb=gdk_pixbuf_new_from_file (file, NULL); + g_free(file); + + if(!pb) { + g_warning("Goat is not available!"); + return; + } + + width = gdk_pixbuf_get_width(pb); + height = gdk_pixbuf_get_height(pb); + + goat_pix[frame] = gdk_pixmap_new(window, + width, height, -1); + cr = gdk_cairo_create (goat_pix[frame]); + gdk_cairo_set_source_pixbuf (cr, pb, 0, 0); + cairo_paint (cr); + cairo_destroy (cr); + + goat_pix_rev[frame] = gdk_pixmap_new(window, + width, height, -1); + cr = gdk_cairo_create (goat_pix_rev[frame]); + gdk_cairo_set_source_pixbuf (cr, pb, 0, 0); + + cairo_matrix_init_identity (&matrix); + cairo_matrix_translate (&matrix, width, 0); + /* scale in -X direction to flip along X */ + cairo_matrix_scale (&matrix, -1.0, 1.0); + pattern = cairo_get_source (cr); + cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST); + cairo_pattern_set_matrix (pattern, &matrix); + + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + cairo_destroy (cr); + + goat_width = MAX (width, goat_width); + goat_height = MAX (height, goat_height); + + g_object_unref (pb); + } +} + +/*thy evil easter egg*/ +int +config_event(GtkWidget *widget,GdkEvent *event,GtkNotebook *nbook) +{ + static int clicks=0; + GdkEventButton *bevent; + + if (!nbook) + return FALSE; + + if(event->type != GDK_BUTTON_PRESS) + return FALSE; + + bevent = (GdkEventButton *)event; + if(bevent->button != 3) + clicks = 0; + else + clicks++; + + if(clicks<3) + return FALSE; + clicks = 0; + + if(!goat_loaded) { + goat_darea = gtk_drawing_area_new(); + + g_signal_connect (G_OBJECT(goat_darea),"destroy", + G_CALLBACK (destroy_egg),NULL); + g_signal_connect (GTK_OBJECT(goat_darea),"expose_event", + G_CALLBACK (goat_expose),NULL); + g_signal_connect_after (G_OBJECT(goat_darea),"realize", + G_CALLBACK (goat_realize),NULL); + + gtk_widget_show(goat_darea); + goat_timeout = g_timeout_add(60,goat_timeout_func,NULL); + /*the GEGL shall not be translated*/ + g_object_set (G_OBJECT (nbook), + "show_tabs", TRUE, + "show_border", TRUE, + NULL); + gtk_notebook_append_page (nbook, goat_darea, + gtk_label_new ("GEGL")); + gtk_notebook_set_current_page(nbook,-1); + goat_loaded = TRUE; + } else { + gtk_notebook_set_current_page(nbook,-1); + } + return FALSE; +} + +/* phish code */ +#define PHSHFRAMES 8 +#define PHSHORIGWIDTH 288 +#define PHSHORIGHEIGHT 22 +#define PHSHWIDTH (PHSHORIGWIDTH/PHSHFRAMES) +#define PHSHHEIGHT PHSHORIGHEIGHT +#define PHSHCHECKTIMEOUT (g_random_int()%120*1000) +#define PHSHTIMEOUT 120 +#define PHSHHIDETIMEOUT 80 +#define PHSHXS 5 +#define PHSHYS ((g_random_int() % 2) + 1) +#define PHSHXSHIDEFACTOR 2.5 +#define PHSHYSHIDEFACTOR 2.5 +#define PHSHPIXELSTOREMOVE(p) (p[3] < 55 || p[2] > 200) + +/* Some important code copied from PonG */ +typedef struct _AppletContainer AppletContainer; +struct _AppletContainer { + GdkWindow *win; + gboolean hide_mode; + int state; + int x, y, xs, ys; + int handler; + GdkPixmap *phsh[2*PHSHFRAMES]; + GdkBitmap *phsh_mask[2*PHSHFRAMES]; +}; +static AppletContainer phsh = {NULL}; + +static void +phsh_kill (void) +{ + int i; + for (i = 0; i < 2*PHSHFRAMES; i++) { + if (phsh.phsh[i] != NULL) + g_object_unref (G_OBJECT (phsh.phsh[i])); + phsh.phsh[i] = NULL; + if (phsh.phsh_mask[i] != NULL) + g_object_unref (G_OBJECT (phsh.phsh_mask[i])); + phsh.phsh_mask[i] = NULL; + } + gdk_window_destroy (phsh.win); + g_source_remove (phsh.handler); + memset (&phsh, 0, sizeof (AppletContainer)); +} + +static gboolean +phsh_move (gpointer data) +{ + int orient, state; + gboolean change = TRUE; + + phsh.x += phsh.xs; + phsh.y += phsh.ys; + if (phsh.x <= -PHSHWIDTH || + phsh.x >= gdk_screen_width ()) { + phsh_kill (); + return FALSE; + } + if (phsh.y <= 0 || + phsh.y >= gdk_screen_height () - PHSHHEIGHT || + g_random_int() % (phsh.hide_mode?10:50) == 0) + phsh.ys = -phsh.ys; + + phsh.state ++; + if (phsh.hide_mode) { + phsh.state ++; + if (phsh.state >= 2*PHSHFRAMES) + phsh.state = 0; + } else if (phsh.state >= PHSHFRAMES) + phsh.state = 0; + + if (!phsh.hide_mode || phsh.state % 2 == 0) + change = TRUE; + + state = phsh.state / (phsh.hide_mode?2:1); + orient = phsh.xs >= 0 ? 0 : 1; + + if (change) { + gdk_window_set_back_pixmap (phsh.win, phsh.phsh[orient + 2*state], FALSE); + gdk_window_shape_combine_mask (phsh.win, phsh.phsh_mask[orient + 2*state], 0, 0); + gdk_window_clear (phsh.win); + } + + gdk_window_move (phsh.win, phsh.x, phsh.y); + gdk_window_raise (phsh.win); + + return TRUE; +} + +static void +phsh_unsea(GdkPixbuf *gp) +{ + guchar *pixels = gdk_pixbuf_get_pixels (gp); + int rs = gdk_pixbuf_get_rowstride (gp); + int w = gdk_pixbuf_get_width (gp); + int h = gdk_pixbuf_get_height (gp); + int x, y; + + for (y = 0; y < h; y++, pixels += rs) { + guchar *p = pixels; + for (x = 0; x < w; x++, p+=4) { + if (PHSHPIXELSTOREMOVE(p)) + p[3] = 0; + } + } +} + +static GdkFilterReturn +phsh_filter (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) +{ + XEvent *xevent = (XEvent *)gdk_xevent; + + if (xevent->type == ButtonPress && + ! phsh.hide_mode) { + g_source_remove (phsh.handler); + phsh.handler = g_timeout_add (PHSHHIDETIMEOUT, phsh_move, NULL); + phsh.xs *= PHSHXSHIDEFACTOR; + phsh.ys *= PHSHYSHIDEFACTOR; + phsh.hide_mode = TRUE; + if (phsh.x < (gdk_screen_width () / 2)) + phsh.xs *= -1; + } + return GDK_FILTER_CONTINUE; +} + +static char * +get_phsh_file (void) +{ + char *phsh_file; + + phsh_file = g_strdup_printf ("%s/%cand%c.png", ICONDIR, 'w', 'a'); + + return phsh_file; +} + +static GdkPixbuf * +get_phsh_frame (GdkPixbuf *pb, int frame) +{ + GdkPixbuf *newpb; + + newpb = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, + PHSHWIDTH, PHSHHEIGHT); + gdk_pixbuf_copy_area (pb, frame * PHSHWIDTH, 0, + PHSHWIDTH, PHSHHEIGHT, newpb, 0, 0); + + return newpb; +} + +/* this checks the screen */ +static void +check_screen (void) +{ + GdkWindowAttr attributes; + char *phsh_file; + GdkPixbuf *gp, *tmp; + int i; + + if (phsh.win != NULL) + return; + + phsh_file = get_phsh_file (); + + if (phsh_file == NULL) + return; + + tmp = gdk_pixbuf_new_from_file (phsh_file, NULL); + if (tmp == NULL) + return; + + g_free (phsh_file); + + if (gdk_pixbuf_get_width (tmp) != PHSHORIGWIDTH || + gdk_pixbuf_get_height (tmp) != PHSHORIGHEIGHT) { + g_object_unref (G_OBJECT (tmp)); + return; + } + + phsh.state = 0; + phsh.hide_mode = FALSE; + phsh.x = -PHSHWIDTH; + phsh.y = (g_random_int() % (gdk_screen_height() - PHSHHEIGHT - 2)) + 1; + phsh.xs = PHSHXS; + phsh.ys = PHSHYS; + + for (i = 0; i < PHSHFRAMES; i++) { + gp = get_phsh_frame (tmp, i); + phsh_unsea (gp); + gdk_pixbuf_render_pixmap_and_mask (gp, &phsh.phsh[2*i+1], + &phsh.phsh_mask[2*i+1], 128); + pixbuf_reverse (gp); + gdk_pixbuf_render_pixmap_and_mask (gp, &phsh.phsh[2*i], + &phsh.phsh_mask[2*i], 128); + g_object_unref (G_OBJECT (gp)); + } + + g_object_unref (G_OBJECT (tmp)); + + attributes.window_type = GDK_WINDOW_TEMP; + attributes.x = phsh.x; + attributes.y = phsh.y; + attributes.width = PHSHWIDTH; + attributes.height = PHSHHEIGHT; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gdk_rgb_get_visual(); + attributes.colormap = gdk_rgb_get_colormap(); + attributes.event_mask = GDK_BUTTON_PRESS_MASK; + + phsh.win = gdk_window_new (NULL, &attributes, + GDK_WA_X | GDK_WA_Y | + GDK_WA_VISUAL | GDK_WA_COLORMAP); + gdk_window_set_back_pixmap (phsh.win, phsh.phsh[0], FALSE); + gdk_window_shape_combine_mask (phsh.win, phsh.phsh_mask[0], 0, 0); + + /* setup the keys filter */ + gdk_window_add_filter (phsh.win, + phsh_filter, + NULL); + + gdk_window_show (phsh.win); + phsh.handler = g_timeout_add (PHSHTIMEOUT, phsh_move, NULL); +} + +static guint screen_check_id = 0; + +static gboolean +check_screen_timeout (gpointer data) +{ + screen_check_id = 0; + + check_screen (); + + screen_check_id = g_timeout_add (PHSHCHECKTIMEOUT, + check_screen_timeout, NULL); + return FALSE; +} + +void +start_screen_check (void) +{ + if (screen_check_id > 0) + g_source_remove (screen_check_id); + + check_screen_timeout (NULL); +} + +typedef struct { + gboolean live; + int x, y; +} InvGoat; + +typedef struct { + gboolean good; + int y; + int x; +} InvShot; + + +static GtkWidget *geginv = NULL; +static GtkWidget *geginv_canvas = NULL; +static GtkWidget *geginv_label = NULL; +static GdkPixmap *geginv_pixmap = NULL; +static GdkPixmap *inv_goat1 = NULL; +static GdkPixmap *inv_goat2 = NULL; +static GdkPixmap *inv_phsh1 = NULL; +static GdkBitmap *inv_phsh1_mask = NULL; +static GdkPixmap *inv_phsh2 = NULL; +static GdkBitmap *inv_phsh2_mask = NULL; +static int inv_phsh_state = 0; +static int inv_goat_state = 0; +static int inv_width = 0; +static int inv_height = 0; +static int inv_goat_width = 0; +static int inv_goat_height = 0; +static int inv_phsh_width = 0; +static int inv_phsh_height = 0; +#define INV_ROWS 3 +#define INV_COLS 5 +static InvGoat invs[INV_COLS][INV_ROWS] = { { { FALSE, 0, 0 } } }; +static int inv_num = INV_ROWS * INV_COLS; +static double inv_factor = 1.0; +static int inv_our_x = 0; +static int inv_x = 0; +static int inv_y = 0; +static int inv_first_col = 0; +static int inv_last_col = INV_COLS-1; +static int inv_level = 0; +static int inv_lives = 0; +static gboolean inv_do_pause = FALSE; +static gboolean inv_reverse = FALSE; +static gboolean inv_game_over = FALSE; +static gboolean inv_left_pressed = FALSE; +static gboolean inv_right_pressed = FALSE; +static gboolean inv_fire_pressed = FALSE; +static gboolean inv_left_released = FALSE; +static gboolean inv_right_released = FALSE; +static gboolean inv_fire_released = FALSE; +static gboolean inv_paused = FALSE; +static GSList *inv_shots = NULL; +static guint inv_draw_idle = 0; + +static void +inv_show_status (void) +{ + gchar *s, *t, *u, *v, *w; + if (geginv == NULL) + return; + + if (inv_game_over) { + t = g_strdup_printf (_("<b>GAME OVER</b> at level %d!"), + inv_level+1); + u = g_strdup_printf ("<big>%s</big>", t); + /* Translators: the first and third strings are similar to a + * title, and the second string is a small information text. + * The spaces are there only to separate all the strings, so + try to keep them as is. */ + s = g_strdup_printf (_("%1$s %2$s %3$s"), + u, _("Press 'q' to quit"), u); + g_free (t); + g_free (u); + + } else if (inv_paused) { + t = g_strdup_printf("<big><b>%s</b></big>", _("Paused")); + /* Translators: the first string is a title and the second + * string is a small information text. */ + s = g_strdup_printf (_("%1$s\t%2$s"), + t, _("Press 'p' to unpause")); + g_free (t); + + } else { + t = g_strdup_printf ("<b>%d</b>", inv_level+1); + u = g_strdup_printf ("<b>%d</b>", inv_lives); + v = g_strdup_printf (_("Level: %s, Lives: %s"), t, u); + w = g_strdup_printf ("<big>%s</big>", v); + /* Translators: the first string is a title and the second + * string is a small information text. */ + s = g_strdup_printf (_("%1$s\t%2$s"), w, + _("Left/Right to move, Space to fire, 'p' to pause, 'q' to quit")); + g_free (t); + g_free (u); + g_free (v); + g_free (w); + + } + gtk_label_set_markup (GTK_LABEL (geginv_label), s); + + g_free (s); +} + +static gboolean +inv_draw (gpointer data) +{ + GtkStyle *style; + GdkPixmap *goat; + GSList *li; + int i, j; + + if (data != geginv) { + inv_draw_idle = 0; + return FALSE; + } + + if ( ! gtk_widget_is_drawable (geginv_canvas) || + geginv_pixmap == NULL) + return TRUE; + + style = gtk_widget_get_style (geginv_canvas); + + gdk_draw_rectangle (geginv_pixmap, + style->white_gc, + TRUE /* filled */, + 0, 0, + inv_width, inv_height); + + if (inv_goat_state == 0) + goat = inv_goat1; + else + goat = inv_goat2; + + for (i = 0; i < INV_COLS; i++) { + for (j = 0; j < INV_ROWS; j++) { + int x, y; + if ( ! invs[i][j].live) + continue; + + x = invs[i][j].x*inv_factor - inv_goat_width/2, + y = invs[i][j].y*inv_factor - inv_goat_height/2, + + gdk_draw_drawable (geginv_pixmap, + style->white_gc, + goat, + 0, 0, + x, y, + inv_goat_width, + inv_goat_height); + } + } + + for (li = inv_shots; li != NULL; li = li->next) { + InvShot *shot = li->data; + + gdk_draw_rectangle (geginv_pixmap, + style->black_gc, + TRUE /* filled */, + (shot->x-1)*inv_factor, + (shot->y-4)*inv_factor, + 3, 8); + } + + if ( ! inv_game_over) { + GdkPixmap *phsh; + GdkBitmap *mask; + + if (inv_phsh_state < 5) { + phsh = inv_phsh1; + mask = inv_phsh1_mask; + } else { + phsh = inv_phsh2; + mask = inv_phsh2_mask; + } + + gdk_gc_set_clip_origin (style->white_gc, + inv_our_x*inv_factor - inv_phsh_width/2, + 550*inv_factor - inv_phsh_height/2); + + gdk_gc_set_clip_mask (style->white_gc, + mask); + + gdk_draw_drawable (geginv_pixmap, + style->white_gc, + phsh, + 0, 0, + inv_our_x*inv_factor - inv_phsh_width/2, + 550*inv_factor - inv_phsh_height/2, + inv_phsh_width, + inv_phsh_height); + + gdk_gc_set_clip_origin (style->white_gc, 0, 0); + + gdk_gc_set_clip_mask (style->white_gc, NULL); + } + + gdk_draw_drawable (gtk_widget_get_window (geginv_canvas), + style->white_gc, + geginv_pixmap, + 0, 0, + 0, 0, + inv_width, inv_height); + + gdk_flush (); + + if (inv_do_pause) { + sleep (1); + inv_do_pause = FALSE; + } + + inv_draw_idle = 0; + return FALSE; +} + +static void +inv_queue_draw (GtkWidget *window) +{ + if (inv_draw_idle == 0) + inv_draw_idle = g_idle_add (inv_draw, window); +} + +static void +inv_draw_explosion (int x, int y) +{ + GdkWindow *window; + GtkStyle *style; + int i; + GdkColormap *cmap; + GdkColor red; + GdkGC *gc; + + if ( ! gtk_widget_is_drawable (geginv_canvas)) + return; + + window = gtk_widget_get_window (geginv_canvas); + style = gtk_widget_get_style (geginv_canvas); + + cmap = gdk_drawable_get_colormap (window); + gdk_color_parse ("red", &red); + gdk_colormap_alloc_color (cmap, &red, FALSE, TRUE); + + gc = gdk_gc_new (window); + gdk_gc_set_foreground (gc, &red); + gdk_gc_set_background (gc, &red); + + for (i = 5; i < 100; i += 5) { + gdk_draw_arc (window, + gc, + TRUE /* filled */, + x-i, y-i, + i*2, i*2, + 0, 360*64); + gdk_flush (); + g_usleep (50000); + } + + g_object_unref (G_OBJECT (gc)); + + for (i = 5; i < 100; i += 5) { + gdk_draw_arc (window, + style->white_gc, + TRUE /* filled */, + x-i, y-i, + i*2, i*2, + 0, 360*64); + gdk_flush (); + g_usleep (50000); + } + + gdk_colormap_free_colors (cmap, &red, 1); + + inv_queue_draw (geginv); +} + + +static void +inv_do_game_over (void) +{ + GSList *li; + + inv_game_over = TRUE; + + for (li = inv_shots; li != NULL; li = li->next) { + InvShot *shot = li->data; + shot->good = FALSE; + } + + inv_queue_draw (geginv); + + inv_show_status (); +} + + +static GdkPixbuf * +pb_scale (GdkPixbuf *pb, double scale) +{ + int w, h; + + if (scale == 1.0) + return (GdkPixbuf *)g_object_ref ((GObject *)pb); + + w = gdk_pixbuf_get_width (pb) * scale; + h = gdk_pixbuf_get_height (pb) * scale; + + return gdk_pixbuf_scale_simple (pb, w, h, + GDK_INTERP_BILINEAR); +} + +static void +refind_first_and_last (void) +{ + int i, j; + + for (i = 0; i < INV_COLS; i++) { + gboolean all_null = TRUE; + for (j = 0; j < INV_ROWS; j++) { + if (invs[i][j].live) { + all_null = FALSE; + break; + } + } + if ( ! all_null) { + inv_first_col = i; + break; + } + } + + for (i = INV_COLS-1; i >= 0; i--) { + gboolean all_null = TRUE; + for (j = 0; j < INV_ROWS; j++) { + if (invs[i][j].live) { + all_null = FALSE; + break; + } + } + if ( ! all_null) { + inv_last_col = i; + break; + } + } +} + +static void +whack_gegl (int i, int j) +{ + if ( ! invs[i][j].live) + return; + + invs[i][j].live = FALSE; + inv_num --; + + if (inv_num > 0) { + refind_first_and_last (); + } else { + inv_x = 70; + inv_y = 70; + inv_first_col = 0; + inv_last_col = INV_COLS-1; + inv_reverse = FALSE; + + g_slist_foreach (inv_shots, (GFunc)g_free, NULL); + g_slist_free (inv_shots); + inv_shots = NULL; + + for (i = 0; i < INV_COLS; i++) { + for (j = 0; j < INV_ROWS; j++) { + invs[i][j].live = TRUE; + invs[i][j].x = 70 + i * 100; + invs[i][j].y = 70 + j * 80; + } + } + inv_num = INV_ROWS * INV_COLS; + + inv_level ++; + + inv_show_status (); + } + + inv_queue_draw (geginv); +} + +static gboolean +geginv_timeout (gpointer data) +{ + int i, j; + int limitx1; + int limitx2; + int speed; + int shots; + int max_shots; + + if (inv_paused) + return TRUE; + + if (geginv != data || + inv_num <= 0 || + inv_y > 700) + return FALSE; + + limitx1 = 70 - (inv_first_col * 100); + limitx2 = 800 - 70 - (inv_last_col * 100); + + if (inv_game_over) { + inv_y += 30; + } else { + if (inv_num < (INV_COLS*INV_ROWS)/3) + speed = 45+2*inv_level; + else if (inv_num < (2*INV_COLS*INV_ROWS)/3) + speed = 30+2*inv_level; + else + speed = 15+2*inv_level; + + if (inv_reverse) { + inv_x -= speed; + if (inv_x < limitx1) { + inv_reverse = FALSE; + inv_x = (limitx1 + (limitx1 - inv_x)); + inv_y += 30+inv_level; + } + } else { + inv_x += speed; + if (inv_x > limitx2) { + inv_reverse = TRUE; + inv_x = (limitx2 - (inv_x - limitx2)); + inv_y += 30+inv_level; + } + } + } + + for (i = 0; i < INV_COLS; i++) { + for (j = 0; j < INV_ROWS; j++) { + if (invs[i][j].live) { + invs[i][j].x = inv_x + i * 100; + invs[i][j].y = inv_y + j * 80; + + if ( ! inv_game_over && + invs[i][j].y >= 570) { + inv_do_game_over (); + } else if ( ! inv_game_over && + invs[i][j].y >= 530 && + invs[i][j].x + 40 > inv_our_x - 25 && + invs[i][j].x - 40 < inv_our_x + 25) { + whack_gegl (i,j); + inv_lives --; + inv_draw_explosion (inv_our_x, 550); + if (inv_lives <= 0) { + inv_do_game_over (); + } else { + g_slist_foreach (inv_shots, (GFunc)g_free, NULL); + g_slist_free (inv_shots); + inv_shots = NULL; + inv_our_x = 400; + inv_do_pause = TRUE; + inv_show_status (); + } + } + } + } + } + + shots = 0; + max_shots = (g_random_int () >> 3) % (2+inv_level); + while ( ! inv_game_over && shots < MIN (max_shots, inv_num)) { + int i = (g_random_int () >> 3) % INV_COLS; + for (j = INV_ROWS-1; j >= 0; j--) { + if (invs[i][j].live) { + InvShot *shot = g_new0 (InvShot, 1); + + shot->good = FALSE; + shot->x = invs[i][j].x + (g_random_int () % 6) - 3; + shot->y = invs[i][j].y + inv_goat_height/2 + (g_random_int () % 3); + + inv_shots = g_slist_prepend (inv_shots, shot); + shots++; + break; + } + } + } + + inv_goat_state = (inv_goat_state+1) % 2; + + inv_queue_draw (geginv); + + g_timeout_add (((inv_num/4)+1) * 100, geginv_timeout, geginv); + + return FALSE; +} + +static gboolean +find_gegls (int x, int y) +{ + int i, j; + + /* FIXME: this is stupid, we can do better */ + for (i = 0; i < INV_COLS; i++) { + for (j = 0; j < INV_ROWS; j++) { + int ix = invs[i][j].x; + int iy = invs[i][j].y; + + if ( ! invs[i][j].live) + continue; + + if (y >= iy - 30 && + y <= iy + 30 && + x >= ix - 40 && + x <= ix + 40) { + whack_gegl (i, j); + return TRUE; + } + } + } + + return FALSE; +} + + +static gboolean +geginv_move_timeout (gpointer data) +{ + GSList *li; + static int shot_inhibit = 0; + + if (inv_paused) + return TRUE; + + if (geginv != data || + inv_num <= 0 || + inv_y > 700) + return FALSE; + + inv_phsh_state = (inv_phsh_state+1)%10; + + /* we will be drawing something */ + if (inv_shots != NULL) + inv_queue_draw (geginv); + + li = inv_shots; + while (li != NULL) { + InvShot *shot = li->data; + + if (shot->good) { + shot->y -= 30; + if (find_gegls (shot->x, shot->y) || + shot->y <= 0) { + GSList *list = li; + /* we were restarted */ + if (inv_shots == NULL) + return TRUE; + li = li->next; + g_free (shot); + inv_shots = g_slist_delete_link (inv_shots, list); + continue; + } + } else /* bad */ { + shot->y += 30; + if ( ! inv_game_over && + shot->y >= 535 && + shot->y <= 565 && + shot->x >= inv_our_x - 25 && + shot->x <= inv_our_x + 25) { + inv_lives --; + inv_draw_explosion (inv_our_x, 550); + if (inv_lives <= 0) { + inv_do_game_over (); + } else { + g_slist_foreach (inv_shots, (GFunc)g_free, NULL); + g_slist_free (inv_shots); + inv_shots = NULL; + inv_our_x = 400; + inv_do_pause = TRUE; + inv_show_status (); + return TRUE; + } + } + + if (shot->y >= 600) { + GSList *list = li; + li = li->next; + g_free (shot); + inv_shots = g_slist_delete_link (inv_shots, list); + continue; + } + } + + li = li->next; + } + + if ( ! inv_game_over) { + if (inv_left_pressed && inv_our_x > 100) { + inv_our_x -= 20; + inv_queue_draw (geginv); + } else if (inv_right_pressed && inv_our_x < 700) { + inv_our_x += 20; + inv_queue_draw (geginv); + } + } + + if (shot_inhibit > 0) + shot_inhibit--; + + if ( ! inv_game_over && inv_fire_pressed && shot_inhibit == 0) { + InvShot *shot = g_new0 (InvShot, 1); + + shot->good = TRUE; + shot->x = inv_our_x; + shot->y = 540; + + inv_shots = g_slist_prepend (inv_shots, shot); + + shot_inhibit = 5; + + inv_queue_draw (geginv); + } + + if (inv_left_released) + inv_left_pressed = FALSE; + if (inv_right_released) + inv_right_pressed = FALSE; + if (inv_fire_released) + inv_fire_pressed = FALSE; + + return TRUE; +} + +static gboolean +inv_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data) +{ + switch (event->keyval) { + case GDK_Left: + case GDK_KP_Left: + case GDK_Pointer_Left: + inv_left_pressed = TRUE; + inv_left_released = FALSE; + return TRUE; + case GDK_Right: + case GDK_KP_Right: + case GDK_Pointer_Right: + inv_right_pressed = TRUE; + inv_right_released = FALSE; + return TRUE; + case GDK_space: + case GDK_KP_Space: + inv_fire_pressed = TRUE; + inv_fire_released = FALSE; + return TRUE; + default: + break; + } + return FALSE; +} + +static gboolean +inv_key_release (GtkWidget *widget, GdkEventKey *event, gpointer data) +{ + switch (event->keyval) { + case GDK_Left: + case GDK_KP_Left: + case GDK_Pointer_Left: + inv_left_released = TRUE; + return TRUE; + case GDK_Right: + case GDK_KP_Right: + case GDK_Pointer_Right: + inv_right_released = TRUE; + return TRUE; + case GDK_space: + case GDK_KP_Space: + inv_fire_released = TRUE; + return TRUE; + case GDK_q: + case GDK_Q: + gtk_widget_destroy (widget); + return TRUE; + case GDK_p: + case GDK_P: + inv_paused = ! inv_paused; + inv_show_status (); + return TRUE; + default: + break; + } + return FALSE; +} + +static gboolean +ensure_creatures (void) +{ + GdkPixbuf *pb, *pb1, *phsh1, *phsh2, *goat1, *goat2; + char *phsh_file; + char *goat_file; + + if (inv_goat1 != NULL) + return TRUE; + + phsh_file = get_phsh_file (); + + if (phsh_file == NULL) + return FALSE; + + pb = gdk_pixbuf_new_from_file (phsh_file, NULL); + g_free (phsh_file); + if (pb == NULL) + return FALSE; + + pb1 = get_phsh_frame (pb, 1); + phsh1 = pb_scale (pb1, inv_factor); + g_object_unref (G_OBJECT (pb1)); + phsh_unsea (phsh1); + + pb1 = get_phsh_frame (pb, 2); + phsh2 = pb_scale (pb1, inv_factor); + g_object_unref (G_OBJECT (pb1)); + phsh_unsea (phsh2); + + g_object_unref (G_OBJECT (pb)); + + goat_file = g_strdup_printf ("%s/mate-gegl2.png", ICONDIR); + if (goat_file == NULL) { + g_object_unref (G_OBJECT (phsh1)); + g_object_unref (G_OBJECT (phsh2)); + return FALSE; + } + + pb = gdk_pixbuf_new_from_file (goat_file, NULL); + g_free (goat_file); + if (pb == NULL) { + g_object_unref (G_OBJECT (phsh1)); + g_object_unref (G_OBJECT (phsh2)); + return FALSE; + } + + goat1 = pb_scale (pb, inv_factor * 0.66); + g_object_unref (pb); + + goat_file = g_strdup_printf ("%s/mate-gegl2-2.png", ICONDIR); + if (goat_file == NULL) { + g_object_unref (G_OBJECT (goat1)); + g_object_unref (G_OBJECT (phsh1)); + g_object_unref (G_OBJECT (phsh2)); + return FALSE; + } + + pb = gdk_pixbuf_new_from_file (goat_file, NULL); + g_free (goat_file); + if (pb == NULL) { + g_object_unref (G_OBJECT (goat1)); + g_object_unref (G_OBJECT (phsh1)); + g_object_unref (G_OBJECT (phsh2)); + return FALSE; + } + + goat2 = pb_scale (pb, inv_factor * 0.66); + g_object_unref (pb); + + inv_goat_width = gdk_pixbuf_get_width (goat1); + inv_goat_height = gdk_pixbuf_get_height (goat1); + inv_phsh_width = gdk_pixbuf_get_width (phsh1); + inv_phsh_height = gdk_pixbuf_get_height (phsh1); + + gdk_pixbuf_render_pixmap_and_mask (goat1, &inv_goat1, NULL, 127); + g_object_unref (G_OBJECT (goat1)); + gdk_pixbuf_render_pixmap_and_mask (goat2, &inv_goat2, NULL, 127); + g_object_unref (G_OBJECT (goat2)); + gdk_pixbuf_render_pixmap_and_mask (phsh1, &inv_phsh1, &inv_phsh1_mask, 127); + g_object_unref (G_OBJECT (phsh1)); + gdk_pixbuf_render_pixmap_and_mask (phsh2, &inv_phsh2, &inv_phsh2_mask, 127); + g_object_unref (G_OBJECT (phsh2)); + + return TRUE; +} + +static void +geginv_destroyed (GtkWidget *w, gpointer data) +{ + geginv = NULL; + if (geginv_pixmap != NULL) + g_object_unref (G_OBJECT (geginv_pixmap)); + geginv_pixmap = NULL; +} + +static void +geginv_realized (GtkWidget *w, gpointer data) +{ + if (geginv_pixmap == NULL) + geginv_pixmap = gdk_pixmap_new (gtk_widget_get_window (w), + inv_width, inv_height, + gdk_visual_get_depth (gtk_widget_get_visual (w))); +} + +static gboolean +inv_expose (GtkWidget *widget, GdkEventExpose *event) +{ + if ( ! gtk_widget_is_drawable (widget) || + geginv_pixmap == NULL) + return FALSE; + + inv_queue_draw (geginv); + /* + gdk_draw_drawable (geginv_canvas->window, + geginv_canvas->style->white_gc, + geginv_pixmap, + event->area.x, event->area.x, + event->area.x, event->area.x, + event->area.width, event->area.height); + */ + + return FALSE; +} + +void +start_geginv (void) +{ + GtkWidget *vbox; + int i, j; + + if (geginv != NULL) { + gtk_window_present (GTK_WINDOW (geginv)); + return; + } + + inv_width = 800; + inv_height = 600; + + if (inv_width > gdk_screen_width () * 0.9) { + inv_width = gdk_screen_width () * 0.9; + inv_height = inv_width * (600.0/800.0); + } + + if (inv_height > gdk_screen_height () * 0.9) { + inv_height = gdk_screen_height () * 0.9; + inv_width = inv_height * (800.0/600.0); + } + + inv_factor = (double)inv_width / 800.0; + + if ( ! ensure_creatures ()) + return; + + geginv = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (geginv), _("Killer GEGLs from Outer Space")); + g_object_set (G_OBJECT (geginv), "resizable", FALSE, NULL); + g_signal_connect (G_OBJECT (geginv), "destroy", + G_CALLBACK (geginv_destroyed), + NULL); + + geginv_canvas = gtk_drawing_area_new (); + gtk_widget_set_double_buffered (GTK_WIDGET (geginv_canvas), FALSE); + gtk_widget_set_size_request (geginv_canvas, inv_width, inv_height); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (geginv), vbox); + gtk_box_pack_start (GTK_BOX (vbox), geginv_canvas, TRUE, TRUE, 0); + + geginv_label = gtk_label_new (""); + gtk_box_pack_start (GTK_BOX (vbox), geginv_label, FALSE, FALSE, 0); + + inv_our_x = 400; + inv_x = 70; + inv_y = 70; + inv_first_col = 0; + inv_level = 0; + inv_lives = 3; + inv_last_col = INV_COLS-1; + inv_reverse = FALSE; + inv_game_over = FALSE; + inv_left_pressed = FALSE; + inv_right_pressed = FALSE; + inv_fire_pressed = FALSE; + inv_left_released = FALSE; + inv_right_released = FALSE; + inv_fire_released = FALSE; + inv_paused = FALSE; + + gtk_widget_add_events (geginv, GDK_KEY_RELEASE_MASK); + + g_signal_connect (G_OBJECT (geginv), "key_press_event", + G_CALLBACK (inv_key_press), NULL); + g_signal_connect (G_OBJECT (geginv), "key_release_event", + G_CALLBACK (inv_key_release), NULL); + g_signal_connect (G_OBJECT (geginv), "realize", + G_CALLBACK (geginv_realized), NULL); + g_signal_connect (GTK_OBJECT (geginv_canvas), "expose_event", + G_CALLBACK (inv_expose), NULL); + + g_slist_foreach (inv_shots, (GFunc)g_free, NULL); + g_slist_free (inv_shots); + inv_shots = NULL; + + for (i = 0; i < INV_COLS; i++) { + for (j = 0; j < INV_ROWS; j++) { + invs[i][j].live = TRUE; + invs[i][j].x = 70 + i * 100; + invs[i][j].y = 70 + j * 80; + } + } + inv_num = INV_ROWS * INV_COLS; + + g_timeout_add (((inv_num/4)+1) * 100, geginv_timeout, geginv); + g_timeout_add (90, geginv_move_timeout, geginv); + + inv_show_status (); + + gtk_widget_show_all (geginv); +} + +static gboolean +move_window_handler (gpointer data) +{ + int x, y, sx, sy, wx, wy, foox, fooy; + GtkWidget *win = data; + GtkAllocation allocation; + + data = g_object_get_data (G_OBJECT (win), "move_speed_x"); + sx = GPOINTER_TO_INT (data); + data = g_object_get_data (G_OBJECT (win), "move_speed_y"); + sy = GPOINTER_TO_INT (data); + + gtk_widget_get_allocation (win, &allocation); + + gdk_window_get_pointer (NULL, &x, &y, NULL); + wx = allocation.x; + wy = allocation.y; + + foox = wx + (allocation.width / 2); + fooy = wy + (allocation.height / 2); + + if (sqrt ((foox - x)*(foox - x) + (fooy - y)*(fooy - y)) < + MAX (allocation.width, allocation.height)) { + if (foox < x) sx -= 5; + else sx += 5; + if (fooy < y) sy -= 5; + else sy += 5; + } else { + sx /= 2; + sy /= 2; + } + + if (sx > 50) sx = 50; + else if (sx < -50) sx = -50; + if (sy > 50) sy = 50; + else if (sy < -50) sy = -50; + + wx += sx; + wy += sy; + + if (wx < 0) wx = 0; + if (wy < 0) wy = 0; + if (wx + allocation.width > gdk_screen_width ()) + wx = gdk_screen_width () - allocation.width; + if (wy + allocation.height > gdk_screen_height ()) + wy = gdk_screen_height () - allocation.height; + + gtk_window_move (GTK_WINDOW (win), wx, wy); + allocation.x = wx; + allocation.y = wy; + gtk_widget_set_allocation (win, &allocation); + + data = GINT_TO_POINTER (sx); + g_object_set_data (G_OBJECT (win), "move_speed_x", data); + data = GINT_TO_POINTER (sy); + g_object_set_data (G_OBJECT (win), "move_speed_y", data); + + return TRUE; +} + +static void +move_window_destroyed (GtkWidget *win) +{ + gpointer data = g_object_get_data (G_OBJECT (win), "move_window_handler"); + int handler = GPOINTER_TO_INT (data); + + if (handler != 0) + g_source_remove (handler); + g_object_set_data (G_OBJECT (win), "move_window_handler", NULL); +} + +static void +doblah (GtkWidget *window) +{ + gpointer data = g_object_get_data (G_OBJECT (window), "move_window_handler"); + int handler = GPOINTER_TO_INT (data); + + if (handler == 0) { + handler = g_timeout_add (30, move_window_handler, window); + data = GINT_TO_POINTER (handler); + g_object_set_data (G_OBJECT (window), "move_window_handler", data); + g_signal_connect (G_OBJECT (window), "destroy", + G_CALLBACK (move_window_destroyed), + NULL); + } +} + +gboolean +panel_dialog_window_event (GtkWidget *window, + GdkEvent *event) +{ + switch (event->type) { + static int foo = 0; + case GDK_KEY_PRESS: + if((event->key.state & GDK_CONTROL_MASK) && foo < 4) { + switch (event->key.keyval) { + case GDK_r: + case GDK_R: + if(foo == 3) { doblah (window); } foo = 0; break; + case GDK_a: + case GDK_A: + if(foo == 2) { foo++; } else { foo = 0; } break; + case GDK_e: + case GDK_E: + if(foo == 1) { foo++; } else { foo = 0; } break; + case GDK_f: + case GDK_F: + if(foo == 0) { foo++; } else { foo = 0; } break; + default: + foo = 0; + } + } + default: + break; + } + + return FALSE; +} |