!!! タイムアウト * 一定の時間間隔で関数を呼び出す * プログラムを終了させる前に、イベントを停止させる必要がある ** 停止せずに終了すると、まれにcoreを吐く ** 終了処理中にもタイムアウトが発生して、既に解放されたものを使おうとするためらしい !! タイムアウトの設定 8< guint g_timeout_add (guint interval, GSourceFunc function, gpointer data); >8 * [g_timeout_add|http://developer.gnome.org/glib/2.30/glib-The-Main-Event-Loop.html#g-timeout-add] ** 入門GTK+ 3版pdf:63(75)ページ 8< gboolean g_source_remove (guint tag); >8 * [g_source_remove|http://developer.gnome.org/glib/2.30//glib-The-Main-Event-Loop.html#g-source-remove] ** 入門GTK+ 3版pdf:63(75)ページ ! 30msごとにmove_sprite(draw_animation)を呼ぶ * my_animation_ball関数 8< anime->timeout = g_timeout_add(30, (GSourceFunc)move_sprite, anime); /* 終了時のコールバックを設定 */ g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(cb_delete_event), (gpointer)anime); >8 * move_sprite関数 8< /* スプライトを動かす */ static gint move_sprite(gpointer data) { anime_pack *anime = (anime_pack *)data; gint x = anime->x, y = anime->y; gint dx = anime->dx, dy = anime->dy; gint s_width = anime->s_width; gint s_height = anime->s_height; /* スプライトの座標を更新 */ x += dx; y += dy; /* 端まで行ったら跳ね返す */ if(x < 0) { x += 0 - x; dx = -dx; } if(y < 0) { y += 0 - y; dy = -dy; } if(x > WIDTH - s_width) { x += WIDTH - s_width - x; dx = -dx; } if(y > HEIGHT - s_height) { y += HEIGHT - s_height - y; dy = -dy; } anime->x = x; anime->y = y; anime->dx = dx; anime->dy = dy; /* ドローイングエリアを更新 */ draw_animation(anime); return TRUE; } >8 6< * 呼び出された関数が、FALSEを返すまで繰り返し呼び出す ** FALSEを返したら止まる >9 * cb_delete_event関数 8< /* 終了処理 */ static gint cb_delete_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { anime_pack *anime = (anime_pack *)data; /* timeoutイベントを停止させる */ if(anime->timeout) g_source_remove(anime->timeout); if(anime->s_timeout) g_source_remove(anime->s_timeout); /* 続けてdestroyを実行 */ return FALSE; } >8 6< * 戻り値をFALSEにすると、続けてdestroyを実行 * 戻り値をTRUEにすると、終了しない ** 「本当に終了しますか? Y or N」のようなプログラムは、delete_eventのコールバックに書く >9