169 lines
4.0 KiB
C
169 lines
4.0 KiB
C
#include <gmodule.h>
|
|
#include <clutter/clutter.h>
|
|
#include <string.h>
|
|
|
|
#define DOT_SIZE 2
|
|
#define TEX_SIZE 64
|
|
|
|
typedef struct _CallbackData CallbackData;
|
|
|
|
struct _CallbackData
|
|
{
|
|
ClutterActor *stage;
|
|
ClutterActor *tex;
|
|
ClutterActor *box;
|
|
ClutterMotionEvent event;
|
|
guint idle_source;
|
|
};
|
|
|
|
static ClutterActor *
|
|
make_label (void)
|
|
{
|
|
ClutterActor *label;
|
|
gchar *text;
|
|
gchar *argv[] = { "ls", "--help", NULL };
|
|
|
|
label = clutter_text_new ();
|
|
clutter_text_set_font_name (CLUTTER_TEXT (label), "Sans 10");
|
|
|
|
if (g_spawn_sync (NULL, argv, NULL,
|
|
G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_SEARCH_PATH,
|
|
NULL, NULL, &text, NULL, NULL, NULL))
|
|
{
|
|
clutter_text_set_text (CLUTTER_TEXT (label), text);
|
|
g_free (text);
|
|
}
|
|
|
|
return label;
|
|
}
|
|
|
|
static ClutterActor *
|
|
make_tex (void)
|
|
{
|
|
ClutterActor *tex = clutter_texture_new ();
|
|
|
|
clutter_actor_set_size (tex, TEX_SIZE * 2, TEX_SIZE * 2);
|
|
|
|
return tex;
|
|
}
|
|
|
|
static ClutterActor *
|
|
make_box (void)
|
|
{
|
|
ClutterActor *box;
|
|
static const ClutterColor blue = { 0x00, 0x00, 0xff, 0xff };
|
|
|
|
box = clutter_rectangle_new_with_color (&blue);
|
|
clutter_actor_set_size (box, DOT_SIZE + 2, DOT_SIZE + 2);
|
|
clutter_actor_hide (box);
|
|
|
|
return box;
|
|
}
|
|
|
|
static gboolean
|
|
on_motion_idle (gpointer user_data)
|
|
{
|
|
CallbackData *data = (CallbackData *) user_data;
|
|
guchar *pixels, *p;
|
|
gfloat stage_width, stage_height;
|
|
gint x, y;
|
|
|
|
data->idle_source = 0;
|
|
|
|
clutter_actor_get_size (data->stage, &stage_width, &stage_height);
|
|
|
|
x = CLAMP (data->event.x - TEX_SIZE / 2, 0, stage_width - TEX_SIZE);
|
|
y = CLAMP (data->event.y - TEX_SIZE / 2, 0, stage_height - TEX_SIZE);
|
|
|
|
clutter_actor_set_position (data->box,
|
|
x + TEX_SIZE / 2 - 1,
|
|
y + TEX_SIZE / 2 - 1);
|
|
clutter_actor_show (data->box);
|
|
|
|
/* Redraw so that the layouting will be done and the box will be
|
|
drawn in the right position */
|
|
clutter_stage_ensure_redraw (CLUTTER_STAGE (data->stage));
|
|
|
|
pixels = clutter_stage_read_pixels (CLUTTER_STAGE (data->stage),
|
|
x, y,
|
|
TEX_SIZE, TEX_SIZE);
|
|
|
|
/* Make a red dot in the center */
|
|
p = pixels + (TEX_SIZE / 2 - DOT_SIZE / 2) * TEX_SIZE * 4
|
|
+ (TEX_SIZE / 2 - DOT_SIZE / 2) * 4;
|
|
for (y = 0; y < DOT_SIZE; y++)
|
|
{
|
|
for (x = 0; x < DOT_SIZE; x++)
|
|
{
|
|
*(p++) = 255;
|
|
memset (p, 0, 3);
|
|
p += 3;
|
|
}
|
|
p += TEX_SIZE * 4 - DOT_SIZE * 4;
|
|
}
|
|
|
|
/* Set all of the alpa values to full */
|
|
for (p = pixels + TEX_SIZE * TEX_SIZE * 4; p > pixels; p -= 4)
|
|
*(p - 1) = 255;
|
|
|
|
clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (data->tex),
|
|
pixels, TRUE,
|
|
TEX_SIZE, TEX_SIZE,
|
|
TEX_SIZE * 4, 4, 0, NULL);
|
|
g_free (pixels);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
on_motion (ClutterActor *stage, ClutterMotionEvent *event, CallbackData *data)
|
|
{
|
|
/* Handle the motion event in an idle handler so that multiple
|
|
events will be combined into one */
|
|
if (data->idle_source == 0)
|
|
data->idle_source = clutter_threads_add_idle (on_motion_idle, data);
|
|
|
|
data->event = *event;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
G_MODULE_EXPORT int
|
|
test_stage_read_pixels_main (int argc, char **argv)
|
|
{
|
|
CallbackData data;
|
|
|
|
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
|
return 1;
|
|
|
|
data.idle_source = 0;
|
|
data.stage = clutter_stage_new ();
|
|
clutter_stage_set_title (CLUTTER_STAGE (data.stage), "Read Pixels");
|
|
g_signal_connect (data.stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
|
|
|
data.tex = make_tex ();
|
|
data.box = make_box ();
|
|
clutter_actor_set_position (data.tex,
|
|
clutter_actor_get_width (data.stage)
|
|
- clutter_actor_get_width (data.tex),
|
|
clutter_actor_get_height (data.stage)
|
|
- clutter_actor_get_height (data.tex));
|
|
|
|
clutter_container_add (CLUTTER_CONTAINER (data.stage),
|
|
make_label (), data.tex, data.box, NULL);
|
|
|
|
g_signal_connect (data.stage, "motion-event", G_CALLBACK (on_motion), &data);
|
|
|
|
clutter_actor_show (data.stage);
|
|
|
|
clutter_main ();
|
|
|
|
return 0;
|
|
}
|
|
|
|
G_MODULE_EXPORT const char *
|
|
test_stage_read_pixels_describe (void)
|
|
{
|
|
return "Read back pixels from a Stage.";
|
|
}
|