|
Ivan Mahonin |
d6430f |
#include <math.h>
|
|
Ivan Mahonin |
d6430f |
#include <gtk/gtk.h>
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
const double pi = 3.141592653589793;
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
GtkWidget *window;
|
|
Ivan Mahonin |
d6430f |
cairo_surface_t *surface;
|
|
Ivan Mahonin |
d6430f |
cairo_t *context;
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
gboolean dropping = FALSE;
|
|
Ivan Mahonin |
d6430f |
double x = 0.0;
|
|
Ivan Mahonin |
d6430f |
double y = 0.0;
|
|
Ivan Mahonin |
d6430f |
double r = 0.0;
|
|
Ivan Mahonin |
d6430f |
double speed = 0.0;
|
|
Ivan Mahonin |
d6430f |
double mouse_x = 0.0;
|
|
Ivan Mahonin |
d6430f |
double mouse_y = 0.0;
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
gboolean timeout(gpointer data) {
|
|
Ivan Mahonin |
d6430f |
if (dropping) {
|
|
Ivan Mahonin |
d6430f |
y += speed;
|
|
Ivan Mahonin |
d6430f |
r += 1.0;
|
|
Ivan Mahonin |
d6430f |
speed += 1.0;
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
int iy = (int)y;
|
|
Ivan Mahonin |
d6430f |
int ix = (int)x;
|
|
Ivan Mahonin |
d6430f |
if ( ix < 0 || ix >= cairo_image_surface_get_width(surface)
|
|
Ivan Mahonin |
d6430f |
|| iy < 0 || iy >= cairo_image_surface_get_height(surface) )
|
|
Ivan Mahonin |
d6430f |
{
|
|
Ivan Mahonin |
d6430f |
dropping = FALSE;
|
|
Ivan Mahonin |
d6430f |
} else {
|
|
Ivan Mahonin |
d6430f |
unsigned char *pixels = cairo_image_surface_get_data(surface);
|
|
Ivan Mahonin |
d6430f |
int stright = cairo_image_surface_get_stride(surface);
|
|
Ivan Mahonin |
d6430f |
unsigned char *pixel = pixels + iy*stright + ix*4;
|
|
Ivan Mahonin |
d6430f |
if (pixel[3] > 0) { // alpha channel
|
|
Ivan Mahonin |
d6430f |
dropping = FALSE;
|
|
Ivan Mahonin |
d6430f |
cairo_save(context);
|
|
Ivan Mahonin |
d6430f |
cairo_set_operator(context, CAIRO_OPERATOR_CLEAR);
|
|
Ivan Mahonin |
d6430f |
cairo_arc(context, x, y, r, 0, 2*pi);
|
|
Ivan Mahonin |
d6430f |
cairo_fill(context);
|
|
Ivan Mahonin |
d6430f |
cairo_restore(context);
|
|
Ivan Mahonin |
d6430f |
cairo_surface_flush(surface);
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
gtk_widget_queue_draw(window);
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
return TRUE;
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
gboolean motion(GtkWidget *widget, GdkEventMotion *event, gpointer data) {
|
|
Ivan Mahonin |
d6430f |
if (event->state & GDK_BUTTON1_MASK) {
|
|
Ivan Mahonin |
d6430f |
cairo_save(context);
|
|
Ivan Mahonin |
d6430f |
cairo_set_line_cap(context, CAIRO_LINE_CAP_ROUND);
|
|
Ivan Mahonin |
d6430f |
cairo_set_line_width(context, 50);
|
|
Ivan Mahonin |
d6430f |
cairo_set_source_rgba(context, 0, 0, 0, 1);
|
|
Ivan Mahonin |
d6430f |
cairo_move_to(context, mouse_x, mouse_y);
|
|
Ivan Mahonin |
d6430f |
cairo_line_to(context, event->x, event->y);
|
|
Ivan Mahonin |
d6430f |
cairo_stroke(context);
|
|
Ivan Mahonin |
d6430f |
cairo_restore(context);
|
|
Ivan Mahonin |
d6430f |
cairo_surface_flush(surface);
|
|
Ivan Mahonin |
d6430f |
gtk_widget_queue_draw(window);
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
mouse_x = event->x;
|
|
Ivan Mahonin |
d6430f |
mouse_y = event->y;
|
|
Ivan Mahonin |
d6430f |
return TRUE;
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
gboolean button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) {
|
|
Ivan Mahonin |
d6430f |
if (event->button == 2) {
|
|
Ivan Mahonin |
d6430f |
cairo_save(context);
|
|
Ivan Mahonin |
d6430f |
cairo_set_operator(context, CAIRO_OPERATOR_CLEAR);
|
|
Ivan Mahonin |
d6430f |
cairo_paint(context);
|
|
Ivan Mahonin |
d6430f |
cairo_restore(context);
|
|
Ivan Mahonin |
d6430f |
cairo_surface_flush(surface);
|
|
Ivan Mahonin |
d6430f |
gtk_widget_queue_draw(window);
|
|
Ivan Mahonin |
d6430f |
} else
|
|
Ivan Mahonin |
d6430f |
if (event->button == 3) {
|
|
Ivan Mahonin |
d6430f |
x = event->x;
|
|
Ivan Mahonin |
d6430f |
y = event->y;
|
|
Ivan Mahonin |
d6430f |
r = 0;
|
|
Ivan Mahonin |
d6430f |
speed = 0;
|
|
Ivan Mahonin |
d6430f |
dropping = TRUE;
|
|
Ivan Mahonin |
d6430f |
gtk_widget_queue_draw(window);
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
return TRUE;
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
gboolean draw(GtkWidget *widget, cairo_t *cr, gpointer data) {
|
|
Ivan Mahonin |
d6430f |
cairo_set_source_rgba(cr, 0.9, 0.9, 0.9, 1);
|
|
Ivan Mahonin |
d6430f |
cairo_paint(cr);
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
cairo_set_source_surface(cr, surface, 0, 0);
|
|
Ivan Mahonin |
d6430f |
cairo_paint(cr);
|
|
Ivan Mahonin |
d6430f |
if (dropping) {
|
|
Ivan Mahonin |
d6430f |
cairo_set_line_width(cr, 1);
|
|
Ivan Mahonin |
d6430f |
cairo_arc(cr, x, y, r, 0, 2*pi);
|
|
Ivan Mahonin |
d6430f |
cairo_set_source_rgba(cr, 1, 1, 1, 1);
|
|
Ivan Mahonin |
d6430f |
cairo_fill_preserve(cr);
|
|
Ivan Mahonin |
d6430f |
cairo_set_source_rgba(cr, 0, 0, 0, 1);
|
|
Ivan Mahonin |
d6430f |
cairo_stroke(cr);
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
return TRUE;
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
void activate(GtkApplication* app, gpointer data) {
|
|
Ivan Mahonin |
d6430f |
window = gtk_application_window_new (app);
|
|
Ivan Mahonin |
d6430f |
g_signal_connect(window, "draw", G_CALLBACK(draw), NULL);
|
|
Ivan Mahonin |
d6430f |
g_signal_connect(window, "motion-notify-event", G_CALLBACK(motion), NULL);
|
|
Ivan Mahonin |
d6430f |
g_signal_connect(window, "button-press-event", G_CALLBACK(button_press), NULL);
|
|
Ivan Mahonin |
d6430f |
gtk_widget_add_events(window, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK);
|
|
Ivan Mahonin |
d6430f |
gtk_window_set_default_size(
|
|
Ivan Mahonin |
d6430f |
GTK_WINDOW(window),
|
|
Ivan Mahonin |
d6430f |
cairo_image_surface_get_width(surface),
|
|
Ivan Mahonin |
d6430f |
cairo_image_surface_get_height(surface) );
|
|
Ivan Mahonin |
d6430f |
gtk_widget_show_all(window);
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
g_timeout_add(10, timeout, NULL);
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
int main(int argc, char **argv) {
|
|
Ivan Mahonin |
d6430f |
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 700, 500);
|
|
Ivan Mahonin |
d6430f |
context = cairo_create(surface);
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
GtkApplication *application = gtk_application_new(NULL, 0);
|
|
Ivan Mahonin |
d6430f |
g_signal_connect(application, "activate", G_CALLBACK(activate), NULL);
|
|
Ivan Mahonin |
d6430f |
int status = g_application_run(G_APPLICATION(application), argc, argv);
|
|
Ivan Mahonin |
d6430f |
g_object_unref(application);
|
|
Ivan Mahonin |
d6430f |
|
|
Ivan Mahonin |
d6430f |
cairo_destroy(context);
|
|
Ivan Mahonin |
d6430f |
cairo_surface_destroy(surface);
|
|
Ivan Mahonin |
d6430f |
return status;
|
|
Ivan Mahonin |
d6430f |
}
|
|
Ivan Mahonin |
d6430f |
|