mirror of
https://github.com/brl/mutter.git
synced 2025-06-14 01:09:30 +00:00
clutter: Move tests to src/tests
Clutter doesn't hold anymore backend implementations, move tests where we have one that we may assign. https://gitlab.gnome.org/GNOME/mutter/merge_requests/672
This commit is contained in:

committed by
Jonas Ådahl

parent
c0a71720af
commit
cfb8f18cef
38
src/tests/clutter/README
Normal file
38
src/tests/clutter/README
Normal file
@ -0,0 +1,38 @@
|
||||
Outline of test categories:
|
||||
|
||||
The conform/ tests should be non-interactive unit-tests that verify a single
|
||||
feature is behaving as documented. Use the GLib and Clutter test API and macros
|
||||
to write the test units. The conformance test suites are meant to be used with
|
||||
continuous integration builds.
|
||||
|
||||
The performance/ tests are performance tests, both focused tests testing single
|
||||
metrics and larger tests. These tests are used to report one or more
|
||||
performance markers for the build of Clutter. Each performance marker is picked
|
||||
up from the standard output of running the tests from strings having the form
|
||||
"\n@ marker-name: 42.23" where 'marker-name' and '42.23' are the key/value pairs
|
||||
of a single metric. Each test can provide multiple key/value pairs. Note that
|
||||
if framerate is the feedback metric the test should forcibly enable FPS
|
||||
debugging itself. The file test-common.h contains utility function helping to
|
||||
do fps reporting.
|
||||
|
||||
The interactive/ tests are any tests whose status can not be determined without
|
||||
a user looking at some visual output, or providing some manual input etc. This
|
||||
covers most of the original Clutter tests. Ideally some of these tests will be
|
||||
migrated into the conform/ directory.
|
||||
|
||||
The accessibility/ tests are tests created to test the accessibility support of
|
||||
clutter, testing some of the atk interfaces.
|
||||
|
||||
Other notes:
|
||||
|
||||
• All tests should ideally include a detailed description in the source
|
||||
explaining exactly what the test is for, how the test was designed to work,
|
||||
and possibly a rationale for the approach taken for testing. Tests for specific
|
||||
bugs should reference the bug report URL or number.
|
||||
|
||||
• When running tests under Valgrind, you should follow the instructions
|
||||
available here:
|
||||
|
||||
https://wiki.gnome.org/Valgrind
|
||||
|
||||
and also use the suppression file available in the Git repository.
|
5
src/tests/clutter/accessibility/.gitignore
vendored
Normal file
5
src/tests/clutter/accessibility/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/cally-atkcomponent-example
|
||||
/cally-atkeditabletext-example
|
||||
/cally-atkevents-example
|
||||
/cally-atktext-example
|
||||
/cally-clone-example
|
94
src/tests/clutter/accessibility/cally-atkcomponent-example.c
Normal file
94
src/tests/clutter/accessibility/cally-atkcomponent-example.c
Normal file
@ -0,0 +1,94 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "cally-examples-util.h"
|
||||
|
||||
#define WIDTH 300
|
||||
#define HEIGHT 300
|
||||
#define SIZE 50
|
||||
#define DEPTH -100
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage = NULL;
|
||||
ClutterActor *button1 = NULL;
|
||||
ClutterActor *button2 = NULL;
|
||||
ClutterActor *button3 = NULL;
|
||||
ClutterActor *button4 = NULL;
|
||||
ClutterActor *group[4];
|
||||
int i = 0;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
cally_util_a11y_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkComponent Test");
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_White);
|
||||
clutter_actor_set_size (stage, WIDTH, HEIGHT);
|
||||
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
button1 = clutter_rectangle_new_with_color (CLUTTER_COLOR_Yellow);
|
||||
clutter_actor_set_size (button1, SIZE, SIZE);
|
||||
|
||||
button2 = clutter_rectangle_new_with_color (CLUTTER_COLOR_Green);
|
||||
clutter_actor_set_position (button2, 2 * SIZE, 0);
|
||||
clutter_actor_set_size (button2, SIZE, SIZE);
|
||||
|
||||
button3 = clutter_rectangle_new_with_color (CLUTTER_COLOR_Blue);
|
||||
clutter_actor_set_position (button3, 0, 2 * SIZE);
|
||||
clutter_actor_set_size (button3, SIZE, SIZE);
|
||||
clutter_actor_set_depth( button3, DEPTH);
|
||||
|
||||
/* a nested hierarchy, to check that the relative positions are
|
||||
computed properly */
|
||||
button4 = clutter_rectangle_new_with_color (CLUTTER_COLOR_Magenta);
|
||||
clutter_actor_set_position (button4, SIZE / 2, SIZE / 2);
|
||||
clutter_actor_set_size (button4, SIZE, SIZE);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
group[i] = clutter_group_new ();
|
||||
clutter_actor_set_position (group[i], SIZE / 2, SIZE / 2);
|
||||
clutter_actor_set_size (group[i], SIZE, SIZE);
|
||||
|
||||
if (i > 0)
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (group[i]), group [i - 1]);
|
||||
}
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button1);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button2);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button3);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group[3]);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (group[0]), button4);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
268
src/tests/clutter/accessibility/cally-atkeditabletext-example.c
Normal file
268
src/tests/clutter/accessibility/cally-atkeditabletext-example.c
Normal file
@ -0,0 +1,268 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <atk/atk.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "cally-examples-util.h"
|
||||
|
||||
#define WIDTH 800
|
||||
#define HEIGHT 600
|
||||
|
||||
static ClutterActor *text_actor = NULL;
|
||||
static ClutterActor *text_editable_actor = NULL;
|
||||
|
||||
/*
|
||||
* Test AtkText interface
|
||||
*/
|
||||
static void
|
||||
test_atk_text (ClutterActor *actor)
|
||||
{
|
||||
AtkObject *object = NULL;
|
||||
AtkEditableText *cally_editable_text = NULL;
|
||||
gint pos = 0;
|
||||
|
||||
object = atk_gobject_accessible_for_object (G_OBJECT (actor));
|
||||
cally_editable_text = ATK_EDITABLE_TEXT (object);
|
||||
|
||||
if (cally_editable_text != NULL) {
|
||||
atk_editable_text_set_text_contents (cally_editable_text, "New text");
|
||||
atk_editable_text_delete_text (cally_editable_text, 0, 3);
|
||||
pos = 3;
|
||||
atk_editable_text_insert_text (cally_editable_text, "New", 0, &pos);
|
||||
|
||||
/* Not implemented in cally, just checking that we can call this
|
||||
functions */
|
||||
atk_editable_text_copy_text (cally_editable_text, 0, -1);
|
||||
atk_editable_text_paste_text (cally_editable_text, 5);
|
||||
atk_editable_text_cut_text (cally_editable_text, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
insert_text_press_cb (ClutterActor *actor,
|
||||
ClutterButtonEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
AtkObject *object = NULL;
|
||||
AtkEditableText *cally_editable_text = NULL;
|
||||
gint pos = 0;
|
||||
|
||||
object = atk_gobject_accessible_for_object (G_OBJECT (text_editable_actor));
|
||||
cally_editable_text = ATK_EDITABLE_TEXT (object);
|
||||
|
||||
pos = 3;
|
||||
atk_editable_text_insert_text (cally_editable_text, "New", 0, &pos);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
delete_text_press_cb (ClutterActor *actor,
|
||||
ClutterButtonEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
AtkObject *object = NULL;
|
||||
AtkEditableText *cally_editable_text = NULL;
|
||||
|
||||
object = atk_gobject_accessible_for_object (G_OBJECT (text_editable_actor));
|
||||
cally_editable_text = ATK_EDITABLE_TEXT (object);
|
||||
|
||||
atk_editable_text_delete_text (cally_editable_text, 0, 3);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_text_press_cb (ClutterActor *actor,
|
||||
ClutterButtonEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
AtkObject *object = NULL;
|
||||
AtkEditableText *cally_editable_text = NULL;
|
||||
|
||||
object = atk_gobject_accessible_for_object (G_OBJECT (text_editable_actor));
|
||||
cally_editable_text = ATK_EDITABLE_TEXT (object);
|
||||
|
||||
atk_editable_text_set_text_contents (cally_editable_text, "New text");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
activate_deactivate_press_cb (ClutterActor *actor,
|
||||
ClutterButtonEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean active = FALSE;
|
||||
|
||||
active = clutter_text_get_activatable (CLUTTER_TEXT (text_editable_actor));
|
||||
clutter_text_set_activatable (CLUTTER_TEXT (text_editable_actor), !active);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
print_cursor_position_press_cb (ClutterActor *actor,
|
||||
ClutterButtonEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
gint pos = 0;
|
||||
|
||||
pos = clutter_text_get_cursor_position (CLUTTER_TEXT (text_editable_actor));
|
||||
|
||||
g_print ("current cursor position %i\n", pos);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
activate_cb (ClutterActor *actor,
|
||||
gpointer data)
|
||||
{
|
||||
g_print ("Actor activated\n");
|
||||
}
|
||||
|
||||
static ClutterActor*
|
||||
_create_button (const gchar *text)
|
||||
{
|
||||
ClutterActor *button = NULL;
|
||||
ClutterActor *rectangle = NULL;
|
||||
ClutterActor *label = NULL;
|
||||
|
||||
button = clutter_group_new ();
|
||||
rectangle = clutter_rectangle_new_with_color (CLUTTER_COLOR_Magenta);
|
||||
clutter_actor_set_size (rectangle, 375, 35);
|
||||
|
||||
label = clutter_text_new_full ("Sans Bold 32px",
|
||||
text,
|
||||
CLUTTER_COLOR_Black);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (button), rectangle);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (button), label);
|
||||
clutter_actor_set_reactive (button, TRUE);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
static void
|
||||
make_ui (ClutterActor *stage)
|
||||
{
|
||||
ClutterActor *button = NULL;
|
||||
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkEditable Test");
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_White);
|
||||
clutter_actor_set_size (stage, WIDTH, HEIGHT);
|
||||
|
||||
/* text */
|
||||
text_actor = clutter_text_new_full ("Sans Bold 32px",
|
||||
"Lorem ipsum dolor sit amet",
|
||||
CLUTTER_COLOR_Red);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_actor);
|
||||
|
||||
/* text_editable */
|
||||
text_editable_actor = clutter_text_new_full ("Sans Bold 32px",
|
||||
"consectetur adipisicing elit",
|
||||
CLUTTER_COLOR_Red);
|
||||
clutter_actor_set_position (text_editable_actor, 0, 100);
|
||||
clutter_text_set_editable (CLUTTER_TEXT (text_editable_actor), TRUE);
|
||||
clutter_text_set_selectable (CLUTTER_TEXT (text_editable_actor), TRUE);
|
||||
clutter_text_set_selection_color (CLUTTER_TEXT (text_editable_actor),
|
||||
CLUTTER_COLOR_Green);
|
||||
clutter_text_set_activatable (CLUTTER_TEXT (text_editable_actor),
|
||||
TRUE);
|
||||
clutter_text_set_line_wrap (CLUTTER_TEXT (text_editable_actor), TRUE);
|
||||
clutter_actor_grab_key_focus (text_editable_actor);
|
||||
clutter_actor_set_reactive (text_editable_actor, TRUE);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_editable_actor);
|
||||
g_signal_connect (text_editable_actor, "activate",
|
||||
G_CALLBACK (activate_cb), NULL);
|
||||
|
||||
/* test buttons */
|
||||
button = _create_button ("Set");
|
||||
clutter_actor_set_position (button, 100, 200);
|
||||
|
||||
g_signal_connect_after (button, "button-press-event",
|
||||
G_CALLBACK (set_text_press_cb), NULL);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button);
|
||||
|
||||
button = _create_button ("Delete");
|
||||
clutter_actor_set_position (button, 100, 250);
|
||||
|
||||
g_signal_connect_after (button, "button-press-event",
|
||||
G_CALLBACK (delete_text_press_cb), NULL);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button);
|
||||
|
||||
button = _create_button ("Insert");
|
||||
clutter_actor_set_position (button, 100, 300);
|
||||
|
||||
g_signal_connect_after (button, "button-press-event",
|
||||
G_CALLBACK (insert_text_press_cb), NULL);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button);
|
||||
|
||||
button = _create_button ("Activate/Deactivate");
|
||||
clutter_actor_set_position (button, 100, 350);
|
||||
|
||||
g_signal_connect_after (button, "button-press-event",
|
||||
G_CALLBACK (activate_deactivate_press_cb), NULL);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button);
|
||||
|
||||
button = _create_button ("Cursor position");
|
||||
clutter_actor_set_position (button, 100, 450);
|
||||
|
||||
g_signal_connect_after (button, "button-press-event",
|
||||
G_CALLBACK (print_cursor_position_press_cb), NULL);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage = NULL;
|
||||
|
||||
g_set_application_name ("AtkEditableText");
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
cally_util_a11y_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
make_ui (stage);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
test_atk_text (text_actor);
|
||||
test_atk_text (text_editable_actor);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
196
src/tests/clutter/accessibility/cally-atkevents-example.c
Normal file
196
src/tests/clutter/accessibility/cally-atkevents-example.c
Normal file
@ -0,0 +1,196 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The purpose of this example is test key event and global event
|
||||
* implementation, specifically:
|
||||
*
|
||||
* atk_add_global_event_listener
|
||||
* atk_remove_global_event_listener
|
||||
* atk_add_key_event_listener
|
||||
* atk_remove_key_event_listener
|
||||
*/
|
||||
#include <atk/atk.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <cally/cally.h>
|
||||
|
||||
#include "cally-examples-util.h"
|
||||
|
||||
#define WIDTH 800
|
||||
#define HEIGHT 600
|
||||
#define HEIGHT_STEP 100
|
||||
#define NUM_ENTRIES 3
|
||||
|
||||
struct _Data{
|
||||
gint value;
|
||||
};
|
||||
typedef struct _Data Data;
|
||||
|
||||
static gboolean
|
||||
atk_key_listener (AtkKeyEventStruct *event, gpointer data)
|
||||
{
|
||||
Data *my_data = (Data*) data;
|
||||
|
||||
g_print ("atk_listener: 0x%x ", event->keyval);
|
||||
|
||||
if (my_data != NULL) {
|
||||
g_print ("\t Data value: %i\n", my_data->value);
|
||||
} else {
|
||||
g_print ("\tNo data!!\n");
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
window_event_listener (GSignalInvocationHint * signal_hint,
|
||||
guint n_param_values,
|
||||
const GValue * param_values, gpointer data)
|
||||
{
|
||||
AtkObject *accessible;
|
||||
GSignalQuery signal_query;
|
||||
const gchar *name, *s;
|
||||
|
||||
g_signal_query (signal_hint->signal_id, &signal_query);
|
||||
name = signal_query.signal_name;
|
||||
|
||||
accessible = ATK_OBJECT (g_value_get_object (¶m_values[0]));
|
||||
s = atk_object_get_name (accessible);
|
||||
|
||||
g_print ("Detected window event \"%s\" from object \"%p\" named \"%s\"\n",
|
||||
name, accessible, s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
static void
|
||||
make_ui (ClutterActor *stage)
|
||||
{
|
||||
gint i = 0;
|
||||
ClutterActor *editable = NULL;
|
||||
ClutterActor *rectangle = NULL;
|
||||
ClutterActor *label = NULL;
|
||||
ClutterColor color_sel = { 0x00, 0xff, 0x00, 0x55 };
|
||||
ClutterColor color_label = { 0x00, 0xff, 0x55, 0xff };
|
||||
ClutterColor color_rect = { 0x00, 0xff, 0xff, 0x55 };
|
||||
float label_geom_y, editable_geom_y;
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_White);
|
||||
clutter_actor_set_size (stage, WIDTH, HEIGHT);
|
||||
|
||||
label_geom_y = 50;
|
||||
editable_geom_y = 50;
|
||||
|
||||
for (i = 0; i < NUM_ENTRIES; i++)
|
||||
{
|
||||
/* label */
|
||||
label = clutter_text_new_full ("Sans Bold 32px",
|
||||
"Entry",
|
||||
&color_label);
|
||||
clutter_actor_set_position (label, 0, label_geom_y);
|
||||
|
||||
/* editable */
|
||||
editable = clutter_text_new_full ("Sans Bold 32px",
|
||||
"ddd",
|
||||
CLUTTER_COLOR_Red);
|
||||
clutter_actor_set_position (editable, 150, editable_geom_y);
|
||||
clutter_actor_set_size (editable, 500, 75);
|
||||
clutter_text_set_editable (CLUTTER_TEXT (editable), TRUE);
|
||||
clutter_text_set_selectable (CLUTTER_TEXT (editable), TRUE);
|
||||
clutter_text_set_selection_color (CLUTTER_TEXT (editable),
|
||||
&color_sel);
|
||||
clutter_actor_grab_key_focus (editable);
|
||||
clutter_actor_set_reactive (editable, TRUE);
|
||||
|
||||
/* rectangle: to create a entry "feeling" */
|
||||
rectangle = clutter_rectangle_new_with_color (&color_rect);
|
||||
clutter_actor_set_position (rectangle, 150, editable_geom_y);
|
||||
clutter_actor_set_size (rectangle, 500, 75);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), label);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), editable);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rectangle);
|
||||
|
||||
label_geom_y += HEIGHT_STEP;
|
||||
editable_geom_y += HEIGHT_STEP;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *stage_main;
|
||||
Data data1, data2, data3;
|
||||
guint id_1 = 0, id_2 = 0, id_3 = 0;
|
||||
|
||||
g_set_application_name ("AtkText");
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
if (cally_util_a11y_init (&argc, &argv) == FALSE)
|
||||
{
|
||||
g_error ("This example requires the accessibility support, "
|
||||
"especifically AtkUtil implementation loaded, "
|
||||
"as it tries to register and remove event listeners");
|
||||
}
|
||||
|
||||
data1.value = 10;
|
||||
data2.value = 20;
|
||||
data3.value = 30;
|
||||
|
||||
/* key event listeners */
|
||||
id_1 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data1);
|
||||
atk_remove_key_event_listener (id_1);
|
||||
id_2 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data2);
|
||||
id_3 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data3);
|
||||
|
||||
atk_remove_key_event_listener (id_2);
|
||||
|
||||
g_print ("key event listener ids registered: (%i, %i, %i)\n", id_1, id_2, id_3);
|
||||
|
||||
/* event listeners */
|
||||
atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:create");
|
||||
atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:destroy");
|
||||
atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:activate");
|
||||
atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:deactivate");
|
||||
|
||||
stage_main = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage_main), "Cally - AtkEvents/1");
|
||||
g_signal_connect (stage_main, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
make_ui (stage_main);
|
||||
|
||||
clutter_actor_show_all (stage_main);
|
||||
|
||||
if (clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE))
|
||||
{
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkEvents/2");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
make_ui (stage);
|
||||
clutter_actor_show_all (stage);
|
||||
}
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
255
src/tests/clutter/accessibility/cally-atktext-example.c
Normal file
255
src/tests/clutter/accessibility/cally-atktext-example.c
Normal file
@ -0,0 +1,255 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <atk/atk.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "cally-examples-util.h"
|
||||
|
||||
#define WIDTH 800
|
||||
#define HEIGHT 600
|
||||
|
||||
static ClutterActor *text_actor = NULL;
|
||||
static ClutterActor *text_editable_actor = NULL;
|
||||
|
||||
/*
|
||||
* Test AtkText interface
|
||||
*/
|
||||
static void
|
||||
test_atk_text (ClutterActor *actor)
|
||||
{
|
||||
gchar *text = NULL;
|
||||
AtkObject *object = NULL;
|
||||
AtkText *cally_text = NULL;
|
||||
gboolean bool = FALSE;
|
||||
gunichar unichar;
|
||||
gint count = -1;
|
||||
gint start = -1;
|
||||
gint end = -1;
|
||||
gint pos = -1;
|
||||
AtkAttributeSet *at_set = NULL;
|
||||
GSList *attrs;
|
||||
gchar *buf;
|
||||
gint x, y, width, height;
|
||||
|
||||
object = atk_gobject_accessible_for_object (G_OBJECT (actor));
|
||||
cally_text = ATK_TEXT (object);
|
||||
|
||||
if (!cally_text)
|
||||
return;
|
||||
|
||||
text = atk_text_get_text (cally_text, 0, -1);
|
||||
g_print ("atk_text_get_text output: %s\n", text);
|
||||
|
||||
unichar = atk_text_get_character_at_offset (cally_text, 5);
|
||||
buf = g_ucs4_to_utf8 (&unichar, 1, NULL, NULL, NULL);
|
||||
g_print ("atk_text_get_character_at_offset(5): '%s' vs '%c'\n", buf, text[5]);
|
||||
g_free (text); text = NULL;
|
||||
g_free (buf); buf = NULL;
|
||||
|
||||
text = atk_text_get_string_at_offset (cally_text,
|
||||
5,
|
||||
ATK_TEXT_GRANULARITY_WORD,
|
||||
&start, &end);
|
||||
g_print ("atk_text_get_string_at_offset: %s, %i, %i\n",
|
||||
text, start, end);
|
||||
g_free (text); text = NULL;
|
||||
|
||||
pos = atk_text_get_caret_offset (cally_text);
|
||||
g_print ("atk_text_get_caret_offset: %i\n", pos);
|
||||
|
||||
atk_text_set_caret_offset (cally_text, 5);
|
||||
|
||||
count = atk_text_get_character_count (cally_text);
|
||||
g_print ("atk_text_get_character_count: %i\n", count);
|
||||
|
||||
count = atk_text_get_n_selections (cally_text);
|
||||
g_print ("atk_text_get_n_selections: %i\n", count);
|
||||
|
||||
text = atk_text_get_selection (cally_text, 0, &start, &end);
|
||||
g_print ("atk_text_get_selection: %s, %i, %i\n", text, start, end);
|
||||
g_free(text); text = NULL;
|
||||
|
||||
bool = atk_text_remove_selection (cally_text, 0);
|
||||
g_print ("atk_text_remove_selection (0): %i\n", bool);
|
||||
|
||||
bool = atk_text_remove_selection (cally_text, 1);
|
||||
g_print ("atk_text_remove_selection (1): %i\n", bool);
|
||||
|
||||
bool = atk_text_add_selection (cally_text, 5, 10);
|
||||
g_print ("atk_text_add_selection: %i\n", bool);
|
||||
|
||||
bool = atk_text_set_selection (cally_text, 0, 6, 10);
|
||||
g_print ("atk_text_set_selection: %i\n", bool);
|
||||
|
||||
at_set = atk_text_get_run_attributes (cally_text, 0,
|
||||
&start, &end);
|
||||
g_print ("atk_text_get_run_attributes: %i, %i\n", start, end);
|
||||
attrs = (GSList*) at_set;
|
||||
while (attrs)
|
||||
{
|
||||
AtkAttribute *at = (AtkAttribute *) attrs->data;
|
||||
g_print ("text run %s = %s\n", at->name, at->value);
|
||||
attrs = g_slist_next (attrs);
|
||||
}
|
||||
|
||||
atk_text_get_character_extents (cally_text, 0, &x, &y, &width, &height,
|
||||
ATK_XY_WINDOW);
|
||||
g_print ("atk_text_get_character_extents (0, window): x=%i y=%i width=%i height=%i\n",
|
||||
x, y, width, height);
|
||||
|
||||
atk_text_get_character_extents (cally_text, 0, &x, &y, &width, &height,
|
||||
ATK_XY_SCREEN);
|
||||
g_print ("atk_text_get_character_extents (0, screen): x=%i y=%i width=%i height=%i\n",
|
||||
x, y, width, height);
|
||||
|
||||
pos = atk_text_get_offset_at_point (cally_text, 200, 10, ATK_XY_WINDOW);
|
||||
g_print ("atk_text_get_offset_at_point (200, 10, window): %i\n", pos);
|
||||
|
||||
pos = atk_text_get_offset_at_point (cally_text, 200, 100, ATK_XY_SCREEN);
|
||||
g_print ("atk_text_get_offset_at_point (200, 100, screen): %i\n", pos);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
dump_actor_default_atk_attributes (ClutterActor *actor)
|
||||
{
|
||||
AtkObject *object = NULL;
|
||||
AtkText *cally_text = NULL;
|
||||
AtkAttributeSet *at_set = NULL;
|
||||
GSList *attrs;
|
||||
const gchar *text_value = NULL;
|
||||
|
||||
object = atk_gobject_accessible_for_object (G_OBJECT (actor));
|
||||
cally_text = ATK_TEXT (object);
|
||||
|
||||
if (!cally_text)
|
||||
return;
|
||||
|
||||
text_value = clutter_text_get_text (CLUTTER_TEXT (actor));
|
||||
g_print ("text value = %s\n", text_value);
|
||||
|
||||
at_set = atk_text_get_default_attributes (cally_text);
|
||||
attrs = (GSList*) at_set;
|
||||
while (attrs) {
|
||||
AtkAttribute *at = (AtkAttribute *) attrs->data;
|
||||
g_print ("text default %s = %s\n", at->name, at->value);
|
||||
attrs = g_slist_next (attrs);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
button_press_cb (ClutterActor *actor,
|
||||
ClutterButtonEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
test_atk_text (text_actor);
|
||||
test_atk_text (text_editable_actor);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
make_ui (ClutterActor *stage)
|
||||
{
|
||||
ClutterColor color_stage = { 0x00, 0x00, 0x00, 0xff };
|
||||
ClutterColor color_text = { 0xff, 0x00, 0x00, 0xff };
|
||||
ClutterColor color_sel = { 0x00, 0xff, 0x00, 0x55 };
|
||||
ClutterColor color_rect = { 0x00, 0xff, 0xff, 0xff };
|
||||
ClutterColor color_label = { 0x00, 0x00, 0x00, 0xff };
|
||||
ClutterActor *button = NULL;
|
||||
ClutterActor *rectangle = NULL;
|
||||
ClutterActor *label = NULL;
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &color_stage);
|
||||
clutter_actor_set_size (stage, WIDTH, HEIGHT);
|
||||
|
||||
/* text */
|
||||
text_actor = clutter_text_new_full ("Sans Bold 32px",
|
||||
"",
|
||||
&color_text);
|
||||
clutter_text_set_markup (CLUTTER_TEXT(text_actor),
|
||||
"<span fgcolor=\"#FFFF00\" bgcolor=\"#00FF00\"><s>Lorem ipsum dolor sit amet</s></span>");
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_actor);
|
||||
dump_actor_default_atk_attributes (text_actor);
|
||||
|
||||
/* text_editable */
|
||||
text_editable_actor = clutter_text_new_full ("Sans Bold 32px",
|
||||
"consectetur adipisicing elit",
|
||||
&color_text);
|
||||
clutter_actor_set_position (text_editable_actor, 20, 100);
|
||||
clutter_text_set_editable (CLUTTER_TEXT (text_editable_actor), TRUE);
|
||||
clutter_text_set_selectable (CLUTTER_TEXT (text_editable_actor), TRUE);
|
||||
clutter_text_set_selection_color (CLUTTER_TEXT (text_editable_actor),
|
||||
&color_sel);
|
||||
clutter_text_set_line_wrap (CLUTTER_TEXT (text_editable_actor), TRUE);
|
||||
clutter_actor_grab_key_focus (text_editable_actor);
|
||||
clutter_actor_set_reactive (text_editable_actor, TRUE);
|
||||
dump_actor_default_atk_attributes (text_editable_actor);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_editable_actor);
|
||||
|
||||
/* test button */
|
||||
button = clutter_group_new ();
|
||||
rectangle = clutter_rectangle_new_with_color (&color_rect);
|
||||
clutter_actor_set_size (rectangle, 75, 35);
|
||||
|
||||
label = clutter_text_new_full ("Sans Bold 32px",
|
||||
"Test", &color_label);
|
||||
clutter_actor_set_position (button, 100, 200);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (button), rectangle);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (button), label);
|
||||
clutter_actor_set_reactive (button, TRUE);
|
||||
|
||||
g_signal_connect_after (button, "button-press-event",
|
||||
G_CALLBACK (button_press_cb), NULL);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
|
||||
g_set_application_name ("AtkText");
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
cally_util_a11y_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkText Test");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
make_ui (stage);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
test_atk_text (text_actor);
|
||||
test_atk_text (text_editable_actor);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
116
src/tests/clutter/accessibility/cally-clone-example.c
Normal file
116
src/tests/clutter/accessibility/cally-clone-example.c
Normal file
@ -0,0 +1,116 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <atk/atk.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "cally-examples-util.h"
|
||||
|
||||
#define WIDTH 800
|
||||
#define HEIGHT 600
|
||||
#define HEIGHT_STEP 100
|
||||
#define NUM_ENTRIES 3
|
||||
|
||||
static void
|
||||
make_ui (ClutterActor *stage)
|
||||
{
|
||||
ClutterActor *editable = NULL;
|
||||
ClutterActor *rectangle = NULL;
|
||||
ClutterActor *label = NULL;
|
||||
ClutterColor color_stage = { 0x00, 0x00, 0x00, 0xff };
|
||||
ClutterColor color_text = { 0xff, 0x00, 0x00, 0xff };
|
||||
ClutterColor color_sel = { 0x00, 0xff, 0x00, 0x55 };
|
||||
ClutterColor color_label = { 0x00, 0xff, 0x55, 0xff };
|
||||
ClutterColor color_rect = { 0x00, 0xff, 0xff, 0x55 };
|
||||
ClutterActor *full_entry = NULL;
|
||||
ClutterActor *cloned_entry = NULL;
|
||||
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &color_stage);
|
||||
clutter_actor_set_size (stage, WIDTH, HEIGHT);
|
||||
|
||||
label = clutter_text_new_full ("Sans Bold 32px",
|
||||
"Entry",
|
||||
&color_label);
|
||||
clutter_actor_set_position (label, 0, 50);
|
||||
|
||||
/* editable */
|
||||
editable = clutter_text_new_full ("Sans Bold 32px",
|
||||
"ddd",
|
||||
&color_text);
|
||||
clutter_actor_set_position (editable, 150, 50);
|
||||
clutter_text_set_editable (CLUTTER_TEXT (editable), TRUE);
|
||||
clutter_text_set_selectable (CLUTTER_TEXT (editable), TRUE);
|
||||
clutter_text_set_selection_color (CLUTTER_TEXT (editable),
|
||||
&color_sel);
|
||||
clutter_actor_grab_key_focus (editable);
|
||||
clutter_actor_set_reactive (editable, TRUE);
|
||||
|
||||
/* rectangle: to create a entry "feeling" */
|
||||
rectangle = clutter_rectangle_new_with_color (&color_rect);
|
||||
clutter_actor_set_position (rectangle, 150, 50);
|
||||
clutter_actor_add_constraint (rectangle, clutter_bind_constraint_new (editable, CLUTTER_BIND_SIZE, 0));
|
||||
|
||||
full_entry = clutter_group_new ();
|
||||
clutter_actor_set_position (full_entry, 0, 50);
|
||||
clutter_actor_set_size (full_entry, 100, 75);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (full_entry), label);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (full_entry), editable);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (full_entry), rectangle);
|
||||
clutter_actor_show_all (full_entry);
|
||||
clutter_actor_set_scale (full_entry, 2, 1);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), full_entry);
|
||||
|
||||
/* Cloning! */
|
||||
cloned_entry = clutter_clone_new (full_entry);
|
||||
clutter_actor_set_position (cloned_entry, 50, 200);
|
||||
clutter_actor_set_scale (cloned_entry, 1, 2);
|
||||
clutter_actor_show_all (cloned_entry);
|
||||
clutter_actor_set_reactive (cloned_entry, TRUE);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), cloned_entry);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
|
||||
g_set_application_name ("Clone Example");
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
cally_util_a11y_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - Clone Test");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
make_ui (stage);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
146
src/tests/clutter/accessibility/cally-examples-util.c
Normal file
146
src/tests/clutter/accessibility/cally-examples-util.c
Normal file
@ -0,0 +1,146 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <gmodule.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "cally-examples-util.h"
|
||||
|
||||
/* Checking the at-spi sources, the module directory is
|
||||
* $(libdir)/gtk-2.0/modules
|
||||
*
|
||||
* It is supposed cally would be installed on the same libdir.
|
||||
*
|
||||
* You could use the option atk-bridge-dir to use other directory.
|
||||
*/
|
||||
#define ATK_BRIDGE_DEFAULT_MODULE_DIRECTORY PREFIXDIR"/gtk-2.0/modules"
|
||||
|
||||
static gchar *
|
||||
_search_for_bridge_module (const gchar *module_name)
|
||||
{
|
||||
/* We simplify the search for the atk bridge, see see the definition
|
||||
* of the macro for more information*/
|
||||
return g_strdup (ATK_BRIDGE_DEFAULT_MODULE_DIRECTORY);
|
||||
}
|
||||
|
||||
static gchar*
|
||||
_a11y_check_custom_bridge (int *argc,
|
||||
char ***argv)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
static gchar *bridge_dir = NULL;
|
||||
static GOptionEntry entries [] =
|
||||
{
|
||||
{"atk-bridge-dir", 'd', 0, G_OPTION_ARG_STRING, &bridge_dir, "atk-bridge module directory", NULL}
|
||||
};
|
||||
|
||||
context = g_option_context_new ("- cally examples");
|
||||
g_option_context_add_main_entries (context, entries, NULL);
|
||||
if (!g_option_context_parse (context, argc, argv, &error))
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_print ("Use --help for more information.\n");
|
||||
exit (0);
|
||||
}
|
||||
|
||||
return bridge_dir;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
_a11y_invoke_module (const gchar *module_path,
|
||||
gboolean init)
|
||||
{
|
||||
GModule *handle;
|
||||
void (*invoke_fn) (void);
|
||||
const char *method;
|
||||
|
||||
if (init)
|
||||
method = "gnome_accessibility_module_init";
|
||||
else
|
||||
method = "gnome_accessibility_module_shutdown";
|
||||
|
||||
if (!module_path)
|
||||
return FALSE;
|
||||
|
||||
if (!(handle = g_module_open (module_path, G_MODULE_BIND_LAZY)))
|
||||
{
|
||||
g_warning ("Accessibility: failed to load module '%s': '%s'",
|
||||
module_path, g_module_error ());
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!g_module_symbol (handle, method, (gpointer *)&invoke_fn))
|
||||
{
|
||||
g_warning ("Accessibility: error library '%s' does not include "
|
||||
"method '%s' required for accessibility support",
|
||||
module_path, method);
|
||||
g_module_close (handle);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_debug ("Module %s loaded successfully", module_path);
|
||||
invoke_fn ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will initialize the accessibility support provided by cally.
|
||||
*
|
||||
* Basically it will load the cally module using gmodule functions.
|
||||
*
|
||||
* Returns if it was able to init the a11y support or not.
|
||||
*/
|
||||
gboolean
|
||||
cally_util_a11y_init (int *argc, char ***argv)
|
||||
{
|
||||
gchar *bridge_dir = NULL;
|
||||
gchar *bridge_path = NULL;
|
||||
gboolean result = FALSE;
|
||||
|
||||
if (clutter_get_accessibility_enabled () == FALSE)
|
||||
{
|
||||
g_warning ("Accessibility: clutter has no accessibility enabled"
|
||||
" skipping the atk-bridge load");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bridge_dir = _a11y_check_custom_bridge (argc, argv);
|
||||
if (bridge_dir == NULL)
|
||||
bridge_dir = _search_for_bridge_module ("atk-bridge");
|
||||
|
||||
bridge_path = g_module_build_path (bridge_dir, "libatk-bridge");
|
||||
|
||||
result = _a11y_invoke_module (bridge_path, TRUE);
|
||||
|
||||
g_free (bridge_dir);
|
||||
g_free (bridge_path);
|
||||
|
||||
return result;
|
||||
}
|
24
src/tests/clutter/accessibility/cally-examples-util.h
Normal file
24
src/tests/clutter/accessibility/cally-examples-util.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
gboolean
|
||||
cally_util_a11y_init (int *argc, char ***argv);
|
38
src/tests/clutter/accessibility/meson.build
Normal file
38
src/tests/clutter/accessibility/meson.build
Normal file
@ -0,0 +1,38 @@
|
||||
clutter_test_accessibility_common_sources = [
|
||||
'cally-examples-util.c',
|
||||
'cally-examples-util.h',
|
||||
]
|
||||
|
||||
clutter_test_accessibility_c_args = [
|
||||
'-DPREFIXDIR="@0@"'.format(libdir),
|
||||
'-DCLUTTER_DISABLE_DEPRECATION_WARNINGS',
|
||||
'-DGLIB_DISABLE_DEPRECATION_WARNINGS',
|
||||
]
|
||||
|
||||
clutter_test_accessibility_c_args += clutter_debug_c_args
|
||||
|
||||
clutter_accessibility_tests_dependencies = [
|
||||
clutter_deps,
|
||||
libmutter_clutter_dep,
|
||||
]
|
||||
|
||||
clutter_accessibility_tests = [
|
||||
'cally-atkcomponent-example',
|
||||
'cally-atktext-example',
|
||||
'cally-atkevents-example',
|
||||
'cally-atkeditabletext-example',
|
||||
'cally-clone-example',
|
||||
]
|
||||
|
||||
foreach test : clutter_accessibility_tests
|
||||
executable(test,
|
||||
sources: [
|
||||
clutter_test_accessibility_common_sources,
|
||||
test + '.c',
|
||||
],
|
||||
include_directories: clutter_includes,
|
||||
c_args: clutter_test_accessibility_c_args,
|
||||
dependencies: [clutter_accessibility_tests_dependencies],
|
||||
install: false,
|
||||
)
|
||||
endforeach
|
173
src/tests/clutter/clutter-1.0.suppressions
Normal file
173
src/tests/clutter/clutter-1.0.suppressions
Normal file
@ -0,0 +1,173 @@
|
||||
{
|
||||
ioctl_1
|
||||
Memcheck:Param
|
||||
ioctl(generic)
|
||||
fun:ioctl
|
||||
fun:driDrawableInitVBlank
|
||||
fun:intelMakeCurrent
|
||||
fun:glXMakeContextCurrent
|
||||
}
|
||||
|
||||
{
|
||||
ioctl_2
|
||||
Memcheck:Param
|
||||
ioctl(generic)
|
||||
fun:ioctl
|
||||
fun:driDrawableGetMSC32
|
||||
fun:clutter_backend_glx_redraw
|
||||
}
|
||||
|
||||
{
|
||||
ioctl_3
|
||||
Memcheck:Param
|
||||
ioctl(generic)
|
||||
fun:ioctl
|
||||
fun:driWaitForMSC32
|
||||
fun:clutter_backend_glx_redraw
|
||||
}
|
||||
|
||||
{
|
||||
mesa_init_context
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:glXCreateNewContext
|
||||
}
|
||||
|
||||
{
|
||||
type_register
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:g_type_register_*
|
||||
}
|
||||
|
||||
{
|
||||
type_ref
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:g_type_class_ref
|
||||
}
|
||||
|
||||
{
|
||||
type_interface_prereq
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:g_type_interface_add_prerequisite
|
||||
}
|
||||
|
||||
{
|
||||
get_charset
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:g_get_charset
|
||||
}
|
||||
|
||||
{
|
||||
cogl_features
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:cogl_get_features
|
||||
}
|
||||
|
||||
{
|
||||
glx_query_version
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:glXQueryVersion
|
||||
}
|
||||
|
||||
{
|
||||
glx_create_context
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:glXCreateNewContext
|
||||
}
|
||||
|
||||
{
|
||||
glx_make_current
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:glXMakeContextCurrent
|
||||
}
|
||||
|
||||
{
|
||||
gl_draw_arrays
|
||||
Memcheck:Leak
|
||||
fun:*malloc
|
||||
...
|
||||
fun:glDrawArrays
|
||||
}
|
||||
|
||||
{
|
||||
cogl_clear
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:cogl_clear
|
||||
}
|
||||
|
||||
{
|
||||
default_font
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:clutter_backend_get_font_name
|
||||
}
|
||||
|
||||
{
|
||||
id_pool
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:clutter_id_pool_new
|
||||
}
|
||||
|
||||
{
|
||||
x_open_display
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:XOpenDisplay
|
||||
}
|
||||
|
||||
# ... and font descriptions from every "sans 12" type string
|
||||
{
|
||||
pango_font_description_from_string
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:pango_font_description_from_string
|
||||
}
|
||||
|
||||
# other lib init
|
||||
{
|
||||
fontconfig_init
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:FcConfigParseAndLoad
|
||||
}
|
||||
|
||||
{
|
||||
freetype_init
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:FT_Open_Face
|
||||
}
|
||||
|
||||
{
|
||||
x_init_ext
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
fun:XInitExtension
|
||||
}
|
740
src/tests/clutter/conform/actor-anchors.c
Normal file
740
src/tests/clutter/conform/actor-anchors.c
Normal file
@ -0,0 +1,740 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define NOTIFY_ANCHOR_X (1 << 0)
|
||||
#define NOTIFY_ANCHOR_Y (1 << 1)
|
||||
#define NOTIFY_ANCHOR_GRAVITY (1 << 2)
|
||||
#define NOTIFY_SCALE_X (1 << 3)
|
||||
#define NOTIFY_SCALE_Y (1 << 4)
|
||||
#define NOTIFY_SCALE_CENTER_X (1 << 5)
|
||||
#define NOTIFY_SCALE_CENTER_Y (1 << 6)
|
||||
#define NOTIFY_SCALE_GRAVITY (1 << 7)
|
||||
#define NOTIFY_ROTATION_ANGLE_X (1 << 8)
|
||||
#define NOTIFY_ROTATION_ANGLE_Y (1 << 9)
|
||||
#define NOTIFY_ROTATION_ANGLE_Z (1 << 10)
|
||||
#define NOTIFY_ROTATION_CENTER_X (1 << 11)
|
||||
#define NOTIFY_ROTATION_CENTER_Y (1 << 12)
|
||||
#define NOTIFY_ROTATION_CENTER_Z (1 << 13)
|
||||
#define NOTIFY_ROTATION_CENTER_Z_GRAVITY (1 << 14)
|
||||
|
||||
#define RECT_WIDTH 100.0
|
||||
#define RECT_HEIGHT 80.0
|
||||
|
||||
/* Allow the transformed position by off by a certain number of
|
||||
pixels */
|
||||
#define POSITION_TOLERANCE 2
|
||||
|
||||
typedef struct _TestState
|
||||
{
|
||||
gulong notifications;
|
||||
ClutterActor *rect;
|
||||
} TestState;
|
||||
|
||||
static const struct
|
||||
{
|
||||
ClutterGravity gravity;
|
||||
gfloat x_pos;
|
||||
gfloat y_pos;
|
||||
} gravities[] =
|
||||
{
|
||||
{ CLUTTER_GRAVITY_NORTH, RECT_WIDTH / 2, 0 },
|
||||
{ CLUTTER_GRAVITY_NORTH_EAST, RECT_WIDTH, 0 },
|
||||
{ CLUTTER_GRAVITY_EAST, RECT_WIDTH, RECT_HEIGHT / 2 },
|
||||
{ CLUTTER_GRAVITY_SOUTH_EAST, RECT_WIDTH, RECT_HEIGHT },
|
||||
{ CLUTTER_GRAVITY_SOUTH, RECT_WIDTH / 2, RECT_HEIGHT },
|
||||
{ CLUTTER_GRAVITY_SOUTH_WEST, 0, RECT_HEIGHT },
|
||||
{ CLUTTER_GRAVITY_WEST, 0, RECT_HEIGHT / 2 },
|
||||
{ CLUTTER_GRAVITY_NORTH_WEST, 0, 0 },
|
||||
{ CLUTTER_GRAVITY_CENTER, RECT_WIDTH / 2, RECT_HEIGHT / 2 }
|
||||
};
|
||||
|
||||
static const char * const properties[] = {
|
||||
"anchor-x",
|
||||
"anchor-y",
|
||||
"anchor-gravity",
|
||||
"scale-x",
|
||||
"scale-y",
|
||||
"scale-center-x",
|
||||
"scale-center-y",
|
||||
"scale-gravity",
|
||||
"rotation-angle-x",
|
||||
"rotation-angle-y",
|
||||
"rotation-angle-z",
|
||||
"rotation-center-x",
|
||||
"rotation-center-y",
|
||||
"rotation-center-z",
|
||||
"rotation-center-z-gravity"
|
||||
};
|
||||
|
||||
static const int n_properties = G_N_ELEMENTS (properties);
|
||||
|
||||
static void
|
||||
notify_cb (GObject *object, GParamSpec *pspec, TestState *state)
|
||||
{
|
||||
int i;
|
||||
int new_flags = 0;
|
||||
int flag = 1;
|
||||
|
||||
for (i = 0; i < n_properties; i++)
|
||||
{
|
||||
if (!strcmp (properties[i], pspec->name))
|
||||
new_flags |= flag;
|
||||
|
||||
flag <<= 1;
|
||||
}
|
||||
|
||||
g_assert ((new_flags & state->notifications) == 0);
|
||||
|
||||
state->notifications |= new_flags;
|
||||
}
|
||||
|
||||
#define assert_notifications(flags) G_STMT_START { \
|
||||
g_assert (state->notifications == (flags)); \
|
||||
state->notifications = 0; } G_STMT_END
|
||||
|
||||
/* Helper macro to assert the transformed position. This needs to be a
|
||||
macro so that the assertion failure will report the right line
|
||||
number */
|
||||
#define assert_coords(state, x_1, y_1, x_2, y_2) G_STMT_START { \
|
||||
ClutterVertex verts[4]; \
|
||||
clutter_actor_get_abs_allocation_vertices ((state)->rect, verts); \
|
||||
check_coords ((state), (x_1), (y_1), (x_2), (y_2), verts); \
|
||||
g_assert (approx_equal ((x_1), verts[0].x)); \
|
||||
g_assert (approx_equal ((y_1), verts[0].y)); \
|
||||
g_assert (approx_equal ((x_2), verts[3].x)); \
|
||||
g_assert (approx_equal ((y_2), verts[3].y)); } G_STMT_END
|
||||
|
||||
#define assert_position(state, x, y) \
|
||||
assert_coords((state), (x), (y), (x) + RECT_WIDTH, (y) + RECT_HEIGHT)
|
||||
|
||||
#define assert_vertex_and_free(v, xc, yc, zc) G_STMT_START { \
|
||||
g_assert (approx_equal (v->x, xc) && \
|
||||
approx_equal (v->y, yc) && \
|
||||
approx_equal (v->z, zc)); \
|
||||
g_boxed_free (CLUTTER_TYPE_VERTEX, v); } G_STMT_END
|
||||
|
||||
static inline gboolean
|
||||
approx_equal (int a, int b)
|
||||
{
|
||||
return abs (a - b) <= POSITION_TOLERANCE;
|
||||
}
|
||||
|
||||
static void
|
||||
check_coords (TestState *state,
|
||||
gint x_1,
|
||||
gint y_1,
|
||||
gint x_2,
|
||||
gint y_2,
|
||||
const ClutterVertex *verts)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("checking that (%i,%i,%i,%i) \xe2\x89\x88 (%i,%i,%i,%i): %s\n",
|
||||
x_1, y_1, x_2, y_2,
|
||||
(int) (verts[0].x),
|
||||
(int) (verts[0].y),
|
||||
(int) (verts[3].x),
|
||||
(int) (verts[3].y),
|
||||
approx_equal (x_1, verts[0].x) &&
|
||||
approx_equal (y_1, verts[0].y) &&
|
||||
approx_equal (x_2, verts[3].x) &&
|
||||
approx_equal (y_2, verts[3].y) ? "yes"
|
||||
: "NO");
|
||||
}
|
||||
|
||||
static void
|
||||
test_anchor_point (TestState *state)
|
||||
{
|
||||
ClutterActor *rect = state->rect;
|
||||
gfloat anchor_x, anchor_y;
|
||||
ClutterGravity anchor_gravity;
|
||||
int i;
|
||||
|
||||
/* Assert the default settings */
|
||||
g_assert (clutter_actor_get_x (rect) == 100);
|
||||
g_assert (clutter_actor_get_y (rect) == 200);
|
||||
g_assert (clutter_actor_get_width (rect) == RECT_WIDTH);
|
||||
g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT);
|
||||
g_object_get (rect,
|
||||
"anchor-x", &anchor_x,
|
||||
"anchor-y", &anchor_y,
|
||||
"anchor-gravity", &anchor_gravity,
|
||||
NULL);
|
||||
g_assert (anchor_x == 0);
|
||||
g_assert (anchor_y == 0);
|
||||
g_assert (anchor_gravity == CLUTTER_GRAVITY_NONE);
|
||||
|
||||
/* Change the anchor point */
|
||||
clutter_actor_set_anchor_point (rect, 20, 30);
|
||||
g_object_get (rect,
|
||||
"anchor-x", &anchor_x,
|
||||
"anchor-y", &anchor_y,
|
||||
"anchor-gravity", &anchor_gravity,
|
||||
NULL);
|
||||
g_assert (anchor_x == 20);
|
||||
g_assert (anchor_y == 30);
|
||||
g_assert (anchor_gravity == CLUTTER_GRAVITY_NONE);
|
||||
assert_position (state, 80, 170);
|
||||
assert_notifications (NOTIFY_ANCHOR_X | NOTIFY_ANCHOR_Y);
|
||||
|
||||
/* Move the anchor point */
|
||||
clutter_actor_move_anchor_point (rect, 40, 50);
|
||||
g_object_get (rect,
|
||||
"anchor-x", &anchor_x,
|
||||
"anchor-y", &anchor_y,
|
||||
"anchor-gravity", &anchor_gravity,
|
||||
NULL);
|
||||
g_assert (anchor_x == 40);
|
||||
g_assert (anchor_y == 50);
|
||||
g_assert (anchor_gravity == CLUTTER_GRAVITY_NONE);
|
||||
assert_position (state, 80, 170);
|
||||
assert_notifications (NOTIFY_ANCHOR_X | NOTIFY_ANCHOR_Y);
|
||||
|
||||
/* Put the actor back to its default position */
|
||||
clutter_actor_set_position (rect, 100, 200);
|
||||
|
||||
/* Change the anchor point with each of the gravities */
|
||||
for (i = 0; i < G_N_ELEMENTS (gravities); i++)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
GEnumClass *gravity_class = g_type_class_ref (CLUTTER_TYPE_GRAVITY);
|
||||
GEnumValue *value = g_enum_get_value (gravity_class,
|
||||
gravities[i].gravity);
|
||||
g_print ("Setting gravity to %s\n",
|
||||
value ? value->value_name : "?");
|
||||
g_type_class_unref (gravity_class);
|
||||
}
|
||||
|
||||
g_object_set (rect, "anchor-gravity", gravities[i].gravity, NULL);
|
||||
|
||||
g_object_get (rect,
|
||||
"anchor-x", &anchor_x,
|
||||
"anchor-y", &anchor_y,
|
||||
"anchor-gravity", &anchor_gravity,
|
||||
NULL);
|
||||
g_assert (anchor_x == gravities[i].x_pos);
|
||||
g_assert (anchor_y == gravities[i].y_pos);
|
||||
g_assert (anchor_gravity == gravities[i].gravity);
|
||||
assert_position (state,
|
||||
100 - gravities[i].x_pos,
|
||||
200 - gravities[i].y_pos);
|
||||
|
||||
assert_notifications (NOTIFY_ANCHOR_X | NOTIFY_ANCHOR_Y
|
||||
| NOTIFY_ANCHOR_GRAVITY);
|
||||
}
|
||||
|
||||
/* Verify that the anchor point moves if the actor changes size when
|
||||
it is set from the gravity */
|
||||
clutter_actor_set_size (rect, RECT_WIDTH * 2, RECT_HEIGHT * 2);
|
||||
g_object_get (rect,
|
||||
"anchor-x", &anchor_x,
|
||||
"anchor-y", &anchor_y,
|
||||
"anchor-gravity", &anchor_gravity,
|
||||
NULL);
|
||||
g_assert (anchor_x == RECT_WIDTH);
|
||||
g_assert (anchor_y == RECT_HEIGHT);
|
||||
g_assert (anchor_gravity == CLUTTER_GRAVITY_CENTER);
|
||||
assert_coords (state, 100 - RECT_WIDTH, 200 - RECT_HEIGHT,
|
||||
100 + RECT_WIDTH, 200 + RECT_HEIGHT);
|
||||
assert_notifications (0);
|
||||
clutter_actor_set_size (rect, RECT_WIDTH, RECT_HEIGHT);
|
||||
|
||||
/* Change the anchor point using units again to assert that the
|
||||
gravity property changes */
|
||||
clutter_actor_set_anchor_point (rect, 20, 30);
|
||||
g_object_get (rect,
|
||||
"anchor-x", &anchor_x, "anchor-y", &anchor_y,
|
||||
"anchor-gravity", &anchor_gravity,
|
||||
NULL);
|
||||
g_assert (anchor_x == 20);
|
||||
g_assert (anchor_y == 30);
|
||||
g_assert (anchor_gravity == CLUTTER_GRAVITY_NONE);
|
||||
assert_position (state, 80, 170);
|
||||
assert_notifications (NOTIFY_ANCHOR_X | NOTIFY_ANCHOR_Y
|
||||
| NOTIFY_ANCHOR_GRAVITY);
|
||||
|
||||
/* Verify that the anchor point doesn't move if the actor changes
|
||||
size when it is set from units */
|
||||
clutter_actor_set_size (rect, RECT_WIDTH * 2, RECT_HEIGHT * 2);
|
||||
g_object_get (rect,
|
||||
"anchor-x", &anchor_x,
|
||||
"anchor-y", &anchor_y,
|
||||
"anchor-gravity", &anchor_gravity,
|
||||
NULL);
|
||||
g_assert (anchor_x == 20);
|
||||
g_assert (anchor_y == 30);
|
||||
g_assert (anchor_gravity == CLUTTER_GRAVITY_NONE);
|
||||
assert_coords (state, 80, 170, 80 + RECT_WIDTH * 2, 170 + RECT_HEIGHT * 2);
|
||||
assert_notifications (0);
|
||||
clutter_actor_set_size (rect, RECT_WIDTH, RECT_HEIGHT);
|
||||
|
||||
/* Put the anchor back */
|
||||
clutter_actor_set_anchor_point_from_gravity (rect, CLUTTER_GRAVITY_NONE);
|
||||
assert_notifications (NOTIFY_ANCHOR_X | NOTIFY_ANCHOR_Y);
|
||||
}
|
||||
|
||||
static void
|
||||
test_scale_center (TestState *state)
|
||||
{
|
||||
ClutterActor *rect = state->rect;
|
||||
gdouble scale_x, scale_y;
|
||||
gfloat center_x, center_y;
|
||||
ClutterGravity gravity;
|
||||
int i;
|
||||
|
||||
/* Assert the default settings */
|
||||
g_assert (clutter_actor_get_x (rect) == 100);
|
||||
g_assert (clutter_actor_get_y (rect) == 200);
|
||||
g_assert (clutter_actor_get_width (rect) == RECT_WIDTH);
|
||||
g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT);
|
||||
g_object_get (rect,
|
||||
"scale-center-x", ¢er_x,
|
||||
"scale-center-y", ¢er_y,
|
||||
"scale-x", &scale_x,
|
||||
"scale-y", &scale_y,
|
||||
"scale-gravity", &gravity,
|
||||
NULL);
|
||||
g_assert (center_x == 0);
|
||||
g_assert (center_y == 0);
|
||||
g_assert (scale_x == 1.0);
|
||||
g_assert (scale_y == 1.0);
|
||||
g_assert (gravity == CLUTTER_GRAVITY_NONE);
|
||||
|
||||
/* Try changing the scale without affecting the center */
|
||||
g_object_set (rect, "scale-x", 2.0, "scale-y", 3.0, NULL);
|
||||
g_assert (clutter_actor_get_x (rect) == 100);
|
||||
g_assert (clutter_actor_get_y (rect) == 200);
|
||||
g_assert (clutter_actor_get_width (rect) == RECT_WIDTH);
|
||||
g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT);
|
||||
g_object_get (rect,
|
||||
"scale-center-x", ¢er_x,
|
||||
"scale-center-y", ¢er_y,
|
||||
"scale-x", &scale_x,
|
||||
"scale-y", &scale_y,
|
||||
"scale-gravity", &gravity,
|
||||
NULL);
|
||||
g_assert (center_x == 0);
|
||||
g_assert (center_y == 0);
|
||||
g_assert (scale_x == 2.0);
|
||||
g_assert (scale_y == 3.0);
|
||||
g_assert (gravity == CLUTTER_GRAVITY_NONE);
|
||||
assert_notifications (NOTIFY_SCALE_X | NOTIFY_SCALE_Y);
|
||||
assert_coords (state, 100, 200, 100 + RECT_WIDTH * 2, 200 + RECT_HEIGHT * 3);
|
||||
|
||||
/* Change the scale and center */
|
||||
g_object_set (rect,
|
||||
"scale-x", 4.0,
|
||||
"scale-y", 2.0,
|
||||
"scale-center-x", 10.0,
|
||||
"scale-center-y", 20.0,
|
||||
NULL);
|
||||
g_assert (clutter_actor_get_x (rect) == 100);
|
||||
g_assert (clutter_actor_get_y (rect) == 200);
|
||||
g_assert (clutter_actor_get_width (rect) == RECT_WIDTH);
|
||||
g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT);
|
||||
g_object_get (rect,
|
||||
"scale-center-x", ¢er_x, "scale-center-y", ¢er_y,
|
||||
"scale-x", &scale_x, "scale-y", &scale_y,
|
||||
"scale-gravity", &gravity,
|
||||
NULL);
|
||||
g_assert (center_x == 10);
|
||||
g_assert (center_y == 20);
|
||||
g_assert (scale_x == 4.0);
|
||||
g_assert (scale_y == 2.0);
|
||||
g_assert (gravity == CLUTTER_GRAVITY_NONE);
|
||||
assert_notifications (NOTIFY_SCALE_X | NOTIFY_SCALE_Y
|
||||
| NOTIFY_SCALE_CENTER_X | NOTIFY_SCALE_CENTER_Y);
|
||||
assert_coords (state, 100 + 10 - 10 * 4, 200 + 20 - 20 * 2,
|
||||
100 + 10 + (RECT_WIDTH - 10) * 4,
|
||||
200 + 20 + (RECT_HEIGHT - 20) * 2);
|
||||
|
||||
/* Change the anchor point with each of the gravities */
|
||||
for (i = 0; i < G_N_ELEMENTS (gravities); i++)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
GEnumClass *gravity_class = g_type_class_ref (CLUTTER_TYPE_GRAVITY);
|
||||
GEnumValue *value = g_enum_get_value (gravity_class,
|
||||
gravities[i].gravity);
|
||||
g_print ("Setting scale center to %s\n",
|
||||
value ? value->value_name : "?");
|
||||
g_type_class_unref (gravity_class);
|
||||
}
|
||||
|
||||
g_object_set (rect, "scale-gravity", gravities[i].gravity, NULL);
|
||||
|
||||
g_assert (clutter_actor_get_x (rect) == 100);
|
||||
g_assert (clutter_actor_get_y (rect) == 200);
|
||||
g_assert (clutter_actor_get_width (rect) == RECT_WIDTH);
|
||||
g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT);
|
||||
g_object_get (rect,
|
||||
"scale-center-x", ¢er_x, "scale-center-y", ¢er_y,
|
||||
"scale-x", &scale_x, "scale-y", &scale_y,
|
||||
"scale-gravity", &gravity,
|
||||
NULL);
|
||||
g_assert (center_x == gravities[i].x_pos);
|
||||
g_assert (center_y == gravities[i].y_pos);
|
||||
g_assert (scale_x == 4.0);
|
||||
g_assert (scale_y == 2.0);
|
||||
g_assert (gravity == gravities[i].gravity);
|
||||
assert_notifications (NOTIFY_SCALE_CENTER_X |
|
||||
NOTIFY_SCALE_CENTER_Y |
|
||||
NOTIFY_SCALE_GRAVITY);
|
||||
assert_coords (state,
|
||||
100 - gravities[i].x_pos * 3,
|
||||
200 - gravities[i].y_pos,
|
||||
100 + (gravities[i].x_pos
|
||||
+ (RECT_WIDTH - gravities[i].x_pos) * 4),
|
||||
200 + (gravities[i].y_pos
|
||||
+ (RECT_HEIGHT - gravities[i].y_pos) * 2));
|
||||
}
|
||||
|
||||
/* Change the scale center using units again to assert that the
|
||||
gravity property changes */
|
||||
clutter_actor_set_scale_full (rect, 4, 2, 10, 20);
|
||||
g_object_get (rect,
|
||||
"scale-center-x", ¢er_x,
|
||||
"scale-center-y", ¢er_y,
|
||||
"scale-x", &scale_x,
|
||||
"scale-y", &scale_y,
|
||||
"scale-gravity", &gravity,
|
||||
NULL);
|
||||
g_assert (center_x == 10);
|
||||
g_assert (center_y == 20);
|
||||
g_assert (scale_x == 4.0);
|
||||
g_assert (scale_y == 2.0);
|
||||
g_assert (gravity == CLUTTER_GRAVITY_NONE);
|
||||
assert_notifications (NOTIFY_SCALE_CENTER_X | NOTIFY_SCALE_CENTER_Y
|
||||
| NOTIFY_SCALE_GRAVITY);
|
||||
assert_coords (state, 100 + 10 - 10 * 4, 200 + 20 - 20 * 2,
|
||||
100 + 10 + (RECT_WIDTH - 10) * 4,
|
||||
200 + 20 + (RECT_HEIGHT - 20) * 2);
|
||||
|
||||
/* Put the scale back to normal */
|
||||
clutter_actor_set_scale_full (rect, 1, 1, 0, 0);
|
||||
assert_notifications (NOTIFY_SCALE_X | NOTIFY_SCALE_Y
|
||||
| NOTIFY_SCALE_CENTER_X | NOTIFY_SCALE_CENTER_Y);
|
||||
}
|
||||
|
||||
static void
|
||||
test_rotate_center (TestState *state)
|
||||
{
|
||||
ClutterActor *rect = state->rect;
|
||||
gdouble angle_x, angle_y, angle_z;
|
||||
ClutterVertex *center_x, *center_y, *center_z;
|
||||
ClutterGravity z_center_gravity;
|
||||
gfloat stage_width, stage_height;
|
||||
gfloat rect_x, rect_y;
|
||||
int i;
|
||||
|
||||
/* Position the rectangle at the center of the stage so that
|
||||
rotations by 90° along the X or Y axis will cause the actor to be
|
||||
appear as a flat line. This makes verifying the transformations
|
||||
easier */
|
||||
clutter_actor_get_size (clutter_actor_get_stage (rect),
|
||||
&stage_width,
|
||||
&stage_height);
|
||||
rect_x = stage_width / 2;
|
||||
rect_y = stage_height / 2;
|
||||
clutter_actor_set_position (rect, rect_x, rect_y);
|
||||
|
||||
/* Assert the default settings */
|
||||
g_assert_cmpfloat (clutter_actor_get_x (rect), ==, rect_x);
|
||||
g_assert_cmpfloat (clutter_actor_get_y (rect), ==, rect_y);
|
||||
g_assert_cmpfloat (clutter_actor_get_width (rect), ==, RECT_WIDTH);
|
||||
g_assert_cmpfloat (clutter_actor_get_height (rect), ==, RECT_HEIGHT);
|
||||
g_object_get (rect,
|
||||
"rotation-angle-x", &angle_x,
|
||||
"rotation-angle-y", &angle_y,
|
||||
"rotation-angle-z", &angle_z,
|
||||
"rotation-center-x", ¢er_x,
|
||||
"rotation-center-y", ¢er_y,
|
||||
"rotation-center-z", ¢er_z,
|
||||
"rotation-center-z-gravity", &z_center_gravity,
|
||||
NULL);
|
||||
g_assert (angle_x == 0.0);
|
||||
g_assert (angle_y == 0.0);
|
||||
g_assert (angle_z == 0.0);
|
||||
assert_vertex_and_free (center_x, 0, 0, 0);
|
||||
assert_vertex_and_free (center_y, 0, 0, 0);
|
||||
assert_vertex_and_free (center_z, 0, 0, 0);
|
||||
g_assert (z_center_gravity == CLUTTER_GRAVITY_NONE);
|
||||
|
||||
/* Change each of the rotation angles without affecting the center
|
||||
point */
|
||||
for (i = CLUTTER_X_AXIS; i <= CLUTTER_Z_AXIS; i++)
|
||||
{
|
||||
char prop_name[] = "rotation-angle- ";
|
||||
prop_name[sizeof (prop_name) - 2] = i - CLUTTER_X_AXIS + 'x';
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Setting %s to 90 degrees\n", prop_name);
|
||||
|
||||
g_object_set (rect, prop_name, 90.0, NULL);
|
||||
assert_notifications (NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS));
|
||||
|
||||
g_assert (clutter_actor_get_x (rect) == rect_x);
|
||||
g_assert (clutter_actor_get_y (rect) == rect_y);
|
||||
g_assert (clutter_actor_get_width (rect) == RECT_WIDTH);
|
||||
g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT);
|
||||
g_object_get (rect,
|
||||
"rotation-angle-x", &angle_x,
|
||||
"rotation-angle-y", &angle_y,
|
||||
"rotation-angle-z", &angle_z,
|
||||
"rotation-center-x", ¢er_x,
|
||||
"rotation-center-y", ¢er_y,
|
||||
"rotation-center-z", ¢er_z,
|
||||
"rotation-center-z-gravity", &z_center_gravity,
|
||||
NULL);
|
||||
if (i == CLUTTER_X_AXIS)
|
||||
{
|
||||
g_assert (angle_x == 90.0);
|
||||
assert_coords (state, rect_x, rect_y, verts[3].x, rect_y);
|
||||
}
|
||||
else
|
||||
g_assert (angle_x == 0.0);
|
||||
if (i == CLUTTER_Y_AXIS)
|
||||
{
|
||||
g_assert (angle_y == 90.0);
|
||||
assert_coords (state, rect_x, rect_y, rect_x, verts[3].y);
|
||||
}
|
||||
else
|
||||
g_assert (angle_y == 0.0);
|
||||
if (i == CLUTTER_Z_AXIS)
|
||||
{
|
||||
g_assert (angle_z == 90.0);
|
||||
assert_coords (state, rect_x, rect_y,
|
||||
rect_x - RECT_HEIGHT,
|
||||
rect_y + RECT_WIDTH);
|
||||
}
|
||||
else
|
||||
g_assert (angle_z == 0.0);
|
||||
assert_vertex_and_free (center_x, 0, 0, 0);
|
||||
assert_vertex_and_free (center_y, 0, 0, 0);
|
||||
assert_vertex_and_free (center_z, 0, 0, 0);
|
||||
g_assert (z_center_gravity == CLUTTER_GRAVITY_NONE);
|
||||
|
||||
g_object_set (rect, prop_name, 0.0, NULL);
|
||||
assert_notifications (NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS));
|
||||
}
|
||||
|
||||
clutter_actor_set_position (rect, rect_x -= 10, rect_y -= 20);
|
||||
|
||||
/* Same test but also change the center position */
|
||||
for (i = CLUTTER_X_AXIS; i <= CLUTTER_Z_AXIS; i++)
|
||||
{
|
||||
char prop_name[] = "rotation-angle- ";
|
||||
prop_name[sizeof (prop_name) - 2] = i - CLUTTER_X_AXIS + 'x';
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Setting %s to 90 degrees with center 10,20,0\n", prop_name);
|
||||
|
||||
clutter_actor_set_rotation (rect, i, 90.0, 10, 20, 0);
|
||||
assert_notifications ((NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS))
|
||||
| (NOTIFY_ROTATION_CENTER_X
|
||||
<< (i - CLUTTER_X_AXIS)));
|
||||
|
||||
g_assert (clutter_actor_get_x (rect) == rect_x);
|
||||
g_assert (clutter_actor_get_y (rect) == rect_y);
|
||||
g_assert (clutter_actor_get_width (rect) == RECT_WIDTH);
|
||||
g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT);
|
||||
g_object_get (rect,
|
||||
"rotation-angle-x", &angle_x,
|
||||
"rotation-angle-y", &angle_y,
|
||||
"rotation-angle-z", &angle_z,
|
||||
"rotation-center-x", ¢er_x,
|
||||
"rotation-center-y", ¢er_y,
|
||||
"rotation-center-z", ¢er_z,
|
||||
"rotation-center-z-gravity", &z_center_gravity,
|
||||
NULL);
|
||||
if (i == CLUTTER_X_AXIS)
|
||||
{
|
||||
g_assert (angle_x == 90.0);
|
||||
assert_coords (state,
|
||||
verts[0].x, rect_y + 20,
|
||||
verts[3].x, rect_y + 20);
|
||||
assert_vertex_and_free (center_x, 10, 20, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (angle_x == 0.0);
|
||||
assert_vertex_and_free (center_x, 0, 0, 0);
|
||||
}
|
||||
if (i == CLUTTER_Y_AXIS)
|
||||
{
|
||||
g_assert (angle_y == 90.0);
|
||||
assert_coords (state,
|
||||
rect_x + 10, verts[0].y,
|
||||
rect_x + 10, verts[3].y);
|
||||
assert_vertex_and_free (center_y, 10, 20, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (angle_y == 0.0);
|
||||
assert_vertex_and_free (center_y, 0, 0, 0);
|
||||
}
|
||||
if (i == CLUTTER_Z_AXIS)
|
||||
{
|
||||
g_assert (angle_z == 90.0);
|
||||
assert_coords (state,
|
||||
rect_x + 10 + 20,
|
||||
rect_y + 20 - 10,
|
||||
rect_x + 10 + 20 - RECT_HEIGHT,
|
||||
rect_y + 20 + RECT_WIDTH - 10);
|
||||
assert_vertex_and_free (center_z, 10, 20, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (angle_z == 0.0);
|
||||
assert_vertex_and_free (center_z, 0, 0, 0);
|
||||
}
|
||||
g_assert (z_center_gravity == CLUTTER_GRAVITY_NONE);
|
||||
|
||||
clutter_actor_set_rotation (rect, i, 0, 0, 0, 0);
|
||||
assert_notifications ((NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS))
|
||||
| (NOTIFY_ROTATION_CENTER_X
|
||||
<< (i - CLUTTER_X_AXIS)));
|
||||
|
||||
}
|
||||
|
||||
/* Try rotating the z with all of the gravities */
|
||||
for (i = 0; i < G_N_ELEMENTS (gravities); i++)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
GEnumClass *gravity_class = g_type_class_ref (CLUTTER_TYPE_GRAVITY);
|
||||
GEnumValue *value = g_enum_get_value (gravity_class,
|
||||
gravities[i].gravity);
|
||||
g_print ("Setting z rotation to 90 degrees with center at %s\n",
|
||||
value ? value->value_name : "?");
|
||||
g_type_class_unref (gravity_class);
|
||||
}
|
||||
|
||||
clutter_actor_set_z_rotation_from_gravity (rect, 90,
|
||||
gravities[i].gravity);
|
||||
assert_notifications (NOTIFY_ROTATION_ANGLE_Z
|
||||
| NOTIFY_ROTATION_CENTER_Z
|
||||
| NOTIFY_ROTATION_CENTER_Z_GRAVITY);
|
||||
|
||||
g_assert (clutter_actor_get_x (rect) == rect_x);
|
||||
g_assert (clutter_actor_get_y (rect) == rect_y);
|
||||
g_assert (clutter_actor_get_width (rect) == RECT_WIDTH);
|
||||
g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT);
|
||||
g_object_get (rect,
|
||||
"rotation-angle-x", &angle_x,
|
||||
"rotation-angle-y", &angle_y,
|
||||
"rotation-angle-z", &angle_z,
|
||||
"rotation-center-x", ¢er_x,
|
||||
"rotation-center-y", ¢er_y,
|
||||
"rotation-center-z", ¢er_z,
|
||||
"rotation-center-z-gravity", &z_center_gravity,
|
||||
NULL);
|
||||
g_assert (angle_x == 0.0);
|
||||
g_assert (angle_y == 0.0);
|
||||
g_assert (angle_z == 90.0);
|
||||
assert_vertex_and_free (center_x, 0, 0, 0);
|
||||
assert_vertex_and_free (center_y, 0, 0, 0);
|
||||
assert_vertex_and_free (center_z,
|
||||
gravities[i].x_pos, gravities[i].y_pos, 0);
|
||||
assert_coords (state,
|
||||
rect_x + gravities[i].x_pos + gravities[i].y_pos,
|
||||
rect_y + gravities[i].y_pos - gravities[i].x_pos,
|
||||
rect_x + gravities[i].x_pos + gravities[i].y_pos
|
||||
- RECT_HEIGHT,
|
||||
rect_y + gravities[i].y_pos + RECT_WIDTH
|
||||
- gravities[i].x_pos);
|
||||
g_assert (z_center_gravity == gravities[i].gravity);
|
||||
g_assert (clutter_actor_get_z_rotation_gravity (rect)
|
||||
== gravities[i].gravity);
|
||||
|
||||
/* Put the rotation back */
|
||||
clutter_actor_set_z_rotation_from_gravity (rect, 0, CLUTTER_GRAVITY_NONE);
|
||||
assert_notifications (NOTIFY_ROTATION_ANGLE_Z
|
||||
| NOTIFY_ROTATION_CENTER_Z
|
||||
| NOTIFY_ROTATION_CENTER_Z_GRAVITY);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_cb (gpointer data)
|
||||
{
|
||||
test_anchor_point (data);
|
||||
test_scale_center (data);
|
||||
test_rotate_center (data);
|
||||
|
||||
clutter_main_quit ();
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
actor_anchors (void)
|
||||
{
|
||||
TestState state;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
|
||||
state.rect = clutter_actor_new ();
|
||||
clutter_actor_add_child (stage, state.rect);
|
||||
clutter_actor_set_position (state.rect, 100, 200);
|
||||
clutter_actor_set_size (state.rect, RECT_WIDTH, RECT_HEIGHT);
|
||||
|
||||
/* Record notifications on the actor properties */
|
||||
state.notifications = 0;
|
||||
g_signal_connect (state.rect, "notify",
|
||||
G_CALLBACK (notify_cb), &state);
|
||||
|
||||
/* Run the tests in a low priority idle function so that we can be
|
||||
sure the stage is correctly setup */
|
||||
clutter_threads_add_idle_full (G_PRIORITY_LOW, idle_cb, &state, NULL);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
}
|
||||
|
||||
static void
|
||||
actor_pivot (void)
|
||||
{
|
||||
ClutterActor *stage, *actor_implicit, *actor_explicit;
|
||||
ClutterMatrix transform, result_implicit, result_explicit;
|
||||
ClutterActorBox allocation = CLUTTER_ACTOR_BOX_INIT (0, 0, 90, 30);
|
||||
gfloat angle = 30;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
|
||||
actor_implicit = clutter_actor_new ();
|
||||
actor_explicit = clutter_actor_new ();
|
||||
|
||||
clutter_actor_add_child (stage, actor_implicit);
|
||||
clutter_actor_add_child (stage, actor_explicit);
|
||||
|
||||
/* Fake allocation or pivot-point will not have any effect */
|
||||
clutter_actor_allocate (actor_implicit, &allocation, CLUTTER_ALLOCATION_NONE);
|
||||
clutter_actor_allocate (actor_explicit, &allocation, CLUTTER_ALLOCATION_NONE);
|
||||
|
||||
clutter_actor_set_pivot_point (actor_implicit, 0.5, 0.5);
|
||||
clutter_actor_set_pivot_point (actor_explicit, 0.5, 0.5);
|
||||
|
||||
/* Implict transformation */
|
||||
clutter_actor_set_rotation_angle (actor_implicit, CLUTTER_Z_AXIS, angle);
|
||||
|
||||
/* Explict transformation */
|
||||
clutter_matrix_init_identity(&transform);
|
||||
cogl_matrix_rotate (&transform, angle, 0, 0, 1.0);
|
||||
clutter_actor_set_transform (actor_explicit, &transform);
|
||||
|
||||
clutter_actor_get_transform (actor_implicit, &result_implicit);
|
||||
clutter_actor_get_transform (actor_explicit, &result_explicit);
|
||||
|
||||
g_assert (cogl_matrix_equal (&result_implicit, &result_explicit));
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/transforms/anchor-point", actor_anchors)
|
||||
CLUTTER_TEST_UNIT ("/actor/transforms/pivot-point", actor_pivot)
|
||||
)
|
195
src/tests/clutter/conform/actor-destroy.c
Normal file
195
src/tests/clutter/conform/actor-destroy.c
Normal file
@ -0,0 +1,195 @@
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define TEST_TYPE_DESTROY (test_destroy_get_type ())
|
||||
#define TEST_DESTROY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_DESTROY, TestDestroy))
|
||||
#define TEST_IS_DESTROY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_DESTROY))
|
||||
|
||||
typedef struct _TestDestroy TestDestroy;
|
||||
typedef struct _TestDestroyClass TestDestroyClass;
|
||||
|
||||
struct _TestDestroy
|
||||
{
|
||||
ClutterActor parent_instance;
|
||||
|
||||
ClutterActor *bg;
|
||||
ClutterActor *label;
|
||||
ClutterActor *tex;
|
||||
|
||||
GList *children;
|
||||
};
|
||||
|
||||
struct _TestDestroyClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
};
|
||||
|
||||
static void clutter_container_init (ClutterContainerIface *iface);
|
||||
|
||||
GType test_destroy_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (TestDestroy, test_destroy, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
|
||||
clutter_container_init));
|
||||
|
||||
static void
|
||||
test_destroy_add (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
TestDestroy *self = TEST_DESTROY (container);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Adding '%s' (type:%s)\n",
|
||||
clutter_actor_get_name (actor),
|
||||
G_OBJECT_TYPE_NAME (actor));
|
||||
|
||||
self->children = g_list_prepend (self->children, actor);
|
||||
clutter_actor_set_parent (actor, CLUTTER_ACTOR (container));
|
||||
}
|
||||
|
||||
static void
|
||||
test_destroy_remove (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
TestDestroy *self = TEST_DESTROY (container);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Removing '%s' (type:%s)\n",
|
||||
clutter_actor_get_name (actor),
|
||||
G_OBJECT_TYPE_NAME (actor));
|
||||
|
||||
g_assert (actor != self->bg);
|
||||
g_assert (actor != self->label);
|
||||
|
||||
if (!g_list_find (self->children, actor))
|
||||
g_assert (actor == self->tex);
|
||||
else
|
||||
self->children = g_list_remove (self->children, actor);
|
||||
|
||||
clutter_actor_unparent (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_container_init (ClutterContainerIface *iface)
|
||||
{
|
||||
iface->add = test_destroy_add;
|
||||
iface->remove = test_destroy_remove;
|
||||
}
|
||||
|
||||
static void
|
||||
test_destroy_destroy (ClutterActor *self)
|
||||
{
|
||||
TestDestroy *test = TEST_DESTROY (self);
|
||||
|
||||
if (test->bg != NULL)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("Destroying '%s' (type:%s)\n",
|
||||
clutter_actor_get_name (test->bg),
|
||||
G_OBJECT_TYPE_NAME (test->bg));
|
||||
|
||||
clutter_actor_destroy (test->bg);
|
||||
test->bg = NULL;
|
||||
}
|
||||
|
||||
if (test->label != NULL)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("Destroying '%s' (type:%s)\n",
|
||||
clutter_actor_get_name (test->label),
|
||||
G_OBJECT_TYPE_NAME (test->label));
|
||||
|
||||
clutter_actor_destroy (test->label);
|
||||
test->label = NULL;
|
||||
}
|
||||
|
||||
if (test->tex != NULL)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("Destroying '%s' (type:%s)\n",
|
||||
clutter_actor_get_name (test->tex),
|
||||
G_OBJECT_TYPE_NAME (test->tex));
|
||||
|
||||
clutter_actor_destroy (test->tex);
|
||||
test->tex = NULL;
|
||||
}
|
||||
|
||||
g_assert_nonnull (test->children);
|
||||
|
||||
if (CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy)
|
||||
CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy (self);
|
||||
|
||||
g_assert_null (test->children);
|
||||
}
|
||||
|
||||
static void
|
||||
test_destroy_class_init (TestDestroyClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
actor_class->destroy = test_destroy_destroy;
|
||||
}
|
||||
|
||||
static void
|
||||
test_destroy_init (TestDestroy *self)
|
||||
{
|
||||
clutter_actor_push_internal (CLUTTER_ACTOR (self));
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Adding internal children...\n");
|
||||
|
||||
self->bg = clutter_rectangle_new ();
|
||||
clutter_actor_set_parent (self->bg, CLUTTER_ACTOR (self));
|
||||
clutter_actor_set_name (self->bg, "Background");
|
||||
|
||||
self->label = clutter_text_new ();
|
||||
clutter_actor_set_parent (self->label, CLUTTER_ACTOR (self));
|
||||
clutter_actor_set_name (self->label, "Label");
|
||||
|
||||
clutter_actor_pop_internal (CLUTTER_ACTOR (self));
|
||||
|
||||
self->tex = clutter_texture_new ();
|
||||
clutter_actor_set_parent (self->tex, CLUTTER_ACTOR (self));
|
||||
clutter_actor_set_name (self->tex, "Texture");
|
||||
}
|
||||
|
||||
static void
|
||||
on_destroy (ClutterActor *actor,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean *destroy_called = data;
|
||||
|
||||
*destroy_called = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
actor_destruction (void)
|
||||
{
|
||||
ClutterActor *test = g_object_new (TEST_TYPE_DESTROY, NULL);
|
||||
ClutterActor *child = clutter_rectangle_new ();
|
||||
gboolean destroy_called = FALSE;
|
||||
|
||||
g_object_ref_sink (test);
|
||||
|
||||
g_object_add_weak_pointer (G_OBJECT (test), (gpointer *) &test);
|
||||
g_object_add_weak_pointer (G_OBJECT (child), (gpointer *) &child);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Adding external child...\n");
|
||||
|
||||
clutter_actor_set_name (child, "Child");
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (test), child);
|
||||
g_signal_connect (child, "destroy", G_CALLBACK (on_destroy), &destroy_called);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Calling destroy()...\n");
|
||||
|
||||
clutter_actor_destroy (test);
|
||||
g_assert (destroy_called);
|
||||
g_assert_null (child);
|
||||
g_assert_null (test);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/destruction", actor_destruction)
|
||||
)
|
550
src/tests/clutter/conform/actor-graph.c
Normal file
550
src/tests/clutter/conform/actor-graph.c
Normal file
@ -0,0 +1,550 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
actor_add_child (void)
|
||||
{
|
||||
ClutterActor *actor = clutter_actor_new ();
|
||||
ClutterActor *iter;
|
||||
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "foo",
|
||||
NULL));
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "bar",
|
||||
NULL));
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "baz",
|
||||
NULL));
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3);
|
||||
|
||||
iter = clutter_actor_get_first_child (actor);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
|
||||
|
||||
iter = clutter_actor_get_next_sibling (iter);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
|
||||
|
||||
iter = clutter_actor_get_next_sibling (iter);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
|
||||
g_assert (iter == clutter_actor_get_last_child (actor));
|
||||
g_assert (clutter_actor_get_next_sibling (iter) == NULL);
|
||||
|
||||
iter = clutter_actor_get_last_child (actor);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
|
||||
|
||||
iter = clutter_actor_get_previous_sibling (iter);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
|
||||
|
||||
iter = clutter_actor_get_previous_sibling (iter);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
|
||||
g_assert (iter == clutter_actor_get_first_child (actor));
|
||||
g_assert (clutter_actor_get_previous_sibling (iter) == NULL);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_insert_child (void)
|
||||
{
|
||||
ClutterActor *actor = clutter_actor_new ();
|
||||
ClutterActor *iter;
|
||||
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
clutter_actor_insert_child_at_index (actor,
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "foo",
|
||||
NULL),
|
||||
0);
|
||||
|
||||
iter = clutter_actor_get_first_child (actor);
|
||||
g_assert (iter != NULL);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
|
||||
g_assert (iter == clutter_actor_get_child_at_index (actor, 0));
|
||||
|
||||
clutter_actor_insert_child_below (actor,
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "bar",
|
||||
NULL),
|
||||
iter);
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 2);
|
||||
|
||||
iter = clutter_actor_get_first_child (actor);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
|
||||
iter = clutter_actor_get_next_sibling (iter);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
|
||||
g_assert (iter == clutter_actor_get_child_at_index (actor, 1));
|
||||
|
||||
iter = clutter_actor_get_first_child (actor);
|
||||
clutter_actor_insert_child_above (actor,
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "baz",
|
||||
NULL),
|
||||
iter);
|
||||
|
||||
iter = clutter_actor_get_last_child (actor);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
|
||||
|
||||
iter = clutter_actor_get_previous_sibling (iter);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
|
||||
|
||||
iter = clutter_actor_get_previous_sibling (iter);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
|
||||
|
||||
clutter_actor_remove_all_children (actor);
|
||||
|
||||
clutter_actor_insert_child_at_index (actor,
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "1",
|
||||
NULL),
|
||||
0);
|
||||
iter = clutter_actor_get_child_at_index (actor, 0);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "1");
|
||||
g_assert (clutter_actor_get_first_child (actor) == iter);
|
||||
g_assert (clutter_actor_get_last_child (actor) == iter);
|
||||
|
||||
clutter_actor_insert_child_at_index (actor,
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "2",
|
||||
NULL),
|
||||
0);
|
||||
iter = clutter_actor_get_child_at_index (actor, 0);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "2");
|
||||
g_assert (clutter_actor_get_first_child (actor) == iter);
|
||||
iter = clutter_actor_get_child_at_index (actor, 1);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "1");
|
||||
g_assert (clutter_actor_get_last_child (actor) == iter);
|
||||
|
||||
clutter_actor_insert_child_at_index (actor,
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "3",
|
||||
NULL),
|
||||
-1);
|
||||
iter = clutter_actor_get_child_at_index (actor, 2);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "3");
|
||||
g_assert (clutter_actor_get_last_child (actor) == iter);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_remove_child (void)
|
||||
{
|
||||
ClutterActor *actor = clutter_actor_new ();
|
||||
ClutterActor *iter;
|
||||
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "foo",
|
||||
NULL));
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "bar",
|
||||
NULL));
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 2);
|
||||
|
||||
g_assert (clutter_actor_get_first_child (actor) != clutter_actor_get_last_child (actor));
|
||||
|
||||
iter = clutter_actor_get_first_child (actor);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
|
||||
|
||||
iter = clutter_actor_get_last_child (actor);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
|
||||
|
||||
clutter_actor_remove_child (actor, clutter_actor_get_first_child (actor));
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1);
|
||||
|
||||
iter = clutter_actor_get_first_child (actor);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
|
||||
g_assert (clutter_actor_get_first_child (actor) == clutter_actor_get_last_child (actor));
|
||||
|
||||
clutter_actor_remove_child (actor, clutter_actor_get_first_child (actor));
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 0);
|
||||
g_assert (clutter_actor_get_first_child (actor) == NULL);
|
||||
g_assert (clutter_actor_get_last_child (actor) == NULL);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_raise_child (void)
|
||||
{
|
||||
ClutterActor *actor = clutter_actor_new ();
|
||||
ClutterActor *iter;
|
||||
gboolean show_on_set_parent;
|
||||
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "foo",
|
||||
"visible", FALSE,
|
||||
NULL));
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "bar",
|
||||
"visible", FALSE,
|
||||
NULL));
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "baz",
|
||||
"visible", FALSE,
|
||||
NULL));
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3);
|
||||
|
||||
iter = clutter_actor_get_child_at_index (actor, 1);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
|
||||
|
||||
clutter_actor_set_child_above_sibling (actor, iter,
|
||||
clutter_actor_get_child_at_index (actor, 2));
|
||||
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)),
|
||||
==,
|
||||
"foo");
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)),
|
||||
==,
|
||||
"baz");
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)),
|
||||
==,
|
||||
"bar");
|
||||
g_assert (!clutter_actor_is_visible (iter));
|
||||
g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL);
|
||||
g_assert (!show_on_set_parent);
|
||||
|
||||
iter = clutter_actor_get_child_at_index (actor, 0);
|
||||
clutter_actor_set_child_above_sibling (actor, iter, NULL);
|
||||
g_object_add_weak_pointer (G_OBJECT (iter), (gpointer *) &iter);
|
||||
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)),
|
||||
==,
|
||||
"baz");
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)),
|
||||
==,
|
||||
"bar");
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)),
|
||||
==,
|
||||
"foo");
|
||||
g_assert (!clutter_actor_is_visible (iter));
|
||||
g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL);
|
||||
g_assert (!show_on_set_parent);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
g_assert (iter == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_lower_child (void)
|
||||
{
|
||||
ClutterActor *actor = clutter_actor_new ();
|
||||
ClutterActor *iter;
|
||||
gboolean show_on_set_parent;
|
||||
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "foo",
|
||||
"visible", FALSE,
|
||||
NULL));
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "bar",
|
||||
"visible", FALSE,
|
||||
NULL));
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "baz",
|
||||
"visible", FALSE,
|
||||
NULL));
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3);
|
||||
|
||||
iter = clutter_actor_get_child_at_index (actor, 1);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
|
||||
|
||||
clutter_actor_set_child_below_sibling (actor, iter,
|
||||
clutter_actor_get_child_at_index (actor, 0));
|
||||
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)),
|
||||
==,
|
||||
"bar");
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)),
|
||||
==,
|
||||
"foo");
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)),
|
||||
==,
|
||||
"baz");
|
||||
g_assert (!clutter_actor_is_visible (iter));
|
||||
g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL);
|
||||
g_assert (!show_on_set_parent);
|
||||
|
||||
iter = clutter_actor_get_child_at_index (actor, 2);
|
||||
clutter_actor_set_child_below_sibling (actor, iter, NULL);
|
||||
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)),
|
||||
==,
|
||||
"baz");
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)),
|
||||
==,
|
||||
"bar");
|
||||
g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)),
|
||||
==,
|
||||
"foo");
|
||||
g_assert (!clutter_actor_is_visible (iter));
|
||||
g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL);
|
||||
g_assert (!show_on_set_parent);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_replace_child (void)
|
||||
{
|
||||
ClutterActor *actor = clutter_actor_new ();
|
||||
ClutterActor *iter;
|
||||
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "foo",
|
||||
NULL));
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "bar",
|
||||
NULL));
|
||||
|
||||
iter = clutter_actor_get_child_at_index (actor, 0);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
|
||||
|
||||
clutter_actor_replace_child (actor, iter,
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "baz",
|
||||
NULL));
|
||||
|
||||
iter = clutter_actor_get_child_at_index (actor, 0);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
|
||||
|
||||
iter = clutter_actor_get_child_at_index (actor, 1);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
|
||||
|
||||
clutter_actor_replace_child (actor, iter,
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "qux",
|
||||
NULL));
|
||||
|
||||
iter = clutter_actor_get_child_at_index (actor, 0);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
|
||||
|
||||
iter = clutter_actor_get_child_at_index (actor, 1);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "qux");
|
||||
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "foo",
|
||||
NULL));
|
||||
|
||||
clutter_actor_replace_child (actor, iter,
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "bar",
|
||||
NULL));
|
||||
|
||||
iter = clutter_actor_get_last_child (actor);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
|
||||
iter = clutter_actor_get_previous_sibling (iter);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
|
||||
iter = clutter_actor_get_previous_sibling (iter);
|
||||
g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_remove_all (void)
|
||||
{
|
||||
ClutterActor *actor = clutter_actor_new ();
|
||||
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "foo",
|
||||
NULL));
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "bar",
|
||||
NULL));
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "baz",
|
||||
NULL));
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3);
|
||||
|
||||
clutter_actor_remove_all_children (actor);
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 0);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_added (ClutterContainer *container,
|
||||
ClutterActor *child,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterActor *actor = CLUTTER_ACTOR (container);
|
||||
int *counter = data;
|
||||
ClutterActor *old_child;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Adding actor '%s'\n", clutter_actor_get_name (child));
|
||||
|
||||
old_child = clutter_actor_get_child_at_index (actor, 0);
|
||||
if (old_child != child)
|
||||
clutter_actor_remove_child (actor, old_child);
|
||||
|
||||
*counter += 1;
|
||||
}
|
||||
|
||||
static void
|
||||
actor_removed (ClutterContainer *container,
|
||||
ClutterActor *child,
|
||||
gpointer data)
|
||||
{
|
||||
int *counter = data;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Removing actor '%s'\n", clutter_actor_get_name (child));
|
||||
|
||||
*counter += 1;
|
||||
}
|
||||
|
||||
static void
|
||||
actor_container_signals (void)
|
||||
{
|
||||
ClutterActor *actor = clutter_actor_new ();
|
||||
int add_count, remove_count;
|
||||
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
add_count = remove_count = 0;
|
||||
g_signal_connect (actor,
|
||||
"actor-added", G_CALLBACK (actor_added),
|
||||
&add_count);
|
||||
g_signal_connect (actor,
|
||||
"actor-removed", G_CALLBACK (actor_removed),
|
||||
&remove_count);
|
||||
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "foo",
|
||||
NULL));
|
||||
|
||||
g_assert_cmpint (add_count, ==, 1);
|
||||
g_assert_cmpint (remove_count, ==, 0);
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1);
|
||||
|
||||
clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"name", "bar",
|
||||
NULL));
|
||||
|
||||
g_assert_cmpint (add_count, ==, 2);
|
||||
g_assert_cmpint (remove_count, ==, 1);
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (actor, G_CALLBACK (actor_added),
|
||||
&add_count);
|
||||
g_signal_handlers_disconnect_by_func (actor, G_CALLBACK (actor_removed),
|
||||
&remove_count);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_contains (void)
|
||||
{
|
||||
/* This build up the following tree:
|
||||
*
|
||||
* a
|
||||
* ╱ │ ╲
|
||||
* ╱ │ ╲
|
||||
* b c d
|
||||
* ╱ ╲ ╱ ╲ ╱ ╲
|
||||
* e f g h i j
|
||||
*/
|
||||
struct {
|
||||
ClutterActor *actor_a, *actor_b, *actor_c, *actor_d, *actor_e;
|
||||
ClutterActor *actor_f, *actor_g, *actor_h, *actor_i, *actor_j;
|
||||
} d;
|
||||
int x, y;
|
||||
ClutterActor **actor_array = &d.actor_a;
|
||||
|
||||
/* Matrix of expected results */
|
||||
static const gboolean expected_results[] =
|
||||
{ /* a, b, c, d, e, f, g, h, i, j */
|
||||
/* a */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
/* b */ 0, 1, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
/* c */ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0,
|
||||
/* d */ 0, 0, 0, 1, 0, 0, 0, 0, 1, 1,
|
||||
/* e */ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
|
||||
/* f */ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||
/* g */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
/* h */ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||
/* i */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
|
||||
/* j */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
|
||||
};
|
||||
|
||||
d.actor_a = clutter_actor_new ();
|
||||
d.actor_b = clutter_actor_new ();
|
||||
d.actor_c = clutter_actor_new ();
|
||||
d.actor_d = clutter_actor_new ();
|
||||
d.actor_e = clutter_actor_new ();
|
||||
d.actor_f = clutter_actor_new ();
|
||||
d.actor_g = clutter_actor_new ();
|
||||
d.actor_h = clutter_actor_new ();
|
||||
d.actor_i = clutter_actor_new ();
|
||||
d.actor_j = clutter_actor_new ();
|
||||
|
||||
clutter_actor_add_child (d.actor_a, d.actor_b);
|
||||
clutter_actor_add_child (d.actor_a, d.actor_c);
|
||||
clutter_actor_add_child (d.actor_a, d.actor_d);
|
||||
|
||||
clutter_actor_add_child (d.actor_b, d.actor_e);
|
||||
clutter_actor_add_child (d.actor_b, d.actor_f);
|
||||
|
||||
clutter_actor_add_child (d.actor_c, d.actor_g);
|
||||
clutter_actor_add_child (d.actor_c, d.actor_h);
|
||||
|
||||
clutter_actor_add_child (d.actor_d, d.actor_i);
|
||||
clutter_actor_add_child (d.actor_d, d.actor_j);
|
||||
|
||||
for (y = 0; y < 10; y++)
|
||||
for (x = 0; x < 10; x++)
|
||||
g_assert_cmpint (clutter_actor_contains (actor_array[x],
|
||||
actor_array[y]),
|
||||
==,
|
||||
expected_results[x * 10 + y]);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/graph/add-child", actor_add_child)
|
||||
CLUTTER_TEST_UNIT ("/actor/graph/insert-child", actor_insert_child)
|
||||
CLUTTER_TEST_UNIT ("/actor/graph/remove-child", actor_remove_child)
|
||||
CLUTTER_TEST_UNIT ("/actor/graph/raise-child", actor_raise_child)
|
||||
CLUTTER_TEST_UNIT ("/actor/graph/lower-child", actor_lower_child)
|
||||
CLUTTER_TEST_UNIT ("/actor/graph/replace-child", actor_replace_child)
|
||||
CLUTTER_TEST_UNIT ("/actor/graph/remove-all", actor_remove_all)
|
||||
CLUTTER_TEST_UNIT ("/actor/graph/container-signals", actor_container_signals)
|
||||
CLUTTER_TEST_UNIT ("/actor/graph/contains", actor_contains)
|
||||
)
|
371
src/tests/clutter/conform/actor-invariants.c
Normal file
371
src/tests/clutter/conform/actor-invariants.c
Normal file
@ -0,0 +1,371 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
actor_initial_state (void)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("initial state - visible: %s, realized: %s, mapped: %s\n",
|
||||
CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no",
|
||||
CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no",
|
||||
CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no");
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_shown_not_parented (void)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
clutter_actor_show (actor);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("show without a parent - visible: %s, realized: %s, mapped: %s\n",
|
||||
CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no",
|
||||
CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no",
|
||||
CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no");
|
||||
|
||||
g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_realized (void)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
|
||||
clutter_actor_hide (actor); /* don't show, so won't map */
|
||||
clutter_actor_add_child (stage, actor);
|
||||
clutter_actor_realize (actor);
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
}
|
||||
|
||||
static void
|
||||
actor_mapped (void)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
clutter_actor_show (stage);
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
|
||||
clutter_actor_add_child (stage, actor);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("adding to a container should map - "
|
||||
"visible: %s, realized: %s, mapped: %s\n",
|
||||
CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no",
|
||||
CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no",
|
||||
CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no");
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
|
||||
clutter_actor_hide (actor);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("hiding should unmap - "
|
||||
"visible: %s, realized: %s, mapped: %s\n",
|
||||
CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no",
|
||||
CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no",
|
||||
CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no");
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
}
|
||||
|
||||
static void
|
||||
actor_visibility_not_recursive (void)
|
||||
{
|
||||
ClutterActor *actor, *group;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
|
||||
group = clutter_actor_new ();
|
||||
actor = clutter_actor_new ();
|
||||
|
||||
clutter_actor_hide (group); /* don't show, so won't map */
|
||||
clutter_actor_hide (actor); /* don't show, so won't map */
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (stage)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
|
||||
clutter_actor_add_child (stage, group);
|
||||
clutter_actor_add_child (group, actor);
|
||||
|
||||
clutter_actor_show (actor);
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
g_assert (!CLUTTER_ACTOR_IS_VISIBLE (group));
|
||||
g_assert (!CLUTTER_ACTOR_IS_VISIBLE (stage));
|
||||
|
||||
clutter_actor_show (stage);
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
g_assert (!CLUTTER_ACTOR_IS_VISIBLE (group));
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (stage));
|
||||
|
||||
clutter_actor_hide (actor);
|
||||
clutter_actor_hide (group);
|
||||
clutter_actor_hide (stage);
|
||||
g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
|
||||
clutter_actor_show (stage);
|
||||
g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
}
|
||||
|
||||
static void
|
||||
actor_realize_not_recursive (void)
|
||||
{
|
||||
ClutterActor *actor, *group;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
clutter_actor_show (stage);
|
||||
|
||||
group = clutter_actor_new ();
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
|
||||
clutter_actor_hide (group); /* don't show, so won't map */
|
||||
clutter_actor_hide (actor); /* don't show, so won't map */
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
|
||||
clutter_actor_add_child (stage, group);
|
||||
clutter_actor_add_child (group, actor);
|
||||
|
||||
clutter_actor_realize (group);
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (group));
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group)));
|
||||
|
||||
/* realizing group did not realize the child */
|
||||
g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
}
|
||||
|
||||
static void
|
||||
actor_map_recursive (void)
|
||||
{
|
||||
ClutterActor *actor, *group;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
clutter_actor_show (stage);
|
||||
|
||||
group = clutter_actor_new ();
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
|
||||
clutter_actor_hide (group); /* hide at first */
|
||||
clutter_actor_show (actor); /* show at first */
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group)));
|
||||
g_assert ((CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
|
||||
clutter_actor_add_child (stage, group);
|
||||
clutter_actor_add_child (group, actor);
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group)));
|
||||
g_assert ((CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
|
||||
/* show group, which should map and realize both
|
||||
* group and child.
|
||||
*/
|
||||
clutter_actor_show (group);
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (group));
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_MAPPED (group));
|
||||
g_assert (CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (group));
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
}
|
||||
|
||||
static void
|
||||
actor_show_on_set_parent (void)
|
||||
{
|
||||
ClutterActor *actor, *group;
|
||||
gboolean show_on_set_parent;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
|
||||
group = clutter_actor_new ();
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group)));
|
||||
|
||||
clutter_actor_add_child (stage, group);
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
g_object_get (actor,
|
||||
"show-on-set-parent", &show_on_set_parent,
|
||||
NULL);
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
g_assert (show_on_set_parent);
|
||||
|
||||
clutter_actor_add_child (group, actor);
|
||||
g_object_get (actor,
|
||||
"show-on-set-parent", &show_on_set_parent,
|
||||
NULL);
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
g_assert (show_on_set_parent);
|
||||
|
||||
g_object_ref (actor);
|
||||
clutter_actor_remove_child (group, actor);
|
||||
g_object_get (actor,
|
||||
"show-on-set-parent", &show_on_set_parent,
|
||||
NULL);
|
||||
|
||||
g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
g_assert (show_on_set_parent);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
clutter_actor_destroy (group);
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
clutter_actor_add_child (stage, actor);
|
||||
clutter_actor_hide (actor);
|
||||
g_object_get (actor,
|
||||
"show-on-set-parent", &show_on_set_parent,
|
||||
NULL);
|
||||
g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
g_assert (show_on_set_parent);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
clutter_actor_hide (actor);
|
||||
clutter_actor_add_child (stage, actor);
|
||||
g_object_get (actor,
|
||||
"show-on-set-parent", &show_on_set_parent,
|
||||
NULL);
|
||||
g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
g_assert (!show_on_set_parent);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clone_no_map (void)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *group;
|
||||
ClutterActor *actor;
|
||||
ClutterActor *clone;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
clutter_actor_show (stage);
|
||||
|
||||
group = clutter_actor_new ();
|
||||
actor = clutter_actor_new ();
|
||||
|
||||
clutter_actor_hide (group);
|
||||
|
||||
clutter_actor_add_child (group, actor);
|
||||
clutter_actor_add_child (stage, group);
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
|
||||
clone = clutter_clone_new (group);
|
||||
|
||||
clutter_actor_add_child (stage, clone);
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_MAPPED (clone));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (clone));
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (group));
|
||||
}
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
static void
|
||||
default_stage (void)
|
||||
{
|
||||
ClutterActor *stage, *def_stage;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
def_stage = clutter_stage_get_default ();
|
||||
|
||||
if (clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE))
|
||||
g_assert (stage != def_stage);
|
||||
else
|
||||
g_assert (stage == def_stage);
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (def_stage));
|
||||
}
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/invariants/initial-state", actor_initial_state)
|
||||
CLUTTER_TEST_UNIT ("/actor/invariants/show-not-parented", actor_shown_not_parented)
|
||||
CLUTTER_TEST_UNIT ("/actor/invariants/realized", actor_realized)
|
||||
CLUTTER_TEST_UNIT ("/actor/invariants/mapped", actor_mapped)
|
||||
CLUTTER_TEST_UNIT ("/actor/invariants/visibility-not-recursive", actor_visibility_not_recursive)
|
||||
CLUTTER_TEST_UNIT ("/actor/invariants/realize-not-recursive", actor_realize_not_recursive)
|
||||
CLUTTER_TEST_UNIT ("/actor/invariants/map-recursive", actor_map_recursive)
|
||||
CLUTTER_TEST_UNIT ("/actor/invariants/show-on-set-parent", actor_show_on_set_parent)
|
||||
CLUTTER_TEST_UNIT ("/actor/invariants/clone-no-map", clone_no_map)
|
||||
CLUTTER_TEST_UNIT ("/actor/invariants/default-stage", default_stage)
|
||||
)
|
218
src/tests/clutter/conform/actor-iter.c
Normal file
218
src/tests/clutter/conform/actor-iter.c
Normal file
@ -0,0 +1,218 @@
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
actor_iter_traverse_children (void)
|
||||
{
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *actor;
|
||||
ClutterActor *child;
|
||||
int i, n_actors;
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
clutter_actor_set_name (actor, "root");
|
||||
g_object_ref_sink (actor);
|
||||
|
||||
n_actors = g_random_int_range (10, 50);
|
||||
for (i = 0; i < n_actors; i++)
|
||||
{
|
||||
char *name;
|
||||
|
||||
name = g_strdup_printf ("actor%d", i);
|
||||
child = clutter_actor_new ();
|
||||
clutter_actor_set_name (child, name);
|
||||
|
||||
clutter_actor_add_child (actor, child);
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, n_actors);
|
||||
|
||||
i = 0;
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
g_assert (clutter_actor_iter_is_valid (&iter));
|
||||
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
g_assert (CLUTTER_IS_ACTOR (child));
|
||||
g_assert (clutter_actor_get_parent (child) == actor);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("actor %d = '%s'\n", i, clutter_actor_get_name (child));
|
||||
|
||||
if (i == 0)
|
||||
g_assert (child == clutter_actor_get_first_child (actor));
|
||||
|
||||
if (i == (n_actors - 1))
|
||||
g_assert (child == clutter_actor_get_last_child (actor));
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
g_assert_cmpint (i, ==, n_actors);
|
||||
|
||||
i = 0;
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
g_assert (clutter_actor_iter_is_valid (&iter));
|
||||
|
||||
while (clutter_actor_iter_prev (&iter, &child))
|
||||
{
|
||||
g_assert (CLUTTER_IS_ACTOR (child));
|
||||
g_assert (clutter_actor_get_parent (child) == actor);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("actor %d = '%s'\n", i, clutter_actor_get_name (child));
|
||||
|
||||
if (i == 0)
|
||||
g_assert (child == clutter_actor_get_last_child (actor));
|
||||
|
||||
if (i == (n_actors - 1))
|
||||
g_assert (child == clutter_actor_get_first_child (actor));
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
g_object_unref (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_iter_traverse_remove (void)
|
||||
{
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *actor;
|
||||
ClutterActor *child;
|
||||
int i, n_actors;
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
clutter_actor_set_name (actor, "root");
|
||||
g_object_ref_sink (actor);
|
||||
|
||||
n_actors = g_random_int_range (10, 50);
|
||||
for (i = 0; i < n_actors; i++)
|
||||
{
|
||||
char *name;
|
||||
|
||||
name = g_strdup_printf ("actor%d", i);
|
||||
child = clutter_actor_new ();
|
||||
clutter_actor_set_name (child, name);
|
||||
|
||||
clutter_actor_add_child (actor, child);
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, n_actors);
|
||||
|
||||
i = 0;
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
g_assert (clutter_actor_iter_is_valid (&iter));
|
||||
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
g_assert (CLUTTER_IS_ACTOR (child));
|
||||
g_assert (clutter_actor_get_parent (child) == actor);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("actor %d = '%s'\n", i, clutter_actor_get_name (child));
|
||||
|
||||
if (i == 0)
|
||||
g_assert (child == clutter_actor_get_first_child (actor));
|
||||
|
||||
if (i == (n_actors - 1))
|
||||
g_assert (child == clutter_actor_get_last_child (actor));
|
||||
|
||||
clutter_actor_iter_remove (&iter);
|
||||
g_assert (clutter_actor_iter_is_valid (&iter));
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
g_assert_cmpint (i, ==, n_actors);
|
||||
g_assert_cmpint (0, ==, clutter_actor_get_n_children (actor));
|
||||
}
|
||||
|
||||
static void
|
||||
actor_iter_assignment (void)
|
||||
{
|
||||
ClutterActorIter iter_a, iter_b;
|
||||
ClutterActor *actor;
|
||||
ClutterActor *child;
|
||||
int i, n_actors;
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
clutter_actor_set_name (actor, "root");
|
||||
g_object_ref_sink (actor);
|
||||
|
||||
n_actors = g_random_int_range (10, 50);
|
||||
for (i = 0; i < n_actors; i++)
|
||||
{
|
||||
char *name;
|
||||
|
||||
name = g_strdup_printf ("actor[%02d]", i);
|
||||
child = clutter_actor_new ();
|
||||
clutter_actor_set_name (child, name);
|
||||
|
||||
clutter_actor_add_child (actor, child);
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_n_children (actor), ==, n_actors);
|
||||
|
||||
i = 0;
|
||||
|
||||
clutter_actor_iter_init (&iter_a, actor);
|
||||
|
||||
iter_b = iter_a;
|
||||
|
||||
g_assert (clutter_actor_iter_is_valid (&iter_a));
|
||||
g_assert (clutter_actor_iter_is_valid (&iter_b));
|
||||
|
||||
while (clutter_actor_iter_next (&iter_a, &child))
|
||||
{
|
||||
g_assert (CLUTTER_IS_ACTOR (child));
|
||||
g_assert (clutter_actor_get_parent (child) == actor);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("actor %2d = '%s'\n", i, clutter_actor_get_name (child));
|
||||
|
||||
if (i == 0)
|
||||
g_assert (child == clutter_actor_get_first_child (actor));
|
||||
|
||||
if (i == (n_actors - 1))
|
||||
g_assert (child == clutter_actor_get_last_child (actor));
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
g_assert_cmpint (i, ==, n_actors);
|
||||
|
||||
i = n_actors - 1;
|
||||
|
||||
while (clutter_actor_iter_prev (&iter_b, &child))
|
||||
{
|
||||
g_assert (clutter_actor_get_parent (child) == actor);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("actor %2d = '%s'\n", i, clutter_actor_get_name (child));
|
||||
|
||||
if (i == n_actors - 1)
|
||||
g_assert (child == clutter_actor_get_last_child (actor));
|
||||
|
||||
if (i == 0)
|
||||
g_assert (child == clutter_actor_get_first_child (actor));
|
||||
|
||||
i -= 1;
|
||||
}
|
||||
|
||||
g_assert_cmpint (i, ==, -1);
|
||||
|
||||
g_object_unref (actor);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/iter/traverse-children", actor_iter_traverse_children)
|
||||
CLUTTER_TEST_UNIT ("/actor/iter/traverse-remove", actor_iter_traverse_remove)
|
||||
CLUTTER_TEST_UNIT ("/actor/iter/assignment", actor_iter_assignment)
|
||||
)
|
92
src/tests/clutter/conform/actor-layout.c
Normal file
92
src/tests/clutter/conform/actor-layout.c
Normal file
@ -0,0 +1,92 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
actor_basic_layout (void)
|
||||
{
|
||||
ClutterActor *stage = clutter_test_get_stage ();
|
||||
ClutterActor *vase;
|
||||
ClutterActor *flower[3];
|
||||
ClutterPoint p;
|
||||
|
||||
vase = clutter_actor_new ();
|
||||
clutter_actor_set_name (vase, "Vase");
|
||||
clutter_actor_set_layout_manager (vase, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL));
|
||||
clutter_actor_add_child (stage, vase);
|
||||
|
||||
flower[0] = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (flower[0], CLUTTER_COLOR_Red);
|
||||
clutter_actor_set_size (flower[0], 100, 100);
|
||||
clutter_actor_set_name (flower[0], "Red Flower");
|
||||
clutter_actor_add_child (vase, flower[0]);
|
||||
|
||||
flower[1] = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (flower[1], CLUTTER_COLOR_Yellow);
|
||||
clutter_actor_set_size (flower[1], 100, 100);
|
||||
clutter_actor_set_name (flower[1], "Yellow Flower");
|
||||
clutter_actor_add_child (vase, flower[1]);
|
||||
|
||||
flower[2] = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (flower[2], CLUTTER_COLOR_Green);
|
||||
clutter_actor_set_size (flower[2], 100, 100);
|
||||
clutter_actor_set_name (flower[2], "Green Flower");
|
||||
clutter_actor_add_child (vase, flower[2]);
|
||||
|
||||
clutter_point_init (&p, 50, 50);
|
||||
clutter_test_assert_actor_at_point (stage, &p, flower[0]);
|
||||
|
||||
clutter_point_init (&p, 150, 50);
|
||||
clutter_test_assert_actor_at_point (stage, &p, flower[1]);
|
||||
|
||||
clutter_point_init (&p, 250, 50);
|
||||
clutter_test_assert_actor_at_point (stage, &p, flower[2]);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_margin_layout (void)
|
||||
{
|
||||
ClutterActor *stage = clutter_test_get_stage ();
|
||||
ClutterActor *vase;
|
||||
ClutterActor *flower[3];
|
||||
ClutterPoint p;
|
||||
|
||||
vase = clutter_actor_new ();
|
||||
clutter_actor_set_name (vase, "Vase");
|
||||
clutter_actor_set_layout_manager (vase, clutter_box_layout_new ());
|
||||
clutter_actor_add_child (stage, vase);
|
||||
|
||||
flower[0] = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (flower[0], CLUTTER_COLOR_Red);
|
||||
clutter_actor_set_size (flower[0], 100, 100);
|
||||
clutter_actor_set_name (flower[0], "Red Flower");
|
||||
clutter_actor_add_child (vase, flower[0]);
|
||||
|
||||
flower[1] = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (flower[1], CLUTTER_COLOR_Yellow);
|
||||
clutter_actor_set_size (flower[1], 100, 100);
|
||||
clutter_actor_set_name (flower[1], "Yellow Flower");
|
||||
clutter_actor_set_margin_right (flower[1], 6);
|
||||
clutter_actor_set_margin_left (flower[1], 6);
|
||||
clutter_actor_add_child (vase, flower[1]);
|
||||
|
||||
flower[2] = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (flower[2], CLUTTER_COLOR_Green);
|
||||
clutter_actor_set_size (flower[2], 100, 100);
|
||||
clutter_actor_set_name (flower[2], "Green Flower");
|
||||
clutter_actor_set_margin_top (flower[2], 6);
|
||||
clutter_actor_set_margin_bottom (flower[2], 6);
|
||||
clutter_actor_add_child (vase, flower[2]);
|
||||
|
||||
clutter_point_init (&p, 0, 7);
|
||||
clutter_test_assert_actor_at_point (stage, &p, flower[0]);
|
||||
|
||||
clutter_point_init (&p, 106, 50);
|
||||
clutter_test_assert_actor_at_point (stage, &p, flower[1]);
|
||||
|
||||
clutter_point_init (&p, 212, 7);
|
||||
clutter_test_assert_actor_at_point (stage, &p, flower[2]);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/layout/basic", actor_basic_layout)
|
||||
CLUTTER_TEST_UNIT ("/actor/layout/margin", actor_margin_layout)
|
||||
)
|
40
src/tests/clutter/conform/actor-meta.c
Normal file
40
src/tests/clutter/conform/actor-meta.c
Normal file
@ -0,0 +1,40 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
actor_meta_clear (void)
|
||||
{
|
||||
ClutterActor *actor, *stage;
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
g_object_ref_sink (actor);
|
||||
g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
|
||||
|
||||
clutter_actor_add_action (actor, clutter_click_action_new ());
|
||||
clutter_actor_add_constraint (actor, clutter_bind_constraint_new (stage, CLUTTER_BIND_ALL, 0));
|
||||
clutter_actor_add_effect (actor, clutter_blur_effect_new ());
|
||||
|
||||
g_assert (clutter_actor_has_actions (actor));
|
||||
g_assert (clutter_actor_has_constraints (actor));
|
||||
g_assert (clutter_actor_has_effects (actor));
|
||||
|
||||
clutter_actor_clear_actions (actor);
|
||||
g_assert (!clutter_actor_has_actions (actor));
|
||||
|
||||
clutter_actor_clear_constraints (actor);
|
||||
g_assert (!clutter_actor_has_constraints (actor));
|
||||
|
||||
clutter_actor_clear_effects (actor);
|
||||
g_assert (!clutter_actor_has_effects (actor));
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
g_assert (actor == NULL);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/meta/clear", actor_meta_clear)
|
||||
)
|
349
src/tests/clutter/conform/actor-offscreen-redirect.c
Normal file
349
src/tests/clutter/conform/actor-offscreen-redirect.c
Normal file
@ -0,0 +1,349 @@
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
typedef struct _FooActor FooActor;
|
||||
typedef struct _FooActorClass FooActorClass;
|
||||
|
||||
struct _FooActorClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
};
|
||||
|
||||
struct _FooActor
|
||||
{
|
||||
ClutterActor parent;
|
||||
|
||||
guint8 last_paint_opacity;
|
||||
int paint_count;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ClutterActor *stage;
|
||||
FooActor *foo_actor;
|
||||
ClutterActor *parent_container;
|
||||
ClutterActor *container;
|
||||
ClutterActor *child;
|
||||
ClutterActor *unrelated_actor;
|
||||
gboolean was_painted;
|
||||
} Data;
|
||||
|
||||
GType foo_actor_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_DEFINE_TYPE (FooActor, foo_actor, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
static gboolean group_has_overlaps;
|
||||
|
||||
static void
|
||||
foo_actor_paint (ClutterActor *actor)
|
||||
{
|
||||
FooActor *foo_actor = (FooActor *) actor;
|
||||
ClutterActorBox allocation;
|
||||
|
||||
foo_actor->last_paint_opacity = clutter_actor_get_paint_opacity (actor);
|
||||
foo_actor->paint_count++;
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &allocation);
|
||||
|
||||
/* Paint a red rectangle with the right opacity */
|
||||
cogl_set_source_color4ub (255,
|
||||
0,
|
||||
0,
|
||||
foo_actor->last_paint_opacity);
|
||||
cogl_rectangle (allocation.x1,
|
||||
allocation.y1,
|
||||
allocation.x2,
|
||||
allocation.y2);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
foo_actor_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
return clutter_paint_volume_set_from_allocation (volume, actor);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
foo_actor_has_overlaps (ClutterActor *actor)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
foo_actor_class_init (FooActorClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
|
||||
actor_class->paint = foo_actor_paint;
|
||||
actor_class->get_paint_volume = foo_actor_get_paint_volume;
|
||||
actor_class->has_overlaps = foo_actor_has_overlaps;
|
||||
}
|
||||
|
||||
static void
|
||||
foo_actor_init (FooActor *self)
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct _FooGroup FooGroup;
|
||||
typedef struct _FooGroupClass FooGroupClass;
|
||||
|
||||
struct _FooGroupClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
};
|
||||
|
||||
struct _FooGroup
|
||||
{
|
||||
ClutterActor parent;
|
||||
};
|
||||
|
||||
GType foo_group_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (FooGroup, foo_group, CLUTTER_TYPE_ACTOR)
|
||||
|
||||
static gboolean
|
||||
foo_group_has_overlaps (ClutterActor *actor)
|
||||
{
|
||||
return group_has_overlaps;
|
||||
}
|
||||
|
||||
static void
|
||||
foo_group_class_init (FooGroupClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
|
||||
actor_class->has_overlaps = foo_group_has_overlaps;
|
||||
}
|
||||
|
||||
static void
|
||||
foo_group_init (FooGroup *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
verify_results (Data *data,
|
||||
guint8 expected_color_red,
|
||||
guint8 expected_color_green,
|
||||
guint8 expected_color_blue,
|
||||
int expected_paint_count,
|
||||
int expected_paint_opacity)
|
||||
{
|
||||
guchar *pixel;
|
||||
|
||||
data->foo_actor->paint_count = 0;
|
||||
|
||||
/* Read a pixel at the center of the to determine what color it
|
||||
painted. This should cause a redraw */
|
||||
pixel = clutter_stage_read_pixels (CLUTTER_STAGE (data->stage),
|
||||
50, 50, /* x/y */
|
||||
1, 1 /* width/height */);
|
||||
|
||||
g_assert_cmpint (expected_paint_count, ==, data->foo_actor->paint_count);
|
||||
g_assert_cmpint (expected_paint_opacity,
|
||||
==,
|
||||
data->foo_actor->last_paint_opacity);
|
||||
|
||||
g_assert_cmpint (ABS ((int) expected_color_red - (int) pixel[0]), <=, 2);
|
||||
g_assert_cmpint (ABS ((int) expected_color_green - (int) pixel[1]), <=, 2);
|
||||
g_assert_cmpint (ABS ((int) expected_color_blue - (int) pixel[2]), <=, 2);
|
||||
|
||||
g_free (pixel);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_redraw (Data *data, int expected_paint_count)
|
||||
{
|
||||
GMainLoop *main_loop = g_main_loop_new (NULL, TRUE);
|
||||
guint paint_handler;
|
||||
|
||||
paint_handler = g_signal_connect_data (data->stage,
|
||||
"paint",
|
||||
G_CALLBACK (g_main_loop_quit),
|
||||
main_loop,
|
||||
NULL,
|
||||
G_CONNECT_SWAPPED | G_CONNECT_AFTER);
|
||||
|
||||
/* Queue a redraw on the stage */
|
||||
clutter_actor_queue_redraw (data->stage);
|
||||
|
||||
data->foo_actor->paint_count = 0;
|
||||
|
||||
/* Wait for it to paint */
|
||||
g_main_loop_run (main_loop);
|
||||
|
||||
g_signal_handler_disconnect (data->stage, paint_handler);
|
||||
|
||||
g_assert_cmpint (data->foo_actor->paint_count, ==, expected_paint_count);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
verify_redraws (gpointer user_data)
|
||||
{
|
||||
Data *data = user_data;
|
||||
|
||||
/* Queueing a redraw on the actor should cause a redraw */
|
||||
clutter_actor_queue_redraw (data->container);
|
||||
verify_redraw (data, 1);
|
||||
|
||||
/* Queueing a redraw on a child should cause a redraw */
|
||||
clutter_actor_queue_redraw (data->child);
|
||||
verify_redraw (data, 1);
|
||||
|
||||
/* Modifying the transformation on the parent should not cause a redraw,
|
||||
since the FBO stores pre-transformed rendering that can be reused with
|
||||
any transformation. */
|
||||
clutter_actor_set_anchor_point (data->parent_container, 0, 1);
|
||||
verify_redraw (data, 0);
|
||||
|
||||
/* Redrawing an unrelated actor shouldn't cause a redraw */
|
||||
clutter_actor_set_position (data->unrelated_actor, 0, 1);
|
||||
verify_redraw (data, 0);
|
||||
|
||||
data->was_painted = TRUE;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
run_verify (gpointer user_data)
|
||||
{
|
||||
Data *data = user_data;
|
||||
|
||||
group_has_overlaps = FALSE;
|
||||
|
||||
/* By default the actor shouldn't be redirected so the redraw should
|
||||
cause the actor to be painted */
|
||||
verify_results (data,
|
||||
255, 0, 0,
|
||||
1,
|
||||
255);
|
||||
|
||||
/* Make the actor semi-transparent and verify the paint opacity */
|
||||
clutter_actor_set_opacity (data->container, 127);
|
||||
verify_results (data,
|
||||
255, 127, 127,
|
||||
1,
|
||||
127);
|
||||
|
||||
/* With automatic redirect for opacity it shouldn't redirect if
|
||||
* has_overlaps returns FALSE; */
|
||||
clutter_actor_set_offscreen_redirect
|
||||
(data->container, CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY);
|
||||
verify_results (data,
|
||||
255, 127, 127,
|
||||
1,
|
||||
127);
|
||||
|
||||
/* We do a double check here to verify that the actor wasn't cached
|
||||
* during the last check. If it was cached then this check wouldn't
|
||||
* result in any foo-actor re-paint. */
|
||||
verify_results (data,
|
||||
255, 127, 127,
|
||||
1,
|
||||
127);
|
||||
|
||||
/* With automatic redirect for opacity it should redirect if
|
||||
* has_overlaps returns TRUE.
|
||||
* The first paint will still cause the actor to draw because
|
||||
* it needs to fill the cache first. It should be painted with full
|
||||
* opacity */
|
||||
group_has_overlaps = TRUE;
|
||||
|
||||
verify_results (data,
|
||||
255, 127, 127,
|
||||
1,
|
||||
255);
|
||||
|
||||
/* The second time the actor is painted it should be cached */
|
||||
verify_results (data,
|
||||
255, 127, 127,
|
||||
0,
|
||||
255);
|
||||
|
||||
/* We should be able to change the opacity without causing the actor
|
||||
to redraw */
|
||||
clutter_actor_set_opacity (data->container, 64);
|
||||
verify_results (data,
|
||||
255, 191, 191,
|
||||
0,
|
||||
255);
|
||||
|
||||
/* Changing it back to fully opaque should cause it not to go
|
||||
through the FBO so it will draw */
|
||||
clutter_actor_set_opacity (data->container, 255);
|
||||
verify_results (data,
|
||||
255, 0, 0,
|
||||
1,
|
||||
255);
|
||||
|
||||
/* Tell it to always redirect through the FBO. This should cause a
|
||||
paint of the actor because the last draw didn't go through the
|
||||
FBO */
|
||||
clutter_actor_set_offscreen_redirect (data->container,
|
||||
CLUTTER_OFFSCREEN_REDIRECT_ALWAYS);
|
||||
verify_results (data,
|
||||
255, 0, 0,
|
||||
1,
|
||||
255);
|
||||
|
||||
/* We should be able to change the opacity without causing the actor
|
||||
to redraw */
|
||||
clutter_actor_set_opacity (data->container, 64);
|
||||
verify_results (data,
|
||||
255, 191, 191,
|
||||
0,
|
||||
255);
|
||||
|
||||
/* Even changing it back to fully opaque shouldn't cause a redraw */
|
||||
clutter_actor_set_opacity (data->container, 255);
|
||||
verify_results (data,
|
||||
255, 0, 0,
|
||||
0,
|
||||
255);
|
||||
|
||||
/* Check redraws */
|
||||
g_idle_add (verify_redraws, data);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
actor_offscreen_redirect (void)
|
||||
{
|
||||
Data data = { 0 };
|
||||
|
||||
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||
return;
|
||||
|
||||
data.stage = clutter_test_get_stage ();
|
||||
data.parent_container = clutter_actor_new ();
|
||||
data.container = g_object_new (foo_group_get_type (), NULL);
|
||||
data.foo_actor = g_object_new (foo_actor_get_type (), NULL);
|
||||
clutter_actor_set_size (CLUTTER_ACTOR (data.foo_actor), 100, 100);
|
||||
|
||||
clutter_actor_add_child (data.container, CLUTTER_ACTOR (data.foo_actor));
|
||||
clutter_actor_add_child (data.parent_container, data.container);
|
||||
clutter_actor_add_child (data.stage, data.parent_container);
|
||||
|
||||
data.child = clutter_actor_new ();
|
||||
clutter_actor_set_size (data.child, 1, 1);
|
||||
clutter_actor_add_child (data.container, data.child);
|
||||
|
||||
data.unrelated_actor = clutter_actor_new ();
|
||||
clutter_actor_set_size (data.child, 1, 1);
|
||||
clutter_actor_add_child (data.stage, data.unrelated_actor);
|
||||
|
||||
clutter_actor_show (data.stage);
|
||||
|
||||
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
|
||||
run_verify,
|
||||
&data,
|
||||
NULL);
|
||||
|
||||
while (!data.was_painted)
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/offscreen/redirect", actor_offscreen_redirect)
|
||||
)
|
141
src/tests/clutter/conform/actor-paint-opacity.c
Normal file
141
src/tests/clutter/conform/actor-paint-opacity.c
Normal file
@ -0,0 +1,141 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void
|
||||
opacity_label (void)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *label;
|
||||
ClutterColor label_color = { 255, 0, 0, 128 };
|
||||
ClutterColor color_check = { 0, };
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
|
||||
label = clutter_text_new_with_text ("Sans 18px", "Label, 50% opacity");
|
||||
clutter_text_set_color (CLUTTER_TEXT (label), &label_color);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("label 50%%.get_color()/1\n");
|
||||
clutter_text_get_color (CLUTTER_TEXT (label), &color_check);
|
||||
g_assert (color_check.alpha == label_color.alpha);
|
||||
|
||||
clutter_actor_add_child (stage, label);
|
||||
clutter_actor_set_position (label, 10, 10);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("label 50%%.get_color()/2\n");
|
||||
clutter_text_get_color (CLUTTER_TEXT (label), &color_check);
|
||||
g_assert (color_check.alpha == label_color.alpha);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("label 50%%.get_paint_opacity()/1\n");
|
||||
g_assert (clutter_actor_get_paint_opacity (label) == 255);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("label 50%%.get_paint_opacity()/2\n");
|
||||
clutter_actor_set_opacity (label, 128);
|
||||
g_assert (clutter_actor_get_paint_opacity (label) == 128);
|
||||
}
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
static void
|
||||
opacity_rectangle (void)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *rect;
|
||||
ClutterColor rect_color = { 0, 0, 255, 255 };
|
||||
ClutterColor color_check = { 0, };
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
|
||||
rect = clutter_rectangle_new_with_color (&rect_color);
|
||||
clutter_actor_set_size (rect, 128, 128);
|
||||
clutter_actor_set_position (rect, 150, 90);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("rect 100%%.get_color()/1\n");
|
||||
clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check);
|
||||
g_assert (color_check.alpha == rect_color.alpha);
|
||||
|
||||
clutter_actor_add_child (stage, rect);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("rect 100%%.get_color()/2\n");
|
||||
clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check);
|
||||
g_assert (color_check.alpha == rect_color.alpha);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("rect 100%%.get_paint_opacity()\n");
|
||||
g_assert (clutter_actor_get_paint_opacity (rect) == 255);
|
||||
}
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
static void
|
||||
opacity_paint (void)
|
||||
{
|
||||
ClutterActor *stage, *group1, *group2;
|
||||
ClutterActor *label, *rect;
|
||||
ClutterColor label_color = { 255, 0, 0, 128 };
|
||||
ClutterColor rect_color = { 0, 0, 255, 255 };
|
||||
ClutterColor color_check = { 0, };
|
||||
|
||||
stage = clutter_test_get_stage ();
|
||||
|
||||
group1 = clutter_group_new ();
|
||||
clutter_actor_set_opacity (group1, 128);
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), group1, NULL);
|
||||
clutter_actor_set_position (group1, 10, 30);
|
||||
clutter_actor_show (group1);
|
||||
|
||||
label = clutter_text_new_with_text ("Sans 18px", "Label+Group, 25% opacity");
|
||||
clutter_text_set_color (CLUTTER_TEXT (label), &label_color);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("label 50%% + group 50%%.get_color()/1\n");
|
||||
clutter_text_get_color (CLUTTER_TEXT (label), &color_check);
|
||||
g_assert (color_check.alpha == label_color.alpha);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (group1), label, NULL);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("label 50%% + group 50%%.get_color()/2\n");
|
||||
clutter_text_get_color (CLUTTER_TEXT (label), &color_check);
|
||||
g_assert (color_check.alpha == label_color.alpha);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("label 50%% + group 50%%.get_paint_opacity() = 128\n");
|
||||
g_assert (clutter_actor_get_paint_opacity (label) == 128);
|
||||
|
||||
clutter_actor_destroy (label);
|
||||
|
||||
group2 = clutter_group_new ();
|
||||
clutter_container_add (CLUTTER_CONTAINER (group1), group2, NULL);
|
||||
clutter_actor_set_position (group2, 10, 60);
|
||||
|
||||
rect = clutter_rectangle_new_with_color (&rect_color);
|
||||
clutter_actor_set_size (rect, 128, 128);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("rect 100%% + group 100%% + group 50%%.get_color()/1\n");
|
||||
clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check);
|
||||
g_assert (color_check.alpha == rect_color.alpha);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (group2), rect, NULL);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("rect 100%% + group 100%% + group 50%%.get_color()/2\n");
|
||||
clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check);
|
||||
g_assert (color_check.alpha == rect_color.alpha);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("rect 100%%.get_paint_opacity()\n");
|
||||
g_assert (clutter_actor_get_paint_opacity (rect) == 128);
|
||||
}
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/opacity/text", opacity_label)
|
||||
CLUTTER_TEST_UNIT ("/actor/opacity/rectangle", opacity_rectangle)
|
||||
CLUTTER_TEST_UNIT ("/actor/opacity/paint", opacity_paint)
|
||||
)
|
311
src/tests/clutter/conform/actor-pick.c
Normal file
311
src/tests/clutter/conform/actor-pick.c
Normal file
@ -0,0 +1,311 @@
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define STAGE_WIDTH 640
|
||||
#define STAGE_HEIGHT 480
|
||||
#define ACTORS_X 12
|
||||
#define ACTORS_Y 16
|
||||
#define SHIFT_STEP STAGE_WIDTH / ACTORS_X
|
||||
|
||||
typedef struct _State State;
|
||||
|
||||
struct _State
|
||||
{
|
||||
ClutterActor *stage;
|
||||
int y, x;
|
||||
ClutterActor *actors[ACTORS_X * ACTORS_Y];
|
||||
guint actor_width, actor_height;
|
||||
guint failed_pass;
|
||||
guint failed_idx;
|
||||
gboolean pass;
|
||||
};
|
||||
|
||||
struct _ShiftEffect
|
||||
{
|
||||
ClutterShaderEffect parent_instance;
|
||||
};
|
||||
|
||||
struct _ShiftEffectClass
|
||||
{
|
||||
ClutterShaderEffectClass parent_class;
|
||||
};
|
||||
|
||||
typedef struct _ShiftEffect ShiftEffect;
|
||||
typedef struct _ShiftEffectClass ShiftEffectClass;
|
||||
|
||||
#define TYPE_SHIFT_EFFECT (shift_effect_get_type ())
|
||||
|
||||
GType shift_effect_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (ShiftEffect,
|
||||
shift_effect,
|
||||
CLUTTER_TYPE_SHADER_EFFECT);
|
||||
|
||||
static void
|
||||
shader_paint (ClutterEffect *effect,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
ClutterShaderEffect *shader = CLUTTER_SHADER_EFFECT (effect);
|
||||
float tex_width;
|
||||
ClutterActor *actor =
|
||||
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_debug ("shader_paint");
|
||||
|
||||
clutter_shader_effect_set_shader_source (shader,
|
||||
"uniform sampler2D tex;\n"
|
||||
"uniform float step;\n"
|
||||
"void main (void)\n"
|
||||
"{\n"
|
||||
" cogl_color_out = texture2D(tex, vec2 (cogl_tex_coord_in[0].s + step,\n"
|
||||
" cogl_tex_coord_in[0].t));\n"
|
||||
"}\n");
|
||||
|
||||
tex_width = clutter_actor_get_width (actor);
|
||||
|
||||
clutter_shader_effect_set_uniform (shader, "tex", G_TYPE_INT, 1, 0);
|
||||
clutter_shader_effect_set_uniform (shader, "step", G_TYPE_FLOAT, 1,
|
||||
SHIFT_STEP / tex_width);
|
||||
|
||||
CLUTTER_EFFECT_CLASS (shift_effect_parent_class)->paint (effect, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
shader_pick (ClutterEffect *effect,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
shader_paint (effect, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
shift_effect_class_init (ShiftEffectClass *klass)
|
||||
{
|
||||
ClutterEffectClass *shader_class = CLUTTER_EFFECT_CLASS (klass);
|
||||
|
||||
shader_class->paint = shader_paint;
|
||||
shader_class->pick = shader_pick;
|
||||
}
|
||||
|
||||
static void
|
||||
shift_effect_init (ShiftEffect *self)
|
||||
{
|
||||
}
|
||||
|
||||
static const char *test_passes[] = {
|
||||
"No covering actor",
|
||||
"Invisible covering actor",
|
||||
"Clipped covering actor",
|
||||
"Blur effect",
|
||||
"Shift effect",
|
||||
};
|
||||
|
||||
static gboolean
|
||||
on_timeout (gpointer data)
|
||||
{
|
||||
State *state = data;
|
||||
int test_num = 0;
|
||||
int y, x;
|
||||
ClutterActor *over_actor = NULL;
|
||||
|
||||
/* This will cause an unclipped pick redraw that will get buffered.
|
||||
We'll check below that this buffer is discarded because we also need
|
||||
to pick non-reactive actors */
|
||||
clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage),
|
||||
CLUTTER_PICK_REACTIVE, 10, 10);
|
||||
|
||||
clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage),
|
||||
CLUTTER_PICK_REACTIVE, 10, 10);
|
||||
|
||||
for (test_num = 0; test_num < G_N_ELEMENTS (test_passes); test_num++)
|
||||
{
|
||||
if (test_num == 0)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("No covering actor:\n");
|
||||
}
|
||||
if (test_num == 1)
|
||||
{
|
||||
static const ClutterColor red = { 0xff, 0x00, 0x00, 0xff };
|
||||
/* Create an actor that covers the whole stage but that
|
||||
isn't visible so it shouldn't affect the picking */
|
||||
over_actor = clutter_rectangle_new_with_color (&red);
|
||||
clutter_actor_set_size (over_actor, STAGE_WIDTH, STAGE_HEIGHT);
|
||||
clutter_actor_add_child (state->stage, over_actor);
|
||||
clutter_actor_hide (over_actor);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Invisible covering actor:\n");
|
||||
}
|
||||
else if (test_num == 2)
|
||||
{
|
||||
/* Make the actor visible but set a clip so that only some
|
||||
of the actors are accessible */
|
||||
clutter_actor_show (over_actor);
|
||||
clutter_actor_set_clip (over_actor,
|
||||
state->actor_width * 2,
|
||||
state->actor_height * 2,
|
||||
state->actor_width * (ACTORS_X - 4),
|
||||
state->actor_height * (ACTORS_Y - 4));
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Clipped covering actor:\n");
|
||||
}
|
||||
else if (test_num == 3)
|
||||
{
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
continue;
|
||||
|
||||
clutter_actor_hide (over_actor);
|
||||
|
||||
clutter_actor_add_effect_with_name (CLUTTER_ACTOR (state->stage),
|
||||
"blur",
|
||||
clutter_blur_effect_new ());
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("With blur effect:\n");
|
||||
}
|
||||
else if (test_num == 4)
|
||||
{
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
continue;
|
||||
|
||||
clutter_actor_hide (over_actor);
|
||||
clutter_actor_remove_effect_by_name (CLUTTER_ACTOR (state->stage),
|
||||
"blur");
|
||||
|
||||
clutter_actor_add_effect_with_name (CLUTTER_ACTOR (state->stage),
|
||||
"shift",
|
||||
g_object_new (TYPE_SHIFT_EFFECT,
|
||||
NULL));
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("With shift effect:\n");
|
||||
}
|
||||
|
||||
for (y = 0; y < ACTORS_Y; y++)
|
||||
{
|
||||
if (test_num == 4)
|
||||
x = 1;
|
||||
else
|
||||
x = 0;
|
||||
|
||||
for (; x < ACTORS_X; x++)
|
||||
{
|
||||
gboolean pass = FALSE;
|
||||
gfloat pick_x;
|
||||
ClutterActor *actor;
|
||||
|
||||
pick_x = x * state->actor_width + state->actor_width / 2;
|
||||
|
||||
if (test_num == 4)
|
||||
pick_x -= SHIFT_STEP;
|
||||
|
||||
actor =
|
||||
clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage),
|
||||
CLUTTER_PICK_ALL,
|
||||
pick_x,
|
||||
y * state->actor_height
|
||||
+ state->actor_height / 2);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("% 3i,% 3i / %p -> ",
|
||||
x, y, state->actors[y * ACTORS_X + x]);
|
||||
|
||||
if (actor == NULL)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("NULL: FAIL\n");
|
||||
}
|
||||
else if (actor == over_actor)
|
||||
{
|
||||
if (test_num == 2
|
||||
&& x >= 2 && x < ACTORS_X - 2
|
||||
&& y >= 2 && y < ACTORS_Y - 2)
|
||||
pass = TRUE;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("over_actor: %s\n", pass ? "pass" : "FAIL");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (actor == state->actors[y * ACTORS_X + x]
|
||||
&& (test_num != 2
|
||||
|| x < 2 || x >= ACTORS_X - 2
|
||||
|| y < 2 || y >= ACTORS_Y - 2))
|
||||
pass = TRUE;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("%p: %s\n", actor, pass ? "pass" : "FAIL");
|
||||
}
|
||||
|
||||
if (!pass)
|
||||
{
|
||||
state->failed_pass = test_num;
|
||||
state->failed_idx = y * ACTORS_X + x;
|
||||
state->pass = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clutter_main_quit ();
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
actor_pick (void)
|
||||
{
|
||||
int y, x;
|
||||
State state;
|
||||
|
||||
state.pass = TRUE;
|
||||
|
||||
state.stage = clutter_test_get_stage ();
|
||||
|
||||
state.actor_width = STAGE_WIDTH / ACTORS_X;
|
||||
state.actor_height = STAGE_HEIGHT / ACTORS_Y;
|
||||
|
||||
for (y = 0; y < ACTORS_Y; y++)
|
||||
for (x = 0; x < ACTORS_X; x++)
|
||||
{
|
||||
ClutterColor color = { x * 255 / (ACTORS_X - 1),
|
||||
y * 255 / (ACTORS_Y - 1),
|
||||
128, 255 };
|
||||
ClutterActor *rect = clutter_rectangle_new_with_color (&color);
|
||||
|
||||
clutter_actor_set_position (rect,
|
||||
x * state.actor_width,
|
||||
y * state.actor_height);
|
||||
clutter_actor_set_size (rect,
|
||||
state.actor_width,
|
||||
state.actor_height);
|
||||
|
||||
clutter_actor_add_child (state.stage, rect);
|
||||
|
||||
state.actors[y * ACTORS_X + x] = rect;
|
||||
}
|
||||
|
||||
clutter_actor_show (state.stage);
|
||||
|
||||
clutter_threads_add_idle (on_timeout, &state);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
if (!state.pass)
|
||||
g_test_message ("Failed pass: %s[%d], actor index: %d [%p]\n",
|
||||
test_passes[state.failed_pass],
|
||||
state.failed_pass,
|
||||
state.failed_idx,
|
||||
state.actors[state.failed_idx]);
|
||||
}
|
||||
|
||||
g_assert (state.pass);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/pick", actor_pick)
|
||||
)
|
288
src/tests/clutter/conform/actor-shader-effect.c
Normal file
288
src/tests/clutter/conform/actor-shader-effect.c
Normal file
@ -0,0 +1,288 @@
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
/****************************************************************
|
||||
Old style shader effect
|
||||
This uses clutter_shader_effect_set_source
|
||||
****************************************************************/
|
||||
|
||||
static const gchar
|
||||
old_shader_effect_source[] =
|
||||
"uniform vec3 override_color;\n"
|
||||
"\n"
|
||||
"void\n"
|
||||
"main ()\n"
|
||||
"{\n"
|
||||
" cogl_color_out = vec4 (override_color, 1.0);\n"
|
||||
"}";
|
||||
|
||||
typedef struct _FooOldShaderEffectClass
|
||||
{
|
||||
ClutterShaderEffectClass parent_class;
|
||||
} FooOldShaderEffectClass;
|
||||
|
||||
typedef struct _FooOldShaderEffect
|
||||
{
|
||||
ClutterShaderEffect parent;
|
||||
} FooOldShaderEffect;
|
||||
|
||||
GType foo_old_shader_effect_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (FooOldShaderEffect,
|
||||
foo_old_shader_effect,
|
||||
CLUTTER_TYPE_SHADER_EFFECT);
|
||||
|
||||
static void
|
||||
foo_old_shader_effect_paint_target (ClutterOffscreenEffect *effect)
|
||||
{
|
||||
clutter_shader_effect_set_shader_source (CLUTTER_SHADER_EFFECT (effect),
|
||||
old_shader_effect_source);
|
||||
clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect),
|
||||
"override_color",
|
||||
G_TYPE_FLOAT, 3,
|
||||
1.0f, 0.0f, 0.0f);
|
||||
|
||||
CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_old_shader_effect_parent_class)->
|
||||
paint_target (effect);
|
||||
}
|
||||
|
||||
static void
|
||||
foo_old_shader_effect_class_init (FooOldShaderEffectClass *klass)
|
||||
{
|
||||
ClutterOffscreenEffectClass *offscreen_effect_class =
|
||||
CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
|
||||
offscreen_effect_class->paint_target = foo_old_shader_effect_paint_target;
|
||||
}
|
||||
|
||||
static void
|
||||
foo_old_shader_effect_init (FooOldShaderEffect *self)
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
New style shader effect
|
||||
This overrides get_static_shader_source()
|
||||
****************************************************************/
|
||||
|
||||
static const gchar
|
||||
new_shader_effect_source[] =
|
||||
"uniform vec3 override_color;\n"
|
||||
"\n"
|
||||
"void\n"
|
||||
"main ()\n"
|
||||
"{\n"
|
||||
" cogl_color_out = (vec4 (override_color, 1.0) +\n"
|
||||
" vec4 (0.0, 0.0, 1.0, 0.0));\n"
|
||||
"}";
|
||||
|
||||
typedef struct _FooNewShaderEffectClass
|
||||
{
|
||||
ClutterShaderEffectClass parent_class;
|
||||
} FooNewShaderEffectClass;
|
||||
|
||||
typedef struct _FooNewShaderEffect
|
||||
{
|
||||
ClutterShaderEffect parent;
|
||||
} FooNewShaderEffect;
|
||||
|
||||
GType foo_new_shader_effect_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (FooNewShaderEffect,
|
||||
foo_new_shader_effect,
|
||||
CLUTTER_TYPE_SHADER_EFFECT);
|
||||
|
||||
static gchar *
|
||||
foo_new_shader_effect_get_static_source (ClutterShaderEffect *effect)
|
||||
{
|
||||
static gboolean already_called = FALSE;
|
||||
|
||||
/* This should only be called once even though we have two actors
|
||||
using this effect */
|
||||
g_assert (!already_called);
|
||||
|
||||
already_called = TRUE;
|
||||
|
||||
return g_strdup (new_shader_effect_source);
|
||||
}
|
||||
|
||||
static void
|
||||
foo_new_shader_effect_paint_target (ClutterOffscreenEffect *effect)
|
||||
{
|
||||
clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect),
|
||||
"override_color",
|
||||
G_TYPE_FLOAT, 3,
|
||||
0.0f, 1.0f, 0.0f);
|
||||
|
||||
CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_new_shader_effect_parent_class)->
|
||||
paint_target (effect);
|
||||
}
|
||||
|
||||
static void
|
||||
foo_new_shader_effect_class_init (FooNewShaderEffectClass *klass)
|
||||
{
|
||||
ClutterOffscreenEffectClass *offscreen_effect_class =
|
||||
CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
ClutterShaderEffectClass *shader_effect_class =
|
||||
CLUTTER_SHADER_EFFECT_CLASS (klass);
|
||||
|
||||
offscreen_effect_class->paint_target = foo_new_shader_effect_paint_target;
|
||||
|
||||
shader_effect_class->get_static_shader_source =
|
||||
foo_new_shader_effect_get_static_source;
|
||||
}
|
||||
|
||||
static void
|
||||
foo_new_shader_effect_init (FooNewShaderEffect *self)
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Another new style shader effect
|
||||
This is the same but with a different shader. This is just
|
||||
sanity check that each class gets its own copy of the private
|
||||
data
|
||||
****************************************************************/
|
||||
|
||||
static const gchar
|
||||
another_new_shader_effect_source[] =
|
||||
"\n"
|
||||
"void\n"
|
||||
"main ()\n"
|
||||
"{\n"
|
||||
" cogl_color_out = vec4 (1.0, 0.0, 1.0, 1.0);\n"
|
||||
"}";
|
||||
|
||||
typedef struct _FooAnotherNewShaderEffectClass
|
||||
{
|
||||
ClutterShaderEffectClass parent_class;
|
||||
} FooAnotherNewShaderEffectClass;
|
||||
|
||||
typedef struct _FooAnotherNewShaderEffect
|
||||
{
|
||||
ClutterShaderEffect parent;
|
||||
} FooAnotherNewShaderEffect;
|
||||
|
||||
GType foo_another_new_shader_effect_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (FooAnotherNewShaderEffect,
|
||||
foo_another_new_shader_effect,
|
||||
CLUTTER_TYPE_SHADER_EFFECT);
|
||||
|
||||
static gchar *
|
||||
foo_another_new_shader_effect_get_static_source (ClutterShaderEffect *effect)
|
||||
{
|
||||
return g_strdup (another_new_shader_effect_source);
|
||||
}
|
||||
|
||||
static void
|
||||
foo_another_new_shader_effect_class_init (FooAnotherNewShaderEffectClass *klass)
|
||||
{
|
||||
ClutterShaderEffectClass *shader_effect_class =
|
||||
CLUTTER_SHADER_EFFECT_CLASS (klass);
|
||||
|
||||
shader_effect_class->get_static_shader_source =
|
||||
foo_another_new_shader_effect_get_static_source;
|
||||
}
|
||||
|
||||
static void
|
||||
foo_another_new_shader_effect_init (FooAnotherNewShaderEffect *self)
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
static ClutterActor *
|
||||
make_actor (GType shader_type)
|
||||
{
|
||||
ClutterActor *rect;
|
||||
const ClutterColor white = { 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
rect = clutter_rectangle_new ();
|
||||
clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &white);
|
||||
clutter_actor_set_size (rect, 50, 50);
|
||||
|
||||
clutter_actor_add_effect (rect, g_object_new (shader_type, NULL));
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_pixel (CoglFramebuffer *fb,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
guint8 data[4];
|
||||
|
||||
cogl_framebuffer_read_pixels (fb,
|
||||
x, y, 1, 1,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||
data);
|
||||
|
||||
return (((guint32) data[0] << 16) |
|
||||
((guint32) data[1] << 8) |
|
||||
data[2]);
|
||||
}
|
||||
|
||||
static void
|
||||
view_painted_cb (ClutterStage *stage,
|
||||
ClutterStageView *view,
|
||||
gpointer data)
|
||||
{
|
||||
CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view);
|
||||
gboolean *was_painted = data;
|
||||
|
||||
/* old shader effect */
|
||||
g_assert_cmpint (get_pixel (fb, 0, 25), ==, 0xff0000);
|
||||
/* new shader effect */
|
||||
g_assert_cmpint (get_pixel (fb, 100, 25), ==, 0x00ffff);
|
||||
/* another new shader effect */
|
||||
g_assert_cmpint (get_pixel (fb, 200, 25), ==, 0xff00ff);
|
||||
/* new shader effect */
|
||||
g_assert_cmpint (get_pixel (fb, 300, 25), ==, 0x00ffff);
|
||||
|
||||
*was_painted = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
actor_shader_effect (void)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *rect;
|
||||
gboolean was_painted;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
return;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
|
||||
rect = make_actor (foo_old_shader_effect_get_type ());
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
|
||||
|
||||
rect = make_actor (foo_new_shader_effect_get_type ());
|
||||
clutter_actor_set_x (rect, 100);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
|
||||
|
||||
rect = make_actor (foo_another_new_shader_effect_get_type ());
|
||||
clutter_actor_set_x (rect, 200);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
|
||||
|
||||
rect = make_actor (foo_new_shader_effect_get_type ());
|
||||
clutter_actor_set_x (rect, 300);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
was_painted = FALSE;
|
||||
g_signal_connect_after (stage, "paint-view",
|
||||
G_CALLBACK (view_painted_cb),
|
||||
&was_painted);
|
||||
|
||||
while (!was_painted)
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/shader-effect", actor_shader_effect)
|
||||
)
|
216
src/tests/clutter/conform/actor-size.c
Normal file
216
src/tests/clutter/conform/actor-size.c
Normal file
@ -0,0 +1,216 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define TEST_TYPE_ACTOR (test_actor_get_type ())
|
||||
|
||||
typedef struct _TestActor TestActor;
|
||||
typedef struct _ClutterActorClass TestActorClass;
|
||||
|
||||
struct _TestActor
|
||||
{
|
||||
ClutterActor parent_instance;
|
||||
|
||||
guint preferred_width_called : 1;
|
||||
guint preferred_height_called : 1;
|
||||
};
|
||||
|
||||
GType test_actor_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (TestActor, test_actor, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
static void
|
||||
test_actor_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *nat_width_p)
|
||||
{
|
||||
TestActor *test = (TestActor *) self;
|
||||
|
||||
test->preferred_width_called = TRUE;
|
||||
|
||||
if (for_height == 10)
|
||||
{
|
||||
*min_width_p = 10;
|
||||
*nat_width_p = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
*min_width_p = 100;
|
||||
*nat_width_p = 100;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_actor_get_preferred_height (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *nat_height_p)
|
||||
{
|
||||
TestActor *test = (TestActor *) self;
|
||||
|
||||
test->preferred_height_called = TRUE;
|
||||
|
||||
if (for_width == 10)
|
||||
{
|
||||
*min_height_p = 50;
|
||||
*nat_height_p = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
*min_height_p = 100;
|
||||
*nat_height_p = 100;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_actor_class_init (TestActorClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
actor_class->get_preferred_width = test_actor_get_preferred_width;
|
||||
actor_class->get_preferred_height = test_actor_get_preferred_height;
|
||||
}
|
||||
|
||||
static void
|
||||
test_actor_init (TestActor *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
actor_preferred_size (void)
|
||||
{
|
||||
ClutterActor *test;
|
||||
TestActor *self;
|
||||
gfloat min_width, min_height;
|
||||
gfloat nat_width, nat_height;
|
||||
|
||||
test = g_object_new (TEST_TYPE_ACTOR, NULL);
|
||||
self = (TestActor *) test;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Preferred size\n");
|
||||
|
||||
clutter_actor_get_preferred_size (test,
|
||||
&min_width, &min_height,
|
||||
&nat_width, &nat_height);
|
||||
|
||||
g_assert (self->preferred_width_called);
|
||||
g_assert (self->preferred_height_called);
|
||||
g_assert_cmpfloat (min_width, ==, 100);
|
||||
g_assert_cmpfloat (min_height, ==, 100);
|
||||
g_assert_cmpfloat (nat_width, ==, min_width);
|
||||
g_assert_cmpfloat (nat_height, ==, min_height);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Preferred width\n");
|
||||
self->preferred_width_called = FALSE;
|
||||
clutter_actor_get_preferred_width (test, 10, &min_width, &nat_width);
|
||||
g_assert (self->preferred_width_called);
|
||||
g_assert_cmpfloat (min_width, ==, 10);
|
||||
g_assert_cmpfloat (nat_width, ==, 100);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Preferred height\n");
|
||||
self->preferred_height_called = FALSE;
|
||||
clutter_actor_get_preferred_height (test, 200, &min_height, &nat_height);
|
||||
g_assert (self->preferred_height_called);
|
||||
g_assert_cmpfloat (min_height, !=, 10);
|
||||
g_assert_cmpfloat (nat_height, ==, 100);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Preferred width (cached)\n");
|
||||
self->preferred_width_called = FALSE;
|
||||
clutter_actor_get_preferred_width (test, 10, &min_width, &nat_width);
|
||||
g_assert (!self->preferred_width_called);
|
||||
g_assert_cmpfloat (min_width, ==, 10);
|
||||
g_assert_cmpfloat (nat_width, ==, 100);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Preferred height (cache eviction)\n");
|
||||
self->preferred_height_called = FALSE;
|
||||
clutter_actor_get_preferred_height (test, 10, &min_height, &nat_height);
|
||||
g_assert (self->preferred_height_called);
|
||||
g_assert_cmpfloat (min_height, ==, 50);
|
||||
g_assert_cmpfloat (nat_height, ==, 100);
|
||||
|
||||
clutter_actor_destroy (test);
|
||||
}
|
||||
|
||||
static void
|
||||
actor_fixed_size (void)
|
||||
{
|
||||
ClutterActor *rect;
|
||||
gboolean min_width_set, nat_width_set;
|
||||
gboolean min_height_set, nat_height_set;
|
||||
gfloat min_width, min_height;
|
||||
gfloat nat_width, nat_height;
|
||||
|
||||
rect = clutter_actor_new ();
|
||||
g_object_ref_sink (rect);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Initial size is 0\n");
|
||||
|
||||
g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 0);
|
||||
g_assert_cmpfloat (clutter_actor_get_height (rect), ==, 0);
|
||||
|
||||
clutter_actor_set_size (rect, 100, 100);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Explicit size set\n");
|
||||
|
||||
g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 100);
|
||||
g_assert_cmpfloat (clutter_actor_get_height (rect), ==, 100);
|
||||
|
||||
g_object_get (G_OBJECT (rect),
|
||||
"min-width-set", &min_width_set,
|
||||
"min-height-set", &min_height_set,
|
||||
"natural-width-set", &nat_width_set,
|
||||
"natural-height-set", &nat_height_set,
|
||||
NULL);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Notification properties\n");
|
||||
|
||||
g_assert (min_width_set && nat_width_set);
|
||||
g_assert (min_height_set && nat_height_set);
|
||||
|
||||
clutter_actor_get_preferred_size (rect,
|
||||
&min_width, &min_height,
|
||||
&nat_width, &nat_height);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Preferred size\n");
|
||||
|
||||
g_assert_cmpfloat (min_width, ==, 100);
|
||||
g_assert_cmpfloat (min_height, ==, 100);
|
||||
g_assert_cmpfloat (min_width, ==, nat_width);
|
||||
g_assert_cmpfloat (min_height, ==, nat_height);
|
||||
|
||||
clutter_actor_set_size (rect, -1, -1);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Explicit size unset\n");
|
||||
|
||||
g_object_get (G_OBJECT (rect),
|
||||
"min-width-set", &min_width_set,
|
||||
"min-height-set", &min_height_set,
|
||||
"natural-width-set", &nat_width_set,
|
||||
"natural-height-set", &nat_height_set,
|
||||
NULL);
|
||||
g_assert (!min_width_set && !nat_width_set);
|
||||
g_assert (!min_height_set && !nat_height_set);
|
||||
|
||||
g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 0);
|
||||
g_assert_cmpfloat (clutter_actor_get_height (rect), ==, 0);
|
||||
|
||||
clutter_actor_destroy (rect);
|
||||
g_object_unref (rect);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/actor/size/preferred", actor_preferred_size)
|
||||
CLUTTER_TEST_UNIT ("/actor/size/fixed", actor_fixed_size)
|
||||
)
|
80
src/tests/clutter/conform/behaviours.c
Normal file
80
src/tests/clutter/conform/behaviours.c
Normal file
@ -0,0 +1,80 @@
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
behaviour_opacity (void)
|
||||
{
|
||||
ClutterBehaviour *behaviour;
|
||||
ClutterTimeline *timeline;
|
||||
ClutterAlpha *alpha;
|
||||
guint8 start, end;
|
||||
guint starti;
|
||||
|
||||
timeline = clutter_timeline_new (500);
|
||||
alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR);
|
||||
behaviour = clutter_behaviour_opacity_new (alpha, 0, 255);
|
||||
g_assert (CLUTTER_IS_BEHAVIOUR_OPACITY (behaviour));
|
||||
g_object_add_weak_pointer (G_OBJECT (behaviour), (gpointer *) &behaviour);
|
||||
g_object_add_weak_pointer (G_OBJECT (timeline), (gpointer *) &timeline);
|
||||
|
||||
clutter_behaviour_opacity_get_bounds (CLUTTER_BEHAVIOUR_OPACITY (behaviour),
|
||||
&start,
|
||||
&end);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("BehaviourOpacity:bounds = %d, %d (expected: 0, 255)\n",
|
||||
start,
|
||||
end);
|
||||
|
||||
g_assert_cmpint (start, ==, 0);
|
||||
g_assert_cmpint (end, ==, 255);
|
||||
|
||||
clutter_behaviour_opacity_set_bounds (CLUTTER_BEHAVIOUR_OPACITY (behaviour),
|
||||
255,
|
||||
0);
|
||||
/* XXX: The gobject property is actually a unsigned int not unsigned char
|
||||
* property so we have to be careful not to corrupt the stack by passing
|
||||
* a guint8 pointer here... */
|
||||
starti = 0;
|
||||
g_object_get (G_OBJECT (behaviour), "opacity-start", &starti, NULL);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("BehaviourOpacity:start = %d (expected: 255)\n", start);
|
||||
|
||||
g_assert_cmpint (starti, ==, 255);
|
||||
|
||||
g_object_unref (behaviour);
|
||||
g_object_unref (timeline);
|
||||
|
||||
g_assert_null (behaviour);
|
||||
g_assert_null (timeline);
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
const gchar *path;
|
||||
GTestFunc func;
|
||||
} behaviour_tests[] = {
|
||||
{ "opacity", behaviour_opacity },
|
||||
};
|
||||
|
||||
static const int n_behaviour_tests = G_N_ELEMENTS (behaviour_tests);
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
clutter_test_init (&argc, &argv);
|
||||
|
||||
for (i = 0; i < n_behaviour_tests; i++)
|
||||
{
|
||||
char *path = g_strconcat ("/behaviours/", behaviour_tests[i].path, NULL);
|
||||
|
||||
clutter_test_add (path, behaviour_tests[i].func);
|
||||
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
return clutter_test_run ();
|
||||
}
|
297
src/tests/clutter/conform/binding-pool.c
Normal file
297
src/tests/clutter/conform/binding-pool.c
Normal file
@ -0,0 +1,297 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define TYPE_KEY_GROUP (key_group_get_type ())
|
||||
#define KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_KEY_GROUP, KeyGroup))
|
||||
#define IS_KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_KEY_GROUP))
|
||||
#define KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_KEY_GROUP, KeyGroupClass))
|
||||
#define IS_KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_KEY_GROUP))
|
||||
|
||||
typedef struct _KeyGroup KeyGroup;
|
||||
typedef struct _KeyGroupClass KeyGroupClass;
|
||||
|
||||
struct _KeyGroup
|
||||
{
|
||||
ClutterActor parent_instance;
|
||||
|
||||
gint selected_index;
|
||||
};
|
||||
|
||||
struct _KeyGroupClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
void (* activate) (KeyGroup *group,
|
||||
ClutterActor *child);
|
||||
};
|
||||
|
||||
GType key_group_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (KeyGroup, key_group, CLUTTER_TYPE_ACTOR)
|
||||
|
||||
enum
|
||||
{
|
||||
ACTIVATE,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint group_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
static gboolean
|
||||
key_group_action_move_left (KeyGroup *self,
|
||||
const gchar *action_name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
gint n_children;
|
||||
|
||||
g_assert_cmpstr (action_name, ==, "move-left");
|
||||
g_assert_cmpint (key_val, ==, CLUTTER_KEY_Left);
|
||||
|
||||
n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self));
|
||||
|
||||
self->selected_index -= 1;
|
||||
|
||||
if (self->selected_index < 0)
|
||||
self->selected_index = n_children - 1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
key_group_action_move_right (KeyGroup *self,
|
||||
const gchar *action_name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
gint n_children;
|
||||
|
||||
g_assert_cmpstr (action_name, ==, "move-right");
|
||||
g_assert_cmpint (key_val, ==, CLUTTER_KEY_Right);
|
||||
|
||||
n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self));
|
||||
|
||||
self->selected_index += 1;
|
||||
|
||||
if (self->selected_index >= n_children)
|
||||
self->selected_index = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
key_group_action_activate (KeyGroup *self,
|
||||
const gchar *action_name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
ClutterActor *child = NULL;
|
||||
|
||||
g_assert_cmpstr (action_name, ==, "activate");
|
||||
g_assert (key_val == CLUTTER_KEY_Return ||
|
||||
key_val == CLUTTER_KEY_KP_Enter ||
|
||||
key_val == CLUTTER_KEY_ISO_Enter);
|
||||
|
||||
if (self->selected_index == -1)
|
||||
return FALSE;
|
||||
|
||||
child = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), self->selected_index);
|
||||
if (child != NULL)
|
||||
{
|
||||
g_signal_emit (self, group_signals[ACTIVATE], 0, child);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
key_group_key_press (ClutterActor *actor,
|
||||
ClutterKeyEvent *event)
|
||||
{
|
||||
ClutterBindingPool *pool;
|
||||
gboolean res;
|
||||
|
||||
pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (actor));
|
||||
g_assert (pool != NULL);
|
||||
|
||||
res = clutter_binding_pool_activate (pool,
|
||||
event->keyval,
|
||||
event->modifier_state,
|
||||
G_OBJECT (actor));
|
||||
|
||||
/* if we activate a key binding, redraw the actor */
|
||||
if (res)
|
||||
clutter_actor_queue_redraw (actor);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
key_group_paint (ClutterActor *actor)
|
||||
{
|
||||
KeyGroup *self = KEY_GROUP (actor);
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
gint i = 0;
|
||||
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
/* paint the selection rectangle */
|
||||
if (i == self->selected_index)
|
||||
{
|
||||
ClutterActorBox box = { 0, };
|
||||
|
||||
clutter_actor_get_allocation_box (child, &box);
|
||||
|
||||
box.x1 -= 2;
|
||||
box.y1 -= 2;
|
||||
box.x2 += 2;
|
||||
box.y2 += 2;
|
||||
|
||||
cogl_set_source_color4ub (255, 255, 0, 224);
|
||||
cogl_rectangle (box.x1, box.y1, box.x2, box.y2);
|
||||
}
|
||||
|
||||
clutter_actor_paint (child);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
key_group_class_init (KeyGroupClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
ClutterBindingPool *binding_pool;
|
||||
|
||||
actor_class->paint = key_group_paint;
|
||||
actor_class->key_press_event = key_group_key_press;
|
||||
|
||||
group_signals[ACTIVATE] =
|
||||
g_signal_new (g_intern_static_string ("activate"),
|
||||
G_OBJECT_CLASS_TYPE (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (KeyGroupClass, activate),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
CLUTTER_TYPE_ACTOR);
|
||||
|
||||
binding_pool = clutter_binding_pool_get_for_class (klass);
|
||||
|
||||
clutter_binding_pool_install_action (binding_pool, "move-right",
|
||||
CLUTTER_KEY_Right, 0,
|
||||
G_CALLBACK (key_group_action_move_right),
|
||||
NULL, NULL);
|
||||
clutter_binding_pool_install_action (binding_pool, "move-left",
|
||||
CLUTTER_KEY_Left, 0,
|
||||
G_CALLBACK (key_group_action_move_left),
|
||||
NULL, NULL);
|
||||
clutter_binding_pool_install_action (binding_pool, "activate",
|
||||
CLUTTER_KEY_Return, 0,
|
||||
G_CALLBACK (key_group_action_activate),
|
||||
NULL, NULL);
|
||||
clutter_binding_pool_install_action (binding_pool, "activate",
|
||||
CLUTTER_KEY_KP_Enter, 0,
|
||||
G_CALLBACK (key_group_action_activate),
|
||||
NULL, NULL);
|
||||
clutter_binding_pool_install_action (binding_pool, "activate",
|
||||
CLUTTER_KEY_ISO_Enter, 0,
|
||||
G_CALLBACK (key_group_action_activate),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
key_group_init (KeyGroup *self)
|
||||
{
|
||||
self->selected_index = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
init_event (ClutterKeyEvent *event)
|
||||
{
|
||||
event->type = CLUTTER_KEY_PRESS;
|
||||
event->time = 0; /* not needed */
|
||||
event->flags = CLUTTER_EVENT_FLAG_SYNTHETIC;
|
||||
event->stage = NULL; /* not needed */
|
||||
event->source = NULL; /* not needed */
|
||||
event->modifier_state = 0;
|
||||
event->hardware_keycode = 0; /* not needed */
|
||||
}
|
||||
|
||||
static void
|
||||
send_keyval (KeyGroup *group, int keyval)
|
||||
{
|
||||
ClutterKeyEvent event;
|
||||
|
||||
init_event (&event);
|
||||
event.keyval = keyval;
|
||||
event.unicode_value = 0; /* should be ignored for cursor keys etc. */
|
||||
|
||||
clutter_actor_event (CLUTTER_ACTOR (group), (ClutterEvent *) &event, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_activate (KeyGroup *key_group,
|
||||
ClutterActor *child,
|
||||
gpointer data)
|
||||
{
|
||||
gint _index = GPOINTER_TO_INT (data);
|
||||
|
||||
g_assert_cmpint (key_group->selected_index, ==, _index);
|
||||
}
|
||||
|
||||
static void
|
||||
binding_pool (void)
|
||||
{
|
||||
KeyGroup *key_group = g_object_new (TYPE_KEY_GROUP, NULL);
|
||||
g_object_ref_sink (key_group);
|
||||
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (key_group),
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"width", 50.0,
|
||||
"height", 50.0,
|
||||
"x", 0.0, "y", 0.0,
|
||||
NULL));
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (key_group),
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"width", 50.0,
|
||||
"height", 50.0,
|
||||
"x", 75.0, "y", 0.0,
|
||||
NULL));
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (key_group),
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"width", 50.0,
|
||||
"height", 50.0,
|
||||
"x", 150.0, "y", 0.0,
|
||||
NULL));
|
||||
|
||||
g_assert_cmpint (key_group->selected_index, ==, -1);
|
||||
|
||||
send_keyval (key_group, CLUTTER_KEY_Left);
|
||||
g_assert_cmpint (key_group->selected_index, ==, 2);
|
||||
|
||||
send_keyval (key_group, CLUTTER_KEY_Left);
|
||||
g_assert_cmpint (key_group->selected_index, ==, 1);
|
||||
|
||||
send_keyval (key_group, CLUTTER_KEY_Right);
|
||||
g_assert_cmpint (key_group->selected_index, ==, 2);
|
||||
|
||||
send_keyval (key_group, CLUTTER_KEY_Right);
|
||||
g_assert_cmpint (key_group->selected_index, ==, 0);
|
||||
|
||||
g_signal_connect (key_group,
|
||||
"activate", G_CALLBACK (on_activate),
|
||||
GINT_TO_POINTER (0));
|
||||
|
||||
send_keyval (key_group, CLUTTER_KEY_Return);
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (key_group));
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/binding-pool", binding_pool)
|
||||
)
|
198
src/tests/clutter/conform/cairo-texture.c
Normal file
198
src/tests/clutter/conform/cairo-texture.c
Normal file
@ -0,0 +1,198 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "test-conform-common.h"
|
||||
|
||||
#define BLOCK_SIZE 16
|
||||
|
||||
/* Number of pixels at the border of a block to skip when verifying */
|
||||
#define TEST_INSET 1
|
||||
|
||||
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* The first frame is drawn using clutter_cairo_texture_create. The
|
||||
second frame is an update of the first frame using
|
||||
clutter_cairo_texture_create_region. The states are stored like
|
||||
this because the cairo drawing is done on idle and the validation
|
||||
is done during paint and we need to synchronize the two */
|
||||
TEST_BEFORE_DRAW_FIRST_FRAME,
|
||||
TEST_BEFORE_VALIDATE_FIRST_FRAME,
|
||||
TEST_BEFORE_DRAW_SECOND_FRAME,
|
||||
TEST_BEFORE_VALIDATE_SECOND_FRAME,
|
||||
TEST_DONE
|
||||
} TestProgress;
|
||||
|
||||
typedef struct _TestState
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *ct;
|
||||
guint frame;
|
||||
TestProgress progress;
|
||||
} TestState;
|
||||
|
||||
static void
|
||||
validate_part (int block_x, int block_y, const ClutterColor *color)
|
||||
{
|
||||
guint8 data[BLOCK_SIZE * BLOCK_SIZE * 4];
|
||||
int x, y;
|
||||
|
||||
cogl_read_pixels (block_x * BLOCK_SIZE,
|
||||
block_y * BLOCK_SIZE,
|
||||
BLOCK_SIZE, BLOCK_SIZE,
|
||||
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||
data);
|
||||
|
||||
for (x = 0; x < BLOCK_SIZE - TEST_INSET * 2; x++)
|
||||
for (y = 0; y < BLOCK_SIZE - TEST_INSET * 2; y++)
|
||||
{
|
||||
const guint8 *p = data + ((x + TEST_INSET) * 4 +
|
||||
(y + TEST_INSET) * BLOCK_SIZE * 4);
|
||||
|
||||
g_assert_cmpint (p[0], ==, color->red);
|
||||
g_assert_cmpint (p[1], ==, color->green);
|
||||
g_assert_cmpint (p[2], ==, color->blue);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
paint_cb (ClutterActor *actor, TestState *state)
|
||||
{
|
||||
static const ClutterColor red = { 0xff, 0x00, 0x00, 0xff };
|
||||
static const ClutterColor green = { 0x00, 0xff, 0x00, 0xff };
|
||||
static const ClutterColor blue = { 0x00, 0x00, 0xff, 0xff };
|
||||
|
||||
if (state->frame++ < 2)
|
||||
return;
|
||||
|
||||
switch (state->progress)
|
||||
{
|
||||
case TEST_BEFORE_DRAW_FIRST_FRAME:
|
||||
case TEST_BEFORE_DRAW_SECOND_FRAME:
|
||||
case TEST_DONE:
|
||||
/* Handled by the idle callback */
|
||||
break;
|
||||
|
||||
case TEST_BEFORE_VALIDATE_FIRST_FRAME:
|
||||
/* In the first frame there is a red rectangle next to a green
|
||||
rectangle */
|
||||
validate_part (0, 0, &red);
|
||||
validate_part (1, 0, &green);
|
||||
|
||||
state->progress = TEST_BEFORE_DRAW_SECOND_FRAME;
|
||||
break;
|
||||
|
||||
case TEST_BEFORE_VALIDATE_SECOND_FRAME:
|
||||
/* The second frame is the same except the green rectangle is
|
||||
replaced with a blue one */
|
||||
validate_part (0, 0, &red);
|
||||
validate_part (1, 0, &blue);
|
||||
|
||||
state->progress = TEST_DONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_cb (gpointer data)
|
||||
{
|
||||
TestState *state = data;
|
||||
cairo_t *cr;
|
||||
|
||||
if (state->frame < 2)
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (state->stage));
|
||||
else
|
||||
switch (state->progress)
|
||||
{
|
||||
case TEST_BEFORE_DRAW_FIRST_FRAME:
|
||||
/* Draw two different colour rectangles */
|
||||
cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (state->ct));
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_rectangle (cr, 0, 0, BLOCK_SIZE, BLOCK_SIZE);
|
||||
cairo_clip (cr);
|
||||
cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
|
||||
cairo_paint (cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
cairo_rectangle (cr, BLOCK_SIZE, 0, BLOCK_SIZE, BLOCK_SIZE);
|
||||
cairo_clip (cr);
|
||||
cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
state->progress = TEST_BEFORE_VALIDATE_FIRST_FRAME;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_BEFORE_DRAW_SECOND_FRAME:
|
||||
/* Replace the second rectangle with a blue one */
|
||||
cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (state->ct));
|
||||
|
||||
cairo_rectangle (cr, BLOCK_SIZE, 0, BLOCK_SIZE, BLOCK_SIZE);
|
||||
cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
state->progress = TEST_BEFORE_VALIDATE_SECOND_FRAME;
|
||||
|
||||
break;
|
||||
|
||||
case TEST_BEFORE_VALIDATE_FIRST_FRAME:
|
||||
case TEST_BEFORE_VALIDATE_SECOND_FRAME:
|
||||
/* Handled by the paint callback */
|
||||
break;
|
||||
|
||||
case TEST_DONE:
|
||||
clutter_main_quit ();
|
||||
break;
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
void
|
||||
texture_cairo (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
TestState state;
|
||||
unsigned int idle_source;
|
||||
unsigned int paint_handler;
|
||||
|
||||
state.frame = 0;
|
||||
state.stage = clutter_stage_new ();
|
||||
state.progress = TEST_BEFORE_DRAW_FIRST_FRAME;
|
||||
|
||||
state.ct = clutter_cairo_texture_new (BLOCK_SIZE * 2, BLOCK_SIZE);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (state.stage), state.ct);
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (state.stage), &stage_color);
|
||||
|
||||
/* We force continuous redrawing of the stage, since we need to skip
|
||||
* the first few frames, and we wont be doing anything else that
|
||||
* will trigger redrawing. */
|
||||
idle_source = clutter_threads_add_idle (idle_cb, &state);
|
||||
paint_handler = g_signal_connect_after (state.stage, "paint",
|
||||
G_CALLBACK (paint_cb), &state);
|
||||
|
||||
clutter_actor_show (state.stage);
|
||||
clutter_main ();
|
||||
|
||||
g_signal_handler_disconnect (state.stage, paint_handler);
|
||||
g_source_remove (idle_source);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("OK\n");
|
||||
|
||||
clutter_actor_destroy (state.stage);
|
||||
}
|
||||
|
338
src/tests/clutter/conform/cally-text.c
Normal file
338
src/tests/clutter/conform/cally-text.c
Normal file
@ -0,0 +1,338 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "test-conform-common.h"
|
||||
|
||||
#define TEST_FONT "Sans 10"
|
||||
|
||||
typedef struct _CallbackData CallbackData;
|
||||
|
||||
struct _CallbackData
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *label;
|
||||
gint offset;
|
||||
gboolean test_failed;
|
||||
|
||||
gint extents_x;
|
||||
gint extents_y;
|
||||
gint extents_width;
|
||||
gint extents_height;
|
||||
GSList *run_attributes;
|
||||
GSList *default_attributes;
|
||||
CallbackData *next;
|
||||
};
|
||||
|
||||
|
||||
static gint
|
||||
attribute_lookup_func (gconstpointer data,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
AtkAttribute *lookup_attr = (AtkAttribute*) user_data;
|
||||
AtkAttribute *at = (AtkAttribute *) data;
|
||||
if (!data)
|
||||
return -1;
|
||||
if (!g_strcmp0 (at->name, lookup_attr->name))
|
||||
return g_strcmp0 (at->value, lookup_attr->value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check l1 is a sub-set of l2 */
|
||||
static gboolean
|
||||
compare_lists (GSList* l1, GSList* l2)
|
||||
{
|
||||
gboolean fail = FALSE;
|
||||
|
||||
if (l2 && !l1)
|
||||
return TRUE;
|
||||
|
||||
while (l1)
|
||||
{
|
||||
AtkAttribute *at = (AtkAttribute *) l1->data;
|
||||
GSList* result = g_slist_find_custom ((GSList*) l2,
|
||||
(gconstpointer) at,
|
||||
attribute_lookup_func);
|
||||
if (!result)
|
||||
{
|
||||
fail = TRUE;
|
||||
break;
|
||||
}
|
||||
l1 = g_slist_next (l1);
|
||||
}
|
||||
|
||||
return fail;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_attribute_set (AtkAttributeSet *at_set)
|
||||
{
|
||||
GSList *attrs = (GSList*) at_set;
|
||||
|
||||
while (attrs) {
|
||||
AtkAttribute *at = (AtkAttribute *) attrs->data;
|
||||
g_print ("text attribute %s = %s\n", at->name, at->value);
|
||||
attrs = g_slist_next (attrs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_result (CallbackData *data)
|
||||
{
|
||||
gboolean fail = FALSE;
|
||||
gchar *text = NULL;
|
||||
const gchar *expected_text = NULL;
|
||||
AtkObject *object = NULL;
|
||||
AtkText *cally_text = NULL;
|
||||
gunichar unichar;
|
||||
gunichar expected_char;
|
||||
gint x, y, width, height;
|
||||
gint pos;
|
||||
AtkAttributeSet *at_set = NULL;
|
||||
GSList *attrs;
|
||||
gint start = -1;
|
||||
gint end = -1;
|
||||
|
||||
object = atk_gobject_accessible_for_object (G_OBJECT (data->label));
|
||||
cally_text = ATK_TEXT (object);
|
||||
|
||||
if (!cally_text) {
|
||||
g_print("no text\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
text = atk_text_get_text (cally_text, 0, -1);
|
||||
expected_text = clutter_text_get_text (CLUTTER_TEXT (data->label));
|
||||
|
||||
if (g_strcmp0 (expected_text, text) != 0)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("text value differs %s vs %s\n", expected_text, text);
|
||||
fail = TRUE;
|
||||
}
|
||||
|
||||
unichar = atk_text_get_character_at_offset (cally_text, data->offset);
|
||||
expected_char = g_utf8_get_char (g_utf8_offset_to_pointer (text, data->offset));
|
||||
if (expected_char != unichar)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("text af offset differs\n");
|
||||
fail = TRUE;
|
||||
}
|
||||
|
||||
atk_text_get_character_extents (cally_text, data->offset, &x, &y, &width, &height,
|
||||
ATK_XY_WINDOW);
|
||||
if (x != data->extents_x)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("extents x position at index 0 differs (current value=%d)\n", x);
|
||||
fail = TRUE;
|
||||
}
|
||||
if (y != data->extents_y)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("extents y position at index 0 differs (current value=%d)\n", y);
|
||||
fail = TRUE;
|
||||
}
|
||||
if (width != data->extents_width)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("extents width at index 0 differs (current value=%d)\n", width);
|
||||
fail = TRUE;
|
||||
}
|
||||
if (height != data->extents_height)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("extents height at index 0 differs (current value=%d)\n", height);
|
||||
fail = TRUE;
|
||||
}
|
||||
|
||||
pos = atk_text_get_offset_at_point (cally_text, x, y, ATK_XY_WINDOW);
|
||||
if (pos != data->offset)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("offset at position (%d, %d) differs (current value=%d)\n", x,
|
||||
y, pos);
|
||||
fail = TRUE;
|
||||
}
|
||||
|
||||
at_set = atk_text_get_run_attributes (cally_text, 0,
|
||||
&start, &end);
|
||||
if (start != 0)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("run attributes start offset is not 0: %d\n", start);
|
||||
fail = TRUE;
|
||||
}
|
||||
if (end != g_utf8_strlen (text, -1))
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("run attributes end offset is not text length: %d\n", end);
|
||||
fail = TRUE;
|
||||
}
|
||||
|
||||
attrs = (GSList*) at_set;
|
||||
fail = compare_lists (attrs, data->run_attributes);
|
||||
if (fail && g_test_verbose ())
|
||||
{
|
||||
g_print ("run attributes mismatch\n");
|
||||
dump_attribute_set (attrs);
|
||||
}
|
||||
|
||||
at_set = atk_text_get_default_attributes (cally_text);
|
||||
attrs = (GSList*) at_set;
|
||||
fail = compare_lists (attrs, data->default_attributes);
|
||||
if (fail && g_test_verbose ())
|
||||
{
|
||||
g_print ("default attributes mismatch\n");
|
||||
dump_attribute_set (attrs);
|
||||
}
|
||||
|
||||
g_free (text);
|
||||
text = NULL;
|
||||
|
||||
if (fail)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("FAIL\n");
|
||||
data->test_failed = TRUE;
|
||||
}
|
||||
else if (g_test_verbose ())
|
||||
g_print ("pass\n");
|
||||
|
||||
return fail;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_tests (CallbackData *data)
|
||||
{
|
||||
while (data)
|
||||
{
|
||||
gboolean result = check_result (data);
|
||||
g_assert (result == FALSE);
|
||||
data = data->next;
|
||||
}
|
||||
|
||||
clutter_main_quit ();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GSList*
|
||||
build_attribute_set (const gchar* first_attribute, ...)
|
||||
{
|
||||
AtkAttributeSet *return_set = g_slist_alloc ();
|
||||
va_list args;
|
||||
const gchar *name;
|
||||
const gchar *value;
|
||||
gint i = 0;
|
||||
|
||||
value = first_attribute;
|
||||
va_start (args, first_attribute);
|
||||
|
||||
while (value)
|
||||
{
|
||||
if ((i> 0) && (i % 2 != 0))
|
||||
{
|
||||
AtkAttribute *at = g_malloc (sizeof (AtkAttribute));
|
||||
at->name = g_strdup (name);
|
||||
at->value = g_strdup (value);
|
||||
return_set = g_slist_prepend (return_set, at);
|
||||
}
|
||||
i++;
|
||||
name = g_strdup (value);
|
||||
value = va_arg (args, gchar*);
|
||||
}
|
||||
va_end (args);
|
||||
return return_set;
|
||||
}
|
||||
|
||||
void
|
||||
cally_text (void)
|
||||
{
|
||||
CallbackData data;
|
||||
CallbackData data1;
|
||||
GSList* default_attributes = build_attribute_set ("left-margin", "0",
|
||||
"right-margin", "0",
|
||||
"indent", "0",
|
||||
"invisible", "false",
|
||||
"editable", "false",
|
||||
"pixels-above-lines", "0",
|
||||
"pixels-below-lines", "0",
|
||||
"pixels-inside-wrap", "0",
|
||||
"bg-full-height", "0",
|
||||
"bg-stipple", "false",
|
||||
"fg-stipple", "false",
|
||||
"fg-color", "0,0,0",
|
||||
"wrap-mode", "word",
|
||||
"justification", "left",
|
||||
"size", "10",
|
||||
"weight", "400",
|
||||
"family-name", "Sans",
|
||||
"stretch", "normal",
|
||||
"variant", "normal",
|
||||
"style", "normal",
|
||||
"language", "en-us",
|
||||
"direction", "ltr",
|
||||
NULL);
|
||||
|
||||
memset (&data, 0, sizeof (data));
|
||||
|
||||
data.stage = clutter_stage_new ();
|
||||
|
||||
data.default_attributes = default_attributes;
|
||||
data.run_attributes = build_attribute_set ("fg-color", "0,0,0", NULL);
|
||||
|
||||
data.label = clutter_text_new_with_text (TEST_FONT, "Lorem ipsum dolor sit amet");
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (data.stage), data.label, NULL);
|
||||
data.offset = 6;
|
||||
data.extents_x = 64;
|
||||
data.extents_y = 99;
|
||||
data.extents_width = 3;
|
||||
data.extents_height = 17;
|
||||
clutter_actor_set_position (data.label, 20, 100);
|
||||
|
||||
memset (&data1, 0, sizeof (data1));
|
||||
data1.stage = data.stage;
|
||||
data1.default_attributes = default_attributes;
|
||||
data1.run_attributes = build_attribute_set ("bg-color", "0,65535,0",
|
||||
"fg-color", "65535,65535,0",
|
||||
"strikethrough", "true", NULL);
|
||||
|
||||
data1.label = clutter_text_new_with_text (TEST_FONT, "");
|
||||
clutter_text_set_markup (CLUTTER_TEXT(data1.label), "<span fgcolor=\"#FFFF00\" bgcolor=\"#00FF00\"><s>Lorem ipsum dolor sit amet</s></span>");
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (data1.stage), data1.label, NULL);
|
||||
data1.offset = 10;
|
||||
data1.extents_x = 90;
|
||||
data1.extents_y = 199;
|
||||
data1.extents_width = 13;
|
||||
data1.extents_height = 17;
|
||||
clutter_actor_set_position (data1.label, 20, 200);
|
||||
data.next = &data1;
|
||||
|
||||
clutter_actor_show (data.stage);
|
||||
clutter_threads_add_idle ((GSourceFunc) do_tests, &data);
|
||||
clutter_main ();
|
||||
|
||||
clutter_actor_destroy (data.stage);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("\nOverall result: ");
|
||||
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
if (data.test_failed)
|
||||
g_print ("FAIL\n");
|
||||
else
|
||||
g_print ("pass\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (data.test_failed != TRUE);
|
||||
g_assert (data1.test_failed != TRUE);
|
||||
}
|
||||
}
|
||||
|
319
src/tests/clutter/conform/color.c
Normal file
319
src/tests/clutter/conform/color.c
Normal file
@ -0,0 +1,319 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
color_hls_roundtrip (void)
|
||||
{
|
||||
ClutterColor color;
|
||||
gfloat hue, luminance, saturation;
|
||||
|
||||
/* test luminance only */
|
||||
clutter_color_from_string (&color, "#7f7f7f");
|
||||
g_assert_cmpuint (color.red, ==, 0x7f);
|
||||
g_assert_cmpuint (color.green, ==, 0x7f);
|
||||
g_assert_cmpuint (color.blue, ==, 0x7f);
|
||||
|
||||
clutter_color_to_hls (&color, &hue, &luminance, &saturation);
|
||||
g_assert_cmpfloat (hue, ==, 0.0);
|
||||
g_assert (luminance >= 0.0 && luminance <= 1.0);
|
||||
g_assert_cmpfloat (saturation, ==, 0.0);
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("RGB = { %x, %x, %x }, HLS = { %.2f, %.2f, %.2f }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
hue,
|
||||
luminance,
|
||||
saturation);
|
||||
}
|
||||
|
||||
color.red = color.green = color.blue = 0;
|
||||
clutter_color_from_hls (&color, hue, luminance, saturation);
|
||||
|
||||
g_assert_cmpuint (color.red, ==, 0x7f);
|
||||
g_assert_cmpuint (color.green, ==, 0x7f);
|
||||
g_assert_cmpuint (color.blue, ==, 0x7f);
|
||||
|
||||
/* full conversion */
|
||||
clutter_color_from_string (&color, "#7f8f7f");
|
||||
color.alpha = 255;
|
||||
|
||||
g_assert_cmpuint (color.red, ==, 0x7f);
|
||||
g_assert_cmpuint (color.green, ==, 0x8f);
|
||||
g_assert_cmpuint (color.blue, ==, 0x7f);
|
||||
|
||||
clutter_color_to_hls (&color, &hue, &luminance, &saturation);
|
||||
g_assert (hue >= 0.0 && hue < 360.0);
|
||||
g_assert (luminance >= 0.0 && luminance <= 1.0);
|
||||
g_assert (saturation >= 0.0 && saturation <= 1.0);
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("RGB = { %x, %x, %x }, HLS = { %.2f, %.2f, %.2f }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
hue,
|
||||
luminance,
|
||||
saturation);
|
||||
}
|
||||
|
||||
color.red = color.green = color.blue = 0;
|
||||
clutter_color_from_hls (&color, hue, luminance, saturation);
|
||||
|
||||
g_assert_cmpuint (color.red, ==, 0x7f);
|
||||
g_assert_cmpuint (color.green, ==, 0x8f);
|
||||
g_assert_cmpuint (color.blue, ==, 0x7f);
|
||||
|
||||
/* the alpha channel should be untouched */
|
||||
g_assert_cmpuint (color.alpha, ==, 255);
|
||||
}
|
||||
|
||||
static void
|
||||
color_from_string_invalid (void)
|
||||
{
|
||||
ClutterColor color;
|
||||
|
||||
g_assert (!clutter_color_from_string (&color, "ff0000ff"));
|
||||
g_assert (!clutter_color_from_string (&color, "#decaffbad"));
|
||||
g_assert (!clutter_color_from_string (&color, "ponies"));
|
||||
g_assert (!clutter_color_from_string (&color, "rgb(255, 0, 0, 0)"));
|
||||
g_assert (!clutter_color_from_string (&color, "rgba(1.0, 0, 0)"));
|
||||
g_assert (!clutter_color_from_string (&color, "hsl(100, 0, 0)"));
|
||||
g_assert (!clutter_color_from_string (&color, "hsla(10%, 0%, 50%)"));
|
||||
g_assert (!clutter_color_from_string (&color, "hsla(100%, 0%, 50%, 20%)"));
|
||||
g_assert (!clutter_color_from_string (&color, "hsla(0.5, 0.9, 0.2, 0.4)"));
|
||||
}
|
||||
|
||||
static void
|
||||
color_from_string_valid (void)
|
||||
{
|
||||
ClutterColor color;
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "#ff0000ff"));
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("color = { %x, %x, %x, %x }, expected = { 0xff, 0, 0, 0xff }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha);
|
||||
}
|
||||
g_assert_cmpuint (color.red, ==, 0xff);
|
||||
g_assert_cmpuint (color.green, ==, 0);
|
||||
g_assert_cmpuint (color.blue, ==, 0);
|
||||
g_assert_cmpuint (color.alpha, ==, 0xff);
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "#0f0f"));
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("color = { %x, %x, %x, %x }, expected = { 0, 0xff, 0, 0xff }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha);
|
||||
}
|
||||
g_assert_cmpuint (color.red, ==, 0);
|
||||
g_assert_cmpuint (color.green, ==, 0xff);
|
||||
g_assert_cmpuint (color.blue, ==, 0);
|
||||
g_assert_cmpuint (color.alpha, ==, 0xff);
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "#0000ff"));
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("color = { %x, %x, %x, %x }, expected = { 0, 0, 0xff, 0xff }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha);
|
||||
}
|
||||
g_assert_cmpuint (color.red, ==, 0);
|
||||
g_assert_cmpuint (color.green, ==, 0);
|
||||
g_assert_cmpuint (color.blue, ==, 0xff);
|
||||
g_assert_cmpuint (color.alpha, ==, 0xff);
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "#abc"));
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("color = { %x, %x, %x, %x }, expected = { 0xaa, 0xbb, 0xcc, 0xff }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha);
|
||||
}
|
||||
g_assert_cmpuint (color.red, ==, 0xaa);
|
||||
g_assert_cmpuint (color.green, ==, 0xbb);
|
||||
g_assert_cmpuint (color.blue, ==, 0xcc);
|
||||
g_assert_cmpuint (color.alpha, ==, 0xff);
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "#123abc"));
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("color = { %x, %x, %x, %x }, expected = { 0x12, 0x3a, 0xbc, 0xff }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha);
|
||||
}
|
||||
g_assert (color.red == 0x12);
|
||||
g_assert (color.green == 0x3a);
|
||||
g_assert (color.blue == 0xbc);
|
||||
g_assert (color.alpha == 0xff);
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "rgb(255, 128, 64)"));
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("color = { %x, %x, %x, %x }, expected = { 255, 128, 64, 255 }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha);
|
||||
}
|
||||
g_assert_cmpuint (color.red, ==, 255);
|
||||
g_assert_cmpuint (color.green, ==, 128);
|
||||
g_assert_cmpuint (color.blue, ==, 64);
|
||||
g_assert_cmpuint (color.alpha, ==, 255);
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "rgba ( 30%, 0, 25%, 0.5 ) "));
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("color = { %x, %x, %x, %x }, expected = { %.1f, 0, %.1f, 128 }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha,
|
||||
CLAMP (255.0 / 100.0 * 30.0, 0, 255),
|
||||
CLAMP (255.0 / 100.0 * 25.0, 0, 255));
|
||||
}
|
||||
g_assert_cmpuint (color.red, ==, (255.0 / 100.0 * 30.0));
|
||||
g_assert_cmpuint (color.green, ==, 0);
|
||||
g_assert_cmpuint (color.blue, ==, (255.0 / 100.0 * 25.0));
|
||||
g_assert_cmpuint (color.alpha, ==, 127);
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "rgb( 50%, -50%, 150% )"));
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("color = { %x, %x, %x, %x }, expected = { 127, 0, 255, 255 }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha);
|
||||
}
|
||||
g_assert_cmpuint (color.red, ==, 127);
|
||||
g_assert_cmpuint (color.green, ==, 0);
|
||||
g_assert_cmpuint (color.blue, ==, 255);
|
||||
g_assert_cmpuint (color.alpha, ==, 255);
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "hsl( 0, 100%, 50% )"));
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("color = { %x, %x, %x, %x }, expected = { 255, 0, 0, 255 }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha);
|
||||
}
|
||||
g_assert_cmpuint (color.red, ==, 255);
|
||||
g_assert_cmpuint (color.green, ==, 0);
|
||||
g_assert_cmpuint (color.blue, ==, 0);
|
||||
g_assert_cmpuint (color.alpha, ==, 255);
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "hsl( 0, 100%, 50% )"));
|
||||
|
||||
g_assert (clutter_color_from_string (&color, "hsla( 0, 100%, 50%, 0.5 )"));
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("color = { %x, %x, %x, %x }, expected = { 255, 0, 0, 127 }\n",
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha);
|
||||
}
|
||||
g_assert_cmpuint (color.red, ==, 255);
|
||||
g_assert_cmpuint (color.green, ==, 0);
|
||||
g_assert_cmpuint (color.blue, ==, 0);
|
||||
g_assert_cmpuint (color.alpha, ==, 127);
|
||||
|
||||
g_test_bug ("662818");
|
||||
g_assert (clutter_color_from_string (&color, "hsla(0,100%,50% , 0.5)"));
|
||||
}
|
||||
|
||||
static void
|
||||
color_to_string (void)
|
||||
{
|
||||
ClutterColor color;
|
||||
gchar *str;
|
||||
|
||||
color.red = 0xcc;
|
||||
color.green = 0xcc;
|
||||
color.blue = 0xcc;
|
||||
color.alpha = 0x22;
|
||||
|
||||
str = clutter_color_to_string (&color);
|
||||
g_assert_cmpstr (str, ==, "#cccccc22");
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
static void
|
||||
color_operators (void)
|
||||
{
|
||||
ClutterColor op1, op2;
|
||||
ClutterColor res;
|
||||
|
||||
clutter_color_from_pixel (&op1, 0xff0000ff);
|
||||
g_assert_cmpuint (op1.red, ==, 0xff);
|
||||
g_assert_cmpuint (op1.green, ==, 0);
|
||||
g_assert_cmpuint (op1.blue, ==, 0);
|
||||
g_assert_cmpuint (op1.alpha, ==, 0xff);
|
||||
|
||||
clutter_color_from_pixel (&op2, 0x00ff00ff);
|
||||
g_assert_cmpuint (op2.red, ==, 0);
|
||||
g_assert_cmpuint (op2.green, ==, 0xff);
|
||||
g_assert_cmpuint (op2.blue, ==, 0);
|
||||
g_assert_cmpuint (op2.alpha, ==, 0xff);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Adding %x, %x; expected result: %x\n",
|
||||
clutter_color_to_pixel (&op1),
|
||||
clutter_color_to_pixel (&op2),
|
||||
0xffff00ff);
|
||||
|
||||
clutter_color_add (&op1, &op2, &res);
|
||||
g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0xffff00ff);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Checking alpha channel on color add\n");
|
||||
|
||||
op1.alpha = 0xdd;
|
||||
op2.alpha = 0xcc;
|
||||
clutter_color_add (&op1, &op2, &res);
|
||||
g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0xffff00dd);
|
||||
|
||||
clutter_color_from_pixel (&op1, 0xffffffff);
|
||||
clutter_color_from_pixel (&op2, 0xff00ffff);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Subtracting %x, %x; expected result: %x\n",
|
||||
clutter_color_to_pixel (&op1),
|
||||
clutter_color_to_pixel (&op2),
|
||||
0x00ff00ff);
|
||||
|
||||
clutter_color_subtract (&op1, &op2, &res);
|
||||
g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0x00ff00ff);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Checking alpha channel on color subtract\n");
|
||||
|
||||
op1.alpha = 0xdd;
|
||||
op2.alpha = 0xcc;
|
||||
clutter_color_subtract (&op1, &op2, &res);
|
||||
g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0x00ff00cc);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/color/hls-roundtrip", color_hls_roundtrip)
|
||||
CLUTTER_TEST_UNIT ("/color/from-string/invalid", color_from_string_invalid)
|
||||
CLUTTER_TEST_UNIT ("/color/from-string/valid", color_from_string_valid)
|
||||
CLUTTER_TEST_UNIT ("/color/to-string", color_to_string)
|
||||
CLUTTER_TEST_UNIT ("/color/operators", color_operators)
|
||||
)
|
60
src/tests/clutter/conform/group.c
Normal file
60
src/tests/clutter/conform/group.c
Normal file
@ -0,0 +1,60 @@
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
group_depth_sorting (void)
|
||||
{
|
||||
ClutterActor *group;
|
||||
ClutterActor *child, *test;
|
||||
ClutterGroup *g;
|
||||
GList *children;
|
||||
|
||||
group = clutter_group_new ();
|
||||
g = CLUTTER_GROUP (group);
|
||||
|
||||
child = clutter_rectangle_new ();
|
||||
clutter_actor_set_size (child, 20, 20);
|
||||
clutter_actor_set_depth (child, 0);
|
||||
clutter_actor_set_name (child, "zero");
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (group), child);
|
||||
|
||||
children = clutter_container_get_children (CLUTTER_CONTAINER (group));
|
||||
g_assert (children->data == child);
|
||||
g_assert (children->next == NULL);
|
||||
g_list_free (children);
|
||||
|
||||
child = clutter_rectangle_new ();
|
||||
clutter_actor_set_size (child, 20, 20);
|
||||
clutter_actor_set_depth (child, 10);
|
||||
clutter_actor_set_name (child, "plus-ten");
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (group), child);
|
||||
|
||||
test = clutter_group_get_nth_child (g, 0);
|
||||
g_assert_cmpstr (clutter_actor_get_name (test), ==, "zero");
|
||||
|
||||
test = clutter_group_get_nth_child (g, 1);
|
||||
g_assert_cmpstr (clutter_actor_get_name (test), ==, "plus-ten");
|
||||
|
||||
child = clutter_rectangle_new ();
|
||||
clutter_actor_set_size (child, 20, 20);
|
||||
clutter_actor_set_depth (child, -10);
|
||||
clutter_actor_set_name (child, "minus-ten");
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (group), child);
|
||||
|
||||
g_assert_cmpint (clutter_group_get_n_children (g), ==, 3);
|
||||
|
||||
test = clutter_group_get_nth_child (g, 0);
|
||||
g_assert_cmpstr (clutter_actor_get_name (test), ==, "minus-ten");
|
||||
|
||||
test = clutter_group_get_nth_child (g, 1);
|
||||
g_assert_cmpstr (clutter_actor_get_name (test), ==, "zero");
|
||||
|
||||
test = clutter_group_get_nth_child (g, 2);
|
||||
g_assert_cmpstr (clutter_actor_get_name (test), ==, "plus-ten");
|
||||
|
||||
clutter_actor_destroy (group);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/group/depth-sorting", group_depth_sorting)
|
||||
)
|
117
src/tests/clutter/conform/interval.c
Normal file
117
src/tests/clutter/conform/interval.c
Normal file
@ -0,0 +1,117 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
interval_initial_state (void)
|
||||
{
|
||||
ClutterInterval *interval;
|
||||
int initial, final;
|
||||
const GValue *value;
|
||||
|
||||
interval = clutter_interval_new (G_TYPE_INT, 0, 100);
|
||||
g_assert (CLUTTER_IS_INTERVAL (interval));
|
||||
g_assert (clutter_interval_get_value_type (interval) == G_TYPE_INT);
|
||||
|
||||
clutter_interval_get_interval (interval, &initial, &final);
|
||||
g_assert_cmpint (initial, ==, 0);
|
||||
g_assert_cmpint (final, ==, 100);
|
||||
|
||||
value = clutter_interval_compute (interval, 0);
|
||||
g_assert (G_VALUE_HOLDS_INT (value));
|
||||
g_assert_cmpint (g_value_get_int (value), ==, 0);
|
||||
|
||||
value = clutter_interval_compute (interval, 1);
|
||||
g_assert (G_VALUE_HOLDS_INT (value));
|
||||
g_assert_cmpint (g_value_get_int (value), ==, 100);
|
||||
|
||||
value = clutter_interval_compute (interval, 0.5);
|
||||
g_assert (G_VALUE_HOLDS_INT (value));
|
||||
g_assert_cmpint (g_value_get_int (value), ==, 50);
|
||||
|
||||
clutter_interval_set_final (interval, 200);
|
||||
value = clutter_interval_peek_final_value (interval);
|
||||
g_assert (G_VALUE_HOLDS_INT (value));
|
||||
g_assert_cmpint (g_value_get_int (value), ==, 200);
|
||||
|
||||
g_object_unref (interval);
|
||||
}
|
||||
|
||||
static void
|
||||
interval_transform (void)
|
||||
{
|
||||
ClutterInterval *interval;
|
||||
GValue value = G_VALUE_INIT;
|
||||
const GValue *value_p = NULL;
|
||||
|
||||
interval = clutter_interval_new_with_values (G_TYPE_FLOAT, NULL, NULL);
|
||||
|
||||
g_value_init (&value, G_TYPE_DOUBLE);
|
||||
|
||||
g_value_set_double (&value, 0.0);
|
||||
clutter_interval_set_initial_value (interval, &value);
|
||||
|
||||
g_value_set_double (&value, 100.0);
|
||||
clutter_interval_set_final_value (interval, &value);
|
||||
|
||||
g_value_unset (&value);
|
||||
|
||||
value_p = clutter_interval_peek_initial_value (interval);
|
||||
g_assert (G_VALUE_HOLDS_FLOAT (value_p));
|
||||
g_assert_cmpfloat (g_value_get_float (value_p), ==, 0.f);
|
||||
|
||||
value_p = clutter_interval_peek_final_value (interval);
|
||||
g_assert (G_VALUE_HOLDS_FLOAT (value_p));
|
||||
g_assert_cmpfloat (g_value_get_float (value_p), ==, 100.f);
|
||||
|
||||
g_object_unref (interval);
|
||||
}
|
||||
|
||||
static void
|
||||
interval_from_script (void)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
ClutterInterval *interval;
|
||||
gchar *test_file;
|
||||
GError *error = NULL;
|
||||
GValue *initial, *final;
|
||||
|
||||
test_file = g_test_build_filename (G_TEST_DIST,
|
||||
"scripts",
|
||||
"test-script-interval.json",
|
||||
NULL);
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error)
|
||||
g_printerr ("\tError: %s", error->message);
|
||||
|
||||
g_assert_no_error (error);
|
||||
|
||||
interval = CLUTTER_INTERVAL (clutter_script_get_object (script, "int-1"));
|
||||
initial = clutter_interval_peek_initial_value (interval);
|
||||
if (g_test_verbose ())
|
||||
g_test_message ("\tinitial ['%s'] = '%.2f'",
|
||||
g_type_name (G_VALUE_TYPE (initial)),
|
||||
g_value_get_float (initial));
|
||||
g_assert (G_VALUE_HOLDS (initial, G_TYPE_FLOAT));
|
||||
g_assert_cmpfloat (g_value_get_float (initial), ==, 23.3f);
|
||||
final = clutter_interval_peek_final_value (interval);
|
||||
if (g_test_verbose ())
|
||||
g_test_message ("\tfinal ['%s'] = '%.2f'",
|
||||
g_type_name (G_VALUE_TYPE (final)),
|
||||
g_value_get_float (final));
|
||||
g_assert (G_VALUE_HOLDS (final, G_TYPE_FLOAT));
|
||||
g_assert_cmpfloat (g_value_get_float (final), ==, 42.2f);
|
||||
|
||||
interval = CLUTTER_INTERVAL (clutter_script_get_object (script, "int-2"));
|
||||
initial = clutter_interval_peek_initial_value (interval);
|
||||
g_assert (G_VALUE_HOLDS (initial, CLUTTER_TYPE_COLOR));
|
||||
final = clutter_interval_peek_final_value (interval);
|
||||
g_assert (G_VALUE_HOLDS (final, CLUTTER_TYPE_COLOR));
|
||||
|
||||
g_object_unref (script);
|
||||
g_free (test_file);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/interval/initial-state", interval_initial_state)
|
||||
CLUTTER_TEST_UNIT ("/interval/transform", interval_transform)
|
||||
CLUTTER_TEST_UNIT ("/interval/from-script", interval_from_script)
|
||||
)
|
78
src/tests/clutter/conform/meson.build
Normal file
78
src/tests/clutter/conform/meson.build
Normal file
@ -0,0 +1,78 @@
|
||||
clutter_tests_conform_c_args = [
|
||||
'-DG_LOG_DOMAIN="Clutter-Conform"',
|
||||
'-DCOGL_DISABLE_DEPRECATION_WARNINGS',
|
||||
]
|
||||
clutter_tests_conform_c_args += clutter_debug_c_args
|
||||
|
||||
clutter_tests_conform_link_args = [
|
||||
'-Wl,--export-dynamic',
|
||||
]
|
||||
|
||||
clutter_conform_tests_actor_tests = [
|
||||
'actor-anchors',
|
||||
'actor-destroy',
|
||||
'actor-graph',
|
||||
'actor-invariants',
|
||||
'actor-iter',
|
||||
'actor-layout',
|
||||
'actor-meta',
|
||||
'actor-offscreen-redirect',
|
||||
'actor-paint-opacity',
|
||||
'actor-pick',
|
||||
'actor-shader-effect',
|
||||
'actor-size',
|
||||
]
|
||||
|
||||
clutter_conform_tests_classes_tests = [
|
||||
'text',
|
||||
]
|
||||
|
||||
clutter_conform_tests_general_tests = [
|
||||
'binding-pool',
|
||||
'color',
|
||||
'interval',
|
||||
'script-parser',
|
||||
'units',
|
||||
]
|
||||
|
||||
clutter_conform_tests_deprecated_tests = [
|
||||
'behaviours',
|
||||
'group',
|
||||
'rectangle',
|
||||
'texture',
|
||||
]
|
||||
|
||||
clutter_conform_tests = []
|
||||
clutter_conform_tests += clutter_conform_tests_actor_tests
|
||||
clutter_conform_tests += clutter_conform_tests_classes_tests
|
||||
clutter_conform_tests += clutter_conform_tests_general_tests
|
||||
clutter_conform_tests += clutter_conform_tests_deprecated_tests
|
||||
|
||||
test_env = environment()
|
||||
test_env.set('G_TEST_SRCDIR', meson.current_source_dir())
|
||||
test_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
|
||||
test_env.set('G_ENABLE_DIAGNOSTIC', '0')
|
||||
test_env.set('CLUTTER_ENABLE_DIAGNOSTIC', '0')
|
||||
test_env.set('CLUTTER_SCALE', '1')
|
||||
|
||||
foreach test : clutter_conform_tests
|
||||
test_executable = executable('@0@'.format(test),
|
||||
sources: [
|
||||
'@0@.c'.format(test),
|
||||
],
|
||||
include_directories: clutter_includes,
|
||||
c_args: clutter_tests_conform_c_args,
|
||||
link_args: clutter_tests_conform_link_args,
|
||||
dependencies: [
|
||||
clutter_deps,
|
||||
libmutter_clutter_dep,
|
||||
libmutter_cogl_path_dep
|
||||
],
|
||||
install: false,
|
||||
)
|
||||
|
||||
test(test, test_executable,
|
||||
suite: ['clutter', 'clutter/conform'],
|
||||
env: test_env
|
||||
)
|
||||
endforeach
|
740
src/tests/clutter/conform/path.c
Normal file
740
src/tests/clutter/conform/path.c
Normal file
@ -0,0 +1,740 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include <cairo.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "test-conform-common.h"
|
||||
|
||||
#define MAX_NODES 128
|
||||
|
||||
#define FLOAT_FUZZ_AMOUNT 5.0f
|
||||
|
||||
typedef struct _CallbackData CallbackData;
|
||||
|
||||
typedef gboolean (* PathTestFunc) (CallbackData *data);
|
||||
|
||||
static void compare_node (const ClutterPathNode *node, gpointer data_p);
|
||||
|
||||
struct _CallbackData
|
||||
{
|
||||
ClutterPath *path;
|
||||
|
||||
guint n_nodes;
|
||||
ClutterPathNode nodes[MAX_NODES];
|
||||
|
||||
gboolean nodes_different;
|
||||
guint nodes_found;
|
||||
};
|
||||
|
||||
static const char path_desc[] =
|
||||
"M 21 22 "
|
||||
"L 25 26 "
|
||||
"C 29 30 31 32 33 34 "
|
||||
"m 23 24 "
|
||||
"l 27 28 "
|
||||
"c 35 36 37 38 39 40 "
|
||||
"z";
|
||||
static const ClutterPathNode path_nodes[] =
|
||||
{ { CLUTTER_PATH_MOVE_TO, { { 21, 22 }, { 0, 0 }, { 0, 0 } } },
|
||||
{ CLUTTER_PATH_LINE_TO, { { 25, 26 }, { 0, 0 }, { 0, 0 } } },
|
||||
{ CLUTTER_PATH_CURVE_TO, { { 29, 30 }, { 31, 32 }, { 33, 34 } } },
|
||||
{ CLUTTER_PATH_REL_MOVE_TO, { { 23, 24 }, { 0, 0 }, { 0, 0 } } },
|
||||
{ CLUTTER_PATH_REL_LINE_TO, { { 27, 28 }, { 0, 0 }, { 0, 0 } } },
|
||||
{ CLUTTER_PATH_REL_CURVE_TO, { { 35, 36 }, { 37, 38 }, { 39, 40 } } },
|
||||
{ CLUTTER_PATH_CLOSE, { { 0, 0 }, { 0, 0 }, { 0, 0 } } } };
|
||||
|
||||
static gboolean
|
||||
path_test_add_move_to (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node = { 0, };
|
||||
|
||||
node.type = CLUTTER_PATH_MOVE_TO;
|
||||
node.points[0].x = 1;
|
||||
node.points[0].y = 2;
|
||||
|
||||
clutter_path_add_move_to (data->path, node.points[0].x, node.points[0].y);
|
||||
|
||||
data->nodes[data->n_nodes++] = node;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_add_line_to (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node = { 0, };
|
||||
|
||||
node.type = CLUTTER_PATH_LINE_TO;
|
||||
node.points[0].x = 3;
|
||||
node.points[0].y = 4;
|
||||
|
||||
clutter_path_add_line_to (data->path, node.points[0].x, node.points[0].y);
|
||||
|
||||
data->nodes[data->n_nodes++] = node;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_add_curve_to (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node = { 0, };
|
||||
|
||||
node.type = CLUTTER_PATH_CURVE_TO;
|
||||
node.points[0].x = 5;
|
||||
node.points[0].y = 6;
|
||||
node.points[1].x = 7;
|
||||
node.points[1].y = 8;
|
||||
node.points[2].x = 9;
|
||||
node.points[2].y = 10;
|
||||
|
||||
clutter_path_add_curve_to (data->path,
|
||||
node.points[0].x, node.points[0].y,
|
||||
node.points[1].x, node.points[1].y,
|
||||
node.points[2].x, node.points[2].y);
|
||||
|
||||
data->nodes[data->n_nodes++] = node;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_add_close (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node = { 0, };
|
||||
|
||||
node.type = CLUTTER_PATH_CLOSE;
|
||||
|
||||
clutter_path_add_close (data->path);
|
||||
|
||||
data->nodes[data->n_nodes++] = node;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_add_rel_move_to (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node = { 0, };
|
||||
|
||||
node.type = CLUTTER_PATH_REL_MOVE_TO;
|
||||
node.points[0].x = 11;
|
||||
node.points[0].y = 12;
|
||||
|
||||
clutter_path_add_rel_move_to (data->path, node.points[0].x, node.points[0].y);
|
||||
|
||||
data->nodes[data->n_nodes++] = node;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_add_rel_line_to (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node = { 0, };
|
||||
|
||||
node.type = CLUTTER_PATH_REL_LINE_TO;
|
||||
node.points[0].x = 13;
|
||||
node.points[0].y = 14;
|
||||
|
||||
clutter_path_add_rel_line_to (data->path, node.points[0].x, node.points[0].y);
|
||||
|
||||
data->nodes[data->n_nodes++] = node;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_add_rel_curve_to (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node = { 0, };
|
||||
|
||||
node.type = CLUTTER_PATH_REL_CURVE_TO;
|
||||
node.points[0].x = 15;
|
||||
node.points[0].y = 16;
|
||||
node.points[1].x = 17;
|
||||
node.points[1].y = 18;
|
||||
node.points[2].x = 19;
|
||||
node.points[2].y = 20;
|
||||
|
||||
clutter_path_add_rel_curve_to (data->path,
|
||||
node.points[0].x, node.points[0].y,
|
||||
node.points[1].x, node.points[1].y,
|
||||
node.points[2].x, node.points[2].y);
|
||||
|
||||
data->nodes[data->n_nodes++] = node;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_add_string (CallbackData *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (path_nodes); i++)
|
||||
data->nodes[data->n_nodes++] = path_nodes[i];
|
||||
|
||||
clutter_path_add_string (data->path, path_desc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_add_node_by_struct (CallbackData *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (path_nodes); i++)
|
||||
{
|
||||
data->nodes[data->n_nodes++] = path_nodes[i];
|
||||
clutter_path_add_node (data->path, path_nodes + i);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_get_n_nodes (CallbackData *data)
|
||||
{
|
||||
return clutter_path_get_n_nodes (data->path) == data->n_nodes;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_get_node (CallbackData *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
data->nodes_found = 0;
|
||||
data->nodes_different = FALSE;
|
||||
|
||||
for (i = 0; i < data->n_nodes; i++)
|
||||
{
|
||||
ClutterPathNode node;
|
||||
|
||||
clutter_path_get_node (data->path, i, &node);
|
||||
|
||||
compare_node (&node, data);
|
||||
}
|
||||
|
||||
return !data->nodes_different;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_get_nodes (CallbackData *data)
|
||||
{
|
||||
GSList *list, *node;
|
||||
|
||||
data->nodes_found = 0;
|
||||
data->nodes_different = FALSE;
|
||||
|
||||
list = clutter_path_get_nodes (data->path);
|
||||
|
||||
for (node = list; node; node = node->next)
|
||||
compare_node (node->data, data);
|
||||
|
||||
g_slist_free (list);
|
||||
|
||||
return !data->nodes_different && data->nodes_found == data->n_nodes;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_insert_beginning (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node;
|
||||
|
||||
node.type = CLUTTER_PATH_LINE_TO;
|
||||
node.points[0].x = 41;
|
||||
node.points[0].y = 42;
|
||||
|
||||
memmove (data->nodes + 1, data->nodes,
|
||||
data->n_nodes++ * sizeof (ClutterPathNode));
|
||||
data->nodes[0] = node;
|
||||
|
||||
clutter_path_insert_node (data->path, 0, &node);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_insert_end (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node;
|
||||
|
||||
node.type = CLUTTER_PATH_LINE_TO;
|
||||
node.points[0].x = 43;
|
||||
node.points[0].y = 44;
|
||||
|
||||
data->nodes[data->n_nodes++] = node;
|
||||
|
||||
clutter_path_insert_node (data->path, -1, &node);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_insert_middle (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node;
|
||||
int pos = data->n_nodes / 2;
|
||||
|
||||
node.type = CLUTTER_PATH_LINE_TO;
|
||||
node.points[0].x = 45;
|
||||
node.points[0].y = 46;
|
||||
|
||||
memmove (data->nodes + pos + 1, data->nodes + pos,
|
||||
(data->n_nodes - pos) * sizeof (ClutterPathNode));
|
||||
data->nodes[pos] = node;
|
||||
data->n_nodes++;
|
||||
|
||||
clutter_path_insert_node (data->path, pos, &node);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_clear (CallbackData *data)
|
||||
{
|
||||
clutter_path_clear (data->path);
|
||||
|
||||
data->n_nodes = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_clear_insert (CallbackData *data)
|
||||
{
|
||||
return path_test_clear (data) && path_test_insert_middle (data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_remove_beginning (CallbackData *data)
|
||||
{
|
||||
memmove (data->nodes, data->nodes + 1,
|
||||
--data->n_nodes * sizeof (ClutterPathNode));
|
||||
|
||||
clutter_path_remove_node (data->path, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_remove_end (CallbackData *data)
|
||||
{
|
||||
clutter_path_remove_node (data->path, --data->n_nodes);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_remove_middle (CallbackData *data)
|
||||
{
|
||||
int pos = data->n_nodes / 2;
|
||||
|
||||
memmove (data->nodes + pos, data->nodes + pos + 1,
|
||||
(--data->n_nodes - pos) * sizeof (ClutterPathNode));
|
||||
|
||||
clutter_path_remove_node (data->path, pos);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_remove_only (CallbackData *data)
|
||||
{
|
||||
return path_test_clear (data)
|
||||
&& path_test_add_line_to (data)
|
||||
&& path_test_remove_beginning (data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_replace (CallbackData *data)
|
||||
{
|
||||
ClutterPathNode node;
|
||||
int pos = data->n_nodes / 2;
|
||||
|
||||
node.type = CLUTTER_PATH_LINE_TO;
|
||||
node.points[0].x = 47;
|
||||
node.points[0].y = 48;
|
||||
|
||||
data->nodes[pos] = node;
|
||||
|
||||
clutter_path_replace_node (data->path, pos, &node);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_set_description (CallbackData *data)
|
||||
{
|
||||
data->n_nodes = G_N_ELEMENTS (path_nodes);
|
||||
memcpy (data->nodes, path_nodes, sizeof (path_nodes));
|
||||
|
||||
return clutter_path_set_description (data->path, path_desc);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_get_description (CallbackData *data)
|
||||
{
|
||||
char *desc1, *desc2;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
desc1 = clutter_path_get_description (data->path);
|
||||
clutter_path_clear (data->path);
|
||||
if (!clutter_path_set_description (data->path, desc1))
|
||||
ret = FALSE;
|
||||
desc2 = clutter_path_get_description (data->path);
|
||||
|
||||
if (strcmp (desc1, desc2))
|
||||
ret = FALSE;
|
||||
|
||||
g_free (desc1);
|
||||
g_free (desc2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_convert_to_cairo_path (CallbackData *data)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
cairo_path_t *cpath;
|
||||
guint i, j;
|
||||
ClutterKnot path_start = { 0, 0 }, last_point = { 0, 0 };
|
||||
|
||||
/* Create a temporary image surface and context to hold the cairo
|
||||
path */
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 10, 10);
|
||||
cr = cairo_create (surface);
|
||||
|
||||
/* Convert to a cairo path */
|
||||
clutter_path_to_cairo_path (data->path, cr);
|
||||
|
||||
/* Get a copy of the cairo path data */
|
||||
cpath = cairo_copy_path (cr);
|
||||
|
||||
/* Convert back to a clutter path */
|
||||
clutter_path_clear (data->path);
|
||||
clutter_path_add_cairo_path (data->path, cpath);
|
||||
|
||||
/* The relative nodes will have been converted to absolute so we
|
||||
need to reflect this in the node array for comparison */
|
||||
for (i = 0; i < data->n_nodes; i++)
|
||||
{
|
||||
switch (data->nodes[i].type)
|
||||
{
|
||||
case CLUTTER_PATH_MOVE_TO:
|
||||
path_start = last_point = data->nodes[i].points[0];
|
||||
break;
|
||||
|
||||
case CLUTTER_PATH_LINE_TO:
|
||||
last_point = data->nodes[i].points[0];
|
||||
break;
|
||||
|
||||
case CLUTTER_PATH_CURVE_TO:
|
||||
last_point = data->nodes[i].points[2];
|
||||
break;
|
||||
|
||||
case CLUTTER_PATH_REL_MOVE_TO:
|
||||
last_point.x += data->nodes[i].points[0].x;
|
||||
last_point.y += data->nodes[i].points[0].y;
|
||||
data->nodes[i].points[0] = last_point;
|
||||
data->nodes[i].type = CLUTTER_PATH_MOVE_TO;
|
||||
path_start = last_point;
|
||||
break;
|
||||
|
||||
case CLUTTER_PATH_REL_LINE_TO:
|
||||
last_point.x += data->nodes[i].points[0].x;
|
||||
last_point.y += data->nodes[i].points[0].y;
|
||||
data->nodes[i].points[0] = last_point;
|
||||
data->nodes[i].type = CLUTTER_PATH_LINE_TO;
|
||||
break;
|
||||
|
||||
case CLUTTER_PATH_REL_CURVE_TO:
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
data->nodes[i].points[j].x += last_point.x;
|
||||
data->nodes[i].points[j].y += last_point.y;
|
||||
}
|
||||
last_point = data->nodes[i].points[2];
|
||||
data->nodes[i].type = CLUTTER_PATH_CURVE_TO;
|
||||
break;
|
||||
|
||||
case CLUTTER_PATH_CLOSE:
|
||||
last_point = path_start;
|
||||
|
||||
/* Cairo always adds a move to after every close so we need
|
||||
to insert one here. Since Cairo commit 166453c1abf2 it
|
||||
doesn't seem to do this anymore so will assume that if
|
||||
Cairo's minor version is >= 11 then it includes that
|
||||
commit */
|
||||
if (cairo_version () < CAIRO_VERSION_ENCODE (1, 11, 0))
|
||||
{
|
||||
memmove (data->nodes + i + 2, data->nodes + i + 1,
|
||||
(data->n_nodes - i - 1) * sizeof (ClutterPathNode));
|
||||
data->nodes[i + 1].type = CLUTTER_PATH_MOVE_TO;
|
||||
data->nodes[i + 1].points[0] = last_point;
|
||||
data->n_nodes++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the cairo resources */
|
||||
cairo_path_destroy (cpath);
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
float_fuzzy_equals (float fa, float fb)
|
||||
{
|
||||
return fabs (fa - fb) <= FLOAT_FUZZ_AMOUNT;
|
||||
}
|
||||
|
||||
static void
|
||||
set_triangle_path (CallbackData *data)
|
||||
{
|
||||
/* Triangular shaped path hitting (0,0), (64,64) and (128,0) in four
|
||||
parts. The two curves are actually straight lines */
|
||||
static const ClutterPathNode nodes[] =
|
||||
{ { CLUTTER_PATH_MOVE_TO, { { 0, 0 } } },
|
||||
{ CLUTTER_PATH_LINE_TO, { { 32, 32 } } },
|
||||
{ CLUTTER_PATH_CURVE_TO, { { 40, 40 }, { 56, 56 }, { 64, 64 } } },
|
||||
{ CLUTTER_PATH_REL_CURVE_TO, { { 8, -8 }, { 24, -24 }, { 32, -32 } } },
|
||||
{ CLUTTER_PATH_REL_LINE_TO, { { 32, -32 } } } };
|
||||
gint i;
|
||||
|
||||
clutter_path_clear (data->path);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (nodes); i++)
|
||||
clutter_path_add_node (data->path, nodes + i);
|
||||
|
||||
memcpy (data->nodes, nodes, sizeof (nodes));
|
||||
data->n_nodes = G_N_ELEMENTS (nodes);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_get_position (CallbackData *data)
|
||||
{
|
||||
static const float values[] = { 0.125f, 16.0f, 16.0f,
|
||||
0.375f, 48.0f, 48.0f,
|
||||
0.625f, 80.0f, 48.0f,
|
||||
0.875f, 112.0f, 16.0f };
|
||||
gint i;
|
||||
|
||||
set_triangle_path (data);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (values); i += 3)
|
||||
{
|
||||
ClutterKnot pos;
|
||||
|
||||
clutter_path_get_position (data->path,
|
||||
values[i],
|
||||
&pos);
|
||||
|
||||
if (!float_fuzzy_equals (values[i + 1], pos.x)
|
||||
|| !float_fuzzy_equals (values[i + 2], pos.y))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_get_length (CallbackData *data)
|
||||
{
|
||||
const float actual_length /* sqrt(64**2 + 64**2) * 2 */ = 181.019336f;
|
||||
guint approx_length;
|
||||
|
||||
clutter_path_set_description (data->path, "M 0 0 L 46340 0");
|
||||
g_object_get (data->path, "length", &approx_length, NULL);
|
||||
|
||||
if (!(fabs (approx_length - 46340.f) / 46340.f <= 0.15f))
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("M 0 0 L 46340 0 - Expected 46340, got %d instead.", approx_length);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
clutter_path_set_description (data->path, "M 0 0 L 46341 0");
|
||||
g_object_get (data->path, "length", &approx_length, NULL);
|
||||
|
||||
if (!(fabs (approx_length - 46341.f) / 46341.f <= 0.15f))
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("M 0 0 L 46341 0 - Expected 46341, got %d instead.", approx_length);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
set_triangle_path (data);
|
||||
|
||||
g_object_get (data->path, "length", &approx_length, NULL);
|
||||
|
||||
/* Allow 15% margin of error */
|
||||
if (!(fabs (approx_length - actual_length) / (float) actual_length <= 0.15f))
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("Expected %g, got %d instead.\n", actual_length, approx_length);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
path_test_boxed_type (CallbackData *data)
|
||||
{
|
||||
gboolean ret = TRUE;
|
||||
GSList *nodes, *l;
|
||||
GValue value;
|
||||
|
||||
nodes = clutter_path_get_nodes (data->path);
|
||||
|
||||
memset (&value, 0, sizeof (value));
|
||||
|
||||
for (l = nodes; l; l = l->next)
|
||||
{
|
||||
g_value_init (&value, CLUTTER_TYPE_PATH_NODE);
|
||||
|
||||
g_value_set_boxed (&value, l->data);
|
||||
|
||||
if (!clutter_path_node_equal (l->data,
|
||||
g_value_get_boxed (&value)))
|
||||
ret = FALSE;
|
||||
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
g_slist_free (nodes);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *desc;
|
||||
PathTestFunc func;
|
||||
}
|
||||
path_tests[] =
|
||||
{
|
||||
{ "Add line to", path_test_add_line_to },
|
||||
{ "Add move to", path_test_add_move_to },
|
||||
{ "Add curve to", path_test_add_curve_to },
|
||||
{ "Add close", path_test_add_close },
|
||||
{ "Add relative line to", path_test_add_rel_line_to },
|
||||
{ "Add relative move to", path_test_add_rel_move_to },
|
||||
{ "Add relative curve to", path_test_add_rel_curve_to },
|
||||
{ "Add string", path_test_add_string },
|
||||
{ "Add node by struct", path_test_add_node_by_struct },
|
||||
{ "Get number of nodes", path_test_get_n_nodes },
|
||||
{ "Get a node", path_test_get_node },
|
||||
{ "Get all nodes", path_test_get_nodes },
|
||||
{ "Insert at beginning", path_test_insert_beginning },
|
||||
{ "Insert at end", path_test_insert_end },
|
||||
{ "Insert at middle", path_test_insert_middle },
|
||||
{ "Add after insert", path_test_add_line_to },
|
||||
{ "Clear then insert", path_test_clear_insert },
|
||||
{ "Add string again", path_test_add_string },
|
||||
{ "Remove from beginning", path_test_remove_beginning },
|
||||
{ "Remove from end", path_test_remove_end },
|
||||
{ "Remove from middle", path_test_remove_middle },
|
||||
{ "Add after remove", path_test_add_line_to },
|
||||
{ "Remove only node", path_test_remove_only },
|
||||
{ "Add after remove again", path_test_add_line_to },
|
||||
{ "Replace a node", path_test_replace },
|
||||
{ "Set description", path_test_set_description },
|
||||
{ "Get description", path_test_get_description },
|
||||
{ "Convert to cairo path and back", path_test_convert_to_cairo_path },
|
||||
{ "Clear", path_test_clear },
|
||||
{ "Get position", path_test_get_position },
|
||||
{ "Check node boxed type", path_test_boxed_type },
|
||||
{ "Get length", path_test_get_length }
|
||||
};
|
||||
|
||||
static void
|
||||
compare_node (const ClutterPathNode *node, gpointer data_p)
|
||||
{
|
||||
CallbackData *data = data_p;
|
||||
|
||||
if (data->nodes_found >= data->n_nodes)
|
||||
data->nodes_different = TRUE;
|
||||
else
|
||||
{
|
||||
guint n_points = 0, i;
|
||||
const ClutterPathNode *onode = data->nodes + data->nodes_found;
|
||||
|
||||
if (node->type != onode->type)
|
||||
data->nodes_different = TRUE;
|
||||
|
||||
switch (node->type & ~CLUTTER_PATH_RELATIVE)
|
||||
{
|
||||
case CLUTTER_PATH_MOVE_TO: n_points = 1; break;
|
||||
case CLUTTER_PATH_LINE_TO: n_points = 1; break;
|
||||
case CLUTTER_PATH_CURVE_TO: n_points = 3; break;
|
||||
case CLUTTER_PATH_CLOSE: n_points = 0; break;
|
||||
|
||||
default:
|
||||
data->nodes_different = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_points; i++)
|
||||
if (node->points[i].x != onode->points[i].x
|
||||
|| node->points[i].y != onode->points[i].y)
|
||||
{
|
||||
data->nodes_different = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data->nodes_found++;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
compare_nodes (CallbackData *data)
|
||||
{
|
||||
data->nodes_different = FALSE;
|
||||
data->nodes_found = 0;
|
||||
|
||||
clutter_path_foreach (data->path, compare_node, data);
|
||||
|
||||
return !data->nodes_different && data->nodes_found == data->n_nodes;
|
||||
}
|
||||
|
||||
void
|
||||
path_base (TestConformSimpleFixture *fixture,
|
||||
gconstpointer _data)
|
||||
{
|
||||
CallbackData data;
|
||||
gint i;
|
||||
|
||||
memset (&data, 0, sizeof (data));
|
||||
|
||||
data.path = clutter_path_new ();
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (path_tests); i++)
|
||||
{
|
||||
gboolean succeeded;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("%s... ", path_tests[i].desc);
|
||||
|
||||
succeeded = path_tests[i].func (&data) && compare_nodes (&data);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("%s\n", succeeded ? "ok" : "FAIL");
|
||||
|
||||
g_assert (succeeded);
|
||||
}
|
||||
|
||||
g_object_unref (data.path);
|
||||
}
|
||||
|
51
src/tests/clutter/conform/rectangle.c
Normal file
51
src/tests/clutter/conform/rectangle.c
Normal file
@ -0,0 +1,51 @@
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
rectangle_set_size (void)
|
||||
{
|
||||
ClutterActor *rect = clutter_rectangle_new ();
|
||||
|
||||
/* initial positioning */
|
||||
g_assert_cmpint (clutter_actor_get_x (rect), ==, 0);
|
||||
g_assert_cmpint (clutter_actor_get_y (rect), ==, 0);
|
||||
|
||||
clutter_actor_set_size (rect, 100, 100);
|
||||
|
||||
/* make sure that changing the size does not affect the
|
||||
* rest of the bounding box
|
||||
*/
|
||||
g_assert_cmpint (clutter_actor_get_x (rect), ==, 0);
|
||||
g_assert_cmpint (clutter_actor_get_y (rect), ==, 0);
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_width (rect), ==, 100);
|
||||
g_assert_cmpint (clutter_actor_get_height (rect), ==, 100);
|
||||
|
||||
clutter_actor_destroy (rect);
|
||||
}
|
||||
|
||||
static void
|
||||
rectangle_set_color (void)
|
||||
{
|
||||
ClutterActor *rect = clutter_rectangle_new ();
|
||||
ClutterColor white = { 255, 255, 255, 255 };
|
||||
ClutterColor black = { 0, 0, 0, 255 };
|
||||
ClutterColor check = { 0, };
|
||||
|
||||
clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &black);
|
||||
clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &check);
|
||||
g_assert_cmpint (check.blue, ==, black.blue);
|
||||
|
||||
clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &white);
|
||||
clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &check);
|
||||
g_assert_cmpint (check.green, ==, white.green);
|
||||
|
||||
g_assert_cmpint (clutter_actor_get_opacity (rect), ==, white.alpha);
|
||||
|
||||
clutter_actor_destroy (rect);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/rectangle/set-size", rectangle_set_size)
|
||||
CLUTTER_TEST_UNIT ("/rectangle/set-color", rectangle_set_color)
|
||||
)
|
427
src/tests/clutter/conform/script-parser.c
Normal file
427
src/tests/clutter/conform/script-parser.c
Normal file
@ -0,0 +1,427 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define TEST_TYPE_GROUP (test_group_get_type ())
|
||||
#define TEST_TYPE_GROUP_META (test_group_meta_get_type ())
|
||||
|
||||
#define TEST_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_GROUP, TestGroup))
|
||||
#define TEST_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_GROUP))
|
||||
|
||||
#define TEST_GROUP_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_GROUP_META, TestGroupMeta))
|
||||
#define TEST_IS_GROUP_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_GROUP_META))
|
||||
|
||||
typedef struct _ClutterActor TestGroup;
|
||||
typedef struct _ClutterActorClass TestGroupClass;
|
||||
|
||||
typedef struct _TestGroupMeta {
|
||||
ClutterChildMeta parent_instance;
|
||||
|
||||
guint is_focus : 1;
|
||||
} TestGroupMeta;
|
||||
|
||||
typedef struct _ClutterChildMetaClass TestGroupMetaClass;
|
||||
|
||||
GType test_group_meta_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (TestGroupMeta, test_group_meta, CLUTTER_TYPE_CHILD_META)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_META_0,
|
||||
|
||||
PROP_META_FOCUS
|
||||
};
|
||||
|
||||
static void
|
||||
test_group_meta_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
TestGroupMeta *self = TEST_GROUP_META (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_META_FOCUS:
|
||||
self->is_focus = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_group_meta_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
TestGroupMeta *self = TEST_GROUP_META (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_META_FOCUS:
|
||||
g_value_set_boolean (value, self->is_focus);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_group_meta_class_init (TestGroupMetaClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
gobject_class->set_property = test_group_meta_set_property;
|
||||
gobject_class->get_property = test_group_meta_get_property;
|
||||
|
||||
pspec = g_param_spec_boolean ("focus", "Focus", "Focus",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_META_FOCUS, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
test_group_meta_init (TestGroupMeta *meta)
|
||||
{
|
||||
meta->is_focus = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_container_iface_init (ClutterContainerIface *iface)
|
||||
{
|
||||
iface->child_meta_type = TEST_TYPE_GROUP_META;
|
||||
}
|
||||
|
||||
GType test_group_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (TestGroup, test_group, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
|
||||
clutter_container_iface_init))
|
||||
|
||||
static void
|
||||
test_group_class_init (TestGroupClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
test_group_init (TestGroup *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
script_child (void)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
GObject *container, *actor;
|
||||
GError *error = NULL;
|
||||
gboolean focus_ret;
|
||||
gchar *test_file;
|
||||
|
||||
test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-child.json", NULL);
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error)
|
||||
g_print ("Error: %s", error->message);
|
||||
|
||||
g_assert_no_error (error);
|
||||
|
||||
container = actor = NULL;
|
||||
clutter_script_get_objects (script,
|
||||
"test-group", &container,
|
||||
"test-rect-1", &actor,
|
||||
NULL);
|
||||
g_assert (TEST_IS_GROUP (container));
|
||||
g_assert (CLUTTER_IS_RECTANGLE (actor));
|
||||
|
||||
focus_ret = FALSE;
|
||||
clutter_container_child_get (CLUTTER_CONTAINER (container),
|
||||
CLUTTER_ACTOR (actor),
|
||||
"focus", &focus_ret,
|
||||
NULL);
|
||||
g_assert (focus_ret);
|
||||
|
||||
actor = clutter_script_get_object (script, "test-rect-2");
|
||||
g_assert (CLUTTER_IS_RECTANGLE (actor));
|
||||
|
||||
focus_ret = FALSE;
|
||||
clutter_container_child_get (CLUTTER_CONTAINER (container),
|
||||
CLUTTER_ACTOR (actor),
|
||||
"focus", &focus_ret,
|
||||
NULL);
|
||||
g_assert (!focus_ret);
|
||||
|
||||
g_object_unref (script);
|
||||
g_free (test_file);
|
||||
}
|
||||
|
||||
static void
|
||||
script_single (void)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
ClutterColor color = { 0, };
|
||||
GObject *actor = NULL;
|
||||
GError *error = NULL;
|
||||
ClutterActor *rect;
|
||||
gchar *test_file;
|
||||
|
||||
test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-single.json", NULL);
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error)
|
||||
g_print ("Error: %s", error->message);
|
||||
|
||||
g_assert_no_error (error);
|
||||
|
||||
actor = clutter_script_get_object (script, "test");
|
||||
g_assert (CLUTTER_IS_RECTANGLE (actor));
|
||||
|
||||
rect = CLUTTER_ACTOR (actor);
|
||||
g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 50.0);
|
||||
g_assert_cmpfloat (clutter_actor_get_y (rect), ==, 100.0);
|
||||
|
||||
clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color);
|
||||
g_assert_cmpint (color.red, ==, 255);
|
||||
g_assert_cmpint (color.green, ==, 0xcc);
|
||||
g_assert_cmpint (color.alpha, ==, 0xff);
|
||||
|
||||
g_object_unref (script);
|
||||
g_free (test_file);
|
||||
}
|
||||
|
||||
static void
|
||||
script_implicit_alpha (void)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
ClutterTimeline *timeline;
|
||||
GObject *behaviour = NULL;
|
||||
GError *error = NULL;
|
||||
ClutterAlpha *alpha;
|
||||
gchar *test_file;
|
||||
|
||||
test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-implicit-alpha.json", NULL);
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error)
|
||||
g_print ("Error: %s", error->message);
|
||||
|
||||
#if GLIB_CHECK_VERSION (2, 20, 0)
|
||||
g_assert_no_error (error);
|
||||
#else
|
||||
g_assert (error == NULL);
|
||||
#endif
|
||||
|
||||
behaviour = clutter_script_get_object (script, "test");
|
||||
g_assert (CLUTTER_IS_BEHAVIOUR (behaviour));
|
||||
|
||||
alpha = clutter_behaviour_get_alpha (CLUTTER_BEHAVIOUR (behaviour));
|
||||
g_assert (CLUTTER_IS_ALPHA (alpha));
|
||||
|
||||
g_assert_cmpint (clutter_alpha_get_mode (alpha), ==, CLUTTER_EASE_OUT_CIRC);
|
||||
|
||||
timeline = clutter_alpha_get_timeline (alpha);
|
||||
g_assert (CLUTTER_IS_TIMELINE (timeline));
|
||||
|
||||
g_assert_cmpint (clutter_timeline_get_duration (timeline), ==, 500);
|
||||
|
||||
g_object_unref (script);
|
||||
g_free (test_file);
|
||||
}
|
||||
|
||||
static void
|
||||
script_object_property (void)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
ClutterLayoutManager *manager;
|
||||
GObject *actor = NULL;
|
||||
GError *error = NULL;
|
||||
gchar *test_file;
|
||||
|
||||
test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-object-property.json", NULL);
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error)
|
||||
g_print ("Error: %s", error->message);
|
||||
|
||||
g_assert_no_error (error);
|
||||
|
||||
actor = clutter_script_get_object (script, "test");
|
||||
g_assert (CLUTTER_IS_BOX (actor));
|
||||
|
||||
manager = clutter_box_get_layout_manager (CLUTTER_BOX (actor));
|
||||
g_assert (CLUTTER_IS_BIN_LAYOUT (manager));
|
||||
|
||||
g_object_unref (script);
|
||||
g_free (test_file);
|
||||
}
|
||||
|
||||
static void
|
||||
script_named_object (void)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
ClutterLayoutManager *manager;
|
||||
GObject *actor = NULL;
|
||||
GError *error = NULL;
|
||||
gchar *test_file;
|
||||
|
||||
test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-named-object.json", NULL);
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error)
|
||||
g_print ("Error: %s", error->message);
|
||||
|
||||
g_assert_no_error (error);
|
||||
|
||||
actor = clutter_script_get_object (script, "test");
|
||||
g_assert (CLUTTER_IS_BOX (actor));
|
||||
|
||||
manager = clutter_box_get_layout_manager (CLUTTER_BOX (actor));
|
||||
g_assert (CLUTTER_IS_BOX_LAYOUT (manager));
|
||||
g_assert (clutter_box_layout_get_vertical (CLUTTER_BOX_LAYOUT (manager)));
|
||||
|
||||
g_object_unref (script);
|
||||
g_free (test_file);
|
||||
}
|
||||
|
||||
static void
|
||||
script_animation (void)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
GObject *animation = NULL;
|
||||
GError *error = NULL;
|
||||
gchar *test_file;
|
||||
|
||||
test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-animation.json", NULL);
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error)
|
||||
g_print ("Error: %s", error->message);
|
||||
|
||||
g_assert_no_error (error);
|
||||
|
||||
animation = clutter_script_get_object (script, "test");
|
||||
g_assert (CLUTTER_IS_ANIMATION (animation));
|
||||
|
||||
g_object_unref (script);
|
||||
g_free (test_file);
|
||||
}
|
||||
|
||||
static void
|
||||
script_layout_property (void)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
GObject *manager, *container, *actor1, *actor2;
|
||||
GError *error = NULL;
|
||||
gchar *test_file;
|
||||
gboolean x_fill, expand;
|
||||
ClutterBoxAlignment y_align;
|
||||
|
||||
test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-layout-property.json", NULL);
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error)
|
||||
g_print ("Error: %s", error->message);
|
||||
|
||||
g_assert_no_error (error);
|
||||
|
||||
manager = container = actor1 = actor2 = NULL;
|
||||
clutter_script_get_objects (script,
|
||||
"manager", &manager,
|
||||
"container", &container,
|
||||
"actor-1", &actor1,
|
||||
"actor-2", &actor2,
|
||||
NULL);
|
||||
|
||||
g_assert (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
g_assert (CLUTTER_IS_CONTAINER (container));
|
||||
g_assert (CLUTTER_IS_ACTOR (actor1));
|
||||
g_assert (CLUTTER_IS_ACTOR (actor2));
|
||||
|
||||
x_fill = FALSE;
|
||||
y_align = CLUTTER_BOX_ALIGNMENT_START;
|
||||
expand = FALSE;
|
||||
clutter_layout_manager_child_get (CLUTTER_LAYOUT_MANAGER (manager),
|
||||
CLUTTER_CONTAINER (container),
|
||||
CLUTTER_ACTOR (actor1),
|
||||
"x-fill", &x_fill,
|
||||
"y-align", &y_align,
|
||||
"expand", &expand,
|
||||
NULL);
|
||||
|
||||
g_assert (x_fill);
|
||||
g_assert (y_align == CLUTTER_BOX_ALIGNMENT_CENTER);
|
||||
g_assert (expand);
|
||||
|
||||
x_fill = TRUE;
|
||||
y_align = CLUTTER_BOX_ALIGNMENT_START;
|
||||
expand = TRUE;
|
||||
clutter_layout_manager_child_get (CLUTTER_LAYOUT_MANAGER (manager),
|
||||
CLUTTER_CONTAINER (container),
|
||||
CLUTTER_ACTOR (actor2),
|
||||
"x-fill", &x_fill,
|
||||
"y-align", &y_align,
|
||||
"expand", &expand,
|
||||
NULL);
|
||||
|
||||
g_assert (x_fill == FALSE);
|
||||
g_assert (y_align == CLUTTER_BOX_ALIGNMENT_END);
|
||||
g_assert (expand == FALSE);
|
||||
|
||||
g_object_unref (script);
|
||||
}
|
||||
|
||||
static void
|
||||
script_margin (void)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
ClutterActor *actor;
|
||||
gchar *test_file;
|
||||
GError *error = NULL;
|
||||
|
||||
test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-margin.json", NULL);
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error)
|
||||
g_print ("Error: %s", error->message);
|
||||
|
||||
g_assert_no_error (error);
|
||||
|
||||
actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-1"));
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 10.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 10.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 10.0f);
|
||||
|
||||
actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-2"));
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 20.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 10.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 20.0f);
|
||||
|
||||
actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-3"));
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 20.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 30.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 20.0f);
|
||||
|
||||
actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-4"));
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 20.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 30.0f);
|
||||
g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 40.0f);
|
||||
|
||||
g_object_unref (script);
|
||||
g_free (test_file);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/script/single-object", script_single)
|
||||
CLUTTER_TEST_UNIT ("/script/container-child", script_child)
|
||||
CLUTTER_TEST_UNIT ("/script/named-object", script_named_object)
|
||||
CLUTTER_TEST_UNIT ("/script/animation", script_animation)
|
||||
CLUTTER_TEST_UNIT ("/script/implicit-alpha", script_implicit_alpha)
|
||||
CLUTTER_TEST_UNIT ("/script/object-property", script_object_property)
|
||||
CLUTTER_TEST_UNIT ("/script/layout-property", script_layout_property)
|
||||
CLUTTER_TEST_UNIT ("/script/actor-margin", script_margin)
|
||||
)
|
5
src/tests/clutter/conform/scripts/test-animator-1.json
Normal file
5
src/tests/clutter/conform/scripts/test-animator-1.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"type" : "ClutterAnimator",
|
||||
"id" : "animator",
|
||||
"duration" : 1000
|
||||
}
|
29
src/tests/clutter/conform/scripts/test-animator-2.json
Normal file
29
src/tests/clutter/conform/scripts/test-animator-2.json
Normal file
@ -0,0 +1,29 @@
|
||||
[
|
||||
{
|
||||
"type" : "ClutterRectangle",
|
||||
"id" : "foo",
|
||||
"x" : 0,
|
||||
"y" : 0,
|
||||
"width" : 100,
|
||||
"height" : 100
|
||||
},
|
||||
{
|
||||
"type" : "ClutterAnimator",
|
||||
"id" : "animator",
|
||||
"duration" : 1000,
|
||||
|
||||
"properties" : [
|
||||
{
|
||||
"object" : "foo",
|
||||
"name" : "x",
|
||||
"ease-in" : true,
|
||||
"interpolation" : "linear",
|
||||
"keys" : [
|
||||
[ 0.0, "easeInCubic", 100.0 ],
|
||||
[ 0.2, "easeOutCubic", 150.0 ],
|
||||
[ 0.8, "linear", 200.0 ]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
40
src/tests/clutter/conform/scripts/test-animator-3.json
Normal file
40
src/tests/clutter/conform/scripts/test-animator-3.json
Normal file
@ -0,0 +1,40 @@
|
||||
[
|
||||
{
|
||||
"type" : "ClutterRectangle",
|
||||
"id" : "foo",
|
||||
"x" : 0,
|
||||
"y" : 0,
|
||||
"width" : 100,
|
||||
"height" : 100
|
||||
},
|
||||
{
|
||||
"type" : "ClutterAnimator",
|
||||
"id" : "animator",
|
||||
"duration" : 1000,
|
||||
|
||||
"properties" : [
|
||||
{
|
||||
"object" : "foo",
|
||||
"name" : "x",
|
||||
"ease-in" : true,
|
||||
"interpolation" : "linear",
|
||||
"keys" : [
|
||||
[ 0.0, "easeInCubic", 100.0 ],
|
||||
[ 0.2, "easeOutCubic", 150.0 ],
|
||||
[ 0.8, "linear", 200.0 ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"object" : "foo",
|
||||
"name" : "y",
|
||||
"ease-in" : true,
|
||||
"interpolation" : "linear",
|
||||
"keys" : [
|
||||
[ 0.0, "easeInCubic", 100.0 ],
|
||||
[ 0.2, "easeOutCubic", 150.0 ],
|
||||
[ 0.8, "linear", 200.0 ]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
14
src/tests/clutter/conform/scripts/test-script-animation.json
Normal file
14
src/tests/clutter/conform/scripts/test-script-animation.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"type" : "ClutterAnimation",
|
||||
"id" : "test",
|
||||
"mode" : "easeInCubic",
|
||||
"duration" : 500,
|
||||
"object" : {
|
||||
"type" : "ClutterRectangle",
|
||||
"id" : "rect",
|
||||
"opacity" : 128,
|
||||
"width" : 100,
|
||||
"height" : 16,
|
||||
"color" : "white"
|
||||
}
|
||||
}
|
21
src/tests/clutter/conform/scripts/test-script-child.json
Normal file
21
src/tests/clutter/conform/scripts/test-script-child.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"type" : "TestGroup",
|
||||
"id" : "test-group",
|
||||
"children" : [
|
||||
{
|
||||
"type" : "ClutterRectangle",
|
||||
"id" : "test-rect-1",
|
||||
"width" : 100.0,
|
||||
"height" : 100.0,
|
||||
"color" : [ 255, 0, 0, 255 ],
|
||||
"child::focus" : true
|
||||
},
|
||||
{
|
||||
"type" : "ClutterRectangle",
|
||||
"id" : "test-rect-2",
|
||||
"width" : 100.0,
|
||||
"height" : 100.0,
|
||||
"color" : [ 0, 255, 0, 255 ]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"id" : "test",
|
||||
"type" : "ClutterBehaviourOpacity",
|
||||
"alpha" : {
|
||||
"mode" : "easeOutCirc",
|
||||
"timeline" : { "duration" : 500 }
|
||||
}
|
||||
}
|
16
src/tests/clutter/conform/scripts/test-script-interval.json
Normal file
16
src/tests/clutter/conform/scripts/test-script-interval.json
Normal file
@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
"id" : "int-1",
|
||||
"type" : "ClutterInterval",
|
||||
"value-type" : "gfloat",
|
||||
"initial" : 23.3,
|
||||
"final" : 42.2
|
||||
},
|
||||
{
|
||||
"id" : "int-2",
|
||||
"type" : "ClutterInterval",
|
||||
"value-type" : "ClutterColor",
|
||||
"initial" : "red",
|
||||
"final" : "blue"
|
||||
}
|
||||
]
|
@ -0,0 +1,21 @@
|
||||
[
|
||||
{ "id" : "manager", "type" : "ClutterBoxLayout" },
|
||||
|
||||
{
|
||||
"id" : "container", "type" : "ClutterBox",
|
||||
"layout-manager" : "manager",
|
||||
"children" : [
|
||||
{
|
||||
"id" : "actor-1", "type" : "ClutterRectangle",
|
||||
"layout::x-fill" : true,
|
||||
"layout::y-align" : "center",
|
||||
"layout::expand" : true
|
||||
}, {
|
||||
"id" : "actor-2", "type" : "ClutterRectangle",
|
||||
"layout::x-fill" : false,
|
||||
"layout::y-align" : "end",
|
||||
"layout::expand" : false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
22
src/tests/clutter/conform/scripts/test-script-margin.json
Normal file
22
src/tests/clutter/conform/scripts/test-script-margin.json
Normal file
@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"id" : "actor-1",
|
||||
"type" : "ClutterActor",
|
||||
"margin" : [ 10 ]
|
||||
},
|
||||
{
|
||||
"id" : "actor-2",
|
||||
"type" : "ClutterActor",
|
||||
"margin" : [ 10, 20 ]
|
||||
},
|
||||
{
|
||||
"id" : "actor-3",
|
||||
"type" : "ClutterActor",
|
||||
"margin" : [ 10, 20, 30 ]
|
||||
},
|
||||
{
|
||||
"id" : "actor-4",
|
||||
"type" : "ClutterActor",
|
||||
"margin" : [ 10, 20, 30, 40]
|
||||
}
|
||||
]
|
17
src/tests/clutter/conform/scripts/test-script-model.json
Normal file
17
src/tests/clutter/conform/scripts/test-script-model.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"id" : "test-model",
|
||||
"type" : "ClutterListModel",
|
||||
"columns" : [
|
||||
[ "text-column", "gchararray" ],
|
||||
[ "int-column", "gint" ],
|
||||
[ "actor-column", "ClutterRectangle" ]
|
||||
],
|
||||
"rows" : [
|
||||
[ "text-row-1", 1, null ],
|
||||
[ "text-row-2", 2, { "type" : "ClutterRectangle", "color" : "blue" } ],
|
||||
{
|
||||
"int-column" : 3,
|
||||
"actor-column" : { "type" : "ClutterRectangle", "name" : "actor-row-3" }
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
[
|
||||
{
|
||||
"id" : "layout",
|
||||
"type" : "ClutterBoxLayout",
|
||||
"orientation" : "vertical",
|
||||
"spacing" : 12,
|
||||
"pack-start" : false
|
||||
},
|
||||
{
|
||||
"type" : "ClutterStage",
|
||||
"id" : "main-stage",
|
||||
"children" : [
|
||||
{
|
||||
"id" : "test",
|
||||
"type" : "ClutterBox",
|
||||
"layout-manager" : "layout",
|
||||
"children" : [
|
||||
{
|
||||
"id" : "child-1",
|
||||
"type" : "ClutterRectangle",
|
||||
"width" : "3 em",
|
||||
"height" : "3 em"
|
||||
}
|
||||
],
|
||||
"constraints" : [
|
||||
{
|
||||
"type" : "ClutterAlignConstraint",
|
||||
"name" : "x-align",
|
||||
"factor" : 0.5,
|
||||
"align-axis" : "x-axis",
|
||||
"source" : "main-stage"
|
||||
},
|
||||
{
|
||||
"type" : "ClutterAlignConstraint",
|
||||
"name" : "y-align",
|
||||
"factor" : 0.5,
|
||||
"align-axis" : "y-axis",
|
||||
"source" : "main-stage"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"id" : "test",
|
||||
"type" : "ClutterBox",
|
||||
"layout-manager" : { "id" : "layout", "type" : "ClutterBinLayout" },
|
||||
"children" : [
|
||||
{
|
||||
"id" : "child-1",
|
||||
"type" : "ClutterRectangle",
|
||||
"width" : "3 em",
|
||||
"height" : "3 em"
|
||||
}
|
||||
]
|
||||
}
|
10
src/tests/clutter/conform/scripts/test-script-single.json
Normal file
10
src/tests/clutter/conform/scripts/test-script-single.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"type" : "ClutterRectangle",
|
||||
"id" : "test",
|
||||
"width" : 50.0,
|
||||
"height" : 100.0,
|
||||
"x" : 100.0,
|
||||
"y" : 100.0,
|
||||
"color" : "#ffccdd",
|
||||
"name" : "Test Rectangle"
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"id" : "timeline0",
|
||||
"type" : "ClutterTimeline",
|
||||
"duration" : 1000,
|
||||
|
||||
"markers" : [
|
||||
{ "name" : "marker0", "time" : 250 },
|
||||
{ "name" : "marker1", "time" : 500 },
|
||||
{ "name" : "marker2", "time" : 750 },
|
||||
{ "name" : "marker3", "progress" : 0.5 }
|
||||
]
|
||||
}
|
33
src/tests/clutter/conform/scripts/test-state-1.json
Normal file
33
src/tests/clutter/conform/scripts/test-state-1.json
Normal file
@ -0,0 +1,33 @@
|
||||
[
|
||||
{
|
||||
"type" : "ClutterRectangle",
|
||||
"id" : "rect",
|
||||
"width" : 100,
|
||||
"height" : 100
|
||||
},
|
||||
{
|
||||
"type" : "ClutterState",
|
||||
"id" : "state",
|
||||
|
||||
"transitions" : [
|
||||
{
|
||||
"source" : "base",
|
||||
"target" : "clicked",
|
||||
"duration" : 250,
|
||||
|
||||
"keys" : [
|
||||
[ "rect", "opacity", "linear", 128 ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"source" : "clicked",
|
||||
"target" : "base",
|
||||
"duration" : 150,
|
||||
|
||||
"keys" : [
|
||||
[ "rect", "opacity", "linear", 255 ]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
87
src/tests/clutter/conform/state.c
Normal file
87
src/tests/clutter/conform/state.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "test-conform-common.h"
|
||||
|
||||
void
|
||||
state_base (TestConformSimpleFixture *fixture G_GNUC_UNUSED,
|
||||
gconstpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
GObject *state = NULL;
|
||||
GError *error = NULL;
|
||||
gchar *test_file;
|
||||
GList *states, *keys;
|
||||
ClutterStateKey *state_key;
|
||||
guint duration;
|
||||
|
||||
test_file = clutter_test_get_data_file ("test-state-1.json");
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error)
|
||||
g_print ("Error: %s\n", error->message);
|
||||
|
||||
g_free (test_file);
|
||||
|
||||
#if GLIB_CHECK_VERSION (2, 20, 0)
|
||||
g_assert_no_error (error);
|
||||
#else
|
||||
g_assert (error == NULL);
|
||||
#endif
|
||||
|
||||
state = clutter_script_get_object (script, "state");
|
||||
g_assert (CLUTTER_IS_STATE (state));
|
||||
|
||||
states = clutter_state_get_states (CLUTTER_STATE (state));
|
||||
g_assert (states != NULL);
|
||||
|
||||
g_assert (g_list_find (states, g_intern_static_string ("clicked")));
|
||||
g_list_free (states);
|
||||
|
||||
duration = clutter_state_get_duration (CLUTTER_STATE (state), "base", "clicked");
|
||||
g_assert_cmpint (duration, ==, 250);
|
||||
|
||||
duration = clutter_state_get_duration (CLUTTER_STATE (state), "clicked", "base");
|
||||
g_assert_cmpint (duration, ==, 150);
|
||||
|
||||
keys = clutter_state_get_keys (CLUTTER_STATE (state), "base", "clicked",
|
||||
clutter_script_get_object (script, "rect"),
|
||||
"opacity");
|
||||
|
||||
g_assert (keys != NULL);
|
||||
g_assert_cmpint (g_list_length (keys), ==, 1);
|
||||
|
||||
state_key = keys->data;
|
||||
g_assert (clutter_state_key_get_object (state_key) == clutter_script_get_object (script, "rect"));
|
||||
g_assert (clutter_state_key_get_mode (state_key) == CLUTTER_LINEAR);
|
||||
g_assert_cmpstr (clutter_state_key_get_property_name (state_key), ==, "opacity");
|
||||
|
||||
g_list_free (keys);
|
||||
keys = clutter_state_get_keys (CLUTTER_STATE (state), NULL, NULL, NULL, NULL);
|
||||
g_assert_cmpint (g_list_length (keys), ==, 2);
|
||||
g_list_free (keys);
|
||||
|
||||
|
||||
|
||||
clutter_state_set (CLUTTER_STATE (state), "base", "clicked", state, "state", CLUTTER_LINEAR, "foo", NULL);
|
||||
|
||||
keys = clutter_state_get_keys (CLUTTER_STATE (state), "base", "clicked",
|
||||
NULL, NULL);
|
||||
|
||||
g_assert (keys != NULL);
|
||||
g_assert_cmpint (g_list_length (keys), ==, 2);
|
||||
g_list_free (keys);
|
||||
|
||||
states = clutter_state_get_states (CLUTTER_STATE (state));
|
||||
g_assert_cmpint (g_list_length (states), ==, 2);
|
||||
g_list_free (states);
|
||||
|
||||
clutter_state_remove_key (CLUTTER_STATE (state), NULL, "clicked", NULL, NULL);
|
||||
states = clutter_state_get_states (CLUTTER_STATE (state));
|
||||
|
||||
/* removing the "clicked" state, will also cause the "base" state to be removed
|
||||
* since in the .json there is no default source state
|
||||
*/
|
||||
g_assert_cmpint (g_list_length (states), ==, 0);
|
||||
g_list_free (states);
|
||||
|
||||
g_object_unref (script);
|
||||
}
|
297
src/tests/clutter/conform/text-cache.c
Normal file
297
src/tests/clutter/conform/text-cache.c
Normal file
@ -0,0 +1,297 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "test-conform-common.h"
|
||||
|
||||
#define TEST_FONT "Sans 10"
|
||||
|
||||
static const char long_text[] =
|
||||
"<b>This</b> <i>is</i> some <span size=\"x-large\">REALLY</span> "
|
||||
"long text that contains markup for testing the <tt>use_markup</tt> "
|
||||
"property and to test word-wrapping, justification and alignment.";
|
||||
|
||||
typedef struct _CallbackData CallbackData;
|
||||
|
||||
struct _CallbackData
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *label;
|
||||
|
||||
PangoLayout *old_layout;
|
||||
gboolean layout_changed;
|
||||
PangoRectangle label_extents;
|
||||
|
||||
PangoLayout *test_layout;
|
||||
|
||||
gboolean test_failed;
|
||||
};
|
||||
|
||||
static void
|
||||
on_paint (ClutterActor *stage, CallbackData *data)
|
||||
{
|
||||
PangoLayout *new_layout;
|
||||
|
||||
/* Check whether the layout used for this paint is different from
|
||||
the layout used for the last paint */
|
||||
new_layout = clutter_text_get_layout (CLUTTER_TEXT (data->label));
|
||||
data->layout_changed = data->old_layout != new_layout;
|
||||
|
||||
if (data->old_layout)
|
||||
g_object_unref (data->old_layout);
|
||||
/* Keep a reference to the old layout so we can be sure it won't
|
||||
just reallocate a new layout with the same address */
|
||||
data->old_layout = g_object_ref (new_layout);
|
||||
|
||||
pango_layout_get_extents (new_layout, NULL, &data->label_extents);
|
||||
}
|
||||
|
||||
static void
|
||||
force_redraw (CallbackData *data)
|
||||
{
|
||||
/* XXX - this is fugly; we force a paint on the stage, which
|
||||
* will then paint the Text actor. inside the Text actor we
|
||||
* check for a Layout with the allocation size. if the allocation
|
||||
* has changed it will cause a relayout in the middle of the
|
||||
* paint, which is expensive and broken. this will ensure that
|
||||
* the test passes, though
|
||||
*/
|
||||
clutter_actor_paint (clutter_actor_get_stage (data->label));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_result (CallbackData *data, const char *note,
|
||||
gboolean layout_should_change)
|
||||
{
|
||||
PangoRectangle test_extents;
|
||||
gboolean fail = FALSE;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("%s: ", note);
|
||||
|
||||
/* Force a redraw to get the on_paint handler to run */
|
||||
force_redraw (data);
|
||||
|
||||
/* Compare the extents from the label with the extents from our test
|
||||
layout */
|
||||
pango_layout_get_extents (data->test_layout, NULL, &test_extents);
|
||||
if (memcmp (&test_extents, &data->label_extents, sizeof (PangoRectangle)))
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("extents are different: expected: %d, %d, %d, %d "
|
||||
"-> text: %d, %d, %d, %d\n",
|
||||
test_extents.x / 1024,
|
||||
test_extents.y / 1024,
|
||||
test_extents.width / 1024,
|
||||
test_extents.height / 1024,
|
||||
data->label_extents.x / 1024,
|
||||
data->label_extents.y / 1024,
|
||||
data->label_extents.width / 1024,
|
||||
data->label_extents.height / 1024);
|
||||
|
||||
fail = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("extents are the same, ");
|
||||
}
|
||||
|
||||
if (data->layout_changed)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("layout changed, ");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("layout did not change, ");
|
||||
}
|
||||
|
||||
if (data->layout_changed != layout_should_change)
|
||||
fail = TRUE;
|
||||
|
||||
if (fail)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("FAIL\n");
|
||||
|
||||
data->test_failed = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("pass\n");
|
||||
}
|
||||
|
||||
return fail;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_tests (CallbackData *data)
|
||||
{
|
||||
PangoFontDescription *fd;
|
||||
static const ClutterColor red = { 0xff, 0x00, 0x00, 0xff };
|
||||
PangoAttrList *attr_list, *attr_list_copy;
|
||||
PangoAttribute *attr;
|
||||
|
||||
/* TEST 1: change the text */
|
||||
clutter_text_set_text (CLUTTER_TEXT (data->label), "Counter 0");
|
||||
pango_layout_set_text (data->test_layout, "Counter 0", -1);
|
||||
g_assert (check_result (data, "Change text", TRUE) == FALSE);
|
||||
|
||||
/* TEST 2: change a single character */
|
||||
clutter_text_set_text (CLUTTER_TEXT (data->label), "Counter 1");
|
||||
pango_layout_set_text (data->test_layout, "Counter 1", -1);
|
||||
g_assert (check_result (data, "Change a single character", TRUE) == FALSE);
|
||||
|
||||
/* TEST 3: move the label */
|
||||
clutter_actor_set_position (data->label, 10, 0);
|
||||
g_assert (check_result (data, "Move the label", FALSE) == FALSE);
|
||||
|
||||
/* TEST 4: change the font */
|
||||
clutter_text_set_font_name (CLUTTER_TEXT (data->label), "Serif 15");
|
||||
fd = pango_font_description_from_string ("Serif 15");
|
||||
pango_layout_set_font_description (data->test_layout, fd);
|
||||
pango_font_description_free (fd);
|
||||
g_assert (check_result (data, "Change the font", TRUE) == FALSE);
|
||||
|
||||
/* TEST 5: change the color */
|
||||
clutter_text_set_color (CLUTTER_TEXT (data->label), &red);
|
||||
g_assert (check_result (data, "Change the color", FALSE) == FALSE);
|
||||
|
||||
/* TEST 6: change the attributes */
|
||||
attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
|
||||
attr->start_index = 0;
|
||||
attr->end_index = 2;
|
||||
attr_list = pango_attr_list_new ();
|
||||
pango_attr_list_insert (attr_list, attr);
|
||||
attr_list_copy = pango_attr_list_copy (attr_list);
|
||||
clutter_text_set_attributes (CLUTTER_TEXT (data->label), attr_list);
|
||||
pango_layout_set_attributes (data->test_layout, attr_list_copy);
|
||||
pango_attr_list_unref (attr_list_copy);
|
||||
pango_attr_list_unref (attr_list);
|
||||
g_assert (check_result (data, "Change the attributes", TRUE) == FALSE);
|
||||
|
||||
/* TEST 7: change the text again */
|
||||
clutter_text_set_attributes (CLUTTER_TEXT (data->label), NULL);
|
||||
clutter_text_set_text (CLUTTER_TEXT (data->label), long_text);
|
||||
pango_layout_set_attributes (data->test_layout, NULL);
|
||||
pango_layout_set_text (data->test_layout, long_text, -1);
|
||||
g_assert (check_result (data, "Change the text again", TRUE) == FALSE);
|
||||
|
||||
/* TEST 8: enable markup */
|
||||
clutter_text_set_use_markup (CLUTTER_TEXT (data->label), TRUE);
|
||||
pango_layout_set_markup (data->test_layout, long_text, -1);
|
||||
g_assert (check_result (data, "Enable markup", TRUE) == FALSE);
|
||||
|
||||
/* This part can't be a test because Clutter won't restrict the
|
||||
width if wrapping and ellipsizing is disabled so the extents will
|
||||
be different, but we still want to do it for the later tests */
|
||||
clutter_actor_set_width (data->label, 200);
|
||||
pango_layout_set_width (data->test_layout, 200 * PANGO_SCALE);
|
||||
/* Force a redraw so that changing the width won't affect the
|
||||
results */
|
||||
force_redraw (data);
|
||||
|
||||
/* TEST 9: enable ellipsize */
|
||||
clutter_text_set_ellipsize (CLUTTER_TEXT (data->label),
|
||||
PANGO_ELLIPSIZE_END);
|
||||
pango_layout_set_ellipsize (data->test_layout, PANGO_ELLIPSIZE_END);
|
||||
g_assert (check_result (data, "Enable ellipsize", TRUE) == FALSE);
|
||||
clutter_text_set_ellipsize (CLUTTER_TEXT (data->label),
|
||||
PANGO_ELLIPSIZE_NONE);
|
||||
pango_layout_set_ellipsize (data->test_layout, PANGO_ELLIPSIZE_NONE);
|
||||
force_redraw (data);
|
||||
|
||||
/* TEST 10: enable line wrap */
|
||||
clutter_text_set_line_wrap (CLUTTER_TEXT (data->label), TRUE);
|
||||
pango_layout_set_wrap (data->test_layout, PANGO_WRAP_WORD);
|
||||
g_assert (check_result (data, "Enable line wrap", TRUE) == FALSE);
|
||||
|
||||
/* TEST 11: change wrap mode
|
||||
* FIXME - broken
|
||||
*/
|
||||
clutter_text_set_line_wrap_mode (CLUTTER_TEXT (data->label),
|
||||
PANGO_WRAP_CHAR);
|
||||
pango_layout_set_wrap (data->test_layout, PANGO_WRAP_CHAR);
|
||||
g_assert (check_result (data, "Change wrap mode", TRUE) == FALSE);
|
||||
|
||||
/* TEST 12: enable justify */
|
||||
clutter_text_set_justify (CLUTTER_TEXT (data->label), TRUE);
|
||||
pango_layout_set_justify (data->test_layout, TRUE);
|
||||
/* Pango appears to have a bug which means that you can't change the
|
||||
justification after setting the text but this fixes it.
|
||||
See http://bugzilla.gnome.org/show_bug.cgi?id=551865 */
|
||||
pango_layout_context_changed (data->test_layout);
|
||||
g_assert (check_result (data, "Enable justify", TRUE) == FALSE);
|
||||
|
||||
/* TEST 13: change alignment */
|
||||
clutter_text_set_line_alignment (CLUTTER_TEXT (data->label),
|
||||
PANGO_ALIGN_RIGHT);
|
||||
pango_layout_set_alignment (data->test_layout, PANGO_ALIGN_RIGHT);
|
||||
g_assert (check_result (data, "Change alignment", TRUE) == FALSE);
|
||||
|
||||
clutter_main_quit ();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static PangoLayout *
|
||||
make_layout_like_label (ClutterText *label)
|
||||
{
|
||||
PangoLayout *label_layout, *new_layout;
|
||||
PangoContext *context;
|
||||
PangoFontDescription *fd;
|
||||
|
||||
/* Make another layout using the same context as the layout from the
|
||||
label */
|
||||
label_layout = clutter_text_get_layout (label);
|
||||
context = pango_layout_get_context (label_layout);
|
||||
new_layout = pango_layout_new (context);
|
||||
fd = pango_font_description_from_string (TEST_FONT);
|
||||
pango_layout_set_font_description (new_layout, fd);
|
||||
pango_font_description_free (fd);
|
||||
|
||||
return new_layout;
|
||||
}
|
||||
|
||||
void
|
||||
text_cache (void)
|
||||
{
|
||||
CallbackData data;
|
||||
|
||||
memset (&data, 0, sizeof (data));
|
||||
|
||||
data.stage = clutter_stage_new ();
|
||||
|
||||
data.label = clutter_text_new_with_text (TEST_FONT, "");
|
||||
|
||||
data.test_layout = make_layout_like_label (CLUTTER_TEXT (data.label));
|
||||
|
||||
g_signal_connect (data.stage, "paint", G_CALLBACK (on_paint), &data);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (data.stage), data.label, NULL);
|
||||
|
||||
clutter_actor_show (data.stage);
|
||||
|
||||
clutter_threads_add_idle ((GSourceFunc) do_tests, &data);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
clutter_actor_destroy (data.stage);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("\nOverall result: ");
|
||||
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
if (data.test_failed)
|
||||
g_print ("FAIL\n");
|
||||
else
|
||||
g_print ("pass\n");
|
||||
}
|
||||
else
|
||||
g_assert (data.test_failed != TRUE);
|
||||
}
|
||||
|
563
src/tests/clutter/conform/text.c
Normal file
563
src/tests/clutter/conform/text.c
Normal file
@ -0,0 +1,563 @@
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
gunichar unichar;
|
||||
const char bytes[6];
|
||||
gint nbytes;
|
||||
} TestData;
|
||||
|
||||
static const TestData
|
||||
test_text_data[] = {
|
||||
{ 0xe4, "\xc3\xa4", 2 }, /* LATIN SMALL LETTER A WITH DIAERESIS */
|
||||
{ 0x2665, "\xe2\x99\xa5", 3 } /* BLACK HEART SUIT */
|
||||
};
|
||||
|
||||
static void
|
||||
text_utf8_validation (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_text_data); i++)
|
||||
{
|
||||
const TestData *t = &test_text_data[i];
|
||||
gunichar unichar;
|
||||
char bytes[6];
|
||||
int nbytes;
|
||||
|
||||
g_assert (g_unichar_validate (t->unichar));
|
||||
|
||||
nbytes = g_unichar_to_utf8 (t->unichar, bytes);
|
||||
bytes[nbytes] = '\0';
|
||||
g_assert_cmpint (nbytes, ==, t->nbytes);
|
||||
g_assert (memcmp (t->bytes, bytes, nbytes) == 0);
|
||||
|
||||
unichar = g_utf8_get_char_validated (bytes, nbytes);
|
||||
g_assert_cmpint (unichar, ==, t->unichar);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
get_nbytes (ClutterText *text)
|
||||
{
|
||||
const char *s = clutter_text_get_text (text);
|
||||
return strlen (s);
|
||||
}
|
||||
|
||||
static int
|
||||
get_nchars (ClutterText *text)
|
||||
{
|
||||
const char *s = clutter_text_get_text (text);
|
||||
g_assert (g_utf8_validate (s, -1, NULL));
|
||||
return g_utf8_strlen (s, -1);
|
||||
}
|
||||
|
||||
#define DONT_MOVE_CURSOR (-2)
|
||||
|
||||
static void
|
||||
insert_unichar (ClutterText *text, gunichar unichar, int position)
|
||||
{
|
||||
if (position > DONT_MOVE_CURSOR)
|
||||
{
|
||||
clutter_text_set_cursor_position (text, position);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, position);
|
||||
}
|
||||
|
||||
clutter_text_insert_unichar (text, unichar);
|
||||
}
|
||||
|
||||
static void
|
||||
text_set_empty (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
g_object_ref_sink (text);
|
||||
|
||||
g_assert_cmpstr (clutter_text_get_text (text), ==, "");
|
||||
g_assert_cmpint (*clutter_text_get_text (text), ==, '\0');
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1);
|
||||
|
||||
clutter_text_set_text (text, "");
|
||||
g_assert_cmpint (get_nchars (text), ==, 0);
|
||||
g_assert_cmpint (get_nbytes (text), ==, 0);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1);
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static void
|
||||
text_set_text (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
g_object_ref_sink (text);
|
||||
|
||||
clutter_text_set_text (text, "abcdef");
|
||||
g_assert_cmpint (get_nchars (text), ==, 6);
|
||||
g_assert_cmpint (get_nbytes (text), ==, 6);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1);
|
||||
|
||||
clutter_text_set_cursor_position (text, 5);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 5);
|
||||
|
||||
/* FIXME: cursor position should be -1?
|
||||
clutter_text_set_text (text, "");
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1);
|
||||
*/
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static void
|
||||
text_append_some (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
int i;
|
||||
|
||||
g_object_ref_sink (text);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_text_data); i++)
|
||||
{
|
||||
const TestData *t = &test_text_data[i];
|
||||
int j;
|
||||
|
||||
for (j = 1; j <= 4; j++)
|
||||
{
|
||||
insert_unichar (text, t->unichar, DONT_MOVE_CURSOR);
|
||||
|
||||
g_assert_cmpint (get_nchars (text), ==, j);
|
||||
g_assert_cmpint (get_nbytes (text), ==, j * t->nbytes);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1);
|
||||
}
|
||||
|
||||
clutter_text_set_text (text, "");
|
||||
}
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static void
|
||||
text_prepend_some (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
int i;
|
||||
|
||||
g_object_ref_sink (text);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_text_data); i++)
|
||||
{
|
||||
const TestData *t = &test_text_data[i];
|
||||
int j;
|
||||
|
||||
clutter_text_insert_unichar (text, t->unichar);
|
||||
|
||||
g_assert_cmpint (get_nchars (text), ==, 1);
|
||||
g_assert_cmpint (get_nbytes (text), ==, 1 * t->nbytes);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1);
|
||||
|
||||
for (j = 2; j <= 4; j++)
|
||||
{
|
||||
insert_unichar (text, t->unichar, 0);
|
||||
|
||||
g_assert_cmpint (get_nchars (text), ==, j);
|
||||
g_assert_cmpint (get_nbytes (text), ==, j * t->nbytes);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1);
|
||||
}
|
||||
|
||||
clutter_text_set_text (text, "");
|
||||
}
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static void
|
||||
text_insert (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
int i;
|
||||
|
||||
g_object_ref_sink (text);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_text_data); i++)
|
||||
{
|
||||
const TestData *t = &test_text_data[i];
|
||||
|
||||
clutter_text_insert_unichar (text, t->unichar);
|
||||
clutter_text_insert_unichar (text, t->unichar);
|
||||
|
||||
insert_unichar (text, t->unichar, 1);
|
||||
|
||||
g_assert_cmpint (get_nchars (text), ==, 3);
|
||||
g_assert_cmpint (get_nbytes (text), ==, 3 * t->nbytes);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 2);
|
||||
|
||||
clutter_text_set_text (text, "");
|
||||
}
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static void
|
||||
text_delete_chars (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
int i;
|
||||
|
||||
g_object_ref_sink (text);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_text_data); i++)
|
||||
{
|
||||
const TestData *t = &test_text_data[i];
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
clutter_text_insert_unichar (text, t->unichar);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("text: %s\n", clutter_text_get_text (text));
|
||||
|
||||
clutter_text_set_cursor_position (text, 2);
|
||||
clutter_text_delete_chars (text, 1);
|
||||
if (g_test_verbose ())
|
||||
g_print ("text: %s (cursor at: %d)\n",
|
||||
clutter_text_get_text (text),
|
||||
clutter_text_get_cursor_position (text));
|
||||
g_assert_cmpint (get_nchars (text), ==, 3);
|
||||
g_assert_cmpint (get_nbytes (text), ==, 3 * t->nbytes);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1);
|
||||
|
||||
clutter_text_set_cursor_position (text, 2);
|
||||
clutter_text_delete_chars (text, 1);
|
||||
if (g_test_verbose ())
|
||||
g_print ("text: %s (cursor at: %d)\n",
|
||||
clutter_text_get_text (text),
|
||||
clutter_text_get_cursor_position (text));
|
||||
g_assert_cmpint (get_nchars (text), ==, 2);
|
||||
g_assert_cmpint (get_nbytes (text), ==, 2 * t->nbytes);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1);
|
||||
|
||||
clutter_text_set_text (text, "");
|
||||
}
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static void
|
||||
text_get_chars (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
gchar *chars;
|
||||
|
||||
g_object_ref_sink (text);
|
||||
|
||||
clutter_text_set_text (text, "00abcdef11");
|
||||
g_assert_cmpint (get_nchars (text), ==, 10);
|
||||
g_assert_cmpint (get_nbytes (text), ==, 10);
|
||||
g_assert_cmpstr (clutter_text_get_text (text), ==, "00abcdef11");
|
||||
|
||||
chars = clutter_text_get_chars (text, 2, -1);
|
||||
g_assert_cmpstr (chars, ==, "abcdef11");
|
||||
g_free (chars);
|
||||
|
||||
chars = clutter_text_get_chars (text, 0, 8);
|
||||
g_assert_cmpstr (chars, ==, "00abcdef");
|
||||
g_free (chars);
|
||||
|
||||
chars = clutter_text_get_chars (text, 2, 8);
|
||||
g_assert_cmpstr (chars, ==, "abcdef");
|
||||
g_free (chars);
|
||||
|
||||
chars = clutter_text_get_chars (text, 8, 12);
|
||||
g_assert_cmpstr (chars, ==, "11");
|
||||
g_free (chars);
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static void
|
||||
text_delete_text (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
int i;
|
||||
|
||||
g_object_ref_sink (text);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_text_data); i++)
|
||||
{
|
||||
const TestData *t = &test_text_data[i];
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
clutter_text_insert_unichar (text, t->unichar);
|
||||
|
||||
clutter_text_set_cursor_position (text, 3);
|
||||
clutter_text_delete_text (text, 2, 4);
|
||||
|
||||
g_assert_cmpint (get_nchars (text), ==, 2);
|
||||
g_assert_cmpint (get_nbytes (text), ==, 2 * t->nbytes);
|
||||
|
||||
/* FIXME: cursor position should be -1?
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1);
|
||||
*/
|
||||
|
||||
clutter_text_set_text (text, "");
|
||||
}
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static void
|
||||
text_password_char (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
|
||||
g_object_ref_sink (text);
|
||||
|
||||
g_assert_cmpint (clutter_text_get_password_char (text), ==, 0);
|
||||
|
||||
clutter_text_set_text (text, "hello");
|
||||
g_assert_cmpstr (clutter_text_get_text (text), ==, "hello");
|
||||
|
||||
clutter_text_set_password_char (text, '*');
|
||||
g_assert_cmpint (clutter_text_get_password_char (text), ==, '*');
|
||||
|
||||
g_assert_cmpstr (clutter_text_get_text (text), ==, "hello");
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static ClutterEvent *
|
||||
init_event (void)
|
||||
{
|
||||
ClutterEvent *retval = clutter_event_new (CLUTTER_KEY_PRESS);
|
||||
|
||||
clutter_event_set_time (retval, CLUTTER_CURRENT_TIME);
|
||||
clutter_event_set_flags (retval, CLUTTER_EVENT_FLAG_SYNTHETIC);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
send_keyval (ClutterText *text, int keyval)
|
||||
{
|
||||
ClutterEvent *event = init_event ();
|
||||
|
||||
/* Unicode should be ignored for cursor keys etc. */
|
||||
clutter_event_set_key_unicode (event, 0);
|
||||
clutter_event_set_key_symbol (event, keyval);
|
||||
|
||||
clutter_actor_event (CLUTTER_ACTOR (text), event, FALSE);
|
||||
|
||||
clutter_event_free (event);
|
||||
}
|
||||
|
||||
static void
|
||||
send_unichar (ClutterText *text, gunichar unichar)
|
||||
{
|
||||
ClutterEvent *event = init_event ();
|
||||
|
||||
/* Key symbol should be ignored for printable characters */
|
||||
clutter_event_set_key_symbol (event, 0);
|
||||
clutter_event_set_key_unicode (event, unichar);
|
||||
|
||||
clutter_actor_event (CLUTTER_ACTOR (text), event, FALSE);
|
||||
|
||||
clutter_event_free (event);
|
||||
}
|
||||
|
||||
static void
|
||||
text_cursor (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
int i;
|
||||
|
||||
g_object_ref_sink (text);
|
||||
|
||||
/* only editable entries listen to events */
|
||||
clutter_text_set_editable (text, TRUE);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_text_data); i++)
|
||||
{
|
||||
const TestData *t = &test_text_data[i];
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 4; ++j)
|
||||
clutter_text_insert_unichar (text, t->unichar);
|
||||
|
||||
clutter_text_set_cursor_position (text, 2);
|
||||
|
||||
/* test cursor moves and is clamped */
|
||||
send_keyval (text, CLUTTER_KEY_Left);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1);
|
||||
|
||||
send_keyval (text, CLUTTER_KEY_Left);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 0);
|
||||
|
||||
send_keyval (text, CLUTTER_KEY_Left);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 0);
|
||||
|
||||
/* delete text containing the cursor */
|
||||
clutter_text_set_cursor_position (text, 3);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 3);
|
||||
|
||||
clutter_text_delete_text (text, 2, 4);
|
||||
send_keyval (text, CLUTTER_KEY_Left);
|
||||
|
||||
/* FIXME: cursor position should be -1?
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1);
|
||||
*/
|
||||
|
||||
clutter_text_set_text (text, "");
|
||||
}
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static void
|
||||
text_event (void)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (clutter_text_new ());
|
||||
int i;
|
||||
|
||||
g_object_ref_sink (text);
|
||||
|
||||
/* only editable entries listen to events */
|
||||
clutter_text_set_editable (text, TRUE);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_text_data); i++)
|
||||
{
|
||||
const TestData *t = &test_text_data[i];
|
||||
|
||||
send_unichar (text, t->unichar);
|
||||
|
||||
g_assert_cmpint (get_nchars (text), ==, 1);
|
||||
g_assert_cmpint (get_nbytes (text), ==, 1 * t->nbytes);
|
||||
g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1);
|
||||
|
||||
clutter_text_set_text (text, "");
|
||||
}
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
static inline void
|
||||
validate_markup_attributes (ClutterText *text,
|
||||
PangoAttrType attr_type,
|
||||
int start_index,
|
||||
int end_index)
|
||||
{
|
||||
PangoLayout *layout;
|
||||
PangoAttrList *attrs;
|
||||
PangoAttrIterator *iter;
|
||||
|
||||
layout = clutter_text_get_layout (text);
|
||||
g_assert (layout != NULL);
|
||||
|
||||
attrs = pango_layout_get_attributes (layout);
|
||||
g_assert (attrs != NULL);
|
||||
|
||||
iter = pango_attr_list_get_iterator (attrs);
|
||||
while (pango_attr_iterator_next (iter))
|
||||
{
|
||||
GSList *attributes = pango_attr_iterator_get_attrs (iter);
|
||||
PangoAttribute *a;
|
||||
|
||||
if (attributes == NULL)
|
||||
break;
|
||||
|
||||
g_assert (attributes->data != NULL);
|
||||
|
||||
a = attributes->data;
|
||||
|
||||
if (a->klass->type == PANGO_ATTR_SCALE)
|
||||
{
|
||||
PangoAttrFloat *scale = (PangoAttrFloat*) a;
|
||||
float resource_scale;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (text), &resource_scale))
|
||||
resource_scale = 1.0;
|
||||
|
||||
g_assert_cmpfloat (scale->value, ==, resource_scale);
|
||||
g_slist_free_full (attributes, (GDestroyNotify) pango_attribute_destroy);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_assert (a->klass->type == attr_type);
|
||||
g_assert_cmpint (a->start_index, ==, start_index);
|
||||
g_assert_cmpint (a->end_index, ==, end_index);
|
||||
|
||||
g_slist_free_full (attributes, (GDestroyNotify) pango_attribute_destroy);
|
||||
}
|
||||
|
||||
pango_attr_iterator_destroy (iter);
|
||||
}
|
||||
|
||||
static void
|
||||
text_idempotent_use_markup (void)
|
||||
{
|
||||
ClutterText *text;
|
||||
const char *contents = "foo <b>bar</b>";
|
||||
const char *display = "foo bar";
|
||||
int bar_start_index = strstr (display, "bar") - display;
|
||||
int bar_end_index = bar_start_index + strlen ("bar");
|
||||
|
||||
/* case 1: text -> use_markup */
|
||||
if (g_test_verbose ())
|
||||
g_print ("text: '%s' -> use-markup: TRUE\n", contents);
|
||||
|
||||
text = g_object_new (CLUTTER_TYPE_TEXT,
|
||||
"text", contents, "use-markup", TRUE,
|
||||
NULL);
|
||||
g_object_ref_sink (text);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Contents: '%s' (expected: '%s')\n",
|
||||
clutter_text_get_text (text),
|
||||
display);
|
||||
|
||||
g_assert_cmpstr (clutter_text_get_text (text), ==, display);
|
||||
|
||||
validate_markup_attributes (text,
|
||||
PANGO_ATTR_WEIGHT,
|
||||
bar_start_index,
|
||||
bar_end_index);
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
|
||||
/* case 2: use_markup -> text */
|
||||
if (g_test_verbose ())
|
||||
g_print ("use-markup: TRUE -> text: '%s'\n", contents);
|
||||
|
||||
text = g_object_new (CLUTTER_TYPE_TEXT,
|
||||
"use-markup", TRUE, "text", contents,
|
||||
NULL);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Contents: '%s' (expected: '%s')\n",
|
||||
clutter_text_get_text (text),
|
||||
display);
|
||||
|
||||
g_assert_cmpstr (clutter_text_get_text (text), ==, display);
|
||||
|
||||
validate_markup_attributes (text,
|
||||
PANGO_ATTR_WEIGHT,
|
||||
bar_start_index,
|
||||
bar_end_index);
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (text));
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/text/utf8-validation", text_utf8_validation)
|
||||
CLUTTER_TEST_UNIT ("/text/set-empty", text_set_empty)
|
||||
CLUTTER_TEST_UNIT ("/text/set-text", text_set_text)
|
||||
CLUTTER_TEST_UNIT ("/text/append-some", text_append_some)
|
||||
CLUTTER_TEST_UNIT ("/text/prepend-some", text_prepend_some)
|
||||
CLUTTER_TEST_UNIT ("/text/insert", text_insert)
|
||||
CLUTTER_TEST_UNIT ("/text/delete-chars", text_delete_chars)
|
||||
CLUTTER_TEST_UNIT ("/text/get-chars", text_get_chars)
|
||||
CLUTTER_TEST_UNIT ("/text/delete-text", text_delete_text)
|
||||
CLUTTER_TEST_UNIT ("/text/password-char", text_password_char)
|
||||
CLUTTER_TEST_UNIT ("/text/cursor", text_cursor)
|
||||
CLUTTER_TEST_UNIT ("/text/event", text_event)
|
||||
CLUTTER_TEST_UNIT ("/text/idempotent-use-markup", text_idempotent_use_markup)
|
||||
)
|
235
src/tests/clutter/conform/texture-fbo.c
Normal file
235
src/tests/clutter/conform/texture-fbo.c
Normal file
@ -0,0 +1,235 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "test-conform-common.h"
|
||||
|
||||
#define SOURCE_SIZE 32
|
||||
#define SOURCE_DIVISIONS_X 2
|
||||
#define SOURCE_DIVISIONS_Y 2
|
||||
#define DIVISION_WIDTH (SOURCE_SIZE / SOURCE_DIVISIONS_X)
|
||||
#define DIVISION_HEIGHT (SOURCE_SIZE / SOURCE_DIVISIONS_Y)
|
||||
|
||||
static const ClutterColor
|
||||
corner_colors[SOURCE_DIVISIONS_X * SOURCE_DIVISIONS_Y] =
|
||||
{
|
||||
{ 0xff, 0x00, 0x00, 0xff }, /* red top left */
|
||||
{ 0x00, 0xff, 0x00, 0xff }, /* green top right */
|
||||
{ 0x00, 0x00, 0xff, 0xff }, /* blue bottom left */
|
||||
{ 0xff, 0x00, 0xff, 0xff } /* purple bottom right */
|
||||
};
|
||||
|
||||
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
||||
|
||||
typedef struct _TestState
|
||||
{
|
||||
ClutterActor *stage;
|
||||
guint frame;
|
||||
gboolean was_painted;
|
||||
} TestState;
|
||||
|
||||
static ClutterActor *
|
||||
create_source (void)
|
||||
{
|
||||
int x, y;
|
||||
ClutterActor *group = clutter_group_new ();
|
||||
|
||||
/* Create a group with a different coloured rectangle at each
|
||||
corner */
|
||||
for (y = 0; y < SOURCE_DIVISIONS_Y; y++)
|
||||
for (x = 0; x < SOURCE_DIVISIONS_X; x++)
|
||||
{
|
||||
ClutterActor *rect = clutter_rectangle_new ();
|
||||
clutter_actor_set_size (rect, DIVISION_WIDTH, DIVISION_HEIGHT);
|
||||
clutter_actor_set_position (rect,
|
||||
DIVISION_WIDTH * x,
|
||||
DIVISION_HEIGHT * y);
|
||||
clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect),
|
||||
corner_colors +
|
||||
(y * SOURCE_DIVISIONS_X + x));
|
||||
clutter_container_add (CLUTTER_CONTAINER (group), rect, NULL);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static void
|
||||
pre_paint_clip_cb (void)
|
||||
{
|
||||
/* Generate a clip path that clips out the top left division */
|
||||
cogl_path_move_to (DIVISION_WIDTH, 0);
|
||||
cogl_path_line_to (SOURCE_SIZE, 0);
|
||||
cogl_path_line_to (SOURCE_SIZE, SOURCE_SIZE);
|
||||
cogl_path_line_to (0, SOURCE_SIZE);
|
||||
cogl_path_line_to (0, DIVISION_HEIGHT);
|
||||
cogl_path_line_to (DIVISION_WIDTH, DIVISION_HEIGHT);
|
||||
cogl_path_close ();
|
||||
cogl_clip_push_from_path ();
|
||||
}
|
||||
|
||||
static void
|
||||
post_paint_clip_cb (void)
|
||||
{
|
||||
cogl_clip_pop ();
|
||||
}
|
||||
|
||||
static void
|
||||
validate_part (TestState *state,
|
||||
int xpos, int ypos,
|
||||
int clip_flags)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
/* Check whether the center of each division is the right color */
|
||||
for (y = 0; y < SOURCE_DIVISIONS_Y; y++)
|
||||
for (x = 0; x < SOURCE_DIVISIONS_X; x++)
|
||||
{
|
||||
guchar *pixels;
|
||||
const ClutterColor *correct_color;
|
||||
|
||||
/* Read the center pixels of this division */
|
||||
pixels = clutter_stage_read_pixels (CLUTTER_STAGE (state->stage),
|
||||
x * DIVISION_WIDTH +
|
||||
DIVISION_WIDTH / 2 + xpos,
|
||||
y * DIVISION_HEIGHT +
|
||||
DIVISION_HEIGHT / 2 + ypos,
|
||||
1, 1);
|
||||
|
||||
/* If this division is clipped then it should be the stage
|
||||
color */
|
||||
if ((clip_flags & (1 << ((y * SOURCE_DIVISIONS_X) + x))))
|
||||
correct_color = &stage_color;
|
||||
else
|
||||
/* Otherwise it should be the color for this division */
|
||||
correct_color = corner_colors + (y * SOURCE_DIVISIONS_X) + x;
|
||||
|
||||
g_assert (pixels != NULL);
|
||||
g_assert_cmpint (pixels[0], ==, correct_color->red);
|
||||
g_assert_cmpint (pixels[1], ==, correct_color->green);
|
||||
g_assert_cmpint (pixels[2], ==, correct_color->blue);
|
||||
|
||||
g_free (pixels);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
validate_result (TestState *state)
|
||||
{
|
||||
int ypos = 0;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Testing onscreen clone...\n");
|
||||
validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 0);
|
||||
ypos++;
|
||||
|
||||
#if 0 /* this doesn't work */
|
||||
if (g_test_verbose ())
|
||||
g_print ("Testing offscreen clone...\n");
|
||||
validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 0);
|
||||
#endif
|
||||
ypos++;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Testing onscreen clone with rectangular clip...\n");
|
||||
validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, ~1);
|
||||
ypos++;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Testing onscreen clone with path clip...\n");
|
||||
validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 1);
|
||||
ypos++;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_paint (gpointer data)
|
||||
{
|
||||
TestState *state = data;
|
||||
int frame_num;
|
||||
|
||||
/* XXX: validate_result calls clutter_stage_read_pixels which will result in
|
||||
* another paint run so to avoid infinite recursion we only aim to validate
|
||||
* the first frame. */
|
||||
frame_num = state->frame++;
|
||||
if (frame_num == 1)
|
||||
validate_result (state);
|
||||
|
||||
state->was_painted = TRUE;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
texture_fbo (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
TestState state;
|
||||
ClutterActor *actor;
|
||||
int ypos = 0;
|
||||
|
||||
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("Offscreen buffers are not available, skipping.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
state.frame = 0;
|
||||
|
||||
state.stage = clutter_stage_new ();
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (state.stage), &stage_color);
|
||||
|
||||
/* Onscreen source with clone next to it */
|
||||
actor = create_source ();
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE);
|
||||
actor = clutter_texture_new_from_actor (actor);
|
||||
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
ypos++;
|
||||
|
||||
/* Offscreen source with clone */
|
||||
#if 0 /* this doesn't work */
|
||||
actor = create_source ();
|
||||
actor = clutter_texture_new_from_actor (actor);
|
||||
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
#endif
|
||||
ypos++;
|
||||
|
||||
/* Source clipped to the top left division */
|
||||
actor = create_source ();
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE);
|
||||
clutter_actor_set_clip (actor, 0, 0, DIVISION_WIDTH, DIVISION_HEIGHT);
|
||||
actor = clutter_texture_new_from_actor (actor);
|
||||
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
ypos++;
|
||||
|
||||
/* Source clipped to everything but top left division using a
|
||||
path */
|
||||
actor = create_source ();
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE);
|
||||
g_signal_connect (actor, "paint",
|
||||
G_CALLBACK (pre_paint_clip_cb), NULL);
|
||||
g_signal_connect_after (actor, "paint",
|
||||
G_CALLBACK (post_paint_clip_cb), NULL);
|
||||
actor = clutter_texture_new_from_actor (actor);
|
||||
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
ypos++;
|
||||
|
||||
clutter_actor_show (state.stage);
|
||||
|
||||
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
|
||||
on_paint,
|
||||
&state,
|
||||
NULL);
|
||||
|
||||
while (!state.was_painted)
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
|
||||
clutter_actor_destroy (state.stage);
|
||||
}
|
84
src/tests/clutter/conform/texture.c
Normal file
84
src/tests/clutter/conform/texture.c
Normal file
@ -0,0 +1,84 @@
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include <clutter/clutter.h>
|
||||
#include <string.h>
|
||||
|
||||
static CoglHandle
|
||||
make_texture (void)
|
||||
{
|
||||
guint32 *data = g_malloc (100 * 100 * 4);
|
||||
int x;
|
||||
int y;
|
||||
|
||||
for (y = 0; y < 100; y ++)
|
||||
for (x = 0; x < 100; x++)
|
||||
{
|
||||
if (x < 50 && y < 50)
|
||||
data[y * 100 + x] = 0xff00ff00;
|
||||
else
|
||||
data[y * 100 + x] = 0xff00ffff;
|
||||
}
|
||||
return cogl_texture_new_from_data (100,
|
||||
100,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_ARGB_8888,
|
||||
COGL_PIXEL_FORMAT_ARGB_8888,
|
||||
400,
|
||||
(guchar *)data);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_pick_with_alpha (void)
|
||||
{
|
||||
ClutterTexture *tex = CLUTTER_TEXTURE (clutter_texture_new ());
|
||||
ClutterStage *stage = CLUTTER_STAGE (clutter_test_get_stage ());
|
||||
ClutterActor *actor;
|
||||
|
||||
clutter_texture_set_cogl_texture (tex, make_texture ());
|
||||
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (stage), CLUTTER_ACTOR (tex));
|
||||
|
||||
clutter_actor_show (CLUTTER_ACTOR (stage));
|
||||
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
g_print ("\nstage = %p\n", stage);
|
||||
g_print ("texture = %p\n\n", tex);
|
||||
}
|
||||
|
||||
clutter_texture_set_pick_with_alpha (tex, TRUE);
|
||||
if (g_test_verbose ())
|
||||
g_print ("Testing with pick-with-alpha enabled:\n");
|
||||
|
||||
/* This should fall through and hit the stage: */
|
||||
actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, 10, 10);
|
||||
if (g_test_verbose ())
|
||||
g_print ("actor @ (10, 10) = %p\n", actor);
|
||||
g_assert (actor == CLUTTER_ACTOR (stage));
|
||||
|
||||
/* The rest should hit the texture */
|
||||
actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, 90, 10);
|
||||
if (g_test_verbose ())
|
||||
g_print ("actor @ (90, 10) = %p\n", actor);
|
||||
g_assert (actor == CLUTTER_ACTOR (tex));
|
||||
actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, 90, 90);
|
||||
if (g_test_verbose ())
|
||||
g_print ("actor @ (90, 90) = %p\n", actor);
|
||||
g_assert (actor == CLUTTER_ACTOR (tex));
|
||||
actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, 10, 90);
|
||||
if (g_test_verbose ())
|
||||
g_print ("actor @ (10, 90) = %p\n", actor);
|
||||
g_assert (actor == CLUTTER_ACTOR (tex));
|
||||
|
||||
clutter_texture_set_pick_with_alpha (tex, FALSE);
|
||||
if (g_test_verbose ())
|
||||
g_print ("Testing with pick-with-alpha disabled:\n");
|
||||
|
||||
actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, 10, 10);
|
||||
if (g_test_verbose ())
|
||||
g_print ("actor @ (10, 10) = %p\n", actor);
|
||||
g_assert (actor == CLUTTER_ACTOR (tex));
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/texture/pick-with-alpha", texture_pick_with_alpha)
|
||||
)
|
161
src/tests/clutter/conform/timeline-interpolate.c
Normal file
161
src/tests/clutter/conform/timeline-interpolate.c
Normal file
@ -0,0 +1,161 @@
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "test-conform-common.h"
|
||||
|
||||
/* We ask for 1 frame per millisecond.
|
||||
* Whenever this rate can't be achieved then the timeline
|
||||
* will interpolate the number frames that should have
|
||||
* passed between timeouts. */
|
||||
#define TEST_TIMELINE_FPS 1000
|
||||
#define TEST_TIMELINE_DURATION 5000
|
||||
|
||||
/* We are at the mercy of the system scheduler so this
|
||||
* may not be a very reliable tolerance. */
|
||||
#define TEST_ERROR_TOLERANCE 20
|
||||
|
||||
typedef struct _TestState
|
||||
{
|
||||
ClutterTimeline *timeline;
|
||||
int64_t start_time;
|
||||
guint new_frame_counter;
|
||||
gint expected_frame;
|
||||
gint completion_count;
|
||||
gboolean passed;
|
||||
} TestState;
|
||||
|
||||
|
||||
static void
|
||||
new_frame_cb (ClutterTimeline *timeline,
|
||||
gint frame_num,
|
||||
TestState *state)
|
||||
{
|
||||
int64_t current_time;
|
||||
gint current_frame;
|
||||
glong msec_diff;
|
||||
gint loop_overflow = 0;
|
||||
static gint step = 1;
|
||||
|
||||
current_time = g_get_real_time ();
|
||||
|
||||
current_frame = clutter_timeline_get_elapsed_time (state->timeline);
|
||||
|
||||
msec_diff = (current_time - state->start_time) / G_TIME_SPAN_MILLISECOND;
|
||||
|
||||
/* If we expect to have interpolated past the end of the timeline
|
||||
* we keep track of the overflow so we can determine when
|
||||
* the next timeout will happen. We then clip expected_frames
|
||||
* to TEST_TIMELINE_DURATION since clutter-timeline
|
||||
* semantics guaranty this frame is always signaled before
|
||||
* looping */
|
||||
if (state->expected_frame > TEST_TIMELINE_DURATION)
|
||||
{
|
||||
loop_overflow = state->expected_frame - TEST_TIMELINE_DURATION;
|
||||
state->expected_frame = TEST_TIMELINE_DURATION;
|
||||
}
|
||||
|
||||
if (current_frame >= (state->expected_frame-TEST_ERROR_TOLERANCE)
|
||||
&& current_frame <= (state->expected_frame+TEST_ERROR_TOLERANCE))
|
||||
{
|
||||
g_test_message ("elapsed milliseconds=%-5li "
|
||||
"expected frame=%-4i actual frame=%-4i (OK)",
|
||||
msec_diff,
|
||||
state->expected_frame,
|
||||
current_frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_test_message ("elapsed milliseconds=%-5li "
|
||||
"expected frame=%-4i actual frame=%-4i (FAILED)",
|
||||
msec_diff,
|
||||
state->expected_frame,
|
||||
current_frame);
|
||||
state->passed = FALSE;
|
||||
}
|
||||
|
||||
if (step>0)
|
||||
{
|
||||
state->expected_frame = current_frame + (TEST_TIMELINE_FPS / 4);
|
||||
g_test_message ("Sleeping for 250ms "
|
||||
"so next frame should be (%i + %i) = %i",
|
||||
current_frame,
|
||||
(TEST_TIMELINE_FPS / 4),
|
||||
state->expected_frame);
|
||||
g_usleep (250000);
|
||||
}
|
||||
else
|
||||
{
|
||||
state->expected_frame = current_frame + TEST_TIMELINE_FPS;
|
||||
g_test_message ("Sleeping for 1sec "
|
||||
"so next frame should be (%i + %i) = %i",
|
||||
current_frame,
|
||||
TEST_TIMELINE_FPS,
|
||||
state->expected_frame);
|
||||
g_usleep (1000000);
|
||||
}
|
||||
|
||||
if (current_frame >= TEST_TIMELINE_DURATION)
|
||||
{
|
||||
state->expected_frame += loop_overflow;
|
||||
state->expected_frame -= TEST_TIMELINE_DURATION;
|
||||
g_test_message ("End of timeline reached: "
|
||||
"Wrapping expected frame too %i",
|
||||
state->expected_frame);
|
||||
}
|
||||
|
||||
state->new_frame_counter++;
|
||||
step = -step;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
completed_cb (ClutterTimeline *timeline,
|
||||
TestState *state)
|
||||
{
|
||||
state->completion_count++;
|
||||
|
||||
if (state->completion_count == 2)
|
||||
{
|
||||
if (state->passed)
|
||||
{
|
||||
g_test_message ("Passed\n");
|
||||
clutter_main_quit ();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_test_message ("Failed\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
timeline_interpolation (void)
|
||||
{
|
||||
TestState state;
|
||||
|
||||
state.timeline =
|
||||
clutter_timeline_new (TEST_TIMELINE_DURATION);
|
||||
clutter_timeline_set_loop (state.timeline, TRUE);
|
||||
g_signal_connect (G_OBJECT(state.timeline),
|
||||
"new-frame",
|
||||
G_CALLBACK(new_frame_cb),
|
||||
&state);
|
||||
g_signal_connect (G_OBJECT(state.timeline),
|
||||
"completed",
|
||||
G_CALLBACK(completed_cb),
|
||||
&state);
|
||||
|
||||
state.completion_count = 0;
|
||||
state.new_frame_counter = 0;
|
||||
state.passed = TRUE;
|
||||
state.expected_frame = 0;
|
||||
|
||||
state.start_time = g_get_real_time ();
|
||||
clutter_timeline_start (state.timeline);
|
||||
|
||||
clutter_main();
|
||||
|
||||
g_object_unref (state.timeline);
|
||||
}
|
110
src/tests/clutter/conform/timeline-progress.c
Normal file
110
src/tests/clutter/conform/timeline-progress.c
Normal file
@ -0,0 +1,110 @@
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include "test-conform-common.h"
|
||||
|
||||
void
|
||||
timeline_progress_step (TestConformSimpleFixture *fixture G_GNUC_UNUSED,
|
||||
gconstpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
timeline = clutter_timeline_new (1000);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("mode: step(3, end)\n");
|
||||
|
||||
clutter_timeline_rewind (timeline);
|
||||
clutter_timeline_set_step_progress (timeline, 3, CLUTTER_STEP_MODE_END);
|
||||
g_assert_cmpint (clutter_timeline_get_progress (timeline), ==, 0);
|
||||
|
||||
clutter_timeline_advance (timeline, 1000 / 3 - 1);
|
||||
g_assert_cmpint (clutter_timeline_get_progress (timeline) * 1000, ==, 0);
|
||||
|
||||
clutter_timeline_advance (timeline, 1000 / 3 + 1);
|
||||
g_assert_cmpint (clutter_timeline_get_progress (timeline) * 1000, ==, 333);
|
||||
|
||||
clutter_timeline_advance (timeline, 1000 / 3 * 2 - 1);
|
||||
g_assert_cmpint (clutter_timeline_get_progress (timeline) * 1000, ==, 333);
|
||||
|
||||
clutter_timeline_advance (timeline, 1000 / 3 * 2 + 1);
|
||||
g_assert_cmpint (clutter_timeline_get_progress (timeline) * 1000, ==, 666);
|
||||
|
||||
clutter_timeline_rewind (timeline);
|
||||
clutter_timeline_set_progress_mode (timeline, CLUTTER_STEP_START);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 1);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 500);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 999);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 1000);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("mode: step-start\n");
|
||||
|
||||
clutter_timeline_rewind (timeline);
|
||||
clutter_timeline_set_progress_mode (timeline, CLUTTER_STEP_START);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 1);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 500);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 999);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 1000);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("mode: step-end\n");
|
||||
|
||||
clutter_timeline_rewind (timeline);
|
||||
clutter_timeline_set_progress_mode (timeline, CLUTTER_STEP_END);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 1);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 500);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 999);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 1000);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0);
|
||||
|
||||
g_object_unref (timeline);
|
||||
}
|
||||
|
||||
void
|
||||
timeline_progress_mode (TestConformSimpleFixture *fixture G_GNUC_UNUSED,
|
||||
gconstpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
timeline = clutter_timeline_new (1000);
|
||||
|
||||
g_assert (clutter_timeline_get_progress_mode (timeline) == CLUTTER_LINEAR);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0);
|
||||
|
||||
clutter_timeline_advance (timeline, 500);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.5);
|
||||
|
||||
clutter_timeline_advance (timeline, 1000);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0);
|
||||
|
||||
clutter_timeline_rewind (timeline);
|
||||
g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0);
|
||||
|
||||
g_object_unref (timeline);
|
||||
}
|
92
src/tests/clutter/conform/timeline-rewind.c
Normal file
92
src/tests/clutter/conform/timeline-rewind.c
Normal file
@ -0,0 +1,92 @@
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "test-conform-common.h"
|
||||
|
||||
#define TEST_TIMELINE_DURATION 500
|
||||
#define TEST_WATCHDOG_KICK_IN_SECONDS 10
|
||||
|
||||
typedef struct _TestState
|
||||
{
|
||||
ClutterTimeline *timeline;
|
||||
gint rewind_count;
|
||||
} TestState;
|
||||
|
||||
static gboolean
|
||||
watchdog_timeout (gpointer data)
|
||||
{
|
||||
TestState *state = data;
|
||||
|
||||
g_test_message ("Watchdog timer kicking in");
|
||||
g_test_message ("rewind_count=%i", state->rewind_count);
|
||||
if (state->rewind_count <= 3)
|
||||
{
|
||||
/* The test has hung */
|
||||
g_test_message ("Failed (This test shouldn't have hung!)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_test_message ("Passed");
|
||||
clutter_main_quit ();
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
new_frame_cb (ClutterTimeline *timeline,
|
||||
gint elapsed_time,
|
||||
TestState *state)
|
||||
{
|
||||
if (elapsed_time == TEST_TIMELINE_DURATION)
|
||||
{
|
||||
g_test_message ("new-frame signal received (end of timeline)");
|
||||
g_test_message ("Rewinding timeline");
|
||||
clutter_timeline_rewind (timeline);
|
||||
state->rewind_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (elapsed_time == 0)
|
||||
{
|
||||
g_test_message ("new-frame signal received (start of timeline)");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_test_message ("new-frame signal received (mid frame)");
|
||||
}
|
||||
|
||||
if (state->rewind_count >= 2)
|
||||
{
|
||||
g_test_message ("Sleeping for 1 second");
|
||||
g_usleep (1000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
timeline_rewind (void)
|
||||
{
|
||||
TestState state;
|
||||
|
||||
state.timeline =
|
||||
clutter_timeline_new (TEST_TIMELINE_DURATION);
|
||||
g_signal_connect (G_OBJECT(state.timeline),
|
||||
"new-frame",
|
||||
G_CALLBACK(new_frame_cb),
|
||||
&state);
|
||||
g_test_message ("Installing a watchdog timeout "
|
||||
"to determine if this test hangs");
|
||||
clutter_threads_add_timeout (TEST_WATCHDOG_KICK_IN_SECONDS * 1000,
|
||||
watchdog_timeout,
|
||||
&state);
|
||||
state.rewind_count = 0;
|
||||
|
||||
clutter_timeline_start (state.timeline);
|
||||
|
||||
clutter_main();
|
||||
|
||||
g_object_unref (state.timeline);
|
||||
}
|
361
src/tests/clutter/conform/timeline.c
Normal file
361
src/tests/clutter/conform/timeline.c
Normal file
@ -0,0 +1,361 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "test-conform-common.h"
|
||||
|
||||
/* This test runs three timelines at 30 fps with 10 frames. Some of
|
||||
the timelines have markers. Once the timelines are run it then
|
||||
checks that all of the frames were hit, all of the markers were hit
|
||||
and that the completed signal was fired. The timelines are then run
|
||||
again but this time with a timeout source that introduces a
|
||||
delay. This should cause some frames to be skipped. The test is run
|
||||
again but only the markers and the completed signal is checked
|
||||
for. */
|
||||
|
||||
#define FRAME_COUNT 10
|
||||
#define FPS 30
|
||||
|
||||
typedef struct _TimelineData TimelineData;
|
||||
|
||||
struct _TimelineData
|
||||
{
|
||||
int timeline_num;
|
||||
|
||||
guint frame_hit_count[FRAME_COUNT + 1];
|
||||
GSList *markers_hit;
|
||||
guint completed_count;
|
||||
};
|
||||
|
||||
static void
|
||||
timeline_data_init (TimelineData *data, int timeline_num)
|
||||
{
|
||||
memset (data, 0, sizeof (TimelineData));
|
||||
data->timeline_num = timeline_num;
|
||||
}
|
||||
|
||||
static void
|
||||
timeline_data_destroy (TimelineData *data)
|
||||
{
|
||||
g_slist_free_full (data->markers_hit, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
timeline_complete_cb (ClutterTimeline *timeline,
|
||||
TimelineData *data)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("%i: Completed\n", data->timeline_num);
|
||||
|
||||
data->completed_count++;
|
||||
}
|
||||
|
||||
static void
|
||||
timeline_new_frame_cb (ClutterTimeline *timeline,
|
||||
gint msec,
|
||||
TimelineData *data)
|
||||
{
|
||||
/* Calculate an approximate frame number from the duration with
|
||||
rounding */
|
||||
int frame_no = ((msec * FRAME_COUNT + (FRAME_COUNT * 1000 / FPS) / 2)
|
||||
/ (FRAME_COUNT * 1000 / FPS));
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("%i: Doing frame %d, delta = %i\n",
|
||||
data->timeline_num, frame_no,
|
||||
clutter_timeline_get_delta (timeline));
|
||||
|
||||
g_assert (frame_no >= 0 && frame_no <= FRAME_COUNT);
|
||||
|
||||
data->frame_hit_count[frame_no]++;
|
||||
}
|
||||
|
||||
static void
|
||||
timeline_marker_reached_cb (ClutterTimeline *timeline,
|
||||
const gchar *marker_name,
|
||||
guint frame_num,
|
||||
TimelineData *data)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("%i: Marker '%s' (%d) reached, delta = %i\n",
|
||||
data->timeline_num, marker_name, frame_num,
|
||||
clutter_timeline_get_delta (timeline));
|
||||
data->markers_hit = g_slist_prepend (data->markers_hit,
|
||||
g_strdup (marker_name));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_timeline (ClutterTimeline *timeline,
|
||||
TimelineData *data,
|
||||
gboolean check_missed_frames)
|
||||
{
|
||||
gchar **markers;
|
||||
gsize n_markers;
|
||||
guint *marker_reached_count;
|
||||
gboolean succeeded = TRUE;
|
||||
GSList *node;
|
||||
int i;
|
||||
int missed_frame_count = 0;
|
||||
int frame_offset;
|
||||
|
||||
if (clutter_timeline_get_direction (timeline) == CLUTTER_TIMELINE_BACKWARD)
|
||||
frame_offset = 0;
|
||||
else
|
||||
frame_offset = 1;
|
||||
|
||||
markers = clutter_timeline_list_markers (timeline, -1, &n_markers);
|
||||
marker_reached_count = g_new0 (guint, n_markers);
|
||||
|
||||
for (node = data->markers_hit; node; node = node->next)
|
||||
{
|
||||
for (i = 0; i < n_markers; i++)
|
||||
if (!strcmp (node->data, markers[i]))
|
||||
break;
|
||||
|
||||
if (i < n_markers)
|
||||
marker_reached_count[i]++;
|
||||
else
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("FAIL: unknown marker '%s' hit for timeline %i\n",
|
||||
(char *) node->data, data->timeline_num);
|
||||
succeeded = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n_markers; i++)
|
||||
if (marker_reached_count[i] != 1)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("FAIL: marker '%s' hit %i times for timeline %i\n",
|
||||
markers[i], marker_reached_count[i], data->timeline_num);
|
||||
succeeded = FALSE;
|
||||
}
|
||||
|
||||
if (check_missed_frames)
|
||||
{
|
||||
for (i = 0; i < FRAME_COUNT; i++)
|
||||
if (data->frame_hit_count[i + frame_offset] < 1)
|
||||
missed_frame_count++;
|
||||
|
||||
if (missed_frame_count)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("FAIL: missed %i frame%s for timeline %i\n",
|
||||
missed_frame_count, missed_frame_count == 1 ? "" : "s",
|
||||
data->timeline_num);
|
||||
succeeded = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->completed_count != 1)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("FAIL: timeline %i completed %i times\n",
|
||||
data->timeline_num, data->completed_count);
|
||||
succeeded = FALSE;
|
||||
}
|
||||
|
||||
g_strfreev (markers);
|
||||
g_free (marker_reached_count);
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timeout_cb (gpointer data G_GNUC_UNUSED)
|
||||
{
|
||||
clutter_main_quit ();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
delay_cb (gpointer data)
|
||||
{
|
||||
/* Waste a bit of time so that it will skip frames */
|
||||
g_usleep (G_USEC_PER_SEC * 66 / 1000);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
timeline_base (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
ClutterTimeline *timeline_1;
|
||||
TimelineData data_1;
|
||||
ClutterTimeline *timeline_2;
|
||||
TimelineData data_2;
|
||||
ClutterTimeline *timeline_3;
|
||||
TimelineData data_3;
|
||||
gchar **markers;
|
||||
gsize n_markers;
|
||||
guint delay_tag;
|
||||
|
||||
/* NB: We have to ensure a stage is instantiated else the master
|
||||
* clock wont run... */
|
||||
ClutterActor *stage = clutter_stage_new ();
|
||||
|
||||
timeline_data_init (&data_1, 1);
|
||||
timeline_1 = clutter_timeline_new (FRAME_COUNT * 1000 / FPS);
|
||||
clutter_timeline_add_marker_at_time (timeline_1, "start-marker",
|
||||
0 * 1000 / FPS);
|
||||
clutter_timeline_add_marker_at_time (timeline_1, "foo", 5 * 1000 / FPS);
|
||||
clutter_timeline_add_marker_at_time (timeline_1, "bar", 5 * 1000 / FPS);
|
||||
clutter_timeline_add_marker_at_time (timeline_1, "baz", 5 * 1000 / FPS);
|
||||
clutter_timeline_add_marker_at_time (timeline_1, "near-end-marker",
|
||||
9 * 1000 / FPS);
|
||||
clutter_timeline_add_marker_at_time (timeline_1, "end-marker",
|
||||
10 * 1000 / FPS);
|
||||
markers = clutter_timeline_list_markers (timeline_1, 5 * 1000 / FPS,
|
||||
&n_markers);
|
||||
g_assert (markers != NULL);
|
||||
g_assert (n_markers == 3);
|
||||
g_strfreev (markers);
|
||||
|
||||
timeline_data_init (&data_2, 2);
|
||||
timeline_2 = clutter_timeline_clone (timeline_1);
|
||||
clutter_timeline_add_marker_at_time (timeline_2, "bar", 2 * 1000 / FPS);
|
||||
markers = clutter_timeline_list_markers (timeline_2, -1, &n_markers);
|
||||
g_assert (markers != NULL);
|
||||
g_assert (n_markers == 1);
|
||||
g_assert (strcmp (markers[0], "bar") == 0);
|
||||
g_strfreev (markers);
|
||||
|
||||
timeline_data_init (&data_3, 3);
|
||||
timeline_3 = clutter_timeline_clone (timeline_1);
|
||||
clutter_timeline_set_direction (timeline_3, CLUTTER_TIMELINE_BACKWARD);
|
||||
clutter_timeline_add_marker_at_time (timeline_3, "start-marker",
|
||||
FRAME_COUNT * 1000 / FPS);
|
||||
clutter_timeline_add_marker_at_time (timeline_3, "foo", 5 * 1000 / FPS);
|
||||
clutter_timeline_add_marker_at_time (timeline_3, "baz", 8 * 1000 / FPS);
|
||||
clutter_timeline_add_marker_at_time (timeline_3, "near-end-marker",
|
||||
1 * 1000 / FPS);
|
||||
clutter_timeline_add_marker_at_time (timeline_3, "end-marker",
|
||||
0 * 1000 / FPS);
|
||||
|
||||
g_signal_connect (timeline_1,
|
||||
"marker-reached", G_CALLBACK (timeline_marker_reached_cb),
|
||||
&data_1);
|
||||
g_signal_connect (timeline_1,
|
||||
"new-frame", G_CALLBACK (timeline_new_frame_cb),
|
||||
&data_1);
|
||||
g_signal_connect (timeline_1,
|
||||
"completed", G_CALLBACK (timeline_complete_cb),
|
||||
&data_1);
|
||||
|
||||
g_signal_connect (timeline_2,
|
||||
"marker-reached::bar",
|
||||
G_CALLBACK (timeline_marker_reached_cb),
|
||||
&data_2);
|
||||
g_signal_connect (timeline_2,
|
||||
"new-frame", G_CALLBACK (timeline_new_frame_cb),
|
||||
&data_2);
|
||||
g_signal_connect (timeline_2,
|
||||
"completed", G_CALLBACK (timeline_complete_cb),
|
||||
&data_2);
|
||||
|
||||
g_signal_connect (timeline_3,
|
||||
"marker-reached", G_CALLBACK (timeline_marker_reached_cb),
|
||||
&data_3);
|
||||
g_signal_connect (timeline_3,
|
||||
"new-frame", G_CALLBACK (timeline_new_frame_cb),
|
||||
&data_3);
|
||||
g_signal_connect (timeline_3,
|
||||
"completed", G_CALLBACK (timeline_complete_cb),
|
||||
&data_3);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Without delay...\n");
|
||||
|
||||
clutter_timeline_start (timeline_1);
|
||||
clutter_timeline_start (timeline_2);
|
||||
clutter_timeline_start (timeline_3);
|
||||
|
||||
clutter_threads_add_timeout (2000, timeout_cb, NULL);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_assert (check_timeline (timeline_1, &data_1, TRUE));
|
||||
g_assert (check_timeline (timeline_2, &data_2, TRUE));
|
||||
g_assert (check_timeline (timeline_3, &data_3, TRUE));
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("With delay...\n");
|
||||
|
||||
timeline_data_destroy (&data_1);
|
||||
timeline_data_init (&data_1, 1);
|
||||
timeline_data_destroy (&data_2);
|
||||
timeline_data_init (&data_2, 2);
|
||||
timeline_data_destroy (&data_3);
|
||||
timeline_data_init (&data_3, 3);
|
||||
|
||||
clutter_timeline_start (timeline_1);
|
||||
clutter_timeline_start (timeline_2);
|
||||
clutter_timeline_start (timeline_3);
|
||||
|
||||
clutter_threads_add_timeout (2000, timeout_cb, NULL);
|
||||
delay_tag = clutter_threads_add_timeout (99, delay_cb, NULL);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_assert (check_timeline (timeline_1, &data_1, FALSE));
|
||||
g_assert (check_timeline (timeline_2, &data_2, FALSE));
|
||||
g_assert (check_timeline (timeline_3, &data_3, FALSE));
|
||||
|
||||
g_object_unref (timeline_1);
|
||||
g_object_unref (timeline_2);
|
||||
g_object_unref (timeline_3);
|
||||
|
||||
timeline_data_destroy (&data_1);
|
||||
timeline_data_destroy (&data_2);
|
||||
timeline_data_destroy (&data_3);
|
||||
|
||||
g_source_remove (delay_tag);
|
||||
|
||||
clutter_actor_destroy (stage);
|
||||
}
|
||||
|
||||
void
|
||||
timeline_markers_from_script (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
ClutterScript *script = clutter_script_new ();
|
||||
ClutterTimeline *timeline;
|
||||
GError *error = NULL;
|
||||
gchar *test_file;
|
||||
gchar **markers;
|
||||
gsize n_markers;
|
||||
|
||||
test_file = clutter_test_get_data_file ("test-script-timeline-markers.json");
|
||||
clutter_script_load_from_file (script, test_file, &error);
|
||||
if (g_test_verbose () && error != NULL)
|
||||
g_print ("Error: %s", error->message);
|
||||
|
||||
g_assert_no_error (error);
|
||||
|
||||
timeline = CLUTTER_TIMELINE (clutter_script_get_object (script, "timeline0"));
|
||||
|
||||
g_assert (clutter_timeline_has_marker (timeline, "marker0"));
|
||||
g_assert (clutter_timeline_has_marker (timeline, "marker1"));
|
||||
g_assert (!clutter_timeline_has_marker (timeline, "foo"));
|
||||
g_assert (clutter_timeline_has_marker (timeline, "marker2"));
|
||||
g_assert (clutter_timeline_has_marker (timeline, "marker3"));
|
||||
|
||||
markers = clutter_timeline_list_markers (timeline, -1, &n_markers);
|
||||
g_assert_cmpint (n_markers, ==, 4);
|
||||
g_strfreev (markers);
|
||||
|
||||
markers = clutter_timeline_list_markers (timeline, 500, &n_markers);
|
||||
g_assert_cmpint (n_markers, ==, 2);
|
||||
g_assert (markers != NULL);
|
||||
g_assert_cmpstr (markers[0], ==, "marker3");
|
||||
g_assert_cmpstr (markers[1], ==, "marker1");
|
||||
g_strfreev (markers);
|
||||
|
||||
g_object_unref (script);
|
||||
|
||||
g_free (test_file);
|
||||
}
|
131
src/tests/clutter/conform/units.c
Normal file
131
src/tests/clutter/conform/units.c
Normal file
@ -0,0 +1,131 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
units_cache (void)
|
||||
{
|
||||
ClutterUnits units;
|
||||
ClutterSettings *settings;
|
||||
gfloat pixels;
|
||||
gint old_dpi;
|
||||
|
||||
settings = clutter_settings_get_default ();
|
||||
g_object_get (settings, "font-dpi", &old_dpi, NULL);
|
||||
|
||||
g_object_set (settings, "font-dpi", 96 * 1024, NULL);
|
||||
clutter_units_from_em (&units, 1.0);
|
||||
pixels = clutter_units_to_pixels (&units);
|
||||
|
||||
g_object_set (settings, "font-dpi", ((96 * 2) * 1024), NULL);
|
||||
g_assert_cmpfloat (clutter_units_to_pixels (&units), !=, pixels);
|
||||
|
||||
g_object_set (settings, "font-dpi", (96 * 1024), NULL);
|
||||
g_assert_cmpfloat (clutter_units_to_pixels (&units), ==, pixels);
|
||||
|
||||
g_object_set (settings, "font-dpi", old_dpi, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
units_constructors (void)
|
||||
{
|
||||
ClutterUnits units, units_cm;
|
||||
|
||||
clutter_units_from_pixels (&units, 100);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL);
|
||||
g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 100.0);
|
||||
g_assert_cmpfloat (clutter_units_to_pixels (&units), ==, 100.0);
|
||||
|
||||
clutter_units_from_em (&units, 5.0);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_EM);
|
||||
g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 5.0);
|
||||
g_assert_cmpfloat (clutter_units_to_pixels (&units), !=, 5.0);
|
||||
|
||||
clutter_units_from_cm (&units_cm, 5.0);
|
||||
g_assert (clutter_units_get_unit_type (&units_cm) == CLUTTER_UNIT_CM);
|
||||
g_assert_cmpfloat (clutter_units_get_unit_value (&units_cm), ==, 5.0);
|
||||
g_assert_cmpfloat (clutter_units_to_pixels (&units_cm), !=, 5.0);
|
||||
|
||||
clutter_units_from_mm (&units, 50.0);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_MM);
|
||||
g_assert_cmpfloat (clutter_units_to_pixels (&units),
|
||||
==,
|
||||
clutter_units_to_pixels (&units_cm));
|
||||
}
|
||||
|
||||
static void
|
||||
units_string (void)
|
||||
{
|
||||
ClutterUnits units;
|
||||
gchar *string;
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "") == FALSE);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "10") == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL);
|
||||
g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 10);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "10 px") == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "10 mm") == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_MM);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "10 cm") == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_CM);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "10 ") == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL);
|
||||
g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 10);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "5 em") == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_EM);
|
||||
g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 5);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "5 emeralds") == FALSE);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, " 16 mm") == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_MM);
|
||||
g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 16);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, " 24 pt ") == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_POINT);
|
||||
g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 24);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, " 32 em garbage") == FALSE);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "5.1cm") == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_CM);
|
||||
g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 5.1f);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "5,mm") == FALSE);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, ".5pt") == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_POINT);
|
||||
g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 0.5f);
|
||||
|
||||
g_assert (clutter_units_from_string (&units, "1 omg!!pony") == FALSE);
|
||||
|
||||
clutter_units_from_pt (&units, 24.0);
|
||||
string = clutter_units_to_string (&units);
|
||||
g_assert_cmpstr (string, ==, "24.0 pt");
|
||||
g_free (string);
|
||||
|
||||
clutter_units_from_em (&units, 3.0);
|
||||
string = clutter_units_to_string (&units);
|
||||
g_assert_cmpstr (string, ==, "3.00 em");
|
||||
|
||||
units.unit_type = CLUTTER_UNIT_PIXEL;
|
||||
units.value = 0;
|
||||
|
||||
g_assert (clutter_units_from_string (&units, string) == TRUE);
|
||||
g_assert (clutter_units_get_unit_type (&units) != CLUTTER_UNIT_PIXEL);
|
||||
g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_EM);
|
||||
g_assert_cmpint ((int) clutter_units_get_unit_value (&units), ==, 3);
|
||||
|
||||
g_free (string);
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/units/string", units_string)
|
||||
CLUTTER_TEST_UNIT ("/units/cache", units_cache)
|
||||
CLUTTER_TEST_UNIT ("/units/constructors", units_constructors)
|
||||
)
|
55
src/tests/clutter/interactive/.gitignore
vendored
Normal file
55
src/tests/clutter/interactive/.gitignore
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
/stamp-test-interactive
|
||||
/stamp-test-unit-names
|
||||
/test-actors
|
||||
/test-animation
|
||||
/test-animator
|
||||
/test-bind-constraint
|
||||
/test-binding-pool
|
||||
/test-cairo-clock
|
||||
/test-cairo-flowers
|
||||
/test-clip
|
||||
/test-cogl-multitexture
|
||||
/test-cogl-offscreen
|
||||
/test-cogl-point-sprites
|
||||
/test-cogl-primitives
|
||||
/test-cogl-shader-glsl
|
||||
/test-cogl-tex-convert
|
||||
/test-cogl-tex-foreign
|
||||
/test-cogl-tex-getset
|
||||
/test-cogl-tex-polygon
|
||||
/test-cogl-tex-tile
|
||||
/test-cogl-vertex-buffer
|
||||
/test-content
|
||||
/test-devices
|
||||
/test-easing
|
||||
/test-events
|
||||
/test-fbo
|
||||
/test-grab
|
||||
/test-image
|
||||
/test-interactive
|
||||
/test-keyframe-transition
|
||||
/test-layout
|
||||
/test-multistage
|
||||
/test-paint-wrapper
|
||||
/test-path-constraint
|
||||
/test-pixmap
|
||||
/test-rotate-zoom
|
||||
/test-scale
|
||||
/test-script
|
||||
/test-scrolling
|
||||
/test-shader-effects
|
||||
/test-stage-read-pixels
|
||||
/test-stage-sizing
|
||||
/test-state
|
||||
/test-state-animator
|
||||
/test-state-script
|
||||
/test-swipe-action
|
||||
/test-table-layout
|
||||
/test-text
|
||||
/test-text-field
|
||||
/test-texture-async
|
||||
/test-texture-material
|
||||
/test-texture-quality
|
||||
/test-texture-slicing
|
||||
/test-touch-events
|
||||
/test-unit-names.h
|
91
src/tests/clutter/interactive/meson.build
Normal file
91
src/tests/clutter/interactive/meson.build
Normal file
@ -0,0 +1,91 @@
|
||||
clutter_tests_interactive_srcdir = meson.current_source_dir()
|
||||
clutter_tests_interactive_includepath = include_directories('.')
|
||||
|
||||
clutter_tests_interactive_c_args = [
|
||||
'-DTESTS_DATADIR="@0@"'.format(clutter_tests_interactive_srcdir),
|
||||
'-DG_DISABLE_SINGLE_INCLUDES',
|
||||
'-DGLIB_DISABLE_DEPRECATION_WARNINGS',
|
||||
'-DCOGL_DISABLE_DEPRECATION_WARNINGS',
|
||||
'-DCLUTTER_DISABLE_DEPRECATION_WARNINGS',
|
||||
]
|
||||
clutter_tests_interactive_c_args += clutter_debug_c_args
|
||||
|
||||
clutter_tests_interactive_link_args = [
|
||||
'-Wl,--export-dynamic',
|
||||
]
|
||||
|
||||
clutter_tests_interactive_test_sources = [
|
||||
'test-texture-slicing.c',
|
||||
'test-texture-async.c',
|
||||
'test-texture-material.c',
|
||||
'test-events.c',
|
||||
'test-scale.c',
|
||||
'test-actors.c',
|
||||
'test-shader-effects.c',
|
||||
'test-script.c',
|
||||
'test-grab.c',
|
||||
'test-cogl-shader-glsl.c',
|
||||
'test-state.c',
|
||||
'test-fbo.c',
|
||||
'test-cogl-tex-tile.c',
|
||||
'test-cogl-tex-convert.c',
|
||||
'test-cogl-offscreen.c',
|
||||
'test-cogl-tex-polygon.c',
|
||||
'test-cogl-multitexture.c',
|
||||
'test-stage-read-pixels.c',
|
||||
'test-paint-wrapper.c',
|
||||
'test-texture-quality.c',
|
||||
'test-layout.c',
|
||||
'test-animation.c',
|
||||
'test-easing.c',
|
||||
'test-binding-pool.c',
|
||||
'test-text.c',
|
||||
'test-text-field.c',
|
||||
'test-cairo-clock.c',
|
||||
'test-cairo-flowers.c',
|
||||
'test-cogl-vertex-buffer.c',
|
||||
'test-stage-sizing.c',
|
||||
'test-scrolling.c',
|
||||
'test-swipe-action.c',
|
||||
'test-cogl-point-sprites.c',
|
||||
'test-table-layout.c',
|
||||
'test-path-constraint.c',
|
||||
'test-state-script.c',
|
||||
'test-devices.c',
|
||||
'test-content.c',
|
||||
'test-keyframe-transition.c',
|
||||
'test-bind-constraint.c',
|
||||
'test-touch-events.c',
|
||||
'test-rotate-zoom.c',
|
||||
'test-image.c',
|
||||
]
|
||||
|
||||
gen_test_unit_names = find_program('meson/gen-test-unit-names.sh')
|
||||
clutter_interactive_test_unit_names_h = custom_target('gen-test-unit-names',
|
||||
output: 'test-unit-names.h',
|
||||
input: clutter_tests_interactive_test_sources,
|
||||
command: [gen_test_unit_names, '@OUTPUT@', '@INPUT@'],
|
||||
install: false,
|
||||
)
|
||||
|
||||
clutter_tests_interactive_sources = [
|
||||
'test-main.c',
|
||||
clutter_interactive_test_unit_names_h,
|
||||
clutter_tests_interactive_test_sources
|
||||
]
|
||||
|
||||
executable('test-interactive',
|
||||
sources: clutter_tests_interactive_sources,
|
||||
include_directories: [
|
||||
clutter_includes,
|
||||
clutter_tests_interactive_includepath,
|
||||
],
|
||||
c_args: clutter_tests_interactive_c_args,
|
||||
link_args: clutter_tests_interactive_link_args,
|
||||
dependencies: [
|
||||
clutter_deps,
|
||||
libmutter_clutter_dep,
|
||||
gdk_pixbuf_dep,
|
||||
],
|
||||
install: false,
|
||||
)
|
14
src/tests/clutter/interactive/meson/gen-test-unit-names.sh
Executable file
14
src/tests/clutter/interactive/meson/gen-test-unit-names.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
outputfile=$1
|
||||
shift
|
||||
|
||||
echo '/* ** This file is autogenerated. Do not edit. ** */' > "$outputfile"
|
||||
echo '' >> "$outputfile"
|
||||
echo 'const char *test_unit_names[] = {' >> "$outputfile"
|
||||
|
||||
for test_source_file in "$@"; do
|
||||
echo " \"$(echo "$test_source_file" | sed 's/.*\(test-[a-z0-9\-]\+\)\.c/\1/')\"," >> "$outputfile"
|
||||
done
|
||||
|
||||
echo '};' >> "$outputfile"
|
BIN
src/tests/clutter/interactive/redhand.png
Normal file
BIN
src/tests/clutter/interactive/redhand.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
318
src/tests/clutter/interactive/test-actors.c
Normal file
318
src/tests/clutter/interactive/test-actors.c
Normal file
@ -0,0 +1,318 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#define NHANDS 6
|
||||
|
||||
typedef struct SuperOH
|
||||
{
|
||||
ClutterActor **hand;
|
||||
ClutterActor *bgtex;
|
||||
ClutterActor *real_hand;
|
||||
ClutterActor *group;
|
||||
ClutterActor *stage;
|
||||
|
||||
gint stage_width;
|
||||
gint stage_height;
|
||||
gfloat radius;
|
||||
|
||||
ClutterBehaviour *scaler_1;
|
||||
ClutterBehaviour *scaler_2;
|
||||
ClutterTimeline *timeline;
|
||||
} SuperOH;
|
||||
|
||||
static gint n_hands = NHANDS;
|
||||
|
||||
int
|
||||
test_actors_main (int argc, char *argv[]);
|
||||
|
||||
static GOptionEntry super_oh_entries[] = {
|
||||
{
|
||||
"num-hands", 'n',
|
||||
0,
|
||||
G_OPTION_ARG_INT, &n_hands,
|
||||
"Number of hands", "HANDS"
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
on_group_destroy (ClutterActor *actor,
|
||||
SuperOH *oh)
|
||||
{
|
||||
oh->group = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_hand_destroy (ClutterActor *actor,
|
||||
SuperOH *oh)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_hands; i++)
|
||||
{
|
||||
if (oh->hand[i] == actor)
|
||||
oh->hand[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_button_press_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
SuperOH *oh)
|
||||
{
|
||||
gfloat x, y;
|
||||
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
|
||||
g_print ("*** button press event (button:%d) at %.2f, %.2f on %s ***\n",
|
||||
clutter_event_get_button (event),
|
||||
x, y,
|
||||
clutter_actor_get_name (actor));
|
||||
|
||||
clutter_actor_hide (actor);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
input_cb (ClutterActor *stage,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
SuperOH *oh = data;
|
||||
|
||||
if (event->type == CLUTTER_KEY_RELEASE)
|
||||
{
|
||||
g_print ("*** key press event (key:%c) ***\n",
|
||||
clutter_event_get_key_symbol (event));
|
||||
|
||||
if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_q)
|
||||
{
|
||||
clutter_main_quit ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_r)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < n_hands; i++)
|
||||
{
|
||||
if (oh->hand[i] != NULL)
|
||||
clutter_actor_show (oh->hand[i]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Timeline handler */
|
||||
static void
|
||||
frame_cb (ClutterTimeline *timeline,
|
||||
gint msecs,
|
||||
gpointer data)
|
||||
{
|
||||
SuperOH *oh = data;
|
||||
gint i;
|
||||
float rotation = clutter_timeline_get_progress (timeline) * 360.0f;
|
||||
|
||||
/* Rotate everything clockwise about stage center*/
|
||||
if (oh->group != NULL)
|
||||
clutter_actor_set_rotation (oh->group,
|
||||
CLUTTER_Z_AXIS,
|
||||
rotation,
|
||||
oh->stage_width / 2,
|
||||
oh->stage_height / 2,
|
||||
0);
|
||||
|
||||
for (i = 0; i < n_hands; i++)
|
||||
{
|
||||
/* Rotate each hand around there centers - to get this we need
|
||||
* to take into account any scaling.
|
||||
*/
|
||||
if (oh->hand[i] != NULL)
|
||||
clutter_actor_set_rotation (oh->hand[i],
|
||||
CLUTTER_Z_AXIS,
|
||||
-6.0 * rotation,
|
||||
0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stop_and_quit (ClutterActor *stage,
|
||||
SuperOH *data)
|
||||
{
|
||||
clutter_timeline_stop (data->timeline);
|
||||
|
||||
clutter_main_quit ();
|
||||
}
|
||||
|
||||
static gdouble
|
||||
my_sine_wave (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
|
||||
gdouble progress = clutter_timeline_get_progress (timeline);
|
||||
|
||||
return sin (progress * G_PI);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_actors_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterAlpha *alpha;
|
||||
SuperOH *oh;
|
||||
gint i;
|
||||
GError *error;
|
||||
ClutterActor *real_hand;
|
||||
gchar *file;
|
||||
|
||||
error = NULL;
|
||||
|
||||
if (clutter_init_with_args (&argc, &argv,
|
||||
NULL,
|
||||
super_oh_entries,
|
||||
NULL,
|
||||
&error) != CLUTTER_INIT_SUCCESS)
|
||||
{
|
||||
g_warning ("Unable to initialise Clutter:\n%s",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
oh = g_new (SuperOH, 1);
|
||||
|
||||
oh->stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (oh->stage, 800, 600);
|
||||
clutter_actor_set_name (oh->stage, "Default Stage");
|
||||
clutter_actor_set_background_color (oh->stage, CLUTTER_COLOR_LightSkyBlue);
|
||||
g_signal_connect (oh->stage, "destroy", G_CALLBACK (stop_and_quit), oh);
|
||||
|
||||
clutter_stage_set_title (CLUTTER_STAGE (oh->stage), "Actors");
|
||||
|
||||
/* Create a timeline to manage animation */
|
||||
oh->timeline = clutter_timeline_new (6000);
|
||||
clutter_timeline_set_repeat_count (oh->timeline, -1);
|
||||
|
||||
/* fire a callback for frame change */
|
||||
g_signal_connect (oh->timeline, "new-frame", G_CALLBACK (frame_cb), oh);
|
||||
|
||||
/* Set up some behaviours to handle scaling */
|
||||
alpha = clutter_alpha_new_with_func (oh->timeline, my_sine_wave, NULL, NULL);
|
||||
|
||||
oh->scaler_1 = clutter_behaviour_scale_new (alpha, 0.5, 0.5, 1.0, 1.0);
|
||||
oh->scaler_2 = clutter_behaviour_scale_new (alpha, 1.0, 1.0, 0.5, 0.5);
|
||||
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
real_hand = clutter_texture_new_from_file (file, &error);
|
||||
if (real_hand == NULL)
|
||||
g_error ("image load failed: %s", error->message);
|
||||
|
||||
g_free (file);
|
||||
|
||||
/* create a new actor to hold other actors */
|
||||
oh->group = clutter_actor_new ();
|
||||
clutter_actor_set_layout_manager (oh->group, clutter_fixed_layout_new ());
|
||||
clutter_actor_set_name (oh->group, "Group");
|
||||
g_signal_connect (oh->group, "destroy", G_CALLBACK (on_group_destroy), oh);
|
||||
clutter_actor_add_constraint (oh->group, clutter_align_constraint_new (oh->stage, CLUTTER_ALIGN_BOTH, 0.5));
|
||||
clutter_actor_add_constraint (oh->group, clutter_bind_constraint_new (oh->stage, CLUTTER_BIND_SIZE, 0.0f));
|
||||
|
||||
oh->hand = g_new (ClutterActor*, n_hands);
|
||||
|
||||
oh->stage_width = clutter_actor_get_width (oh->stage);
|
||||
oh->stage_height = clutter_actor_get_height (oh->stage);
|
||||
oh->radius = (oh->stage_width + oh->stage_height)
|
||||
/ n_hands;
|
||||
|
||||
for (i = 0; i < n_hands; i++)
|
||||
{
|
||||
gint x, y, w, h;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
oh->hand[i] = real_hand;
|
||||
clutter_actor_set_name (oh->hand[i], "Real Hand");
|
||||
}
|
||||
else
|
||||
{
|
||||
oh->hand[i] = clutter_clone_new (real_hand);
|
||||
clutter_actor_set_name (oh->hand[i], "Clone Hand");
|
||||
}
|
||||
|
||||
clutter_actor_set_reactive (oh->hand[i], TRUE);
|
||||
|
||||
clutter_actor_set_size (oh->hand[i], 200, 213);
|
||||
|
||||
/* Place around a circle */
|
||||
w = clutter_actor_get_width (oh->hand[i]);
|
||||
h = clutter_actor_get_height (oh->hand[i]);
|
||||
|
||||
x = oh->stage_width / 2
|
||||
+ oh->radius
|
||||
* cos (i * G_PI / (n_hands / 2))
|
||||
- w / 2;
|
||||
|
||||
y = oh->stage_height / 2
|
||||
+ oh->radius
|
||||
* sin (i * G_PI / (n_hands / 2))
|
||||
- h / 2;
|
||||
|
||||
clutter_actor_set_position (oh->hand[i], x, y);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (oh->hand[i],
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
/* Add to our group group */
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (oh->group), oh->hand[i]);
|
||||
|
||||
g_signal_connect (oh->hand[i], "button-press-event",
|
||||
G_CALLBACK (on_button_press_event),
|
||||
oh);
|
||||
|
||||
g_signal_connect (oh->hand[i], "destroy",
|
||||
G_CALLBACK (on_hand_destroy),
|
||||
oh);
|
||||
|
||||
if (i % 2)
|
||||
clutter_behaviour_apply (oh->scaler_1, oh->hand[i]);
|
||||
else
|
||||
clutter_behaviour_apply (oh->scaler_2, oh->hand[i]);
|
||||
}
|
||||
|
||||
/* Add the group to the stage */
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (oh->stage), oh->group);
|
||||
|
||||
/* Show everying */
|
||||
clutter_actor_show (oh->stage);
|
||||
|
||||
g_signal_connect (oh->stage, "key-release-event",
|
||||
G_CALLBACK (input_cb),
|
||||
oh);
|
||||
|
||||
/* and start it */
|
||||
clutter_timeline_start (oh->timeline);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
clutter_timeline_stop (oh->timeline);
|
||||
|
||||
/* clean up */
|
||||
g_object_unref (oh->scaler_1);
|
||||
g_object_unref (oh->scaler_2);
|
||||
g_object_unref (oh->timeline);
|
||||
g_free (oh->hand);
|
||||
g_free (oh);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
130
src/tests/clutter/interactive/test-animation.c
Normal file
130
src/tests/clutter/interactive/test-animation.c
Normal file
@ -0,0 +1,130 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static gboolean is_expanded = FALSE;
|
||||
|
||||
int
|
||||
test_animation_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_animation_describe (void);
|
||||
|
||||
static void
|
||||
on_rect_transitions_completed (ClutterActor *actor)
|
||||
{
|
||||
is_expanded = !is_expanded;
|
||||
|
||||
g_print ("Animation complete\n");
|
||||
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_clicked (ClutterClickAction *action,
|
||||
ClutterActor *actor,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
gfloat old_x, old_y, new_x, new_y;
|
||||
gfloat old_width, old_height, new_width, new_height;
|
||||
gdouble new_angle;
|
||||
const ClutterColor *new_color;
|
||||
guint8 new_opacity;
|
||||
|
||||
clutter_actor_get_position (actor, &old_x, &old_y);
|
||||
clutter_actor_get_size (actor, &old_width, &old_height);
|
||||
|
||||
/* determine the final state of the animation depending on
|
||||
* the state of the actor
|
||||
*/
|
||||
if (!is_expanded)
|
||||
{
|
||||
new_x = old_x - 100;
|
||||
new_y = old_y - 100;
|
||||
new_width = old_width + 200;
|
||||
new_height = old_height + 200;
|
||||
new_angle = 360.0;
|
||||
|
||||
new_color = CLUTTER_COLOR_DarkScarletRed;
|
||||
|
||||
new_opacity = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_x = old_x + 100;
|
||||
new_y = old_y + 100;
|
||||
new_width = old_width - 200;
|
||||
new_height = old_height - 200;
|
||||
new_angle = 0.0;
|
||||
|
||||
new_color = CLUTTER_COLOR_LightOrange;
|
||||
|
||||
new_opacity = 128;
|
||||
}
|
||||
|
||||
clutter_actor_save_easing_state (actor);
|
||||
clutter_actor_set_easing_mode (actor, CLUTTER_EASE_IN_EXPO);
|
||||
clutter_actor_set_easing_duration (actor, 2000);
|
||||
|
||||
clutter_actor_set_position (actor, new_x, new_y);
|
||||
clutter_actor_set_size (actor, new_width, new_height);
|
||||
clutter_actor_set_background_color (actor, new_color);
|
||||
clutter_actor_set_rotation_angle (actor, CLUTTER_Z_AXIS, new_angle);
|
||||
clutter_actor_set_reactive (actor, FALSE);
|
||||
|
||||
/* animate the opacity halfway through, with a different pacing */
|
||||
clutter_actor_save_easing_state (actor);
|
||||
clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR);
|
||||
clutter_actor_set_easing_delay (actor, 1000);
|
||||
clutter_actor_set_easing_duration (actor, 1000);
|
||||
clutter_actor_set_opacity (actor, new_opacity);
|
||||
clutter_actor_restore_easing_state (actor);
|
||||
|
||||
clutter_actor_restore_easing_state (actor);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_animation_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *rect;
|
||||
ClutterAction *action;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Animation");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
rect = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (rect, CLUTTER_COLOR_LightOrange);
|
||||
clutter_actor_add_child (stage, rect);
|
||||
clutter_actor_set_size (rect, 50, 50);
|
||||
clutter_actor_set_pivot_point (rect, .5f, .5f);
|
||||
clutter_actor_set_translation (rect, -25, -25, 0);
|
||||
clutter_actor_set_position (rect,
|
||||
clutter_actor_get_width (stage) / 2,
|
||||
clutter_actor_get_height (stage) / 2);
|
||||
clutter_actor_set_opacity (rect, 128);
|
||||
clutter_actor_set_reactive (rect, TRUE);
|
||||
g_signal_connect (rect, "transitions-completed",
|
||||
G_CALLBACK (on_rect_transitions_completed),
|
||||
NULL);
|
||||
|
||||
action = clutter_click_action_new ();
|
||||
g_signal_connect (action, "clicked", G_CALLBACK (on_clicked), NULL);
|
||||
clutter_actor_add_action_with_name (rect, "click", action);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_animation_describe (void)
|
||||
{
|
||||
return "Simple animation demo";
|
||||
}
|
257
src/tests/clutter/interactive/test-bind-constraint.c
Normal file
257
src/tests/clutter/interactive/test-bind-constraint.c
Normal file
@ -0,0 +1,257 @@
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define RECT_SIZE 128
|
||||
|
||||
#define H_PADDING 32
|
||||
#define V_PADDING 32
|
||||
|
||||
enum
|
||||
{
|
||||
NorthWest, North, NorthEast,
|
||||
West, Center, East,
|
||||
SouthWest, South, SouthEast,
|
||||
|
||||
N_RECTS
|
||||
};
|
||||
|
||||
static ClutterActor *rects[N_RECTS] = { NULL, };
|
||||
static const gchar *colors[N_RECTS] = {
|
||||
"#8ae234", "#73d216", "#4e9a06",
|
||||
"#729fcf", "#3465a4", "#204a87",
|
||||
"#ef2929", "#cc0000", "#a40000"
|
||||
};
|
||||
static const gchar *names[N_RECTS] = {
|
||||
"North West", "North", "North East",
|
||||
"West", "Center", "East",
|
||||
"South West", "South", "South East"
|
||||
};
|
||||
|
||||
static const gchar *desaturare_glsl_shader =
|
||||
"uniform sampler2D tex;\n"
|
||||
"uniform float factor;\n"
|
||||
"\n"
|
||||
"vec3 desaturate (const vec3 color, const float desaturation)\n"
|
||||
"{\n"
|
||||
" const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n"
|
||||
" vec3 gray = vec3 (dot (gray_conv, color));\n"
|
||||
" return vec3 (mix (color.rgb, gray, desaturation));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main ()\n"
|
||||
"{\n"
|
||||
" vec4 color = cogl_color_in * texture2D (tex, vec2 (cogl_tex_coord_in[0].xy));\n"
|
||||
" color.rgb = desaturate (color.rgb, factor);\n"
|
||||
" cogl_color_out = color;\n"
|
||||
"}\n";
|
||||
|
||||
static gboolean is_expanded = FALSE;
|
||||
|
||||
const char *
|
||||
test_bind_constraint_describe (void);
|
||||
|
||||
int
|
||||
test_bind_constraint_main (int argc, char *argv[]);
|
||||
|
||||
static gboolean
|
||||
on_button_release (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data G_GNUC_UNUSED)
|
||||
{
|
||||
if (!is_expanded)
|
||||
{
|
||||
gfloat north_offset, south_offset;
|
||||
gfloat west_offset, east_offset;
|
||||
|
||||
/* expand the 8 rectangles by animating the offset of the
|
||||
* bind constraints
|
||||
*/
|
||||
|
||||
north_offset = (clutter_actor_get_height (rects[Center]) + V_PADDING)
|
||||
* -1.0f;
|
||||
south_offset = (clutter_actor_get_height (rects[Center]) + V_PADDING);
|
||||
|
||||
west_offset = (clutter_actor_get_width (rects[Center]) + H_PADDING)
|
||||
* -1.0f;
|
||||
east_offset = (clutter_actor_get_width (rects[Center]) + H_PADDING);
|
||||
|
||||
clutter_actor_animate (rects[NorthWest], CLUTTER_EASE_OUT_EXPO, 500,
|
||||
"opacity", 255,
|
||||
"@constraints.x-bind.offset", west_offset,
|
||||
"@constraints.y-bind.offset", north_offset,
|
||||
"reactive", TRUE,
|
||||
NULL);
|
||||
clutter_actor_animate (rects[North], CLUTTER_EASE_OUT_EXPO, 500,
|
||||
"opacity", 255,
|
||||
"@constraints.y-bind.offset", north_offset,
|
||||
"reactive", TRUE,
|
||||
NULL);
|
||||
clutter_actor_animate (rects[NorthEast], CLUTTER_EASE_OUT_EXPO, 500,
|
||||
"opacity", 255,
|
||||
"@constraints.x-bind.offset", east_offset,
|
||||
"@constraints.y-bind.offset", north_offset,
|
||||
"reactive", TRUE,
|
||||
NULL);
|
||||
|
||||
clutter_actor_animate (rects[West], CLUTTER_EASE_OUT_EXPO, 500,
|
||||
"opacity", 255,
|
||||
"@constraints.x-bind.offset", west_offset,
|
||||
"reactive", TRUE,
|
||||
NULL);
|
||||
/* turn on the desaturation effect and set the center
|
||||
* rectangle not reactive
|
||||
*/
|
||||
clutter_actor_animate (rects[Center], CLUTTER_LINEAR, 500,
|
||||
"@effects.desaturate.enabled", TRUE,
|
||||
"reactive", FALSE,
|
||||
NULL);
|
||||
clutter_actor_animate (rects[East], CLUTTER_EASE_OUT_EXPO, 500,
|
||||
"opacity", 255,
|
||||
"@constraints.x-bind.offset", east_offset,
|
||||
"reactive", TRUE,
|
||||
NULL);
|
||||
|
||||
clutter_actor_animate (rects[SouthWest], CLUTTER_EASE_OUT_EXPO, 500,
|
||||
"opacity", 255,
|
||||
"@constraints.x-bind.offset", west_offset,
|
||||
"@constraints.y-bind.offset", south_offset,
|
||||
"reactive", TRUE,
|
||||
NULL);
|
||||
clutter_actor_animate (rects[South], CLUTTER_EASE_OUT_EXPO, 500,
|
||||
"opacity", 255,
|
||||
"@constraints.y-bind.offset", south_offset,
|
||||
"reactive", TRUE,
|
||||
NULL);
|
||||
clutter_actor_animate (rects[SouthEast], CLUTTER_EASE_OUT_EXPO, 500,
|
||||
"opacity", 255,
|
||||
"@constraints.x-bind.offset", east_offset,
|
||||
"@constraints.y-bind.offset", south_offset,
|
||||
"reactive", TRUE,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
gint i;
|
||||
|
||||
clutter_actor_animate (rects[Center], CLUTTER_LINEAR, 500,
|
||||
"@effects.desaturate.enabled", FALSE,
|
||||
"reactive", TRUE,
|
||||
NULL);
|
||||
|
||||
for (i = NorthWest; i < N_RECTS; i++)
|
||||
{
|
||||
if (i == Center)
|
||||
continue;
|
||||
|
||||
/* put the 8 rectangles back into their initial state */
|
||||
clutter_actor_animate (rects[i], CLUTTER_EASE_OUT_EXPO, 500,
|
||||
"opacity", 0,
|
||||
"@constraints.x-bind.offset", 0.0f,
|
||||
"@constraints.y-bind.offset", 0.0f,
|
||||
"reactive", FALSE,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
is_expanded = !is_expanded;
|
||||
|
||||
g_print ("Selected: [%s]\n", clutter_actor_get_name (actor));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_bind_constraint_describe (void)
|
||||
{
|
||||
return "Demonstrate the usage of ClutterBindConstraint";
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_bind_constraint_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *rect;
|
||||
ClutterConstraint *constraint;
|
||||
ClutterEffect *effect;
|
||||
ClutterColor rect_color;
|
||||
gint i;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Constraints");
|
||||
clutter_actor_set_size (stage, 800, 600);
|
||||
|
||||
/* main rectangle */
|
||||
clutter_color_from_string (&rect_color, "#3465a4");
|
||||
rect = clutter_actor_new ();
|
||||
g_signal_connect (rect, "button-release-event",
|
||||
G_CALLBACK (on_button_release),
|
||||
NULL);
|
||||
clutter_actor_set_background_color (rect, &rect_color);
|
||||
clutter_actor_set_size (rect, RECT_SIZE, RECT_SIZE);
|
||||
clutter_actor_set_reactive (rect, TRUE);
|
||||
clutter_actor_set_name (rect, names[Center]);
|
||||
clutter_actor_add_child (stage, rect);
|
||||
|
||||
/* align the center rectangle to the center of the stage */
|
||||
constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5);
|
||||
clutter_actor_add_constraint_with_name (rect, "align", constraint);
|
||||
|
||||
/* this is the equivalent of the DesaturateEffect; we cannot animate
|
||||
* the factor because the animation API only understands GObject
|
||||
* properties; so we use the ActorMeta:enabled property to toggle
|
||||
* the shader
|
||||
*/
|
||||
effect = clutter_shader_effect_new (CLUTTER_FRAGMENT_SHADER);
|
||||
clutter_shader_effect_set_shader_source (CLUTTER_SHADER_EFFECT (effect),
|
||||
desaturare_glsl_shader);
|
||||
clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect),
|
||||
"tex", G_TYPE_INT, 1, 0);
|
||||
clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect),
|
||||
"factor", G_TYPE_FLOAT, 1, 0.66);
|
||||
clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE);
|
||||
clutter_actor_add_effect_with_name (rect, "desaturate", effect);
|
||||
|
||||
rects[Center] = rect;
|
||||
|
||||
/* build the other rectangles, and bind their position and size
|
||||
* to the center rectangle. we are going to animate the offset
|
||||
* of the BindConstraints
|
||||
*/
|
||||
for (i = 0; i < N_RECTS; i++)
|
||||
{
|
||||
if (i == Center)
|
||||
continue;
|
||||
|
||||
clutter_color_from_string (&rect_color, colors[i]);
|
||||
|
||||
rect = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (rect, &rect_color);
|
||||
clutter_actor_set_opacity (rect, 0);
|
||||
clutter_actor_set_name (rect, names[i]);
|
||||
clutter_actor_add_child (stage, rect);
|
||||
|
||||
constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_X, 0.0);
|
||||
clutter_actor_add_constraint_with_name (rect, "x-bind", constraint);
|
||||
|
||||
constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_Y, 0.0);
|
||||
clutter_actor_add_constraint_with_name (rect, "y-bind", constraint);
|
||||
|
||||
constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_SIZE, 0.0);
|
||||
clutter_actor_add_constraint_with_name (rect, "size-bind", constraint);
|
||||
|
||||
g_signal_connect (rect, "button-release-event",
|
||||
G_CALLBACK (on_button_release),
|
||||
NULL);
|
||||
|
||||
rects[i] = rect;
|
||||
}
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
316
src/tests/clutter/interactive/test-binding-pool.c
Normal file
316
src/tests/clutter/interactive/test-binding-pool.c
Normal file
@ -0,0 +1,316 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/clutter-keysyms.h>
|
||||
|
||||
#define TYPE_KEY_GROUP (key_group_get_type ())
|
||||
#define KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_KEY_GROUP, KeyGroup))
|
||||
#define IS_KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_KEY_GROUP))
|
||||
#define KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_KEY_GROUP, KeyGroupClass))
|
||||
#define IS_KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_KEY_GROUP))
|
||||
|
||||
typedef struct _KeyGroup KeyGroup;
|
||||
typedef struct _KeyGroupClass KeyGroupClass;
|
||||
|
||||
struct _KeyGroup
|
||||
{
|
||||
ClutterActor parent_instance;
|
||||
|
||||
gint selected_index;
|
||||
};
|
||||
|
||||
struct _KeyGroupClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
void (* activate) (KeyGroup *group,
|
||||
ClutterActor *child);
|
||||
};
|
||||
|
||||
GType key_group_get_type (void);
|
||||
|
||||
int
|
||||
test_binding_pool_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_binding_pool_describe (void);
|
||||
|
||||
G_DEFINE_TYPE (KeyGroup, key_group, CLUTTER_TYPE_ACTOR)
|
||||
|
||||
enum
|
||||
{
|
||||
ACTIVATE,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint group_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
static gboolean
|
||||
key_group_action_move_left (KeyGroup *self,
|
||||
const gchar *action_name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
gint n_children;
|
||||
|
||||
g_debug ("%s: activated '%s' (k:%d, m:%d)",
|
||||
G_STRLOC,
|
||||
action_name,
|
||||
key_val,
|
||||
modifiers);
|
||||
|
||||
n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self));
|
||||
|
||||
self->selected_index -= 1;
|
||||
|
||||
if (self->selected_index < 0)
|
||||
self->selected_index = n_children - 1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
key_group_action_move_right (KeyGroup *self,
|
||||
const gchar *action_name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
gint n_children;
|
||||
|
||||
g_debug ("%s: activated '%s' (k:%d, m:%d)",
|
||||
G_STRLOC,
|
||||
action_name,
|
||||
key_val,
|
||||
modifiers);
|
||||
|
||||
n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self));
|
||||
|
||||
self->selected_index += 1;
|
||||
|
||||
if (self->selected_index >= n_children)
|
||||
self->selected_index = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
key_group_action_activate (KeyGroup *self,
|
||||
const gchar *action_name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
ClutterActor *child = NULL;
|
||||
|
||||
g_debug ("%s: activated '%s' (k:%d, m:%d)",
|
||||
G_STRLOC,
|
||||
action_name,
|
||||
key_val,
|
||||
modifiers);
|
||||
|
||||
if (self->selected_index == -1)
|
||||
return FALSE;
|
||||
|
||||
child = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self),
|
||||
self->selected_index);
|
||||
|
||||
if (child != NULL)
|
||||
{
|
||||
g_signal_emit (self, group_signals[ACTIVATE], 0, child);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
key_group_key_press (ClutterActor *actor,
|
||||
ClutterKeyEvent *event)
|
||||
{
|
||||
ClutterBindingPool *pool;
|
||||
gboolean res;
|
||||
|
||||
pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (actor));
|
||||
g_assert (pool != NULL);
|
||||
|
||||
res = clutter_binding_pool_activate (pool,
|
||||
event->keyval,
|
||||
event->modifier_state,
|
||||
G_OBJECT (actor));
|
||||
|
||||
/* if we activate a key binding, redraw the actor */
|
||||
if (res)
|
||||
clutter_actor_queue_redraw (actor);
|
||||
|
||||
return res ? CLUTTER_EVENT_STOP : CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void
|
||||
key_group_paint (ClutterActor *actor)
|
||||
{
|
||||
KeyGroup *self = KEY_GROUP (actor);
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
gint i = 0;
|
||||
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
/* paint the selection rectangle */
|
||||
if (i == self->selected_index)
|
||||
{
|
||||
ClutterActorBox box = { 0, };
|
||||
|
||||
clutter_actor_get_allocation_box (child, &box);
|
||||
|
||||
box.x1 -= 2;
|
||||
box.y1 -= 2;
|
||||
box.x2 += 2;
|
||||
box.y2 += 2;
|
||||
|
||||
cogl_set_source_color4ub (255, 255, 0, 224);
|
||||
cogl_rectangle (box.x1, box.y1, box.x2, box.y2);
|
||||
}
|
||||
|
||||
clutter_actor_paint (child);
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
key_group_class_init (KeyGroupClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
ClutterBindingPool *binding_pool;
|
||||
|
||||
actor_class->paint = key_group_paint;
|
||||
actor_class->key_press_event = key_group_key_press;
|
||||
|
||||
group_signals[ACTIVATE] =
|
||||
g_signal_new (g_intern_static_string ("activate"),
|
||||
G_OBJECT_CLASS_TYPE (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (KeyGroupClass, activate),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
CLUTTER_TYPE_ACTOR);
|
||||
|
||||
binding_pool = clutter_binding_pool_get_for_class (klass);
|
||||
|
||||
clutter_binding_pool_install_action (binding_pool, "move-right",
|
||||
CLUTTER_KEY_Right, 0,
|
||||
G_CALLBACK (key_group_action_move_right),
|
||||
NULL, NULL);
|
||||
clutter_binding_pool_install_action (binding_pool, "move-left",
|
||||
CLUTTER_KEY_Left, 0,
|
||||
G_CALLBACK (key_group_action_move_left),
|
||||
NULL, NULL);
|
||||
clutter_binding_pool_install_action (binding_pool, "activate",
|
||||
CLUTTER_KEY_Return, 0,
|
||||
G_CALLBACK (key_group_action_activate),
|
||||
NULL, NULL);
|
||||
clutter_binding_pool_install_action (binding_pool, "activate",
|
||||
CLUTTER_KEY_KP_Enter, 0,
|
||||
G_CALLBACK (key_group_action_activate),
|
||||
NULL, NULL);
|
||||
clutter_binding_pool_install_action (binding_pool, "activate",
|
||||
CLUTTER_KEY_ISO_Enter, 0,
|
||||
G_CALLBACK (key_group_action_activate),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
key_group_init (KeyGroup *self)
|
||||
{
|
||||
self->selected_index = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
on_key_group_activate (KeyGroup *group,
|
||||
ClutterActor *child)
|
||||
{
|
||||
g_print ("Child '%s' activated!\n", clutter_actor_get_name (child));
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_binding_pool_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *key_group;
|
||||
gint group_x, group_y;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Key Binding Pool");
|
||||
g_signal_connect (stage,
|
||||
"button-press-event", G_CALLBACK (clutter_main_quit),
|
||||
NULL);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
key_group = g_object_new (TYPE_KEY_GROUP, NULL);
|
||||
clutter_actor_add_child (stage, key_group);
|
||||
|
||||
/* add three rectangles to the key group */
|
||||
clutter_container_add (CLUTTER_CONTAINER (key_group),
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"background-color", CLUTTER_COLOR_Red,
|
||||
"name", "Red Rectangle",
|
||||
"width", 100.0,
|
||||
"height", 100.0,
|
||||
"x", 0.0,
|
||||
"y", 0.0,
|
||||
NULL),
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"background-color", CLUTTER_COLOR_Green,
|
||||
"name", "Green Rectangle",
|
||||
"width", 100.0,
|
||||
"height", 100.0,
|
||||
"x", 125.0,
|
||||
"y", 0.0,
|
||||
NULL),
|
||||
g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"background-color", CLUTTER_COLOR_Blue,
|
||||
"name", "Blue Rectangle",
|
||||
"width", 100.0,
|
||||
"height", 100.0,
|
||||
"x", 250.0,
|
||||
"y", 0.0,
|
||||
NULL),
|
||||
NULL);
|
||||
|
||||
g_signal_connect (key_group,
|
||||
"activate", G_CALLBACK (on_key_group_activate),
|
||||
NULL);
|
||||
|
||||
group_x =
|
||||
(clutter_actor_get_width (stage) - clutter_actor_get_width (key_group))
|
||||
/ 2;
|
||||
group_y =
|
||||
(clutter_actor_get_height (stage) - clutter_actor_get_height (key_group))
|
||||
/ 2;
|
||||
|
||||
clutter_actor_set_position (key_group, group_x, group_y);
|
||||
clutter_actor_set_reactive (key_group, TRUE);
|
||||
|
||||
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), key_group);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_binding_pool_describe (void)
|
||||
{
|
||||
return "Binding pools example";
|
||||
}
|
124
src/tests/clutter/interactive/test-cairo-clock.c
Normal file
124
src/tests/clutter/interactive/test-cairo-clock.c
Normal file
@ -0,0 +1,124 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <cairo.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
int
|
||||
test_cairo_clock_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_cairo_clock_describe (void);
|
||||
|
||||
static gboolean
|
||||
draw_clock (ClutterCanvas *canvas,
|
||||
cairo_t *cr,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GDateTime *now;
|
||||
float hours, minutes, seconds;
|
||||
|
||||
/* get the current time and compute the angles */
|
||||
now = g_date_time_new_now_local ();
|
||||
seconds = g_date_time_get_second (now) * G_PI / 30;
|
||||
minutes = g_date_time_get_minute (now) * G_PI / 30;
|
||||
hours = g_date_time_get_hour (now) * G_PI / 6;
|
||||
|
||||
/* clear the contents of the canvas, to avoid painting
|
||||
* over the previous frame
|
||||
*/
|
||||
cairo_save (cr);
|
||||
cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint (cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
/* scale the modelview to the size of the surface */
|
||||
cairo_scale (cr, width, height);
|
||||
|
||||
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
|
||||
cairo_set_line_width (cr, 0.1);
|
||||
|
||||
/* the black rail that holds the seconds indicator */
|
||||
clutter_cairo_set_source_color (cr, CLUTTER_COLOR_Black);
|
||||
cairo_translate (cr, 0.5, 0.5);
|
||||
cairo_arc (cr, 0, 0, 0.4, 0, G_PI * 2);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* the seconds indicator */
|
||||
clutter_cairo_set_source_color (cr, CLUTTER_COLOR_White);
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_arc (cr, sinf (seconds) * 0.4, - cosf (seconds) * 0.4, 0.05, 0, G_PI * 2);
|
||||
cairo_fill (cr);
|
||||
|
||||
/* the minutes hand */
|
||||
clutter_cairo_set_source_color (cr, CLUTTER_COLOR_DarkChameleon);
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_line_to (cr, sinf (minutes) * 0.4, -cosf (minutes) * 0.4);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* the hours hand */
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_line_to (cr, sinf (hours) * 0.2, -cosf (hours) * 0.2);
|
||||
cairo_stroke (cr);
|
||||
|
||||
g_date_time_unref (now);
|
||||
|
||||
/* we're done drawing */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
invalidate_clock (gpointer data_)
|
||||
{
|
||||
/* invalidate the contents of the canvas */
|
||||
clutter_content_invalidate (data_);
|
||||
|
||||
/* keep the timeout source */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cairo_clock_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterContent *canvas;
|
||||
|
||||
/* initialize Clutter */
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
/* create a resizable stage */
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "2D Clock");
|
||||
clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue);
|
||||
clutter_actor_set_size (stage, 300, 300);
|
||||
clutter_actor_show (stage);
|
||||
|
||||
/* our 2D canvas, courtesy of Cairo */
|
||||
canvas = clutter_canvas_new ();
|
||||
clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 300, 300);
|
||||
clutter_actor_set_content (stage, canvas);
|
||||
|
||||
/* quit on destroy */
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* connect our drawing code */
|
||||
g_signal_connect (canvas, "draw", G_CALLBACK (draw_clock), NULL);
|
||||
|
||||
/* invalidate the canvas, so that we can draw before the main loop starts */
|
||||
clutter_content_invalidate (canvas);
|
||||
|
||||
/* set up a timer that invalidates the canvas every second */
|
||||
clutter_threads_add_timeout (1000, invalidate_clock, canvas);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cairo_clock_describe (void)
|
||||
{
|
||||
return "Simple 2D canvas using a Cairo texture actor";
|
||||
}
|
262
src/tests/clutter/interactive/test-cairo-flowers.c
Normal file
262
src/tests/clutter/interactive/test-cairo-flowers.c
Normal file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Pretty cairo flower hack.
|
||||
*/
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h> /* for sleep(), used for screenshots */
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#ifdef _MSC_VER
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
#define PETAL_MIN 20
|
||||
#define PETAL_VAR 40
|
||||
#define N_FLOWERS 40 /* reduce if you have a small card */
|
||||
|
||||
typedef struct Flower
|
||||
{
|
||||
ClutterActor *ctex;
|
||||
gint x,y,rot,v,rv;
|
||||
}
|
||||
Flower;
|
||||
|
||||
static ClutterActor *stage = NULL;
|
||||
|
||||
int
|
||||
test_cairo_flowers_main (int argc, char **argv);
|
||||
|
||||
const char *
|
||||
test_cairo_flowers_describe (void);
|
||||
|
||||
static gboolean
|
||||
draw_flower (ClutterCanvas *canvas,
|
||||
cairo_t *cr,
|
||||
gint width,
|
||||
gint height,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* No science here, just a hack from toying */
|
||||
gint i, j;
|
||||
|
||||
double colors[] = {
|
||||
0.71, 0.81, 0.83,
|
||||
1.0, 0.78, 0.57,
|
||||
0.64, 0.30, 0.35,
|
||||
0.73, 0.40, 0.39,
|
||||
0.91, 0.56, 0.64,
|
||||
0.70, 0.47, 0.45,
|
||||
0.92, 0.75, 0.60,
|
||||
0.82, 0.86, 0.85,
|
||||
0.51, 0.56, 0.67,
|
||||
1.0, 0.79, 0.58,
|
||||
|
||||
};
|
||||
|
||||
gint size;
|
||||
gint petal_size;
|
||||
gint n_groups; /* Num groups of petals 1-3 */
|
||||
gint n_petals; /* num of petals 4 - 8 */
|
||||
gint pm1, pm2;
|
||||
|
||||
gint idx, last_idx = -1;
|
||||
|
||||
petal_size = GPOINTER_TO_INT (user_data);
|
||||
size = petal_size * 8;
|
||||
|
||||
n_groups = rand() % 3 + 1;
|
||||
|
||||
cairo_set_tolerance (cr, 0.1);
|
||||
|
||||
/* Clear */
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_paint(cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
|
||||
cairo_translate(cr, size/2, size/2);
|
||||
|
||||
for (i=0; i<n_groups; i++)
|
||||
{
|
||||
n_petals = rand() % 5 + 4;
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_rotate (cr, rand() % 6);
|
||||
|
||||
do {
|
||||
idx = (rand() % (sizeof (colors) / sizeof (double) / 3)) * 3;
|
||||
} while (idx == last_idx);
|
||||
|
||||
cairo_set_source_rgba (cr, colors[idx], colors[idx+1],
|
||||
colors[idx+2], 0.5);
|
||||
|
||||
last_idx = idx;
|
||||
|
||||
/* some bezier randomness */
|
||||
pm1 = rand() % 20;
|
||||
pm2 = rand() % 4;
|
||||
|
||||
for (j=1; j<n_petals+1; j++)
|
||||
{
|
||||
cairo_save (cr);
|
||||
cairo_rotate (cr, ((2*M_PI)/n_petals)*j);
|
||||
|
||||
/* Petals are made up beziers */
|
||||
cairo_new_path (cr);
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_rel_curve_to (cr,
|
||||
petal_size, petal_size,
|
||||
(pm2+2)*petal_size, petal_size,
|
||||
(2*petal_size) + pm1, 0);
|
||||
cairo_rel_curve_to (cr,
|
||||
0 + (pm2*petal_size), -petal_size,
|
||||
-petal_size, -petal_size,
|
||||
-((2*petal_size) + pm1), 0);
|
||||
cairo_close_path (cr);
|
||||
cairo_fill (cr);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
petal_size -= rand() % (size/8);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
/* Finally draw flower center */
|
||||
do {
|
||||
idx = (rand() % (sizeof (colors) / sizeof (double) / 3)) * 3;
|
||||
} while (idx == last_idx);
|
||||
|
||||
if (petal_size < 0)
|
||||
petal_size = rand() % 10;
|
||||
|
||||
cairo_set_source_rgba (cr, colors[idx], colors[idx+1], colors[idx+2], 0.5);
|
||||
|
||||
cairo_arc(cr, 0, 0, petal_size, 0, M_PI * 2);
|
||||
cairo_fill(cr);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
make_flower_actor (void)
|
||||
{
|
||||
gint petal_size = PETAL_MIN + rand() % PETAL_VAR;
|
||||
gint size = petal_size * 8;
|
||||
ClutterActor *ctex;
|
||||
ClutterContent *canvas;
|
||||
|
||||
canvas = clutter_canvas_new ();
|
||||
g_signal_connect (canvas, "draw",
|
||||
G_CALLBACK (draw_flower), GINT_TO_POINTER (petal_size));
|
||||
|
||||
clutter_canvas_set_size (CLUTTER_CANVAS (canvas), size, size);
|
||||
ctex = g_object_new (CLUTTER_TYPE_ACTOR,
|
||||
"content", canvas,
|
||||
"width", (gfloat) size,
|
||||
"height", (gfloat) size,
|
||||
NULL);
|
||||
|
||||
g_object_unref (canvas);
|
||||
|
||||
return ctex;
|
||||
}
|
||||
|
||||
static void
|
||||
tick (ClutterTimeline *timeline,
|
||||
gint msecs,
|
||||
gpointer data)
|
||||
{
|
||||
Flower **flowers = data;
|
||||
gint i = 0;
|
||||
|
||||
for (i = 0; i < N_FLOWERS; i++)
|
||||
{
|
||||
flowers[i]->y += flowers[i]->v;
|
||||
flowers[i]->rot += flowers[i]->rv;
|
||||
|
||||
if (flowers[i]->y > (gint) clutter_actor_get_height (stage))
|
||||
flowers[i]->y = -clutter_actor_get_height (flowers[i]->ctex);
|
||||
|
||||
clutter_actor_set_position (flowers[i]->ctex,
|
||||
flowers[i]->x, flowers[i]->y);
|
||||
|
||||
clutter_actor_set_rotation (flowers[i]->ctex,
|
||||
CLUTTER_Z_AXIS,
|
||||
flowers[i]->rot,
|
||||
clutter_actor_get_width (flowers[i]->ctex)/2,
|
||||
clutter_actor_get_height (flowers[i]->ctex)/2,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stop_and_quit (ClutterActor *actor,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
clutter_timeline_stop (timeline);
|
||||
clutter_main_quit ();
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cairo_flowers_main (int argc, char **argv)
|
||||
{
|
||||
Flower *flowers[N_FLOWERS];
|
||||
ClutterTimeline *timeline;
|
||||
int i;
|
||||
|
||||
srand (time (NULL));
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
/* Create a timeline to manage animation */
|
||||
timeline = clutter_timeline_new (6000);
|
||||
clutter_timeline_set_repeat_count (timeline, -1);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cairo Flowers");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (stop_and_quit), timeline);
|
||||
|
||||
clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black);
|
||||
|
||||
for (i=0; i< N_FLOWERS; i++)
|
||||
{
|
||||
flowers[i] = g_new0(Flower, 1);
|
||||
flowers[i]->ctex = make_flower_actor();
|
||||
flowers[i]->x = rand() % (int) clutter_actor_get_width (stage)
|
||||
- (PETAL_MIN + PETAL_VAR) * 2;
|
||||
flowers[i]->y = rand() % (int) clutter_actor_get_height (stage);
|
||||
flowers[i]->rv = rand() % 5 + 1;
|
||||
flowers[i]->v = rand() % 10 + 2;
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage),
|
||||
flowers[i]->ctex);
|
||||
clutter_actor_set_position (flowers[i]->ctex,
|
||||
flowers[i]->x, flowers[i]->y);
|
||||
}
|
||||
|
||||
/* fire a callback for frame change */
|
||||
g_signal_connect (timeline, "new-frame", G_CALLBACK (tick), flowers);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_timeline_start (timeline);
|
||||
|
||||
g_signal_connect (stage, "key-press-event",
|
||||
G_CALLBACK (clutter_main_quit),
|
||||
NULL);
|
||||
|
||||
clutter_main();
|
||||
|
||||
g_object_unref (timeline);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cairo_flowers_describe (void)
|
||||
{
|
||||
return "Drawing pretty flowers with Cairo";
|
||||
}
|
243
src/tests/clutter/interactive/test-cogl-multitexture.c
Normal file
243
src/tests/clutter/interactive/test-cogl-multitexture.c
Normal file
@ -0,0 +1,243 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
typedef struct _TestMultiLayerMaterialState
|
||||
{
|
||||
ClutterActor *group;
|
||||
CoglHandle alpha_tex;
|
||||
CoglHandle redhand_tex;
|
||||
gfloat *tex_coords;
|
||||
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
CoglHandle material0;
|
||||
CoglMatrix tex_matrix0;
|
||||
CoglMatrix rot_matrix0;
|
||||
CoglHandle light_tex0;
|
||||
|
||||
CoglHandle material1;
|
||||
CoglMatrix tex_matrix1;
|
||||
CoglMatrix rot_matrix1;
|
||||
CoglHandle light_tex1;
|
||||
|
||||
} TestMultiLayerMaterialState;
|
||||
|
||||
int
|
||||
test_cogl_multitexture_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_cogl_multitexture_describe (void);
|
||||
|
||||
static void
|
||||
frame_cb (ClutterTimeline *timeline,
|
||||
gint frame_no,
|
||||
gpointer data)
|
||||
{
|
||||
TestMultiLayerMaterialState *state = data;
|
||||
|
||||
cogl_matrix_multiply (&state->tex_matrix0,
|
||||
&state->tex_matrix0,
|
||||
&state->rot_matrix0);
|
||||
cogl_material_set_layer_matrix (state->material0, 2, &state->tex_matrix0);
|
||||
|
||||
cogl_matrix_multiply (&state->tex_matrix1,
|
||||
&state->tex_matrix1,
|
||||
&state->rot_matrix1);
|
||||
cogl_material_set_layer_matrix (state->material1, 2, &state->tex_matrix1);
|
||||
}
|
||||
|
||||
static void
|
||||
material_rectangle_paint (ClutterActor *actor, gpointer data)
|
||||
{
|
||||
TestMultiLayerMaterialState *state = data;
|
||||
|
||||
cogl_push_matrix ();
|
||||
|
||||
cogl_translate (150, 15, 0);
|
||||
|
||||
cogl_set_source (state->material0);
|
||||
cogl_rectangle_with_multitexture_coords (0, 0, 200, 213,
|
||||
state->tex_coords,
|
||||
12);
|
||||
cogl_translate (-300, -30, 0);
|
||||
cogl_set_source (state->material1);
|
||||
cogl_rectangle_with_multitexture_coords (0, 0, 200, 213,
|
||||
state->tex_coords,
|
||||
12);
|
||||
|
||||
cogl_pop_matrix ();
|
||||
}
|
||||
|
||||
static void
|
||||
animation_completed_cb (ClutterAnimation *animation,
|
||||
TestMultiLayerMaterialState *state)
|
||||
{
|
||||
static gboolean go_back = FALSE;
|
||||
gdouble new_rotation_y;
|
||||
|
||||
if (go_back)
|
||||
new_rotation_y = 30;
|
||||
else
|
||||
new_rotation_y = -30;
|
||||
go_back = !go_back;
|
||||
|
||||
clutter_actor_animate_with_timeline (state->group,
|
||||
CLUTTER_LINEAR,
|
||||
state->timeline,
|
||||
"rotation-angle-y", new_rotation_y,
|
||||
"signal-after::completed",
|
||||
animation_completed_cb, state,
|
||||
NULL);
|
||||
|
||||
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_multitexture_main (int argc, char *argv[])
|
||||
{
|
||||
GError *error = NULL;
|
||||
ClutterActor *stage;
|
||||
ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff };
|
||||
TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1);
|
||||
gfloat stage_w, stage_h;
|
||||
gchar **files;
|
||||
gfloat tex_coords[] =
|
||||
{
|
||||
/* tx1 ty1 tx2 ty2 */
|
||||
0, 0, 1, 1,
|
||||
0, 0, 1, 1,
|
||||
0, 0, 1, 1
|
||||
};
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_get_size (stage, &stage_w, &stage_h);
|
||||
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl: Multi-texturing");
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* We create a non-descript actor that we know doesn't have a
|
||||
* default paint handler, so that we can easily control
|
||||
* painting in a paint signal handler, without having to
|
||||
* sub-class anything etc. */
|
||||
state->group = clutter_group_new ();
|
||||
clutter_actor_set_position (state->group, stage_w / 2, stage_h / 2);
|
||||
g_signal_connect (state->group, "paint",
|
||||
G_CALLBACK(material_rectangle_paint), state);
|
||||
|
||||
files = g_new (gchar*, 4);
|
||||
files[0] = g_build_filename (TESTS_DATADIR, "redhand_alpha.png", NULL);
|
||||
files[1] = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
files[2] = g_build_filename (TESTS_DATADIR, "light0.png", NULL);
|
||||
files[3] = NULL;
|
||||
|
||||
state->alpha_tex =
|
||||
cogl_texture_new_from_file (files[0],
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
&error);
|
||||
if (!state->alpha_tex)
|
||||
g_critical ("Failed to load redhand_alpha.png: %s", error->message);
|
||||
|
||||
state->redhand_tex =
|
||||
cogl_texture_new_from_file (files[1],
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
&error);
|
||||
if (!state->redhand_tex)
|
||||
g_critical ("Failed to load redhand.png: %s", error->message);
|
||||
|
||||
state->light_tex0 =
|
||||
cogl_texture_new_from_file (files[2],
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
&error);
|
||||
if (!state->light_tex0)
|
||||
g_critical ("Failed to load light0.png: %s", error->message);
|
||||
|
||||
state->light_tex1 =
|
||||
cogl_texture_new_from_file (files[2],
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
&error);
|
||||
if (!state->light_tex1)
|
||||
g_critical ("Failed to load light0.png: %s", error->message);
|
||||
|
||||
g_strfreev (files);
|
||||
|
||||
state->material0 = cogl_material_new ();
|
||||
cogl_material_set_layer (state->material0, 0, state->alpha_tex);
|
||||
cogl_material_set_layer (state->material0, 1, state->redhand_tex);
|
||||
cogl_material_set_layer (state->material0, 2, state->light_tex0);
|
||||
|
||||
state->material1 = cogl_material_new ();
|
||||
cogl_material_set_layer (state->material1, 0, state->alpha_tex);
|
||||
cogl_material_set_layer (state->material1, 1, state->redhand_tex);
|
||||
cogl_material_set_layer (state->material1, 2, state->light_tex1);
|
||||
|
||||
state->tex_coords = tex_coords;
|
||||
|
||||
cogl_matrix_init_identity (&state->tex_matrix0);
|
||||
cogl_matrix_init_identity (&state->tex_matrix1);
|
||||
cogl_matrix_init_identity (&state->rot_matrix0);
|
||||
cogl_matrix_init_identity (&state->rot_matrix1);
|
||||
|
||||
cogl_matrix_translate (&state->rot_matrix0, 0.5, 0.5, 0);
|
||||
cogl_matrix_rotate (&state->rot_matrix0, 10.0, 0, 0, 1.0);
|
||||
cogl_matrix_translate (&state->rot_matrix0, -0.5, -0.5, 0);
|
||||
|
||||
cogl_matrix_translate (&state->rot_matrix1, 0.5, 0.5, 0);
|
||||
cogl_matrix_rotate (&state->rot_matrix1, -10.0, 0, 0, 1.0);
|
||||
cogl_matrix_translate (&state->rot_matrix1, -0.5, -0.5, 0);
|
||||
|
||||
clutter_actor_set_anchor_point (state->group, 86, 125);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER(stage),
|
||||
state->group);
|
||||
|
||||
state->timeline = clutter_timeline_new (2812);
|
||||
|
||||
g_signal_connect (state->timeline, "new-frame", G_CALLBACK (frame_cb), state);
|
||||
|
||||
clutter_actor_animate_with_timeline (state->group,
|
||||
CLUTTER_LINEAR,
|
||||
state->timeline,
|
||||
"rotation-angle-y", 30.0,
|
||||
"signal-after::completed",
|
||||
animation_completed_cb, state,
|
||||
NULL);
|
||||
|
||||
/* start the timeline and thus the animations */
|
||||
clutter_timeline_start (state->timeline);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main();
|
||||
|
||||
cogl_handle_unref (state->material1);
|
||||
cogl_handle_unref (state->material0);
|
||||
cogl_handle_unref (state->alpha_tex);
|
||||
cogl_handle_unref (state->redhand_tex);
|
||||
cogl_handle_unref (state->light_tex0);
|
||||
cogl_handle_unref (state->light_tex1);
|
||||
g_free (state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cogl_multitexture_describe (void)
|
||||
{
|
||||
return "Multi-texturing support in Cogl.";
|
||||
}
|
337
src/tests/clutter/interactive/test-cogl-offscreen.c
Normal file
337
src/tests/clutter/interactive/test-cogl-offscreen.c
Normal file
@ -0,0 +1,337 @@
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
/* Coglbox declaration
|
||||
*--------------------------------------------------*/
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define TEST_TYPE_COGLBOX test_coglbox_get_type()
|
||||
|
||||
#define TEST_COGLBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
TEST_TYPE_COGLBOX, TestCoglbox))
|
||||
|
||||
#define TEST_COGLBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
#define TEST_IS_COGLBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
TEST_TYPE_COGLBOX))
|
||||
|
||||
#define TEST_IS_COGLBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
TEST_TYPE_COGLBOX))
|
||||
|
||||
#define TEST_COGLBOX_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
typedef struct _TestCoglbox TestCoglbox;
|
||||
typedef struct _TestCoglboxClass TestCoglboxClass;
|
||||
typedef struct _TestCoglboxPrivate TestCoglboxPrivate;
|
||||
|
||||
struct _TestCoglbox
|
||||
{
|
||||
ClutterActor parent;
|
||||
|
||||
/*< private >*/
|
||||
TestCoglboxPrivate *priv;
|
||||
};
|
||||
|
||||
struct _TestCoglboxClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
void (*_test_coglbox1) (void);
|
||||
void (*_test_coglbox2) (void);
|
||||
void (*_test_coglbox3) (void);
|
||||
void (*_test_coglbox4) (void);
|
||||
};
|
||||
|
||||
static GType test_coglbox_get_type (void) G_GNUC_CONST;
|
||||
|
||||
int
|
||||
test_cogl_offscreen_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_cogl_offscreen_describe (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
/* Coglbox private declaration
|
||||
*--------------------------------------------------*/
|
||||
|
||||
struct _TestCoglboxPrivate
|
||||
{
|
||||
CoglHandle texhand_id;
|
||||
CoglHandle texture_id;
|
||||
CoglHandle offscreen_id;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
#define TEST_COGLBOX_GET_PRIVATE(obj) \
|
||||
(test_coglbox_get_instance_private (TEST_COGLBOX ((obj))))
|
||||
|
||||
/* Coglbox implementation
|
||||
*--------------------------------------------------*/
|
||||
|
||||
static void
|
||||
test_coglbox_paint (ClutterActor *self)
|
||||
{
|
||||
TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self);
|
||||
gfloat texcoords[4] = { 0, 0, 1, 1 };
|
||||
CoglHandle material;
|
||||
|
||||
cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff);
|
||||
cogl_rectangle (0, 0, 400, 400);
|
||||
|
||||
cogl_set_source_texture (priv->texhand_id);
|
||||
cogl_rectangle_with_texture_coords (0, 0,
|
||||
400, 400,
|
||||
0, 0,
|
||||
6, 6);
|
||||
|
||||
cogl_push_framebuffer (priv->offscreen_id);
|
||||
|
||||
cogl_set_source_color4ub (0xff, 0, 0, 0xff);
|
||||
cogl_rectangle (20, 20, 20 + 100, 20 + 100);
|
||||
|
||||
cogl_set_source_color4ub (0, 0xff, 0, 0xff);
|
||||
cogl_rectangle (80, 80, 80 + 100, 80 + 100);
|
||||
|
||||
cogl_pop_framebuffer ();
|
||||
|
||||
material = cogl_material_new ();
|
||||
cogl_material_set_color4ub (material, 0x88, 0x88, 0x88, 0x88);
|
||||
cogl_material_set_layer (material, 0, priv->texture_id);
|
||||
cogl_set_source (material);
|
||||
cogl_rectangle_with_texture_coords (100, 100,
|
||||
300, 300,
|
||||
texcoords[0],
|
||||
texcoords[1],
|
||||
texcoords[2],
|
||||
texcoords[3]);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_dispose (GObject *object)
|
||||
{
|
||||
TestCoglboxPrivate *priv;
|
||||
|
||||
priv = TEST_COGLBOX_GET_PRIVATE (object);
|
||||
|
||||
cogl_handle_unref (priv->texture_id);
|
||||
cogl_handle_unref (priv->offscreen_id);
|
||||
|
||||
G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
/* A newly created Cogl framebuffer will be initialized with a
|
||||
* viewport covering the size of the viewport i.e. equavalent to:
|
||||
*
|
||||
* calling cogl_framebuffer_set_viewport (
|
||||
* fb,
|
||||
* 0, 0,
|
||||
* cogl_framebuffer_get_viewport_width (fb),
|
||||
* cogl_framebuffer_get_viewport_width (fb));
|
||||
*
|
||||
* The projection matrix will be an identity matrix.
|
||||
*
|
||||
* The modelview matrix will be an identity matrix, and this will
|
||||
* create a coordinate system - like OpenGL - with the viewport
|
||||
* being mapped to a unit cube with the origin (0, 0, 0) in the
|
||||
* center, x, y and z ranging from -1 to 1 with (-1, -1) being top
|
||||
* left and (1, 1) bottom right.
|
||||
*
|
||||
* This sets up a Clutter like coordinate system for a Cogl
|
||||
* framebuffer
|
||||
*/
|
||||
static void
|
||||
setup_viewport (unsigned int width,
|
||||
unsigned int height,
|
||||
float fovy,
|
||||
float aspect,
|
||||
float z_near,
|
||||
float z_far)
|
||||
{
|
||||
float z_camera;
|
||||
CoglMatrix projection_matrix;
|
||||
CoglMatrix mv_matrix;
|
||||
|
||||
cogl_set_viewport (0, 0, width, height);
|
||||
|
||||
/* For Ortho projection.
|
||||
* _cogl_matrix_stack_ortho (projection_stack, 0, width, 0, height, -1, 1);
|
||||
*/
|
||||
|
||||
cogl_perspective (fovy, aspect, z_near, z_far);
|
||||
|
||||
/*
|
||||
* In theory, we can compute the camera distance from screen as:
|
||||
*
|
||||
* 0.5 * tan (FOV)
|
||||
*
|
||||
* However, it's better to compute the z_camera from our projection
|
||||
* matrix so that we get a 1:1 mapping at the screen distance. Consider
|
||||
* the upper-left corner of the screen. It has object coordinates
|
||||
* (0,0,0), so by the transform below, ends up with eye coordinate
|
||||
*
|
||||
* x_eye = x_object / width - 0.5 = - 0.5
|
||||
* y_eye = (height - y_object) / width - 0.5 = 0.5
|
||||
* z_eye = z_object / width - z_camera = - z_camera
|
||||
*
|
||||
* From cogl_perspective(), we know that the projection matrix has
|
||||
* the form:
|
||||
*
|
||||
* (x, 0, 0, 0)
|
||||
* (0, y, 0, 0)
|
||||
* (0, 0, c, d)
|
||||
* (0, 0, -1, 0)
|
||||
*
|
||||
* Applied to the above, we get clip coordinates of
|
||||
*
|
||||
* x_clip = x * (- 0.5)
|
||||
* y_clip = y * 0.5
|
||||
* w_clip = - 1 * (- z_camera) = z_camera
|
||||
*
|
||||
* Dividing through by w to get normalized device coordinates, we
|
||||
* have, x_nd = x * 0.5 / z_camera, y_nd = - y * 0.5 / z_camera.
|
||||
* The upper left corner of the screen has normalized device coordinates,
|
||||
* (-1, 1), so to have the correct 1:1 mapping, we have to have:
|
||||
*
|
||||
* z_camera = 0.5 * x = 0.5 * y
|
||||
*
|
||||
* If x != y, then we have a non-uniform aspect ration, and a 1:1 mapping
|
||||
* doesn't make sense.
|
||||
*/
|
||||
|
||||
cogl_get_projection_matrix (&projection_matrix);
|
||||
z_camera = 0.5 * projection_matrix.xx;
|
||||
|
||||
cogl_matrix_init_identity (&mv_matrix);
|
||||
cogl_matrix_translate (&mv_matrix, -0.5f, -0.5f, -z_camera);
|
||||
cogl_matrix_scale (&mv_matrix, 1.0f / width, -1.0f / height, 1.0f / width);
|
||||
cogl_matrix_translate (&mv_matrix, 0.0f, -1.0 * height, 0.0f);
|
||||
cogl_set_modelview_matrix (&mv_matrix);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_map (ClutterActor *actor)
|
||||
{
|
||||
TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (actor);
|
||||
ClutterActor *stage;
|
||||
ClutterPerspective perspective;
|
||||
float stage_width;
|
||||
float stage_height;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (test_coglbox_parent_class)->map (actor);
|
||||
|
||||
printf ("Creating offscreen\n");
|
||||
priv->offscreen_id = cogl_offscreen_new_to_texture (priv->texture_id);
|
||||
|
||||
stage = clutter_actor_get_stage (actor);
|
||||
clutter_stage_get_perspective (CLUTTER_STAGE (stage), &perspective);
|
||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||
|
||||
cogl_push_framebuffer (priv->offscreen_id);
|
||||
|
||||
setup_viewport (stage_width, stage_height,
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
perspective.z_far);
|
||||
|
||||
cogl_pop_framebuffer ();
|
||||
|
||||
if (priv->offscreen_id == COGL_INVALID_HANDLE)
|
||||
printf ("Failed creating offscreen to texture!\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_init (TestCoglbox *self)
|
||||
{
|
||||
TestCoglboxPrivate *priv;
|
||||
gchar *file;
|
||||
|
||||
self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self);
|
||||
|
||||
printf ("Loading redhand.png\n");
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
priv->texhand_id = cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
NULL);
|
||||
g_free (file);
|
||||
|
||||
printf ("Creating texture with size\n");
|
||||
priv->texture_id = cogl_texture_new_with_size (200, 200,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_RGB_888);
|
||||
|
||||
if (priv->texture_id == COGL_INVALID_HANDLE)
|
||||
printf ("Failed creating texture with size!\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_class_init (TestCoglboxClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = test_coglbox_finalize;
|
||||
gobject_class->dispose = test_coglbox_dispose;
|
||||
|
||||
actor_class->map = test_coglbox_map;
|
||||
actor_class->paint = test_coglbox_paint;
|
||||
}
|
||||
|
||||
static ClutterActor*
|
||||
test_coglbox_new (void)
|
||||
{
|
||||
return g_object_new (TEST_TYPE_COGLBOX, NULL);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_offscreen_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *coglbox;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
/* Stage */
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (stage, 400, 400);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Offscreen Buffers");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* Cogl Box */
|
||||
coglbox = test_coglbox_new ();
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cogl_offscreen_describe (void)
|
||||
{
|
||||
return "Offscreen buffer support in Cogl.";
|
||||
}
|
294
src/tests/clutter/interactive/test-cogl-point-sprites.c
Normal file
294
src/tests/clutter/interactive/test-cogl-point-sprites.c
Normal file
@ -0,0 +1,294 @@
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <math.h>
|
||||
#include <gmodule.h>
|
||||
#include <string.h>
|
||||
|
||||
#define N_FIREWORKS 32
|
||||
/* Units per second per second */
|
||||
#define GRAVITY -1.5f
|
||||
|
||||
#define N_SPARKS (N_FIREWORKS * 32) /* Must be a power of two */
|
||||
#define TIME_PER_SPARK 0.01f /* in seconds */
|
||||
|
||||
#define TEXTURE_SIZE 32
|
||||
|
||||
typedef struct _Firework Firework;
|
||||
|
||||
struct _Firework
|
||||
{
|
||||
float size;
|
||||
float x, y;
|
||||
float start_x, start_y;
|
||||
ClutterColor color;
|
||||
|
||||
/* Velocities are in units per second */
|
||||
float initial_x_velocity;
|
||||
float initial_y_velocity;
|
||||
|
||||
GTimer *timer;
|
||||
};
|
||||
|
||||
typedef struct _Spark Spark;
|
||||
|
||||
struct _Spark
|
||||
{
|
||||
float x, y;
|
||||
ClutterColor color;
|
||||
ClutterColor base_color;
|
||||
};
|
||||
|
||||
typedef struct _Data Data;
|
||||
|
||||
struct _Data
|
||||
{
|
||||
Firework fireworks[N_FIREWORKS];
|
||||
|
||||
int next_spark_num;
|
||||
Spark sparks[N_SPARKS];
|
||||
GTimer *last_spark_time;
|
||||
|
||||
CoglMaterial *material;
|
||||
};
|
||||
|
||||
int
|
||||
test_cogl_point_sprites_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_cogl_point_sprites_describe (void);
|
||||
|
||||
static CoglHandle
|
||||
generate_round_texture (void)
|
||||
{
|
||||
guint8 *p, *data;
|
||||
int x, y;
|
||||
CoglHandle tex;
|
||||
|
||||
p = data = g_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4);
|
||||
|
||||
/* Generate a yellow circle which gets transparent towards the edges */
|
||||
for (y = 0; y < TEXTURE_SIZE; y++)
|
||||
for (x = 0; x < TEXTURE_SIZE; x++)
|
||||
{
|
||||
int dx = x - TEXTURE_SIZE / 2;
|
||||
int dy = y - TEXTURE_SIZE / 2;
|
||||
float value = sqrtf (dx * dx + dy * dy) * 255.0 / (TEXTURE_SIZE / 2);
|
||||
if (value > 255.0f)
|
||||
value = 255.0f;
|
||||
value = 255.0f - value;
|
||||
*(p++) = value;
|
||||
*(p++) = value;
|
||||
*(p++) = value;
|
||||
*(p++) = value;
|
||||
}
|
||||
|
||||
tex = cogl_texture_new_from_data (TEXTURE_SIZE, TEXTURE_SIZE,
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
TEXTURE_SIZE * 4,
|
||||
data);
|
||||
|
||||
g_free (data);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
static void
|
||||
paint_cb (ClutterActor *stage, Data *data)
|
||||
{
|
||||
CoglMatrix old_matrix, new_matrix;
|
||||
int i;
|
||||
float diff_time;
|
||||
CoglHandle vbo;
|
||||
|
||||
cogl_get_projection_matrix (&old_matrix);
|
||||
/* Use an orthogonal projection from -1 -> 1 in both axes */
|
||||
cogl_matrix_init_identity (&new_matrix);
|
||||
cogl_set_projection_matrix (&new_matrix);
|
||||
|
||||
cogl_push_matrix ();
|
||||
cogl_set_modelview_matrix (&new_matrix);
|
||||
|
||||
/* Update all of the firework's positions */
|
||||
for (i = 0; i < N_FIREWORKS; i++)
|
||||
{
|
||||
Firework *firework = data->fireworks + i;
|
||||
|
||||
if ((fabsf (firework->x - firework->start_x) > 2.0f) ||
|
||||
firework->y < -1.0f)
|
||||
{
|
||||
firework->size = g_random_double_range (0.001f, 0.1f);
|
||||
firework->start_x = 1.0f + firework->size;
|
||||
firework->start_y = -1.0f;
|
||||
firework->initial_x_velocity = g_random_double_range (-0.1f, -2.0f);
|
||||
firework->initial_y_velocity = g_random_double_range (0.1f, 4.0f);
|
||||
g_timer_reset (firework->timer);
|
||||
|
||||
/* Pick a random color out of six */
|
||||
if (g_random_boolean ())
|
||||
{
|
||||
memset (&firework->color, 0, sizeof (ClutterColor));
|
||||
((guint8 *) &firework->color)[g_random_int_range (0, 3)] = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (&firework->color, 255, sizeof (ClutterColor));
|
||||
((guint8 *) &firework->color)[g_random_int_range (0, 3)] = 0;
|
||||
}
|
||||
firework->color.alpha = 255;
|
||||
|
||||
/* Fire some of the fireworks from the other side */
|
||||
if (g_random_boolean ())
|
||||
{
|
||||
firework->start_x = -firework->start_x;
|
||||
firework->initial_x_velocity = -firework->initial_x_velocity;
|
||||
}
|
||||
}
|
||||
|
||||
diff_time = g_timer_elapsed (firework->timer, NULL);
|
||||
|
||||
firework->x = (firework->start_x +
|
||||
firework->initial_x_velocity * diff_time);
|
||||
|
||||
firework->y = ((firework->initial_y_velocity * diff_time +
|
||||
0.5f * GRAVITY * diff_time * diff_time) +
|
||||
firework->start_y);
|
||||
}
|
||||
|
||||
diff_time = g_timer_elapsed (data->last_spark_time, NULL);
|
||||
if (diff_time < 0.0f || diff_time >= TIME_PER_SPARK)
|
||||
{
|
||||
/* Add a new spark for each firework, overwriting the oldest ones */
|
||||
for (i = 0; i < N_FIREWORKS; i++)
|
||||
{
|
||||
Spark *spark = data->sparks + data->next_spark_num;
|
||||
Firework *firework = data->fireworks + i;
|
||||
|
||||
spark->x = (firework->x +
|
||||
g_random_double_range (-firework->size / 2.0f,
|
||||
firework->size / 2.0f));
|
||||
spark->y = (firework->y +
|
||||
g_random_double_range (-firework->size / 2.0f,
|
||||
firework->size / 2.0f));
|
||||
spark->base_color = firework->color;
|
||||
|
||||
data->next_spark_num = (data->next_spark_num + 1) & (N_SPARKS - 1);
|
||||
}
|
||||
|
||||
/* Update the colour of each spark */
|
||||
for (i = 0; i < N_SPARKS; i++)
|
||||
{
|
||||
float color_value;
|
||||
|
||||
/* First spark is the oldest */
|
||||
Spark *spark = data->sparks + ((data->next_spark_num + i)
|
||||
& (N_SPARKS - 1));
|
||||
|
||||
color_value = i / (N_SPARKS - 1.0f);
|
||||
spark->color.red = spark->base_color.red * color_value;
|
||||
spark->color.green = spark->base_color.green * color_value;
|
||||
spark->color.blue = spark->base_color.blue * color_value;
|
||||
spark->color.alpha = 255.0f * color_value;
|
||||
}
|
||||
|
||||
g_timer_reset (data->last_spark_time);
|
||||
}
|
||||
|
||||
vbo = cogl_vertex_buffer_new (N_SPARKS);
|
||||
cogl_vertex_buffer_add (vbo, "gl_Vertex", 2,
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT, FALSE,
|
||||
sizeof (Spark),
|
||||
&data->sparks[0].x);
|
||||
cogl_vertex_buffer_add (vbo, "gl_Color", 4,
|
||||
COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE, TRUE,
|
||||
sizeof (Spark),
|
||||
&data->sparks[0].color.red);
|
||||
cogl_vertex_buffer_submit (vbo);
|
||||
|
||||
cogl_set_source (data->material);
|
||||
cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_POINTS, 0, N_SPARKS);
|
||||
|
||||
cogl_handle_unref (vbo);
|
||||
|
||||
cogl_set_projection_matrix (&old_matrix);
|
||||
cogl_pop_matrix ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_cb (gpointer data)
|
||||
{
|
||||
clutter_actor_queue_redraw (data);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_point_sprites_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
CoglHandle tex;
|
||||
Data data;
|
||||
GError *error = NULL;
|
||||
int i;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
data.material = cogl_material_new ();
|
||||
data.last_spark_time = g_timer_new ();
|
||||
data.next_spark_num = 0;
|
||||
cogl_material_set_point_size (data.material, TEXTURE_SIZE);
|
||||
|
||||
tex = generate_round_texture ();
|
||||
cogl_material_set_layer (data.material, 0, tex);
|
||||
cogl_handle_unref (tex);
|
||||
|
||||
if (!cogl_material_set_layer_point_sprite_coords_enabled (data.material,
|
||||
0, TRUE,
|
||||
&error))
|
||||
{
|
||||
g_warning ("Failed to enable point sprite coords: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
for (i = 0; i < N_FIREWORKS; i++)
|
||||
{
|
||||
data.fireworks[i].x = -FLT_MAX;
|
||||
data.fireworks[i].y = FLT_MAX;
|
||||
data.fireworks[i].size = 0.0f;
|
||||
data.fireworks[i].timer = g_timer_new ();
|
||||
}
|
||||
|
||||
for (i = 0; i < N_SPARKS; i++)
|
||||
{
|
||||
data.sparks[i].x = 2.0f;
|
||||
data.sparks[i].y = 2.0f;
|
||||
}
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Point Sprites");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
g_signal_connect_after (stage, "paint", G_CALLBACK (paint_cb), &data);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_threads_add_idle (idle_cb, stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
cogl_object_unref (data.material);
|
||||
g_timer_destroy (data.last_spark_time);
|
||||
|
||||
for (i = 0; i < N_FIREWORKS; i++)
|
||||
g_timer_destroy (data.fireworks[i].timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cogl_point_sprites_describe (void)
|
||||
{
|
||||
return "Point sprites support in Cogl.";
|
||||
}
|
351
src/tests/clutter/interactive/test-cogl-shader-glsl.c
Normal file
351
src/tests/clutter/interactive/test-cogl-shader-glsl.c
Normal file
@ -0,0 +1,351 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
const char *source;
|
||||
} ShaderSource;
|
||||
|
||||
int
|
||||
test_cogl_shader_glsl_main (int argc, char *argv[]);
|
||||
|
||||
/* a couple of boilerplate defines that are common amongst all the
|
||||
* sample shaders
|
||||
*/
|
||||
|
||||
/* FRAGMENT_SHADER_BEGIN: generate boilerplate with a local vec4 color already
|
||||
* initialized, from a sampler2D in a variable tex.
|
||||
*/
|
||||
#define FRAGMENT_SHADER_VARS \
|
||||
"uniform sampler2D tex;" \
|
||||
"uniform float x_step, y_step;"
|
||||
|
||||
#define FRAGMENT_SHADER_BEGIN \
|
||||
"void main (){" \
|
||||
" vec4 color = texture2D (tex, vec2(cogl_tex_coord_in[0]));"
|
||||
|
||||
/* FRAGMENT_SHADER_END: apply the changed color to the output buffer correctly
|
||||
* blended with the gl specified color (makes the opacity of actors work
|
||||
* correctly).
|
||||
*/
|
||||
#define FRAGMENT_SHADER_END \
|
||||
" cogl_color_out = color;" \
|
||||
" cogl_color_out = cogl_color_out * cogl_color_in;" \
|
||||
"}"
|
||||
|
||||
static ShaderSource shaders[]=
|
||||
{
|
||||
{"brightness-contrast",
|
||||
FRAGMENT_SHADER_VARS
|
||||
"uniform float brightness, contrast;"
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" color.rgb /= color.a;"
|
||||
" color.rgb = (color.rgb - vec3(0.5, 0.5, 0.5)) * contrast + "
|
||||
"vec3 (brightness + 0.5, brightness + 0.5, brightness + 0.5);"
|
||||
" color.rgb *= color.a;"
|
||||
FRAGMENT_SHADER_END
|
||||
},
|
||||
|
||||
{"box-blur",
|
||||
FRAGMENT_SHADER_VARS
|
||||
|
||||
"vec4 get_rgba_rel(sampler2D tex, float dx, float dy)"
|
||||
"{"
|
||||
" return texture2D (tex, cogl_tex_coord_in[0].st "
|
||||
" + vec2(dx, dy) * 2.0);"
|
||||
"}"
|
||||
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" float count = 1.0;"
|
||||
" color += get_rgba_rel (tex, -x_step, -y_step); count++;"
|
||||
" color += get_rgba_rel (tex, -x_step, 0.0); count++;"
|
||||
" color += get_rgba_rel (tex, -x_step, y_step); count++;"
|
||||
" color += get_rgba_rel (tex, 0.0, -y_step); count++;"
|
||||
" color += get_rgba_rel (tex, 0.0, 0.0); count++;"
|
||||
" color += get_rgba_rel (tex, 0.0, y_step); count++;"
|
||||
" color += get_rgba_rel (tex, x_step, -y_step); count++;"
|
||||
" color += get_rgba_rel (tex, x_step, 0.0); count++;"
|
||||
" color += get_rgba_rel (tex, x_step, y_step); count++;"
|
||||
" color = color / count;"
|
||||
FRAGMENT_SHADER_END
|
||||
},
|
||||
|
||||
{"invert",
|
||||
FRAGMENT_SHADER_VARS
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" color.rgb /= color.a;"
|
||||
" color.rgb = vec3(1.0, 1.0, 1.0) - color.rgb;\n"
|
||||
" color.rgb *= color.a;"
|
||||
FRAGMENT_SHADER_END
|
||||
},
|
||||
|
||||
{"brightness-contrast",
|
||||
FRAGMENT_SHADER_VARS
|
||||
"uniform float brightness;"
|
||||
"uniform float contrast;"
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" color.rgb /= color.a;"
|
||||
" color.r = (color.r - 0.5) * contrast + brightness + 0.5;"
|
||||
" color.g = (color.g - 0.5) * contrast + brightness + 0.5;"
|
||||
" color.b = (color.b - 0.5) * contrast + brightness + 0.5;"
|
||||
" color.rgb *= color.a;"
|
||||
FRAGMENT_SHADER_END
|
||||
},
|
||||
|
||||
{"gray",
|
||||
FRAGMENT_SHADER_VARS
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" float avg = (color.r + color.g + color.b) / 3.0;"
|
||||
" color.r = avg;"
|
||||
" color.g = avg;"
|
||||
" color.b = avg;"
|
||||
FRAGMENT_SHADER_END
|
||||
},
|
||||
|
||||
{"combined-mirror",
|
||||
FRAGMENT_SHADER_VARS
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" vec4 colorB = texture2D (tex, vec2(cogl_tex_coord_in[0].ts));"
|
||||
" float avg = (color.r + color.g + color.b) / 3.0;"
|
||||
" color.r = avg;"
|
||||
" color.g = avg;"
|
||||
" color.b = avg;"
|
||||
" color = (color + colorB)/2.0;"
|
||||
FRAGMENT_SHADER_END
|
||||
},
|
||||
|
||||
{"edge-detect",
|
||||
FRAGMENT_SHADER_VARS
|
||||
"float get_avg_rel(sampler2D texB, float dx, float dy)"
|
||||
"{"
|
||||
" vec4 colorB = texture2D (texB, cogl_tex_coord_in[0].st + vec2(dx, dy));"
|
||||
" return (colorB.r + colorB.g + colorB.b) / 3.0;"
|
||||
"}"
|
||||
FRAGMENT_SHADER_BEGIN
|
||||
" mat3 sobel_h = mat3( 1.0, 2.0, 1.0,"
|
||||
" 0.0, 0.0, 0.0,"
|
||||
" -1.0, -2.0, -1.0);"
|
||||
" mat3 sobel_v = mat3( 1.0, 0.0, -1.0,"
|
||||
" 2.0, 0.0, -2.0,"
|
||||
" 1.0, 0.0, -1.0);"
|
||||
" mat3 map = mat3( get_avg_rel(tex, -x_step, -y_step),"
|
||||
" get_avg_rel(tex, -x_step, 0.0),"
|
||||
" get_avg_rel(tex, -x_step, y_step),"
|
||||
" get_avg_rel(tex, 0.0, -y_step),"
|
||||
" get_avg_rel(tex, 0.0, 0.0),"
|
||||
" get_avg_rel(tex, 0.0, y_step),"
|
||||
" get_avg_rel(tex, x_step, -y_step),"
|
||||
" get_avg_rel(tex, x_step, 0.0),"
|
||||
" get_avg_rel(tex, x_step, y_step) );"
|
||||
" mat3 gh = sobel_h * map;"
|
||||
" mat3 gv = map * sobel_v;"
|
||||
" float avgh = (gh[0][0] + gh[0][1] + gh[0][2] +"
|
||||
" gh[1][0] + gh[1][1] + gh[1][2] +"
|
||||
" gh[2][0] + gh[2][1] + gh[2][2]) / 18.0 + 0.5;"
|
||||
" float avgv = (gv[0][0] + gv[0][1] + gv[0][2] +"
|
||||
" gv[1][0] + gv[1][1] + gv[1][2] +"
|
||||
" gv[2][0] + gv[2][1] + gv[2][2]) / 18.0 + 0.5;"
|
||||
" float avg = (avgh + avgv) / 2.0;"
|
||||
" color.r = avg * color.r;"
|
||||
" color.g = avg * color.g;"
|
||||
" color.b = avg * color.b;"
|
||||
FRAGMENT_SHADER_END
|
||||
}
|
||||
};
|
||||
|
||||
static CoglHandle redhand;
|
||||
static CoglMaterial *material;
|
||||
static unsigned int timeout_id = 0;
|
||||
static int shader_no = 0;
|
||||
|
||||
static void
|
||||
paint_cb (ClutterActor *actor)
|
||||
{
|
||||
float stage_width = clutter_actor_get_width (actor);
|
||||
float stage_height = clutter_actor_get_height (actor);
|
||||
float image_width = cogl_texture_get_width (redhand);
|
||||
float image_height = cogl_texture_get_height (redhand);
|
||||
|
||||
cogl_set_source (material);
|
||||
cogl_rectangle (stage_width/2.0f - image_width/2.0f,
|
||||
stage_height/2.0f - image_height/2.0f,
|
||||
stage_width/2.0f + image_width/2.0f,
|
||||
stage_height/2.0f + image_height/2.0f);
|
||||
}
|
||||
|
||||
static void
|
||||
set_shader_num (int new_no)
|
||||
{
|
||||
CoglHandle shader;
|
||||
CoglHandle program;
|
||||
int image_width = cogl_texture_get_width (redhand);
|
||||
int image_height = cogl_texture_get_height (redhand);
|
||||
int uniform_no;
|
||||
|
||||
g_print ("setting shaders[%i] named '%s'\n",
|
||||
new_no,
|
||||
shaders[new_no].name);
|
||||
|
||||
shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
|
||||
cogl_shader_source (shader, shaders[new_no].source);
|
||||
cogl_shader_compile (shader);
|
||||
|
||||
program = cogl_create_program ();
|
||||
cogl_program_attach_shader (program, shader);
|
||||
cogl_handle_unref (shader);
|
||||
cogl_program_link (program);
|
||||
|
||||
uniform_no = cogl_program_get_uniform_location (program, "tex");
|
||||
cogl_program_set_uniform_1i (program, uniform_no, 0);
|
||||
uniform_no = cogl_program_get_uniform_location (program, "radius");
|
||||
cogl_program_set_uniform_1f (program, uniform_no, 3.0);
|
||||
uniform_no = cogl_program_get_uniform_location (program, "brightness");
|
||||
cogl_program_set_uniform_1f (program, uniform_no, 0.4);
|
||||
uniform_no = cogl_program_get_uniform_location (program, "contrast");
|
||||
cogl_program_set_uniform_1f (program, uniform_no, -1.9);
|
||||
|
||||
uniform_no = cogl_program_get_uniform_location (program, "x_step");
|
||||
cogl_program_set_uniform_1f (program, uniform_no, 1.0f / image_width);
|
||||
uniform_no = cogl_program_get_uniform_location (program, "y_step");
|
||||
cogl_program_set_uniform_1f (program, uniform_no, 1.0f / image_height);
|
||||
|
||||
cogl_material_set_user_program (material, program);
|
||||
cogl_handle_unref (program);
|
||||
|
||||
shader_no = new_no;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
button_release_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
int new_no;
|
||||
|
||||
/* Stop the automatic cycling if the user want to manually control
|
||||
* which shader to display */
|
||||
if (timeout_id)
|
||||
{
|
||||
g_source_remove (timeout_id);
|
||||
timeout_id = 0;
|
||||
}
|
||||
|
||||
if (event->button.button == 1)
|
||||
{
|
||||
new_no = shader_no - 1;
|
||||
if (new_no < 0)
|
||||
new_no = G_N_ELEMENTS (shaders) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_no = shader_no + 1;
|
||||
if (new_no >= G_N_ELEMENTS (shaders))
|
||||
new_no = 0;
|
||||
}
|
||||
|
||||
set_shader_num (new_no);
|
||||
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
key_release_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
guint keysym = clutter_event_get_key_symbol (event);
|
||||
ClutterModifierType mods = clutter_event_get_state (event);
|
||||
|
||||
if (keysym == CLUTTER_KEY_q ||
|
||||
((mods & CLUTTER_SHIFT_MASK) && keysym == CLUTTER_KEY_q))
|
||||
clutter_main_quit ();
|
||||
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timeout_cb (gpointer user_data)
|
||||
{
|
||||
shader_no++;
|
||||
if (shader_no > (G_N_ELEMENTS (shaders) - 1))
|
||||
shader_no = 0;
|
||||
|
||||
set_shader_num (shader_no);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_cb (gpointer data)
|
||||
{
|
||||
clutter_actor_queue_redraw (data);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
destroy_window_cb (ClutterStage *stage,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
clutter_main_quit ();
|
||||
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_shader_glsl_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
char *file;
|
||||
GError *error;
|
||||
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Assembly Shader Test");
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
error = NULL;
|
||||
redhand = cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NO_ATLAS,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
&error);
|
||||
if (redhand == COGL_INVALID_HANDLE)
|
||||
g_error ("image load failed: %s", error->message);
|
||||
|
||||
material = cogl_material_new ();
|
||||
cogl_material_set_layer (material, 0, redhand);
|
||||
|
||||
set_shader_num (0);
|
||||
g_signal_connect_after (stage, "paint", G_CALLBACK (paint_cb), NULL);
|
||||
|
||||
clutter_actor_set_reactive (stage, TRUE);
|
||||
g_signal_connect (stage, "button-release-event",
|
||||
G_CALLBACK (button_release_cb), NULL);
|
||||
g_signal_connect (stage, "key-release-event",
|
||||
G_CALLBACK (key_release_cb), NULL);
|
||||
|
||||
g_signal_connect (stage, "delete-event",
|
||||
G_CALLBACK (destroy_window_cb), NULL);
|
||||
|
||||
timeout_id = clutter_threads_add_timeout (1000, timeout_cb, NULL);
|
||||
|
||||
clutter_threads_add_idle (idle_cb, stage);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
229
src/tests/clutter/interactive/test-cogl-tex-convert.c
Normal file
229
src/tests/clutter/interactive/test-cogl-tex-convert.c
Normal file
@ -0,0 +1,229 @@
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
/* Coglbox declaration
|
||||
*--------------------------------------------------*/
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define TEST_TYPE_COGLBOX test_coglbox_get_type()
|
||||
|
||||
#define TEST_COGLBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
TEST_TYPE_COGLBOX, TestCoglbox))
|
||||
|
||||
#define TEST_COGLBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
#define TEST_IS_COGLBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
TEST_TYPE_COGLBOX))
|
||||
|
||||
#define TEST_IS_COGLBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
TEST_TYPE_COGLBOX))
|
||||
|
||||
#define TEST_COGLBOX_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
typedef struct _TestCoglbox TestCoglbox;
|
||||
typedef struct _TestCoglboxClass TestCoglboxClass;
|
||||
typedef struct _TestCoglboxPrivate TestCoglboxPrivate;
|
||||
|
||||
struct _TestCoglbox
|
||||
{
|
||||
ClutterActor parent;
|
||||
|
||||
/*< private >*/
|
||||
TestCoglboxPrivate *priv;
|
||||
};
|
||||
|
||||
struct _TestCoglboxClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
void (*_test_coglbox1) (void);
|
||||
void (*_test_coglbox2) (void);
|
||||
void (*_test_coglbox3) (void);
|
||||
void (*_test_coglbox4) (void);
|
||||
};
|
||||
|
||||
static GType test_coglbox_get_type (void) G_GNUC_CONST;
|
||||
|
||||
int
|
||||
test_cogl_tex_convert_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_cogl_tex_convert_describe (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
/* Coglbox private declaration
|
||||
*--------------------------------------------------*/
|
||||
|
||||
struct _TestCoglboxPrivate
|
||||
{
|
||||
CoglHandle cogl_tex_id[4];
|
||||
gint frame;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
#define TEST_COGLBOX_GET_PRIVATE(obj) \
|
||||
(test_coglbox_get_instance_private (TEST_COGLBOX ((obj))))
|
||||
|
||||
/* Coglbox implementation
|
||||
*--------------------------------------------------*/
|
||||
|
||||
static void
|
||||
test_coglbox_paint(ClutterActor *self)
|
||||
{
|
||||
TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self);
|
||||
gfloat texcoords[4] = { 0.0, 0.0, 1.0, 1.0 };
|
||||
|
||||
priv = TEST_COGLBOX_GET_PRIVATE (self);
|
||||
|
||||
cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff);
|
||||
cogl_rectangle (0, 0, 400, 400);
|
||||
|
||||
cogl_push_matrix ();
|
||||
cogl_set_source_texture (priv->cogl_tex_id[0]);
|
||||
cogl_rectangle_with_texture_coords (0, 0, 200, 213,
|
||||
texcoords[0], texcoords[1],
|
||||
texcoords[2], texcoords[3]);
|
||||
|
||||
cogl_pop_matrix ();
|
||||
cogl_push_matrix ();
|
||||
cogl_translate (200, 0, 0);
|
||||
cogl_set_source_texture (priv->cogl_tex_id[1]);
|
||||
cogl_rectangle_with_texture_coords (0, 0, 200, 213,
|
||||
texcoords[0], texcoords[1],
|
||||
texcoords[2], texcoords[3]);
|
||||
|
||||
cogl_pop_matrix ();
|
||||
cogl_push_matrix ();
|
||||
cogl_translate (0, 200, 0);
|
||||
cogl_set_source_texture (priv->cogl_tex_id[2]);
|
||||
cogl_rectangle_with_texture_coords (0, 0, 200, 213,
|
||||
texcoords[0], texcoords[1],
|
||||
texcoords[2], texcoords[3]);
|
||||
|
||||
cogl_pop_matrix ();
|
||||
cogl_push_matrix ();
|
||||
cogl_translate (200, 200, 0);
|
||||
cogl_set_source_texture (priv->cogl_tex_id[3]);
|
||||
cogl_rectangle_with_texture_coords (0, 0, 200, 213,
|
||||
texcoords[0], texcoords[1],
|
||||
texcoords[2], texcoords[3]);
|
||||
|
||||
cogl_pop_matrix();
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_dispose (GObject *object)
|
||||
{
|
||||
TestCoglboxPrivate *priv;
|
||||
|
||||
priv = TEST_COGLBOX_GET_PRIVATE (object);
|
||||
cogl_handle_unref (priv->cogl_tex_id);
|
||||
|
||||
G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_init (TestCoglbox *self)
|
||||
{
|
||||
TestCoglboxPrivate *priv;
|
||||
gchar *file;
|
||||
|
||||
self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self);
|
||||
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
|
||||
priv->cogl_tex_id[0] =
|
||||
cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
NULL);
|
||||
|
||||
priv->cogl_tex_id[1] =
|
||||
cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_BGRA_8888,
|
||||
NULL);
|
||||
|
||||
priv->cogl_tex_id[2] =
|
||||
cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_ARGB_8888,
|
||||
NULL);
|
||||
|
||||
priv->cogl_tex_id[3] =
|
||||
cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_G_8,
|
||||
NULL);
|
||||
|
||||
g_free (file);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_class_init (TestCoglboxClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = test_coglbox_finalize;
|
||||
gobject_class->dispose = test_coglbox_dispose;
|
||||
actor_class->paint = test_coglbox_paint;
|
||||
}
|
||||
|
||||
static ClutterActor*
|
||||
test_coglbox_new (void)
|
||||
{
|
||||
return g_object_new (TEST_TYPE_COGLBOX, NULL);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_tex_convert_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *coglbox;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
/* Stage */
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (stage, 400, 400);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Texture Conversion");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* Cogl Box */
|
||||
coglbox = test_coglbox_new ();
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cogl_tex_convert_describe (void)
|
||||
{
|
||||
return "Pixel format conversion of Cogl textures.";
|
||||
}
|
425
src/tests/clutter/interactive/test-cogl-tex-polygon.c
Normal file
425
src/tests/clutter/interactive/test-cogl-tex-polygon.c
Normal file
@ -0,0 +1,425 @@
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
/* Coglbox declaration
|
||||
*--------------------------------------------------*/
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define TEST_TYPE_COGLBOX test_coglbox_get_type()
|
||||
|
||||
#define TEST_COGLBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
TEST_TYPE_COGLBOX, TestCoglbox))
|
||||
|
||||
#define TEST_COGLBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
#define TEST_IS_COGLBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
TEST_TYPE_COGLBOX))
|
||||
|
||||
#define TEST_IS_COGLBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
TEST_TYPE_COGLBOX))
|
||||
|
||||
#define TEST_COGLBOX_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
typedef struct _TestCoglbox TestCoglbox;
|
||||
typedef struct _TestCoglboxClass TestCoglboxClass;
|
||||
typedef struct _TestCoglboxPrivate TestCoglboxPrivate;
|
||||
|
||||
struct _TestCoglbox
|
||||
{
|
||||
ClutterActor parent;
|
||||
|
||||
/*< private >*/
|
||||
TestCoglboxPrivate *priv;
|
||||
};
|
||||
|
||||
struct _TestCoglboxClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
void (*_test_coglbox1) (void);
|
||||
void (*_test_coglbox2) (void);
|
||||
void (*_test_coglbox3) (void);
|
||||
void (*_test_coglbox4) (void);
|
||||
};
|
||||
|
||||
static GType test_coglbox_get_type (void) G_GNUC_CONST;
|
||||
|
||||
int
|
||||
test_cogl_tex_polygon_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_cogl_tex_polygon_describe (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
/* Coglbox private declaration
|
||||
*--------------------------------------------------*/
|
||||
|
||||
struct _TestCoglboxPrivate
|
||||
{
|
||||
CoglHandle sliced_tex, not_sliced_tex;
|
||||
gint frame;
|
||||
gboolean use_sliced;
|
||||
gboolean use_linear_filtering;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
#define TEST_COGLBOX_GET_PRIVATE(obj) \
|
||||
((TestCoglboxPrivate *)test_coglbox_get_instance_private (TEST_COGLBOX ((obj))))
|
||||
|
||||
/* Coglbox implementation
|
||||
*--------------------------------------------------*/
|
||||
|
||||
static void
|
||||
test_coglbox_fade_texture (gfloat x1,
|
||||
gfloat y1,
|
||||
gfloat x2,
|
||||
gfloat y2,
|
||||
gfloat tx1,
|
||||
gfloat ty1,
|
||||
gfloat tx2,
|
||||
gfloat ty2)
|
||||
{
|
||||
CoglTextureVertex vertices[4];
|
||||
int i;
|
||||
|
||||
vertices[0].x = x1;
|
||||
vertices[0].y = y1;
|
||||
vertices[0].z = 0;
|
||||
vertices[0].tx = tx1;
|
||||
vertices[0].ty = ty1;
|
||||
vertices[1].x = x1;
|
||||
vertices[1].y = y2;
|
||||
vertices[1].z = 0;
|
||||
vertices[1].tx = tx1;
|
||||
vertices[1].ty = ty2;
|
||||
vertices[2].x = x2;
|
||||
vertices[2].y = y2;
|
||||
vertices[2].z = 0;
|
||||
vertices[2].tx = tx2;
|
||||
vertices[2].ty = ty2;
|
||||
vertices[3].x = x2;
|
||||
vertices[3].y = y1;
|
||||
vertices[3].z = 0;
|
||||
vertices[3].tx = tx2;
|
||||
vertices[3].ty = ty1;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
cogl_color_init_from_4ub (&(vertices[i].color),
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
((i ^ (i >> 1)) & 1) ? 0 : 128);
|
||||
cogl_color_premultiply (&(vertices[i].color));
|
||||
}
|
||||
|
||||
cogl_polygon (vertices, 4, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_triangle_texture (int tex_width,
|
||||
int tex_height,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gfloat tx1,
|
||||
gfloat ty1,
|
||||
gfloat tx2,
|
||||
gfloat ty2,
|
||||
gfloat tx3,
|
||||
gfloat ty3)
|
||||
{
|
||||
CoglTextureVertex vertices[3];
|
||||
|
||||
vertices[0].x = x + tx1 * tex_width;
|
||||
vertices[0].y = y + ty1 * tex_height;
|
||||
vertices[0].z = 0;
|
||||
vertices[0].tx = tx1;
|
||||
vertices[0].ty = ty1;
|
||||
|
||||
vertices[1].x = x + tx2 * tex_width;
|
||||
vertices[1].y = y + ty2 * tex_height;
|
||||
vertices[1].z = 0;
|
||||
vertices[1].tx = tx2;
|
||||
vertices[1].ty = ty2;
|
||||
|
||||
vertices[2].x = x + tx3 * tex_width;
|
||||
vertices[2].y = y + ty3 * tex_height;
|
||||
vertices[2].z = 0;
|
||||
vertices[2].tx = tx3;
|
||||
vertices[2].ty = ty3;
|
||||
|
||||
cogl_polygon (vertices, 3, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_paint (ClutterActor *self)
|
||||
{
|
||||
TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self);
|
||||
CoglHandle tex_handle = priv->use_sliced ? priv->sliced_tex
|
||||
: priv->not_sliced_tex;
|
||||
int tex_width = cogl_texture_get_width (tex_handle);
|
||||
int tex_height = cogl_texture_get_height (tex_handle);
|
||||
CoglHandle material = cogl_material_new ();
|
||||
|
||||
cogl_material_set_layer (material, 0, tex_handle);
|
||||
|
||||
cogl_material_set_layer_filters (material, 0,
|
||||
priv->use_linear_filtering
|
||||
? COGL_MATERIAL_FILTER_LINEAR :
|
||||
COGL_MATERIAL_FILTER_NEAREST,
|
||||
priv->use_linear_filtering
|
||||
? COGL_MATERIAL_FILTER_LINEAR :
|
||||
COGL_MATERIAL_FILTER_NEAREST);
|
||||
|
||||
cogl_push_matrix ();
|
||||
cogl_translate (tex_width / 2, 0, 0);
|
||||
cogl_rotate (priv->frame, 0, 1, 0);
|
||||
cogl_translate (-tex_width / 2, 0, 0);
|
||||
|
||||
/* Draw a hand and refect it */
|
||||
cogl_set_source (material);
|
||||
cogl_rectangle_with_texture_coords (0, 0, tex_width, tex_height,
|
||||
0, 0, 1, 1);
|
||||
test_coglbox_fade_texture (0, tex_height,
|
||||
tex_width, (tex_height * 3 / 2),
|
||||
0.0, 1.0,
|
||||
1.0, 0.5);
|
||||
|
||||
cogl_pop_matrix ();
|
||||
|
||||
cogl_push_matrix ();
|
||||
cogl_translate (tex_width * 3 / 2 + 60, 0, 0);
|
||||
cogl_rotate (priv->frame, 0, 1, 0);
|
||||
cogl_translate (-tex_width / 2 - 10, 0, 0);
|
||||
|
||||
/* Draw the texture split into two triangles */
|
||||
test_coglbox_triangle_texture (tex_width, tex_height,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 1,
|
||||
1, 1);
|
||||
test_coglbox_triangle_texture (tex_width, tex_height,
|
||||
20, 0,
|
||||
0, 0,
|
||||
1, 0,
|
||||
1, 1);
|
||||
|
||||
cogl_pop_matrix ();
|
||||
|
||||
cogl_handle_unref (material);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_dispose (GObject *object)
|
||||
{
|
||||
TestCoglboxPrivate *priv;
|
||||
|
||||
priv = TEST_COGLBOX_GET_PRIVATE (object);
|
||||
cogl_handle_unref (priv->not_sliced_tex);
|
||||
cogl_handle_unref (priv->sliced_tex);
|
||||
|
||||
G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_init (TestCoglbox *self)
|
||||
{
|
||||
TestCoglboxPrivate *priv;
|
||||
GError *error = NULL;
|
||||
gchar *file;
|
||||
|
||||
self->priv = priv = TEST_COGLBOX_GET_PRIVATE (self);
|
||||
|
||||
priv->use_linear_filtering = FALSE;
|
||||
priv->use_sliced = FALSE;
|
||||
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
priv->sliced_tex =
|
||||
cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
&error);
|
||||
if (priv->sliced_tex == COGL_INVALID_HANDLE)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Texture loading failed: %s", error->message);
|
||||
g_error_free (error);
|
||||
error = NULL;
|
||||
}
|
||||
else
|
||||
g_warning ("Texture loading failed: <unknown>");
|
||||
}
|
||||
|
||||
priv->not_sliced_tex =
|
||||
cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
&error);
|
||||
if (priv->not_sliced_tex == COGL_INVALID_HANDLE)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Texture loading failed: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
g_warning ("Texture loading failed: <unknown>");
|
||||
}
|
||||
|
||||
g_free (file);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_class_init (TestCoglboxClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = test_coglbox_finalize;
|
||||
gobject_class->dispose = test_coglbox_dispose;
|
||||
actor_class->paint = test_coglbox_paint;
|
||||
}
|
||||
|
||||
static ClutterActor*
|
||||
test_coglbox_new (void)
|
||||
{
|
||||
return g_object_new (TEST_TYPE_COGLBOX, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
frame_cb (ClutterTimeline *timeline,
|
||||
gint elapsed_msecs,
|
||||
gpointer data)
|
||||
{
|
||||
TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (data);
|
||||
gdouble progress = clutter_timeline_get_progress (timeline);
|
||||
|
||||
priv->frame = 360.0 * progress;
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
|
||||
}
|
||||
|
||||
static void
|
||||
update_toggle_text (ClutterText *button, gboolean val)
|
||||
{
|
||||
clutter_text_set_text (button, val ? "Enabled" : "Disabled");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_toggle_click (ClutterActor *button, ClutterEvent *event,
|
||||
gboolean *toggle_val)
|
||||
{
|
||||
update_toggle_text (CLUTTER_TEXT (button), *toggle_val = !*toggle_val);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
make_toggle (const char *label_text, gboolean *toggle_val)
|
||||
{
|
||||
ClutterActor *group = clutter_group_new ();
|
||||
ClutterActor *label = clutter_text_new_with_text ("Sans 14", label_text);
|
||||
ClutterActor *button = clutter_text_new_with_text ("Sans 14", "");
|
||||
|
||||
clutter_actor_set_reactive (button, TRUE);
|
||||
|
||||
update_toggle_text (CLUTTER_TEXT (button), *toggle_val);
|
||||
|
||||
clutter_actor_set_position (button, clutter_actor_get_width (label) + 10, 0);
|
||||
clutter_container_add (CLUTTER_CONTAINER (group), label, button, NULL);
|
||||
|
||||
g_signal_connect (button, "button-press-event", G_CALLBACK (on_toggle_click),
|
||||
toggle_val);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_tex_polygon_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *coglbox;
|
||||
ClutterActor *filtering_toggle;
|
||||
ClutterActor *slicing_toggle;
|
||||
ClutterActor *note;
|
||||
ClutterTimeline *timeline;
|
||||
ClutterColor blue = { 0x30, 0x30, 0xff, 0xff };
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
/* Stage */
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &blue);
|
||||
clutter_actor_set_size (stage, 640, 480);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Texture Polygon");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* Cogl Box */
|
||||
coglbox = test_coglbox_new ();
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox);
|
||||
|
||||
/* Timeline for animation */
|
||||
timeline = clutter_timeline_new (6000);
|
||||
clutter_timeline_set_loop (timeline, TRUE);
|
||||
g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), coglbox);
|
||||
clutter_timeline_start (timeline);
|
||||
|
||||
/* Labels for toggling settings */
|
||||
slicing_toggle = make_toggle ("Texture slicing: ",
|
||||
&(TEST_COGLBOX_GET_PRIVATE (coglbox)
|
||||
->use_sliced));
|
||||
clutter_actor_set_position (slicing_toggle, 0,
|
||||
clutter_actor_get_height (stage)
|
||||
- clutter_actor_get_height (slicing_toggle));
|
||||
filtering_toggle = make_toggle ("Linear filtering: ",
|
||||
&(TEST_COGLBOX_GET_PRIVATE (coglbox)
|
||||
->use_linear_filtering));
|
||||
clutter_actor_set_position (filtering_toggle, 0,
|
||||
clutter_actor_get_y (slicing_toggle)
|
||||
- clutter_actor_get_height (filtering_toggle));
|
||||
note = clutter_text_new_with_text ("Sans 10", "<- Click to change");
|
||||
clutter_actor_set_position (note,
|
||||
clutter_actor_get_width (filtering_toggle) + 10,
|
||||
(clutter_actor_get_height (stage)
|
||||
+ clutter_actor_get_y (filtering_toggle)) / 2
|
||||
- clutter_actor_get_height (note) / 2);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage),
|
||||
slicing_toggle,
|
||||
filtering_toggle,
|
||||
note,
|
||||
NULL);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cogl_tex_polygon_describe (void)
|
||||
{
|
||||
return "Texture polygon primitive.";
|
||||
}
|
223
src/tests/clutter/interactive/test-cogl-tex-tile.c
Normal file
223
src/tests/clutter/interactive/test-cogl-tex-tile.c
Normal file
@ -0,0 +1,223 @@
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
/* Coglbox declaration
|
||||
*--------------------------------------------------*/
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define TEST_TYPE_COGLBOX test_coglbox_get_type()
|
||||
|
||||
#define TEST_COGLBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
TEST_TYPE_COGLBOX, TestCoglbox))
|
||||
|
||||
#define TEST_COGLBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
#define TEST_IS_COGLBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
TEST_TYPE_COGLBOX))
|
||||
|
||||
#define TEST_IS_COGLBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
TEST_TYPE_COGLBOX))
|
||||
|
||||
#define TEST_COGLBOX_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
typedef struct _TestCoglbox TestCoglbox;
|
||||
typedef struct _TestCoglboxClass TestCoglboxClass;
|
||||
typedef struct _TestCoglboxPrivate TestCoglboxPrivate;
|
||||
|
||||
struct _TestCoglbox
|
||||
{
|
||||
ClutterActor parent;
|
||||
|
||||
/*< private >*/
|
||||
TestCoglboxPrivate *priv;
|
||||
};
|
||||
|
||||
struct _TestCoglboxClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
void (*_test_coglbox1) (void);
|
||||
void (*_test_coglbox2) (void);
|
||||
void (*_test_coglbox3) (void);
|
||||
void (*_test_coglbox4) (void);
|
||||
};
|
||||
|
||||
static GType test_coglbox_get_type (void) G_GNUC_CONST;
|
||||
|
||||
int
|
||||
test_cogl_tex_tile_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_cogl_tex_tile_describe (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
/* Coglbox private declaration
|
||||
*--------------------------------------------------*/
|
||||
|
||||
struct _TestCoglboxPrivate
|
||||
{
|
||||
CoglHandle cogl_tex_id;
|
||||
gdouble animation_progress;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
#define TEST_COGLBOX_GET_PRIVATE(obj) \
|
||||
(test_coglbox_get_instance_private (TEST_COGLBOX ((obj))))
|
||||
|
||||
/* Coglbox implementation
|
||||
*--------------------------------------------------*/
|
||||
|
||||
static void
|
||||
test_coglbox_paint (ClutterActor *self)
|
||||
{
|
||||
TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self);
|
||||
gfloat texcoords[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
gfloat angle;
|
||||
gfloat frac;
|
||||
gint t;
|
||||
|
||||
angle = priv->animation_progress * 2 * G_PI;
|
||||
|
||||
frac = ((priv->animation_progress <= 0.5f
|
||||
? priv->animation_progress
|
||||
: 1.0f - priv->animation_progress) + 0.5f) * 2.0f;
|
||||
|
||||
for (t=0; t<4; t+=2)
|
||||
{
|
||||
texcoords[t] += cos (angle);
|
||||
texcoords[t+1] += sin (angle);
|
||||
|
||||
texcoords[t] *= frac;
|
||||
texcoords[t+1] *= frac;
|
||||
}
|
||||
|
||||
priv = TEST_COGLBOX_GET_PRIVATE (self);
|
||||
|
||||
cogl_push_matrix ();
|
||||
|
||||
cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff);
|
||||
cogl_rectangle (0, 0, 400, 400);
|
||||
|
||||
cogl_translate (100, 100, 0);
|
||||
cogl_set_source_texture (priv->cogl_tex_id);
|
||||
cogl_rectangle_with_texture_coords (0, 0, 200, 213,
|
||||
texcoords[0], texcoords[1],
|
||||
texcoords[2], texcoords[3]);
|
||||
|
||||
cogl_pop_matrix();
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_dispose (GObject *object)
|
||||
{
|
||||
TestCoglboxPrivate *priv;
|
||||
|
||||
priv = TEST_COGLBOX_GET_PRIVATE (object);
|
||||
cogl_handle_unref (priv->cogl_tex_id);
|
||||
|
||||
G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_init (TestCoglbox *self)
|
||||
{
|
||||
TestCoglboxPrivate *priv;
|
||||
gchar *file;
|
||||
|
||||
self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self);
|
||||
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
priv->cogl_tex_id = cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
NULL);
|
||||
g_free (file);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_class_init (TestCoglboxClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = test_coglbox_finalize;
|
||||
gobject_class->dispose = test_coglbox_dispose;
|
||||
actor_class->paint = test_coglbox_paint;
|
||||
}
|
||||
|
||||
static ClutterActor*
|
||||
test_coglbox_new (void)
|
||||
{
|
||||
return g_object_new (TEST_TYPE_COGLBOX, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
frame_cb (ClutterTimeline *timeline,
|
||||
gint msecs,
|
||||
gpointer data)
|
||||
{
|
||||
TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (data);
|
||||
|
||||
priv->animation_progress = clutter_timeline_get_progress (timeline);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_tex_tile_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *coglbox;
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
/* Stage */
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (stage, 400, 400);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Texture Tiling");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* Cogl Box */
|
||||
coglbox = test_coglbox_new ();
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox);
|
||||
|
||||
/* Timeline for animation */
|
||||
timeline = clutter_timeline_new (6000); /* 6 second duration */
|
||||
clutter_timeline_set_loop (timeline, TRUE);
|
||||
g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), coglbox);
|
||||
clutter_timeline_start (timeline);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cogl_tex_tile_describe (void)
|
||||
{
|
||||
return "Texture tiling.";
|
||||
}
|
396
src/tests/clutter/interactive/test-cogl-vertex-buffer.c
Normal file
396
src/tests/clutter/interactive/test-cogl-vertex-buffer.c
Normal file
@ -0,0 +1,396 @@
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Defines the size and resolution of the quad mesh we morph:
|
||||
*/
|
||||
#define MESH_WIDTH 100.0 /* number of quads along x axis */
|
||||
#define MESH_HEIGHT 100.0 /* number of quads along y axis */
|
||||
#define QUAD_WIDTH 5.0 /* width in pixels of a single quad */
|
||||
#define QUAD_HEIGHT 5.0 /* height in pixels of a single quad */
|
||||
|
||||
/* Defines a sine wave that sweeps across the mesh:
|
||||
*/
|
||||
#define WAVE_DEPTH ((MESH_WIDTH * QUAD_WIDTH) / 16.0) /* peak amplitude */
|
||||
#define WAVE_PERIODS 4.0
|
||||
#define WAVE_SPEED 10.0
|
||||
|
||||
/* Defines a rippling sine wave emitted from a point:
|
||||
*/
|
||||
#define RIPPLE_CENTER_X ((MESH_WIDTH / 2.0) * QUAD_WIDTH)
|
||||
#define RIPPLE_CENTER_Y ((MESH_HEIGHT / 2.0) * QUAD_HEIGHT)
|
||||
#define RIPPLE_RADIUS (MESH_WIDTH * QUAD_WIDTH)
|
||||
#define RIPPLE_DEPTH ((MESH_WIDTH * QUAD_WIDTH) / 16.0) /* peak amplitude */
|
||||
#define RIPPLE_PERIODS 4.0
|
||||
#define RIPPLE_SPEED -10.0
|
||||
|
||||
/* Defines the width of the gaussian bell used to fade out the alpha
|
||||
* towards the edges of the mesh (starting from the ripple center):
|
||||
*/
|
||||
#define GAUSSIAN_RADIUS ((MESH_WIDTH * QUAD_WIDTH) / 6.0)
|
||||
|
||||
/* Our hues lie in the range [0, 1], and this defines how we map amplitude
|
||||
* to hues (before scaling by {WAVE,RIPPLE}_DEPTH)
|
||||
* As we are interferring two sine waves together; amplitudes lie in the
|
||||
* range [-2, 2]
|
||||
*/
|
||||
#define HSL_OFFSET 0.5 /* the hue that we map an amplitude of 0 too */
|
||||
#define HSL_SCALE 0.25
|
||||
|
||||
typedef struct _TestState
|
||||
{
|
||||
ClutterActor *dummy;
|
||||
CoglHandle buffer;
|
||||
float *quad_mesh_verts;
|
||||
guint8 *quad_mesh_colors;
|
||||
guint16 *static_indices;
|
||||
guint n_static_indices;
|
||||
CoglHandle indices;
|
||||
ClutterTimeline *timeline;
|
||||
guint frame_id;
|
||||
} TestState;
|
||||
|
||||
int
|
||||
test_cogl_vertex_buffer_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_cogl_vertex_buffer_describe (void);
|
||||
|
||||
static void
|
||||
frame_cb (ClutterTimeline *timeline,
|
||||
gint elapsed_msecs,
|
||||
TestState *state)
|
||||
{
|
||||
guint x, y;
|
||||
float period_progress = clutter_timeline_get_progress (timeline);
|
||||
float period_progress_sin = sinf (period_progress);
|
||||
float wave_shift = period_progress * WAVE_SPEED;
|
||||
float ripple_shift = period_progress * RIPPLE_SPEED;
|
||||
|
||||
for (y = 0; y <= MESH_HEIGHT; y++)
|
||||
for (x = 0; x <= MESH_WIDTH; x++)
|
||||
{
|
||||
guint vert_index = (MESH_WIDTH + 1) * y + x;
|
||||
float *vert = &state->quad_mesh_verts[3 * vert_index];
|
||||
|
||||
float real_x = x * QUAD_WIDTH;
|
||||
float real_y = y * QUAD_HEIGHT;
|
||||
|
||||
float wave_offset = (float)x / (MESH_WIDTH + 1);
|
||||
float wave_angle =
|
||||
(WAVE_PERIODS * 2 * G_PI * wave_offset) + wave_shift;
|
||||
float wave_sin = sinf (wave_angle);
|
||||
|
||||
float a_sqr = (RIPPLE_CENTER_X - real_x) * (RIPPLE_CENTER_X - real_x);
|
||||
float b_sqr = (RIPPLE_CENTER_Y - real_y) * (RIPPLE_CENTER_Y - real_y);
|
||||
float ripple_offset = sqrtf (a_sqr + b_sqr) / RIPPLE_RADIUS;
|
||||
float ripple_angle =
|
||||
(RIPPLE_PERIODS * 2 * G_PI * ripple_offset) + ripple_shift;
|
||||
float ripple_sin = sinf (ripple_angle);
|
||||
|
||||
float h, s, l;
|
||||
guint8 *color;
|
||||
|
||||
vert[2] = (wave_sin * WAVE_DEPTH) + (ripple_sin * RIPPLE_DEPTH);
|
||||
|
||||
/* Burn some CPU time picking a pretty color... */
|
||||
h = (HSL_OFFSET
|
||||
+ wave_sin
|
||||
+ ripple_sin
|
||||
+ period_progress_sin) * HSL_SCALE;
|
||||
s = 0.5;
|
||||
l = 0.25 + (period_progress_sin + 1.0) / 4.0;
|
||||
color = &state->quad_mesh_colors[4 * vert_index];
|
||||
/* A bit of a sneaky cast, but it seems safe to assume the ClutterColor
|
||||
* typedef is set in stone... */
|
||||
clutter_color_from_hls ((ClutterColor *)color, h * 360.0, l, s);
|
||||
|
||||
color[0] = (color[0] * color[3] + 128) / 255;
|
||||
color[1] = (color[1] * color[3] + 128) / 255;
|
||||
color[2] = (color[2] * color[3] + 128) / 255;
|
||||
}
|
||||
|
||||
cogl_vertex_buffer_add (state->buffer,
|
||||
"gl_Vertex",
|
||||
3, /* n components */
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT,
|
||||
FALSE, /* normalized */
|
||||
0, /* stride */
|
||||
state->quad_mesh_verts);
|
||||
cogl_vertex_buffer_add (state->buffer,
|
||||
"gl_Color",
|
||||
4, /* n components */
|
||||
COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE,
|
||||
FALSE, /* normalized */
|
||||
0, /* stride */
|
||||
state->quad_mesh_colors);
|
||||
|
||||
cogl_vertex_buffer_submit (state->buffer);
|
||||
|
||||
clutter_actor_set_rotation (state->dummy,
|
||||
CLUTTER_Z_AXIS,
|
||||
360 * period_progress,
|
||||
(MESH_WIDTH * QUAD_WIDTH) / 2,
|
||||
(MESH_HEIGHT * QUAD_HEIGHT) / 2,
|
||||
0);
|
||||
clutter_actor_set_rotation (state->dummy,
|
||||
CLUTTER_X_AXIS,
|
||||
360 * period_progress,
|
||||
(MESH_WIDTH * QUAD_WIDTH) / 2,
|
||||
(MESH_HEIGHT * QUAD_HEIGHT) / 2,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
on_paint (ClutterActor *actor, TestState *state)
|
||||
{
|
||||
cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
|
||||
cogl_vertex_buffer_draw_elements (state->buffer,
|
||||
COGL_VERTICES_MODE_TRIANGLE_STRIP,
|
||||
state->indices,
|
||||
0, /* min index */
|
||||
(MESH_WIDTH + 1) *
|
||||
(MESH_HEIGHT + 1) - 1, /* max index */
|
||||
0, /* indices offset */
|
||||
state->n_static_indices);
|
||||
}
|
||||
|
||||
static void
|
||||
init_static_index_arrays (TestState *state)
|
||||
{
|
||||
guint n_indices;
|
||||
int x, y;
|
||||
guint16 *i;
|
||||
guint dir;
|
||||
|
||||
/* - Each row takes (2 + 2 * MESH_WIDTH indices)
|
||||
* - Thats 2 to start the triangle strip then 2 indices to add 2 triangles
|
||||
* per mesh quad.
|
||||
* - We have MESH_HEIGHT rows
|
||||
* - It takes one extra index for linking between rows (MESH_HEIGHT - 1)
|
||||
* - A 2 x 3 mesh == 20 indices... */
|
||||
n_indices = (2 + 2 * MESH_WIDTH) * MESH_HEIGHT + (MESH_HEIGHT - 1);
|
||||
state->static_indices = g_malloc (sizeof (guint16) * n_indices);
|
||||
state->n_static_indices = n_indices;
|
||||
|
||||
#define MESH_INDEX(X, Y) (Y) * (MESH_WIDTH + 1) + (X)
|
||||
|
||||
i = state->static_indices;
|
||||
|
||||
/* NB: front facing == anti-clockwise winding */
|
||||
|
||||
i[0] = MESH_INDEX (0, 0);
|
||||
i[1] = MESH_INDEX (0, 1);
|
||||
i += 2;
|
||||
|
||||
#define LEFT 0
|
||||
#define RIGHT 1
|
||||
|
||||
dir = RIGHT;
|
||||
|
||||
for (y = 0; y < MESH_HEIGHT; y++)
|
||||
{
|
||||
for (x = 0; x < MESH_WIDTH; x++)
|
||||
{
|
||||
/* Add 2 triangles per mesh quad... */
|
||||
if (dir == RIGHT)
|
||||
{
|
||||
i[0] = MESH_INDEX (x + 1, y);
|
||||
i[1] = MESH_INDEX (x + 1, y + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
i[0] = MESH_INDEX (MESH_WIDTH - x - 1, y);
|
||||
i[1] = MESH_INDEX (MESH_WIDTH - x - 1, y + 1);
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
|
||||
/* Link rows... */
|
||||
|
||||
if (y == (MESH_HEIGHT - 1))
|
||||
break;
|
||||
|
||||
if (dir == RIGHT)
|
||||
{
|
||||
i[0] = MESH_INDEX (MESH_WIDTH, y + 1);
|
||||
i[1] = MESH_INDEX (MESH_WIDTH, y + 1);
|
||||
i[2] = MESH_INDEX (MESH_WIDTH, y + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
i[0] = MESH_INDEX (0, y + 1);
|
||||
i[1] = MESH_INDEX (0, y + 1);
|
||||
i[2] = MESH_INDEX (0, y + 2);
|
||||
}
|
||||
i += 3;
|
||||
dir = !dir;
|
||||
}
|
||||
|
||||
#undef MESH_INDEX
|
||||
|
||||
state->indices =
|
||||
cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT,
|
||||
state->static_indices,
|
||||
state->n_static_indices);
|
||||
}
|
||||
|
||||
static float
|
||||
gaussian (float x, float y)
|
||||
{
|
||||
/* Bell width */
|
||||
float c = GAUSSIAN_RADIUS;
|
||||
|
||||
/* Peak amplitude */
|
||||
float a = 1.0;
|
||||
/* float a = 1.0 / (c * sqrtf (2.0 * G_PI)); */
|
||||
|
||||
/* Center offset */
|
||||
float b = 0.0;
|
||||
|
||||
float dist;
|
||||
x = x - RIPPLE_CENTER_X;
|
||||
y = y - RIPPLE_CENTER_Y;
|
||||
dist = sqrtf (x*x + y*y);
|
||||
|
||||
return a * exp ((- ((dist - b) * (dist - b))) / (2.0 * c * c));
|
||||
}
|
||||
|
||||
static void
|
||||
init_quad_mesh (TestState *state)
|
||||
{
|
||||
int x, y;
|
||||
float *vert;
|
||||
guint8 *color;
|
||||
|
||||
/* Note: we maintain the minimum number of vertices possible. This minimizes
|
||||
* the work required when we come to morph the geometry.
|
||||
*
|
||||
* We use static indices into our mesh so that we can treat the data like a
|
||||
* single triangle list and drawing can be done in one operation (Note: We
|
||||
* are using degenerate triangles at the edges to link to the next row)
|
||||
*/
|
||||
state->quad_mesh_verts =
|
||||
g_malloc0 (sizeof (float) * 3 * (MESH_WIDTH + 1) * (MESH_HEIGHT + 1));
|
||||
|
||||
state->quad_mesh_colors =
|
||||
g_malloc0 (sizeof (guint8) * 4 * (MESH_WIDTH + 1) * (MESH_HEIGHT + 1));
|
||||
|
||||
vert = state->quad_mesh_verts;
|
||||
color = state->quad_mesh_colors;
|
||||
for (y = 0; y <= MESH_HEIGHT; y++)
|
||||
for (x = 0; x <= MESH_WIDTH; x++)
|
||||
{
|
||||
vert[0] = x * QUAD_WIDTH;
|
||||
vert[1] = y * QUAD_HEIGHT;
|
||||
vert += 3;
|
||||
|
||||
color[3] = gaussian (x * QUAD_WIDTH,
|
||||
y * QUAD_HEIGHT) * 255.0;
|
||||
color += 4;
|
||||
}
|
||||
|
||||
state->buffer = cogl_vertex_buffer_new ((MESH_WIDTH + 1)*(MESH_HEIGHT + 1));
|
||||
cogl_vertex_buffer_add (state->buffer,
|
||||
"gl_Vertex",
|
||||
3, /* n components */
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT,
|
||||
FALSE, /* normalized */
|
||||
0, /* stride */
|
||||
state->quad_mesh_verts);
|
||||
|
||||
cogl_vertex_buffer_add (state->buffer,
|
||||
"gl_Color",
|
||||
4, /* n components */
|
||||
COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE,
|
||||
FALSE, /* normalized */
|
||||
0, /* stride */
|
||||
state->quad_mesh_colors);
|
||||
|
||||
cogl_vertex_buffer_submit (state->buffer);
|
||||
|
||||
init_static_index_arrays (state);
|
||||
}
|
||||
|
||||
/* This creates an actor that has a specific size but that does not result
|
||||
* in any drawing so we can do our own drawing using Cogl... */
|
||||
static ClutterActor *
|
||||
create_dummy_actor (guint width, guint height)
|
||||
{
|
||||
ClutterActor *group, *rect;
|
||||
ClutterColor clr = { 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
group = clutter_group_new ();
|
||||
rect = clutter_rectangle_new_with_color (&clr);
|
||||
clutter_actor_set_size (rect, width, height);
|
||||
clutter_actor_hide (rect);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (group), rect);
|
||||
return group;
|
||||
}
|
||||
|
||||
static void
|
||||
stop_and_quit (ClutterActor *actor,
|
||||
TestState *state)
|
||||
{
|
||||
clutter_timeline_stop (state->timeline);
|
||||
clutter_main_quit ();
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_vertex_buffer_main (int argc, char *argv[])
|
||||
{
|
||||
TestState state;
|
||||
ClutterActor *stage;
|
||||
gfloat stage_w, stage_h;
|
||||
gint dummy_width, dummy_height;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Vertex Buffers");
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (stop_and_quit), &state);
|
||||
clutter_actor_get_size (stage, &stage_w, &stage_h);
|
||||
|
||||
dummy_width = MESH_WIDTH * QUAD_WIDTH;
|
||||
dummy_height = MESH_HEIGHT * QUAD_HEIGHT;
|
||||
state.dummy = create_dummy_actor (dummy_width, dummy_height);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), state.dummy);
|
||||
clutter_actor_set_position (state.dummy,
|
||||
(stage_w / 2.0) - (dummy_width / 2.0),
|
||||
(stage_h / 2.0) - (dummy_height / 2.0));
|
||||
|
||||
state.timeline = clutter_timeline_new (1000);
|
||||
clutter_timeline_set_loop (state.timeline, TRUE);
|
||||
|
||||
state.frame_id = g_signal_connect (state.timeline,
|
||||
"new-frame",
|
||||
G_CALLBACK (frame_cb),
|
||||
&state);
|
||||
|
||||
g_signal_connect (state.dummy, "paint", G_CALLBACK (on_paint), &state);
|
||||
|
||||
init_quad_mesh (&state);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_timeline_start (state.timeline);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
cogl_handle_unref (state.buffer);
|
||||
cogl_handle_unref (state.indices);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cogl_vertex_buffer_describe (void)
|
||||
{
|
||||
return "Vertex buffers support in Cogl.";
|
||||
}
|
240
src/tests/clutter/interactive/test-content.c
Normal file
240
src/tests/clutter/interactive/test-content.c
Normal file
@ -0,0 +1,240 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
typedef struct _ColorContent {
|
||||
GObject parent_instance;
|
||||
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
double alpha;
|
||||
|
||||
float padding;
|
||||
} ColorContent;
|
||||
|
||||
typedef struct _ColorContentClass {
|
||||
GObjectClass parent_class;
|
||||
} ColorContentClass;
|
||||
|
||||
static void clutter_content_iface_init (ClutterContentInterface *iface);
|
||||
|
||||
GType color_content_get_type (void);
|
||||
|
||||
int
|
||||
test_content_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_content_describe (void);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ColorContent, color_content, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT,
|
||||
clutter_content_iface_init))
|
||||
|
||||
static void
|
||||
color_content_paint_content (ClutterContent *content,
|
||||
ClutterActor *actor,
|
||||
ClutterPaintNode *root)
|
||||
{
|
||||
ColorContent *self = (ColorContent *) content;
|
||||
ClutterActorBox box, content_box;
|
||||
ClutterColor color;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle logical;
|
||||
ClutterPaintNode *node;
|
||||
|
||||
#if 0
|
||||
g_debug ("Painting content [%p] "
|
||||
"{ r:%.2f, g:%.2f, b:%.2f, a:%.2f } "
|
||||
"for actor [%p] (context: [%p])",
|
||||
content,
|
||||
self->red,
|
||||
self->green,
|
||||
self->blue,
|
||||
self->alpha,
|
||||
actor, context);
|
||||
#endif
|
||||
|
||||
clutter_actor_get_content_box (actor, &content_box);
|
||||
|
||||
box = content_box;
|
||||
box.x1 += self->padding;
|
||||
box.y1 += self->padding;
|
||||
box.x2 -= self->padding;
|
||||
box.y2 -= self->padding;
|
||||
|
||||
color.alpha = self->alpha * 255;
|
||||
|
||||
color.red = self->red * 255;
|
||||
color.green = self->green * 255;
|
||||
color.blue = self->blue * 255;
|
||||
|
||||
node = clutter_color_node_new (&color);
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
clutter_paint_node_add_child (root, node);
|
||||
clutter_paint_node_unref (node);
|
||||
|
||||
color.red = (1.0 - self->red) * 255;
|
||||
color.green = (1.0 - self->green) * 255;
|
||||
color.blue = (1.0 - self->blue) * 255;
|
||||
|
||||
layout = clutter_actor_create_pango_layout (actor, "A");
|
||||
pango_layout_get_pixel_extents (layout, NULL, &logical);
|
||||
|
||||
node = clutter_text_node_new (layout, &color);
|
||||
|
||||
/* top-left */
|
||||
box.x1 = clutter_actor_box_get_x (&content_box);
|
||||
box.y1 = clutter_actor_box_get_y (&content_box);
|
||||
box.x2 = box.x1 + logical.width;
|
||||
box.y2 = box.y1 + logical.height;
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
|
||||
/* top-right */
|
||||
box.x1 = clutter_actor_box_get_x (&content_box)
|
||||
+ clutter_actor_box_get_width (&content_box)
|
||||
- logical.width;
|
||||
box.y1 = clutter_actor_box_get_y (&content_box);
|
||||
box.x2 = box.x1 + logical.width;
|
||||
box.y2 = box.y1 + logical.height;
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
|
||||
/* bottom-right */
|
||||
box.x1 = clutter_actor_box_get_x (&content_box)
|
||||
+ clutter_actor_box_get_width (&content_box)
|
||||
- logical.width;
|
||||
box.y1 = clutter_actor_box_get_y (&content_box)
|
||||
+ clutter_actor_box_get_height (&content_box)
|
||||
- logical.height;
|
||||
box.x2 = box.x1 + logical.width;
|
||||
box.y2 = box.y1 + logical.height;
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
|
||||
/* bottom-left */
|
||||
box.x1 = clutter_actor_box_get_x (&content_box);
|
||||
box.y1 = clutter_actor_box_get_y (&content_box)
|
||||
+ clutter_actor_box_get_height (&content_box)
|
||||
- logical.height;
|
||||
box.x2 = box.x1 + logical.width;
|
||||
box.y2 = box.y1 + logical.height;
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
|
||||
/* center */
|
||||
box.x1 = clutter_actor_box_get_x (&content_box)
|
||||
+ (clutter_actor_box_get_width (&content_box) - logical.width) / 2.0;
|
||||
box.y1 = clutter_actor_box_get_y (&content_box)
|
||||
+ (clutter_actor_box_get_height (&content_box) - logical.height) / 2.0;
|
||||
box.x2 = box.x1 + logical.width;
|
||||
box.y2 = box.y1 + logical.height;
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
|
||||
clutter_paint_node_add_child (root, node);
|
||||
clutter_paint_node_unref (node);
|
||||
|
||||
g_object_unref (layout);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_content_iface_init (ClutterContentInterface *iface)
|
||||
{
|
||||
iface->paint_content = color_content_paint_content;
|
||||
}
|
||||
|
||||
static void
|
||||
color_content_class_init (ColorContentClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
color_content_init (ColorContent *self)
|
||||
{
|
||||
}
|
||||
|
||||
static ClutterContent *
|
||||
color_content_new (double red,
|
||||
double green,
|
||||
double blue,
|
||||
double alpha,
|
||||
float padding)
|
||||
{
|
||||
ColorContent *self = g_object_new (color_content_get_type (), NULL);
|
||||
|
||||
self->red = red;
|
||||
self->green = green;
|
||||
self->blue = blue;
|
||||
self->alpha = alpha;
|
||||
self->padding = padding;
|
||||
|
||||
return (ClutterContent *) self;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_content_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *grid;
|
||||
ClutterContent *content;
|
||||
int i, n_rects;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_name (stage, "Stage");
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Content");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
clutter_actor_show (stage);
|
||||
|
||||
grid = clutter_actor_new ();
|
||||
clutter_actor_set_name (grid, "Grid");
|
||||
clutter_actor_set_margin_top (grid, 12);
|
||||
clutter_actor_set_margin_right (grid, 12);
|
||||
clutter_actor_set_margin_bottom (grid, 12);
|
||||
clutter_actor_set_margin_left (grid, 12);
|
||||
clutter_actor_set_layout_manager (grid, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL));
|
||||
clutter_actor_add_constraint (grid, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0));
|
||||
clutter_actor_add_child (stage, grid);
|
||||
|
||||
content = color_content_new (g_random_double_range (0.0, 1.0),
|
||||
g_random_double_range (0.0, 1.0),
|
||||
g_random_double_range (0.0, 1.0),
|
||||
1.0,
|
||||
2.0);
|
||||
|
||||
n_rects = g_random_int_range (12, 24);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
ClutterActor *box = clutter_actor_new ();
|
||||
ClutterColor bg_color = {
|
||||
g_random_int_range (0, 255),
|
||||
g_random_int_range (0, 255),
|
||||
g_random_int_range (0, 255),
|
||||
255
|
||||
};
|
||||
char *name, *color;
|
||||
|
||||
color = clutter_color_to_string (&bg_color);
|
||||
name = g_strconcat ("Box <", color, ">", NULL);
|
||||
clutter_actor_set_name (box, name);
|
||||
|
||||
g_free (name);
|
||||
g_free (color);
|
||||
|
||||
clutter_actor_set_background_color (box, &bg_color);
|
||||
clutter_actor_set_content (box, content);
|
||||
clutter_actor_set_size (box, 64, 64);
|
||||
|
||||
clutter_actor_add_child (grid, box);
|
||||
}
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_object_unref (content);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_content_describe (void)
|
||||
{
|
||||
return "A simple test for ClutterContent";
|
||||
}
|
289
src/tests/clutter/interactive/test-devices.c
Normal file
289
src/tests/clutter/interactive/test-devices.c
Normal file
@ -0,0 +1,289 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#ifdef CLUTTER_WINDOWING_X11
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
ClutterActor *stage;
|
||||
|
||||
GHashTable *devices;
|
||||
} TestDevicesApp;
|
||||
|
||||
int
|
||||
test_devices_main (int argc, char **argv);
|
||||
|
||||
static const gchar *
|
||||
device_type_name (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterInputDeviceType d_type;
|
||||
|
||||
d_type = clutter_input_device_get_device_type (device);
|
||||
switch (d_type)
|
||||
{
|
||||
case CLUTTER_POINTER_DEVICE:
|
||||
return "Pointer";
|
||||
|
||||
case CLUTTER_KEYBOARD_DEVICE:
|
||||
return "Keyboard";
|
||||
|
||||
case CLUTTER_EXTENSION_DEVICE:
|
||||
return "Extension";
|
||||
|
||||
case CLUTTER_PEN_DEVICE:
|
||||
return "Pen";
|
||||
|
||||
case CLUTTER_ERASER_DEVICE:
|
||||
return "Eraser";
|
||||
|
||||
case CLUTTER_CURSOR_DEVICE:
|
||||
return "Cursor";
|
||||
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
axis_type_name (ClutterInputAxis axis)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case CLUTTER_INPUT_AXIS_X:
|
||||
return "Absolute X";
|
||||
|
||||
case CLUTTER_INPUT_AXIS_Y:
|
||||
return "Absolute Y";
|
||||
|
||||
case CLUTTER_INPUT_AXIS_PRESSURE:
|
||||
return "Pressure";
|
||||
|
||||
case CLUTTER_INPUT_AXIS_XTILT:
|
||||
return "X Tilt";
|
||||
|
||||
case CLUTTER_INPUT_AXIS_YTILT:
|
||||
return "Y Tilt";
|
||||
|
||||
case CLUTTER_INPUT_AXIS_WHEEL:
|
||||
return "Wheel";
|
||||
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
stage_button_event_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
TestDevicesApp *app)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
ClutterInputDevice *source_device;
|
||||
ClutterActor *hand = NULL;
|
||||
gdouble *axes;
|
||||
guint n_axes, i;
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
source_device = clutter_event_get_source_device (event);
|
||||
|
||||
hand = g_hash_table_lookup (app->devices, device);
|
||||
|
||||
g_print ("Device: '%s' (id:%d, type: %s, source: '%s', axes: %d)\n",
|
||||
clutter_input_device_get_device_name (device),
|
||||
clutter_input_device_get_device_id (device),
|
||||
device_type_name (device),
|
||||
source_device != device
|
||||
? clutter_input_device_get_device_name (source_device)
|
||||
: "<same>",
|
||||
clutter_input_device_get_n_axes (device));
|
||||
|
||||
if (hand != NULL)
|
||||
{
|
||||
gfloat event_x, event_y;
|
||||
|
||||
clutter_event_get_coords (event, &event_x, &event_y);
|
||||
clutter_actor_set_position (hand, event_x, event_y);
|
||||
}
|
||||
|
||||
axes = clutter_event_get_axes (event, &n_axes);
|
||||
for (i = 0; i < n_axes; i++)
|
||||
{
|
||||
ClutterInputAxis axis;
|
||||
|
||||
axis = clutter_input_device_get_axis (device, i);
|
||||
if (axis == CLUTTER_INPUT_AXIS_IGNORE)
|
||||
continue;
|
||||
|
||||
g_print ("\tAxis[%2d][%s].value: %.2f\n",
|
||||
i,
|
||||
axis_type_name (axis),
|
||||
axes[i]);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
stage_motion_event_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
TestDevicesApp *app)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
ClutterActor *hand = NULL;
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
|
||||
hand = g_hash_table_lookup (app->devices, device);
|
||||
if (hand != NULL)
|
||||
{
|
||||
gfloat event_x, event_y;
|
||||
|
||||
clutter_event_get_coords (event, &event_x, &event_y);
|
||||
clutter_actor_set_position (hand, event_x, event_y);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
manager_device_added_cb (ClutterDeviceManager *manager,
|
||||
ClutterInputDevice *device,
|
||||
TestDevicesApp *app)
|
||||
{
|
||||
ClutterInputDeviceType device_type;
|
||||
ClutterActor *hand = NULL;
|
||||
|
||||
g_print ("got a %s device '%s' with id %d\n",
|
||||
device_type_name (device),
|
||||
clutter_input_device_get_device_name (device),
|
||||
clutter_input_device_get_device_id (device));
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
if (device_type == CLUTTER_POINTER_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_POINTER_DEVICE)
|
||||
{
|
||||
g_print ("*** enabling device '%s' ***\n",
|
||||
clutter_input_device_get_device_name (device));
|
||||
|
||||
clutter_input_device_set_enabled (device, TRUE);
|
||||
|
||||
hand = clutter_texture_new_from_file (TESTS_DATADIR
|
||||
G_DIR_SEPARATOR_S
|
||||
"redhand.png",
|
||||
NULL);
|
||||
g_hash_table_insert (app->devices, device, hand);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
manager_device_removed_cb (ClutterDeviceManager *manager,
|
||||
ClutterInputDevice *device,
|
||||
TestDevicesApp *app)
|
||||
{
|
||||
ClutterInputDeviceType device_type;
|
||||
ClutterActor *hand = NULL;
|
||||
|
||||
g_print ("removed a %s device '%s' with id %d\n",
|
||||
device_type_name (device),
|
||||
clutter_input_device_get_device_name (device),
|
||||
clutter_input_device_get_device_id (device));
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
if (device_type == CLUTTER_POINTER_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_POINTER_DEVICE)
|
||||
{
|
||||
hand = g_hash_table_lookup (app->devices, device);
|
||||
if (hand != NULL)
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand);
|
||||
|
||||
g_hash_table_remove (app->devices, device);
|
||||
}
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_devices_main (int argc, char **argv)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
TestDevicesApp *app;
|
||||
ClutterDeviceManager *manager;
|
||||
const GSList *stage_devices, *l;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
app = g_new0 (TestDevicesApp, 1);
|
||||
app->devices = g_hash_table_new (g_direct_hash, g_direct_equal) ;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Devices");
|
||||
clutter_stage_hide_cursor (CLUTTER_STAGE (stage));
|
||||
g_signal_connect (stage,
|
||||
"destroy", G_CALLBACK (clutter_main_quit),
|
||||
NULL);
|
||||
g_signal_connect (stage,
|
||||
"motion-event", G_CALLBACK (stage_motion_event_cb),
|
||||
app);
|
||||
g_signal_connect (stage,
|
||||
"button-press-event", G_CALLBACK (stage_button_event_cb),
|
||||
app);
|
||||
app->stage = stage;
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
manager = clutter_device_manager_get_default ();
|
||||
g_signal_connect (manager,
|
||||
"device-added", G_CALLBACK (manager_device_added_cb),
|
||||
app);
|
||||
g_signal_connect (manager,
|
||||
"device-removed", G_CALLBACK (manager_device_removed_cb),
|
||||
app);
|
||||
|
||||
stage_devices = clutter_device_manager_peek_devices (manager);
|
||||
|
||||
if (stage_devices == NULL)
|
||||
g_error ("No input devices found.");
|
||||
|
||||
for (l = stage_devices; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterInputDevice *device = l->data;
|
||||
ClutterInputDeviceType device_type;
|
||||
ClutterActor *hand = NULL;
|
||||
|
||||
g_print ("got a %s device '%s' with id %d\n",
|
||||
device_type_name (device),
|
||||
clutter_input_device_get_device_name (device),
|
||||
clutter_input_device_get_device_id (device));
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
if (device_type == CLUTTER_POINTER_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_POINTER_DEVICE)
|
||||
{
|
||||
g_print ("*** enabling device '%s' ***\n",
|
||||
clutter_input_device_get_device_name (device));
|
||||
|
||||
clutter_input_device_set_enabled (device, TRUE);
|
||||
|
||||
hand = clutter_texture_new_from_file (TESTS_DATADIR
|
||||
G_DIR_SEPARATOR_S
|
||||
"redhand.png",
|
||||
NULL);
|
||||
g_hash_table_insert (app->devices, device, hand);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), hand);
|
||||
}
|
||||
}
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
276
src/tests/clutter/interactive/test-easing.c
Normal file
276
src/tests/clutter/interactive/test-easing.c
Normal file
@ -0,0 +1,276 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
/* all the easing modes provided by Clutter */
|
||||
static const struct {
|
||||
const gchar *name;
|
||||
ClutterAnimationMode mode;
|
||||
} easing_modes[] = {
|
||||
{ "linear", CLUTTER_LINEAR },
|
||||
{ "easeInQuad", CLUTTER_EASE_IN_QUAD },
|
||||
{ "easeOutQuad", CLUTTER_EASE_OUT_QUAD },
|
||||
{ "easeInOutQuad", CLUTTER_EASE_IN_OUT_QUAD },
|
||||
{ "easeInCubic", CLUTTER_EASE_IN_CUBIC },
|
||||
{ "easeOutCubic", CLUTTER_EASE_OUT_CUBIC },
|
||||
{ "easeInOutCubic", CLUTTER_EASE_IN_OUT_CUBIC },
|
||||
{ "easeInQuart", CLUTTER_EASE_IN_QUART },
|
||||
{ "easeOutQuart", CLUTTER_EASE_OUT_QUART },
|
||||
{ "easeInOutQuart", CLUTTER_EASE_IN_OUT_QUART },
|
||||
{ "easeInQuint", CLUTTER_EASE_IN_QUINT },
|
||||
{ "easeOutQuint", CLUTTER_EASE_OUT_QUINT },
|
||||
{ "easeInOutQuint", CLUTTER_EASE_IN_OUT_QUINT },
|
||||
{ "easeInSine", CLUTTER_EASE_IN_SINE },
|
||||
{ "easeOutSine", CLUTTER_EASE_OUT_SINE },
|
||||
{ "easeInOutSine", CLUTTER_EASE_IN_OUT_SINE },
|
||||
{ "easeInExpo", CLUTTER_EASE_IN_EXPO },
|
||||
{ "easeOutExpo", CLUTTER_EASE_OUT_EXPO },
|
||||
{ "easeInOutExpo", CLUTTER_EASE_IN_OUT_EXPO },
|
||||
{ "easeInCirc", CLUTTER_EASE_IN_CIRC },
|
||||
{ "easeOutCirc", CLUTTER_EASE_OUT_CIRC },
|
||||
{ "easeInOutCirc", CLUTTER_EASE_IN_OUT_CIRC },
|
||||
{ "easeInElastic", CLUTTER_EASE_IN_ELASTIC },
|
||||
{ "easeOutElastic", CLUTTER_EASE_OUT_ELASTIC },
|
||||
{ "easeInOutElastic", CLUTTER_EASE_IN_OUT_ELASTIC },
|
||||
{ "easeInBack", CLUTTER_EASE_IN_BACK },
|
||||
{ "easeOutBack", CLUTTER_EASE_OUT_BACK },
|
||||
{ "easeInOutBack", CLUTTER_EASE_IN_OUT_BACK },
|
||||
{ "easeInBounce", CLUTTER_EASE_IN_BOUNCE },
|
||||
{ "easeOutBounce", CLUTTER_EASE_OUT_BOUNCE },
|
||||
{ "easeInOutBounce", CLUTTER_EASE_IN_OUT_BOUNCE },
|
||||
};
|
||||
|
||||
#define HELP_TEXT "Easing mode: %s (%d of %d)\n" \
|
||||
"Left click to tween\n" \
|
||||
"Right click to change the easing mode"
|
||||
|
||||
static const gint n_easing_modes = G_N_ELEMENTS (easing_modes);
|
||||
static gint current_mode = 0;
|
||||
|
||||
static gint duration = 1;
|
||||
static gboolean recenter = FALSE;
|
||||
|
||||
static ClutterActor *main_stage = NULL;
|
||||
static ClutterActor *easing_mode_label = NULL;
|
||||
|
||||
static ClutterAnimation *last_animation = NULL;
|
||||
|
||||
int
|
||||
test_easing_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_easing_describe (void);
|
||||
|
||||
/* recenter_bouncer:
|
||||
*
|
||||
* repositions (through an animation) the bouncer at the center of the stage
|
||||
*/
|
||||
static void
|
||||
recenter_bouncer (ClutterAnimation *animation,
|
||||
ClutterActor *rectangle)
|
||||
{
|
||||
gfloat base_x, base_y;
|
||||
gint cur_mode;
|
||||
|
||||
base_x = clutter_actor_get_width (main_stage) / 2;
|
||||
base_y = clutter_actor_get_height (main_stage) / 2;
|
||||
|
||||
cur_mode = easing_modes[current_mode].mode;
|
||||
|
||||
clutter_actor_animate (rectangle, cur_mode, 250,
|
||||
"x", base_x,
|
||||
"y", base_y,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_button_press (ClutterActor *actor,
|
||||
ClutterButtonEvent *event,
|
||||
ClutterActor *rectangle)
|
||||
{
|
||||
if (event->button == CLUTTER_BUTTON_SECONDARY)
|
||||
{
|
||||
gchar *text;
|
||||
|
||||
/* cycle through the various easing modes */
|
||||
current_mode = (current_mode + 1 < n_easing_modes)
|
||||
? current_mode + 1
|
||||
: 0;
|
||||
|
||||
/* update the text of the label */
|
||||
text = g_strdup_printf (HELP_TEXT,
|
||||
easing_modes[current_mode].name,
|
||||
current_mode + 1,
|
||||
n_easing_modes);
|
||||
|
||||
clutter_text_set_text (CLUTTER_TEXT (easing_mode_label), text);
|
||||
g_free (text);
|
||||
}
|
||||
else if (event->button == CLUTTER_BUTTON_PRIMARY)
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
ClutterAnimationMode cur_mode;
|
||||
|
||||
cur_mode = easing_modes[current_mode].mode;
|
||||
|
||||
/* tween the actor using the current easing mode */
|
||||
animation =
|
||||
clutter_actor_animate (rectangle, cur_mode, duration * 1000,
|
||||
"x", event->x,
|
||||
"y", event->y,
|
||||
NULL);
|
||||
|
||||
/* if we were asked to, recenter the bouncer at the end of the
|
||||
* animation. we keep track of the animation to avoid connecting
|
||||
* the signal handler to the same Animation twice.
|
||||
*/
|
||||
if (recenter && last_animation != animation)
|
||||
g_signal_connect_after (animation, "completed",
|
||||
G_CALLBACK (recenter_bouncer),
|
||||
rectangle);
|
||||
|
||||
last_animation = animation;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
draw_bouncer (ClutterCairoTexture *texture,
|
||||
cairo_t *cr)
|
||||
{
|
||||
const ClutterColor *bouncer_color;
|
||||
cairo_pattern_t *pattern;
|
||||
guint width, height;
|
||||
float radius;
|
||||
|
||||
clutter_cairo_texture_get_surface_size (texture, &width, &height);
|
||||
|
||||
radius = MAX (width, height);
|
||||
|
||||
clutter_cairo_texture_clear (texture);
|
||||
|
||||
cairo_arc (cr, radius / 2, radius / 2, radius / 2, 0.0, 2.0 * G_PI);
|
||||
|
||||
bouncer_color = CLUTTER_COLOR_DarkScarletRed;
|
||||
|
||||
pattern = cairo_pattern_create_radial (radius / 2, radius / 2, 0,
|
||||
radius, radius, radius);
|
||||
cairo_pattern_add_color_stop_rgba (pattern,
|
||||
0,
|
||||
bouncer_color->red / 255.0,
|
||||
bouncer_color->green / 255.0,
|
||||
bouncer_color->blue / 255.0,
|
||||
bouncer_color->alpha / 255.0);
|
||||
cairo_pattern_add_color_stop_rgba (pattern,
|
||||
0.85,
|
||||
bouncer_color->red / 255.0,
|
||||
bouncer_color->green / 255.0,
|
||||
bouncer_color->blue / 255.0,
|
||||
0.25);
|
||||
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_fill_preserve (cr);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
make_bouncer (gfloat width,
|
||||
gfloat height)
|
||||
{
|
||||
ClutterActor *retval;
|
||||
|
||||
retval = clutter_cairo_texture_new (width, height);
|
||||
g_signal_connect (retval, "draw", G_CALLBACK (draw_bouncer), NULL);
|
||||
|
||||
clutter_actor_set_name (retval, "bouncer");
|
||||
clutter_actor_set_size (retval, width, height);
|
||||
clutter_actor_set_anchor_point (retval, width / 2, height / 2);
|
||||
clutter_actor_set_reactive (retval, TRUE);
|
||||
|
||||
/* make sure we draw the bouncer immediately */
|
||||
clutter_cairo_texture_invalidate (CLUTTER_CAIRO_TEXTURE (retval));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static GOptionEntry test_easing_entries[] = {
|
||||
{
|
||||
"re-center", 'r',
|
||||
0,
|
||||
G_OPTION_ARG_NONE, &recenter,
|
||||
"Re-center the actor when the animation ends",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"duration", 'd',
|
||||
0,
|
||||
G_OPTION_ARG_INT, &duration,
|
||||
"Duration of the animation",
|
||||
"SECONDS"
|
||||
},
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_easing_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *rect, *label;
|
||||
gchar *text;
|
||||
gfloat stage_width, stage_height;
|
||||
GError *error = NULL;
|
||||
|
||||
if (clutter_init_with_args (&argc, &argv,
|
||||
NULL,
|
||||
test_easing_entries,
|
||||
NULL,
|
||||
&error) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Easing Modes");
|
||||
clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
main_stage = stage;
|
||||
|
||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||
|
||||
/* create the actor that we want to tween */
|
||||
rect = make_bouncer (50, 50);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
|
||||
clutter_actor_set_position (rect, stage_width / 2, stage_height / 2);
|
||||
|
||||
text = g_strdup_printf (HELP_TEXT,
|
||||
easing_modes[current_mode].name,
|
||||
current_mode + 1,
|
||||
n_easing_modes);
|
||||
|
||||
label = clutter_text_new ();
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), label);
|
||||
clutter_text_set_text (CLUTTER_TEXT (label), text);
|
||||
clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.95));
|
||||
clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.95));
|
||||
easing_mode_label = label;
|
||||
|
||||
g_free (text);
|
||||
|
||||
g_signal_connect (stage,
|
||||
"button-press-event", G_CALLBACK (on_button_press),
|
||||
rect);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_easing_describe (void)
|
||||
{
|
||||
return "Visualize all easing modes provided by Clutter";
|
||||
}
|
494
src/tests/clutter/interactive/test-events.c
Normal file
494
src/tests/clutter/interactive/test-events.c
Normal file
@ -0,0 +1,494 @@
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <string.h>
|
||||
|
||||
gboolean IsMotion = TRUE;
|
||||
|
||||
int
|
||||
test_events_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_events_describe (void);
|
||||
|
||||
static const gchar *
|
||||
get_event_type_name (const ClutterEvent *event)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
return "BUTTON PRESS";
|
||||
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
return "BUTTON_RELEASE";
|
||||
|
||||
case CLUTTER_KEY_PRESS:
|
||||
return "KEY PRESS";
|
||||
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
return "KEY RELEASE";
|
||||
|
||||
case CLUTTER_ENTER:
|
||||
return "ENTER";
|
||||
|
||||
case CLUTTER_LEAVE:
|
||||
return "LEAVE";
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
return "MOTION";
|
||||
|
||||
case CLUTTER_DELETE:
|
||||
return "DELETE";
|
||||
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
return "TOUCH BEGIN";
|
||||
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
return "TOUCH UPDATE";
|
||||
|
||||
case CLUTTER_TOUCH_END:
|
||||
return "TOUCH END";
|
||||
|
||||
case CLUTTER_TOUCH_CANCEL:
|
||||
return "TOUCH CANCEL";
|
||||
|
||||
default:
|
||||
return "EVENT";
|
||||
}
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_event_state_string (const ClutterEvent *event)
|
||||
{
|
||||
const char *mods[18];
|
||||
int i = 0;
|
||||
ClutterModifierType state = clutter_event_get_state (event);
|
||||
|
||||
if (state & CLUTTER_SHIFT_MASK)
|
||||
mods[i++] = "shift";
|
||||
if (state & CLUTTER_LOCK_MASK)
|
||||
mods[i++] = "lock";
|
||||
if (state & CLUTTER_CONTROL_MASK)
|
||||
mods[i++] = "ctrl";
|
||||
if (state & CLUTTER_MOD1_MASK)
|
||||
mods[i++] = "mod1";
|
||||
if (state & CLUTTER_MOD2_MASK)
|
||||
mods[i++] = "mod2";
|
||||
if (state & CLUTTER_MOD3_MASK)
|
||||
mods[i++] = "mod3";
|
||||
if (state & CLUTTER_MOD4_MASK)
|
||||
mods[i++] = "mod4";
|
||||
if (state & CLUTTER_MOD5_MASK)
|
||||
mods[i++] = "mod5";
|
||||
if (state & CLUTTER_BUTTON1_MASK)
|
||||
mods[i++] = "btn1";
|
||||
if (state & CLUTTER_BUTTON2_MASK)
|
||||
mods[i++] = "btn2";
|
||||
if (state & CLUTTER_BUTTON3_MASK)
|
||||
mods[i++] = "btn3";
|
||||
if (state & CLUTTER_BUTTON4_MASK)
|
||||
mods[i++] = "btn4";
|
||||
if (state & CLUTTER_BUTTON5_MASK)
|
||||
mods[i++] = "btn5";
|
||||
if (state & CLUTTER_SUPER_MASK)
|
||||
mods[i++] = "super";
|
||||
if (state & CLUTTER_HYPER_MASK)
|
||||
mods[i++] = "hyper";
|
||||
if (state & CLUTTER_META_MASK)
|
||||
mods[i++] = "meta";
|
||||
if (state & CLUTTER_RELEASE_MASK)
|
||||
mods[i++] = "release";
|
||||
|
||||
if (i == 0)
|
||||
mods[i++] = "-";
|
||||
|
||||
mods[i] = NULL;
|
||||
return g_strjoinv (",", (char **) mods);
|
||||
}
|
||||
|
||||
static void
|
||||
stage_state_cb (ClutterStage *stage,
|
||||
gpointer data)
|
||||
{
|
||||
gchar *detail = (gchar*)data;
|
||||
|
||||
printf("[stage signal] %s\n", detail);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
red_button_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
|
||||
if (IsMotion)
|
||||
IsMotion = FALSE;
|
||||
else
|
||||
IsMotion = TRUE;
|
||||
|
||||
stage = clutter_actor_get_stage (actor);
|
||||
clutter_stage_set_motion_events_enabled (CLUTTER_STAGE (stage),
|
||||
IsMotion);
|
||||
|
||||
g_print ("*** Per actor motion events %s ***\n",
|
||||
IsMotion ? "enabled" : "disabled");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
capture_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
g_print ("* captured event '%s' for type '%s' *\n",
|
||||
get_event_type_name (event),
|
||||
G_OBJECT_TYPE_NAME (actor));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
key_focus_in_cb (ClutterActor *actor,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterActor *focus_box = CLUTTER_ACTOR (data);
|
||||
|
||||
if (CLUTTER_IS_STAGE (actor))
|
||||
clutter_actor_hide (focus_box);
|
||||
else
|
||||
{
|
||||
clutter_actor_set_position (focus_box,
|
||||
clutter_actor_get_x (actor) - 5,
|
||||
clutter_actor_get_y (actor) - 5);
|
||||
|
||||
clutter_actor_set_size (focus_box,
|
||||
clutter_actor_get_width (actor) + 10,
|
||||
clutter_actor_get_height (actor) + 10);
|
||||
clutter_actor_show (focus_box);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fill_keybuf (char *keybuf, ClutterKeyEvent *event)
|
||||
{
|
||||
char utf8[6];
|
||||
int len;
|
||||
|
||||
/* printable character, if any (ß, ∑) */
|
||||
len = g_unichar_to_utf8 (event->unicode_value, utf8);
|
||||
utf8[len] = '\0';
|
||||
sprintf (keybuf, "'%s' ", utf8);
|
||||
|
||||
/* key combination (<Mod1>s, <Shift><Mod1>S, <Ctrl><Mod1>Delete) */
|
||||
len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->keyval), utf8);
|
||||
utf8[len] = '\0';
|
||||
|
||||
if (event->modifier_state & CLUTTER_SHIFT_MASK)
|
||||
strcat (keybuf, "<Shift>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_LOCK_MASK)
|
||||
strcat (keybuf, "<Lock>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_CONTROL_MASK)
|
||||
strcat (keybuf, "<Control>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_MOD1_MASK)
|
||||
strcat (keybuf, "<Mod1>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_MOD2_MASK)
|
||||
strcat (keybuf, "<Mod2>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_MOD3_MASK)
|
||||
strcat (keybuf, "<Mod3>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_MOD4_MASK)
|
||||
strcat (keybuf, "<Mod4>");
|
||||
|
||||
if (event->modifier_state & CLUTTER_MOD5_MASK)
|
||||
strcat (keybuf, "<Mod5>");
|
||||
|
||||
strcat (keybuf, utf8);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
input_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterActor *stage = clutter_actor_get_stage (actor);
|
||||
ClutterActor *source_actor = clutter_event_get_source (event);
|
||||
ClutterPoint position;
|
||||
gchar *state;
|
||||
gchar keybuf[128];
|
||||
gint device_id;
|
||||
gint source_device_id = 0;
|
||||
|
||||
device_id = clutter_event_get_device_id (event);
|
||||
if (clutter_event_get_source_device (event) != NULL)
|
||||
source_device_id = clutter_input_device_get_device_id (clutter_event_get_source_device (event));
|
||||
|
||||
state = get_event_state_string (event);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_KEY_PRESS:
|
||||
fill_keybuf (keybuf, &event->key);
|
||||
printf ("[%s] KEY PRESS %s",
|
||||
clutter_actor_get_name (source_actor),
|
||||
keybuf);
|
||||
break;
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
fill_keybuf (keybuf, &event->key);
|
||||
printf ("[%s] KEY RELEASE %s",
|
||||
clutter_actor_get_name (source_actor),
|
||||
keybuf);
|
||||
break;
|
||||
case CLUTTER_MOTION:
|
||||
clutter_event_get_position (event, &position);
|
||||
g_print ("[%s] MOTION (coords:%.02f,%.02f device:%d/%d state:%s)",
|
||||
clutter_actor_get_name (source_actor), position.x, position.y,
|
||||
device_id, source_device_id, state);
|
||||
break;
|
||||
case CLUTTER_ENTER:
|
||||
g_print ("[%s] ENTER (from:%s device:%d/%d state:%s)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
clutter_event_get_related (event) != NULL
|
||||
? clutter_actor_get_name (clutter_event_get_related (event))
|
||||
: "<out of stage>",
|
||||
device_id, source_device_id, state);
|
||||
break;
|
||||
case CLUTTER_LEAVE:
|
||||
g_print ("[%s] LEAVE (to:%s device:%d/%d state:%s)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
clutter_event_get_related (event) != NULL
|
||||
? clutter_actor_get_name (clutter_event_get_related (event))
|
||||
: "<out of stage>",
|
||||
device_id, source_device_id, state);
|
||||
break;
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
clutter_event_get_position (event, &position);
|
||||
g_print ("[%s] BUTTON PRESS (button:%i, click count:%i coords:%.02f,%.02f device:%d/%d, state:%s)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
clutter_event_get_button (event),
|
||||
clutter_event_get_click_count (event),
|
||||
position.x, position.y,
|
||||
device_id, source_device_id, state);
|
||||
break;
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
clutter_event_get_position (event, &position);
|
||||
g_print ("[%s] BUTTON RELEASE (button:%i, click count:%i coords:%.02f,%.02f device:%d/%d state:%s)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
clutter_event_get_button (event),
|
||||
clutter_event_get_click_count (event),
|
||||
position.x, position.y,
|
||||
device_id, source_device_id, state);
|
||||
|
||||
if (source_actor == stage)
|
||||
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), NULL);
|
||||
else if (source_actor == actor &&
|
||||
clutter_actor_get_parent (actor) == stage)
|
||||
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor);
|
||||
break;
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
clutter_event_get_position (event, &position);
|
||||
g_print ("[%s] TOUCH BEGIN (seq:%p coords:%.02f,%.02f device:%d/%d state:%s)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
clutter_event_get_event_sequence (event),
|
||||
position.x, position.y,
|
||||
device_id, source_device_id, state);
|
||||
break;
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
clutter_event_get_position (event, &position);
|
||||
g_print ("[%s] TOUCH UPDATE (seq:%p coords:%.02f,%.02f device:%d/%d state:%s)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
clutter_event_get_event_sequence (event),
|
||||
position.x, position.y,
|
||||
device_id, source_device_id, state);
|
||||
break;
|
||||
case CLUTTER_TOUCH_END:
|
||||
clutter_event_get_position (event, &position);
|
||||
g_print ("[%s] TOUCH END (seq:%p coords:%.02f,%.02f device:%d/%d state:%s)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
clutter_event_get_event_sequence (event),
|
||||
position.x, position.y,
|
||||
device_id, source_device_id, state);
|
||||
break;
|
||||
case CLUTTER_TOUCH_CANCEL:
|
||||
clutter_event_get_position (event, &position);
|
||||
g_print ("[%s] TOUCH CANCEL (seq:%p coords:%.02f,%.02f device:%d/%d state:%s)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
clutter_event_get_event_sequence (event),
|
||||
position.x, position.y,
|
||||
device_id, source_device_id, state);
|
||||
break;
|
||||
case CLUTTER_SCROLL:
|
||||
{
|
||||
ClutterScrollDirection dir = clutter_event_get_scroll_direction (event);
|
||||
|
||||
if (dir == CLUTTER_SCROLL_SMOOTH)
|
||||
{
|
||||
gdouble dx, dy;
|
||||
clutter_event_get_scroll_delta (event, &dx, &dy);
|
||||
g_print ("[%s] BUTTON SCROLL (direction:smooth %.02f,%.02f state:%s)",
|
||||
clutter_actor_get_name (source_actor), dx, dy, state);
|
||||
}
|
||||
else
|
||||
g_print ("[%s] BUTTON SCROLL (direction:%s state:%s)",
|
||||
clutter_actor_get_name (source_actor),
|
||||
dir == CLUTTER_SCROLL_UP ? "up" :
|
||||
dir == CLUTTER_SCROLL_DOWN ? "down" :
|
||||
dir == CLUTTER_SCROLL_LEFT ? "left" :
|
||||
dir == CLUTTER_SCROLL_RIGHT ? "right" : "?",
|
||||
state);
|
||||
}
|
||||
break;
|
||||
case CLUTTER_STAGE_STATE:
|
||||
g_print ("[%s] STAGE STATE", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
g_print ("[%s] DESTROY NOTIFY", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
g_print ("[%s] CLIENT MESSAGE", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_DELETE:
|
||||
g_print ("[%s] DELETE", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_TOUCHPAD_PINCH:
|
||||
g_print ("[%s] TOUCHPAD PINCH", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_TOUCHPAD_SWIPE:
|
||||
g_print ("[%s] TOUCHPAD SWIPE", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
g_print ("[%s] PROXIMITY IN", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
g_print ("[%s] PROXIMITY OUT", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
g_print ("[%s] PAD BUTTON PRESS", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
g_print ("[%s] PAD BUTTON RELEASE", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_PAD_STRIP:
|
||||
g_print ("[%s] PAD STRIP", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_PAD_RING:
|
||||
g_print ("[%s] PAD RING", clutter_actor_get_name (source_actor));
|
||||
break;
|
||||
case CLUTTER_NOTHING:
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_free (state);
|
||||
|
||||
if (source_actor == actor)
|
||||
g_print (" *source*");
|
||||
|
||||
g_print ("\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_events_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *actor, *focus_box, *group;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Events");
|
||||
clutter_actor_set_name (stage, "Stage");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
g_signal_connect (stage, "event", G_CALLBACK (input_cb), (char *) "stage");
|
||||
g_signal_connect (stage, "activate",
|
||||
G_CALLBACK (stage_state_cb), (char *) "activate");
|
||||
g_signal_connect (stage, "deactivate",
|
||||
G_CALLBACK (stage_state_cb), (char *) "deactivate");
|
||||
|
||||
focus_box = clutter_rectangle_new_with_color (CLUTTER_COLOR_Black);
|
||||
clutter_actor_set_name (focus_box, "Focus Box");
|
||||
clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL);
|
||||
|
||||
actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Red);
|
||||
clutter_actor_set_name (actor, "Red Box");
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 100, 100);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), (char *) "red box");
|
||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
/* Toggle motion - enter/leave capture */
|
||||
g_signal_connect (actor, "button-press-event",
|
||||
G_CALLBACK (red_button_cb), NULL);
|
||||
|
||||
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor);
|
||||
|
||||
actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Green);
|
||||
clutter_actor_set_name (actor, "Green Box");
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 250, 100);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), (char *) "green box");
|
||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL);
|
||||
|
||||
/* non reactive */
|
||||
actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Black);
|
||||
clutter_actor_set_name (actor, "Black Box");
|
||||
clutter_actor_set_size (actor, 400, 50);
|
||||
clutter_actor_set_position (actor, 100, 250);
|
||||
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), (char *) "blue box");
|
||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
g_signal_connect (stage, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
|
||||
/* non reactive group, with reactive child */
|
||||
actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Yellow);
|
||||
clutter_actor_set_name (actor, "Yellow Box");
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
|
||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), (char *) "yellow box");
|
||||
|
||||
/* note group not reactive */
|
||||
group = clutter_group_new ();
|
||||
clutter_container_add (CLUTTER_CONTAINER (group), actor, NULL);
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), group, NULL);
|
||||
clutter_actor_set_position (group, 100, 350);
|
||||
clutter_actor_show_all (group);
|
||||
|
||||
/* border actor */
|
||||
actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Magenta);
|
||||
clutter_actor_set_name (actor, "Border Box");
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor,
|
||||
(clutter_actor_get_width (stage) - 100) / 2,
|
||||
clutter_actor_get_height (stage) - 100);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
|
||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), NULL);
|
||||
|
||||
clutter_actor_show_all (CLUTTER_ACTOR (stage));
|
||||
|
||||
clutter_main();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_events_describe (void)
|
||||
{
|
||||
return "Event handling and propagation.";
|
||||
}
|
111
src/tests/clutter/interactive/test-fbo.c
Normal file
111
src/tests/clutter/interactive/test-fbo.c
Normal file
@ -0,0 +1,111 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#define STAGE_WIDTH 800
|
||||
#define STAGE_HEIGHT 600
|
||||
|
||||
int
|
||||
test_fbo_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_fbo_describe (void);
|
||||
|
||||
static ClutterActor *
|
||||
make_source (void)
|
||||
{
|
||||
ClutterActor *source, *actor;
|
||||
GError *error = NULL;
|
||||
gchar *file;
|
||||
|
||||
ClutterColor yellow = {0xff, 0xff, 0x00, 0xff};
|
||||
|
||||
source = clutter_group_new ();
|
||||
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
actor = clutter_texture_new_from_file (file, &error);
|
||||
if (!actor)
|
||||
g_error("pixbuf load failed: %s", error ? error->message : "Unknown");
|
||||
|
||||
g_free (file);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (source), actor);
|
||||
|
||||
actor = clutter_text_new_with_text ("Sans Bold 50px", "Clutter");
|
||||
|
||||
clutter_text_set_color (CLUTTER_TEXT (actor), &yellow);
|
||||
clutter_actor_set_y (actor, clutter_actor_get_height(source) + 5);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (source), actor);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_fbo_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *fbo;
|
||||
ClutterActor *onscreen_source;
|
||||
ClutterActor *stage;
|
||||
ClutterAnimation *animation;
|
||||
int x_pos = 200;
|
||||
int y_pos = 100;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
if (clutter_feature_available (CLUTTER_FEATURE_OFFSCREEN) == FALSE)
|
||||
g_error("This test requires CLUTTER_FEATURE_OFFSCREEN");
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT);
|
||||
clutter_actor_set_background_color (stage, CLUTTER_COLOR_SkyBlue);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Texture from Actor");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* Create the first source */
|
||||
onscreen_source = make_source();
|
||||
clutter_actor_show_all (onscreen_source);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), onscreen_source);
|
||||
|
||||
y_pos = (STAGE_HEIGHT/2.0) -
|
||||
(clutter_actor_get_height (onscreen_source)/2.0);
|
||||
clutter_actor_set_position (onscreen_source, x_pos, y_pos);
|
||||
x_pos += clutter_actor_get_width (onscreen_source);
|
||||
|
||||
animation = clutter_actor_animate (onscreen_source,
|
||||
CLUTTER_LINEAR,
|
||||
5000, /* 1 second duration */
|
||||
"rotation-angle-y", 360.0f,
|
||||
NULL);
|
||||
clutter_animation_set_loop (animation, TRUE);
|
||||
|
||||
/* Second hand = actor from onscreen_source */
|
||||
if ((fbo = clutter_texture_new_from_actor (onscreen_source)) == NULL)
|
||||
g_error("onscreen fbo creation failed");
|
||||
|
||||
clutter_actor_set_position (fbo, x_pos, y_pos);
|
||||
x_pos += clutter_actor_get_width (fbo);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), fbo);
|
||||
|
||||
/* Third hand = actor from Second hand */
|
||||
if ((fbo = clutter_texture_new_from_actor (fbo)) == NULL)
|
||||
g_error("fbo from fbo creation failed");
|
||||
|
||||
clutter_actor_set_position (fbo, x_pos, y_pos);
|
||||
x_pos += clutter_actor_get_width (fbo);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), fbo);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_fbo_describe (void)
|
||||
{
|
||||
return "Create a texture from an actor.";
|
||||
}
|
302
src/tests/clutter/interactive/test-grab.c
Normal file
302
src/tests/clutter/interactive/test-grab.c
Normal file
@ -0,0 +1,302 @@
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
int
|
||||
test_grab_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_grab_describe (void);
|
||||
|
||||
static void
|
||||
stage_state_cb (ClutterStage *stage,
|
||||
gpointer data)
|
||||
{
|
||||
gchar *detail = (gchar*)data;
|
||||
|
||||
printf("[stage signal] %s\n", detail);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
debug_event_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
gchar keybuf[9], *source = (gchar*)data;
|
||||
int len = 0;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_KEY_PRESS:
|
||||
len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->key.keyval),
|
||||
keybuf);
|
||||
keybuf[len] = '\0';
|
||||
printf ("[%s] KEY PRESS '%s'", source, keybuf);
|
||||
break;
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->key.keyval),
|
||||
keybuf);
|
||||
keybuf[len] = '\0';
|
||||
printf ("[%s] KEY RELEASE '%s'", source, keybuf);
|
||||
break;
|
||||
case CLUTTER_MOTION:
|
||||
printf("[%s] MOTION", source);
|
||||
break;
|
||||
case CLUTTER_ENTER:
|
||||
printf("[%s] ENTER", source);
|
||||
break;
|
||||
case CLUTTER_LEAVE:
|
||||
printf("[%s] LEAVE", source);
|
||||
break;
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
printf("[%s] BUTTON PRESS (click count:%i)",
|
||||
source, event->button.click_count);
|
||||
break;
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
printf("[%s] BUTTON RELEASE", source);
|
||||
break;
|
||||
case CLUTTER_SCROLL:
|
||||
printf("[%s] BUTTON SCROLL", source);
|
||||
break;
|
||||
case CLUTTER_STAGE_STATE:
|
||||
printf("[%s] STAGE STATE", source);
|
||||
break;
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
printf("[%s] DESTROY NOTIFY", source);
|
||||
break;
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
printf("[%s] CLIENT MESSAGE\n", source);
|
||||
break;
|
||||
case CLUTTER_DELETE:
|
||||
printf("[%s] DELETE", source);
|
||||
break;
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
g_print ("[%s] TOUCH BEGIN", source);
|
||||
break;
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
g_print ("[%s] TOUCH UPDATE", source);
|
||||
break;
|
||||
case CLUTTER_TOUCH_END:
|
||||
g_print ("[%s] TOUCH END", source);
|
||||
break;
|
||||
case CLUTTER_TOUCH_CANCEL:
|
||||
g_print ("[%s] TOUCH CANCEL", source);
|
||||
break;
|
||||
case CLUTTER_TOUCHPAD_PINCH:
|
||||
g_print ("[%s] TOUCHPAD PINCH", source);
|
||||
break;
|
||||
case CLUTTER_TOUCHPAD_SWIPE:
|
||||
g_print ("[%s] TOUCHPAD SWIPE", source);
|
||||
break;
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
g_print ("[%s] PROXIMITY IN", source);
|
||||
break;
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
g_print ("[%s] PROXIMITY OUT", source);
|
||||
break;
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
g_print ("[%s] PAD BUTTON PRESS", source);
|
||||
break;
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
g_print ("[%s] PAD BUTTON RELEASE", source);
|
||||
break;
|
||||
case CLUTTER_PAD_STRIP:
|
||||
g_print ("[%s] PAD STRIP", source);
|
||||
break;
|
||||
case CLUTTER_PAD_RING:
|
||||
g_print ("[%s] PAD RING", source);
|
||||
break;
|
||||
case CLUTTER_NOTHING:
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (clutter_event_get_source (event) == actor)
|
||||
printf(" *source*");
|
||||
|
||||
printf("\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
grab_pointer_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterInputDevice *device = clutter_event_get_device (event);
|
||||
|
||||
clutter_input_device_grab (device, actor);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
red_release_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterInputDevice *device = clutter_event_get_device (event);
|
||||
|
||||
clutter_input_device_ungrab (device);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
blue_release_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
clutter_actor_destroy (actor);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
green_press_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
gboolean enabled;
|
||||
|
||||
stage = clutter_actor_get_stage (actor);
|
||||
enabled = !clutter_stage_get_motion_events_enabled (CLUTTER_STAGE (stage));
|
||||
|
||||
clutter_stage_set_motion_events_enabled (CLUTTER_STAGE (stage), enabled);
|
||||
|
||||
g_print ("per actor motion events are now %s\n",
|
||||
enabled ? "enabled" : "disabled");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
toggle_grab_pointer_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterInputDevice *device = clutter_event_get_device (event);
|
||||
|
||||
/* we only deal with the event if the source is ourself */
|
||||
if (event->button.source == actor)
|
||||
{
|
||||
if (clutter_input_device_get_grabbed_actor (device) != NULL)
|
||||
clutter_input_device_ungrab (device);
|
||||
else
|
||||
clutter_input_device_grab (device, actor);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cyan_press_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterDeviceManager *dm = clutter_device_manager_get_default ();
|
||||
ClutterInputDevice *device =
|
||||
clutter_device_manager_get_core_device (dm, CLUTTER_KEYBOARD_DEVICE);
|
||||
|
||||
if (clutter_input_device_get_grabbed_actor (device) != NULL)
|
||||
clutter_input_device_ungrab (device);
|
||||
else
|
||||
clutter_input_device_grab (device, actor);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_grab_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *actor;
|
||||
ClutterColor rcol = { 0xff, 0, 0, 0xff},
|
||||
bcol = { 0, 0, 0xff, 0xff },
|
||||
gcol = { 0, 0xff, 0, 0xff },
|
||||
ccol = { 0, 0xff, 0xff, 0xff },
|
||||
ycol = { 0xff, 0xff, 0, 0xff };
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
g_print ("Red box: aquire grab on press, releases it on next button release\n");
|
||||
g_print ("Blue box: aquire grab on press, destroys the blue box actor on release\n");
|
||||
g_print ("Yellow box: aquire grab on press, releases grab on next press on yellow box\n");
|
||||
g_print ("Green box: toggle per actor motion events.\n\n");
|
||||
g_print ("Cyan box: toggle grab (from cyan box) for keyboard events.\n\n");
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Grabs");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
g_signal_connect (stage, "event",
|
||||
G_CALLBACK (debug_event_cb), (char *) "stage");
|
||||
g_signal_connect (stage, "activate",
|
||||
G_CALLBACK (stage_state_cb), (char *) "activate");
|
||||
g_signal_connect (stage, "deactivate",
|
||||
G_CALLBACK (stage_state_cb), (char *) "deactivate");
|
||||
|
||||
actor = clutter_rectangle_new_with_color (&rcol);
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 100, 100);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||
g_signal_connect (actor, "event", G_CALLBACK (debug_event_cb), (char *) "red box");
|
||||
g_signal_connect (actor, "button-press-event",
|
||||
G_CALLBACK (grab_pointer_cb), NULL);
|
||||
g_signal_connect (actor, "button-release-event",
|
||||
G_CALLBACK (red_release_cb), NULL);
|
||||
|
||||
actor = clutter_rectangle_new_with_color (&ycol);
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 100, 300);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||
g_signal_connect (actor, "event", G_CALLBACK (debug_event_cb), (char *) "yellow box");
|
||||
g_signal_connect (actor, "button-press-event",
|
||||
G_CALLBACK (toggle_grab_pointer_cb), NULL);
|
||||
|
||||
actor = clutter_rectangle_new_with_color (&bcol);
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 300, 100);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||
g_signal_connect (actor, "event",
|
||||
G_CALLBACK (debug_event_cb), (char *) "blue box");
|
||||
g_signal_connect (actor, "button-press-event",
|
||||
G_CALLBACK (grab_pointer_cb), NULL);
|
||||
g_signal_connect (actor, "button-release-event",
|
||||
G_CALLBACK (blue_release_cb), NULL);
|
||||
|
||||
actor = clutter_rectangle_new_with_color (&gcol);
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 300, 300);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||
g_signal_connect (actor, "event",
|
||||
G_CALLBACK (debug_event_cb), (char *) "green box");
|
||||
g_signal_connect (actor, "button-press-event",
|
||||
G_CALLBACK (green_press_cb), NULL);
|
||||
|
||||
|
||||
actor = clutter_rectangle_new_with_color (&ccol);
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 500, 100);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL);
|
||||
g_signal_connect (actor, "event",
|
||||
G_CALLBACK (debug_event_cb), (char *) "cyan box");
|
||||
g_signal_connect (actor, "button-press-event",
|
||||
G_CALLBACK (cyan_press_cb), NULL);
|
||||
|
||||
clutter_actor_show_all (CLUTTER_ACTOR (stage));
|
||||
|
||||
clutter_main();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_grab_describe (void)
|
||||
{
|
||||
return "Examples of using actor grabs";
|
||||
}
|
259
src/tests/clutter/interactive/test-image.c
Normal file
259
src/tests/clutter/interactive/test-image.c
Normal file
@ -0,0 +1,259 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
typedef struct _SolidContent {
|
||||
GObject parent_instance;
|
||||
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
double alpha;
|
||||
|
||||
float padding;
|
||||
} SolidContent;
|
||||
|
||||
typedef struct _SolidContentClass {
|
||||
GObjectClass parent_class;
|
||||
} SolidContentClass;
|
||||
|
||||
static void clutter_content_iface_init (ClutterContentInterface *iface);
|
||||
|
||||
GType solid_content_get_type (void);
|
||||
|
||||
const char *
|
||||
test_image_describe (void);
|
||||
|
||||
int
|
||||
test_image_main (int argc, char *argv[]);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (SolidContent, solid_content, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT,
|
||||
clutter_content_iface_init))
|
||||
|
||||
static void
|
||||
solid_content_paint_content (ClutterContent *content,
|
||||
ClutterActor *actor,
|
||||
ClutterPaintNode *root)
|
||||
{
|
||||
SolidContent *self = (SolidContent *) content;
|
||||
ClutterActorBox box, content_box;
|
||||
ClutterColor color;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle logical;
|
||||
ClutterPaintNode *node;
|
||||
|
||||
#if 0
|
||||
g_debug ("Painting content [%p] "
|
||||
"{ r:%.2f, g:%.2f, b:%.2f, a:%.2f } "
|
||||
"for actor [%p] (context: [%p])",
|
||||
content,
|
||||
self->red,
|
||||
self->green,
|
||||
self->blue,
|
||||
self->alpha,
|
||||
actor, context);
|
||||
#endif
|
||||
|
||||
clutter_actor_get_content_box (actor, &content_box);
|
||||
|
||||
box = content_box;
|
||||
box.x1 += self->padding;
|
||||
box.y1 += self->padding;
|
||||
box.x2 -= self->padding;
|
||||
box.y2 -= self->padding;
|
||||
|
||||
color.alpha = self->alpha * 255;
|
||||
|
||||
color.red = self->red * 255;
|
||||
color.green = self->green * 255;
|
||||
color.blue = self->blue * 255;
|
||||
|
||||
node = clutter_color_node_new (&color);
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
clutter_paint_node_add_child (root, node);
|
||||
clutter_paint_node_unref (node);
|
||||
|
||||
color.red = (1.0 - self->red) * 255;
|
||||
color.green = (1.0 - self->green) * 255;
|
||||
color.blue = (1.0 - self->blue) * 255;
|
||||
|
||||
layout = clutter_actor_create_pango_layout (actor, "A");
|
||||
pango_layout_get_pixel_extents (layout, NULL, &logical);
|
||||
|
||||
node = clutter_text_node_new (layout, &color);
|
||||
|
||||
/* top-left */
|
||||
box.x1 = clutter_actor_box_get_x (&content_box);
|
||||
box.y1 = clutter_actor_box_get_y (&content_box);
|
||||
box.x2 = box.x1 + logical.width;
|
||||
box.y2 = box.y1 + logical.height;
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
|
||||
/* top-right */
|
||||
box.x1 = clutter_actor_box_get_x (&content_box)
|
||||
+ clutter_actor_box_get_width (&content_box)
|
||||
- logical.width;
|
||||
box.y1 = clutter_actor_box_get_y (&content_box);
|
||||
box.x2 = box.x1 + logical.width;
|
||||
box.y2 = box.y1 + logical.height;
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
|
||||
/* bottom-right */
|
||||
box.x1 = clutter_actor_box_get_x (&content_box)
|
||||
+ clutter_actor_box_get_width (&content_box)
|
||||
- logical.width;
|
||||
box.y1 = clutter_actor_box_get_y (&content_box)
|
||||
+ clutter_actor_box_get_height (&content_box)
|
||||
- logical.height;
|
||||
box.x2 = box.x1 + logical.width;
|
||||
box.y2 = box.y1 + logical.height;
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
|
||||
/* bottom-left */
|
||||
box.x1 = clutter_actor_box_get_x (&content_box);
|
||||
box.y1 = clutter_actor_box_get_y (&content_box)
|
||||
+ clutter_actor_box_get_height (&content_box)
|
||||
- logical.height;
|
||||
box.x2 = box.x1 + logical.width;
|
||||
box.y2 = box.y1 + logical.height;
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
|
||||
/* center */
|
||||
box.x1 = clutter_actor_box_get_x (&content_box)
|
||||
+ (clutter_actor_box_get_width (&content_box) - logical.width) / 2.0;
|
||||
box.y1 = clutter_actor_box_get_y (&content_box)
|
||||
+ (clutter_actor_box_get_height (&content_box) - logical.height) / 2.0;
|
||||
box.x2 = box.x1 + logical.width;
|
||||
box.y2 = box.y1 + logical.height;
|
||||
clutter_paint_node_add_rectangle (node, &box);
|
||||
|
||||
clutter_paint_node_add_child (root, node);
|
||||
clutter_paint_node_unref (node);
|
||||
|
||||
g_object_unref (layout);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_content_iface_init (ClutterContentInterface *iface)
|
||||
{
|
||||
iface->paint_content = solid_content_paint_content;
|
||||
}
|
||||
|
||||
static void
|
||||
solid_content_class_init (SolidContentClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
solid_content_init (SolidContent *self)
|
||||
{
|
||||
}
|
||||
|
||||
static ClutterContent *
|
||||
solid_content_new (double red,
|
||||
double green,
|
||||
double blue,
|
||||
double alpha,
|
||||
float padding)
|
||||
{
|
||||
SolidContent *self = g_object_new (solid_content_get_type (), NULL);
|
||||
|
||||
self->red = red;
|
||||
self->green = green;
|
||||
self->blue = blue;
|
||||
self->alpha = alpha;
|
||||
self->padding = padding;
|
||||
|
||||
return (ClutterContent *) self;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_image_describe (void)
|
||||
{
|
||||
return "A test with image content.";
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_image_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *grid;
|
||||
ClutterContent *color, *image;
|
||||
GdkPixbuf *pixbuf;
|
||||
int i, n_rects;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_name (stage, "Stage");
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Content");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
clutter_actor_show (stage);
|
||||
|
||||
grid = clutter_actor_new ();
|
||||
clutter_actor_set_name (grid, "Grid");
|
||||
clutter_actor_set_margin_top (grid, 12);
|
||||
clutter_actor_set_margin_right (grid, 12);
|
||||
clutter_actor_set_margin_bottom (grid, 12);
|
||||
clutter_actor_set_margin_left (grid, 12);
|
||||
clutter_actor_set_layout_manager (grid, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL));
|
||||
clutter_actor_add_constraint (grid, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0));
|
||||
clutter_actor_add_child (stage, grid);
|
||||
|
||||
color = solid_content_new (g_random_double_range (0.0, 1.0),
|
||||
g_random_double_range (0.0, 1.0),
|
||||
g_random_double_range (0.0, 1.0),
|
||||
1.0,
|
||||
2.0);
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png", NULL);
|
||||
image = clutter_image_new ();
|
||||
clutter_image_set_data (CLUTTER_IMAGE (image),
|
||||
gdk_pixbuf_get_pixels (pixbuf),
|
||||
gdk_pixbuf_get_has_alpha (pixbuf)
|
||||
? COGL_PIXEL_FORMAT_RGBA_8888
|
||||
: COGL_PIXEL_FORMAT_RGB_888,
|
||||
gdk_pixbuf_get_width (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf),
|
||||
gdk_pixbuf_get_rowstride (pixbuf),
|
||||
NULL);
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
n_rects = g_random_int_range (12, 24);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
ClutterActor *box = clutter_actor_new ();
|
||||
ClutterColor bg_color = {
|
||||
g_random_int_range (0, 255),
|
||||
g_random_int_range (0, 255),
|
||||
g_random_int_range (0, 255),
|
||||
255
|
||||
};
|
||||
char *name, *str;
|
||||
|
||||
str = clutter_color_to_string (&bg_color);
|
||||
name = g_strconcat ("Box <", color, ">", NULL);
|
||||
clutter_actor_set_name (box, name);
|
||||
|
||||
g_free (name);
|
||||
g_free (str);
|
||||
|
||||
if ((i % 2) == 0)
|
||||
clutter_actor_set_content (box, color);
|
||||
else
|
||||
clutter_actor_set_content (box, image);
|
||||
|
||||
clutter_actor_set_size (box, 64, 64);
|
||||
|
||||
clutter_actor_add_child (grid, box);
|
||||
}
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_object_unref (color);
|
||||
g_object_unref (image);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
114
src/tests/clutter/interactive/test-keyframe-transition.c
Normal file
114
src/tests/clutter/interactive/test-keyframe-transition.c
Normal file
@ -0,0 +1,114 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static const ClutterColor colors[] = {
|
||||
{ 255, 0, 0, 255 },
|
||||
{ 0, 255, 0, 255 },
|
||||
{ 0, 0, 255, 255 },
|
||||
};
|
||||
|
||||
#define PADDING (64.0f)
|
||||
#define SIZE (64.0f)
|
||||
|
||||
const char *
|
||||
test_keyframe_transition_describe (void);
|
||||
|
||||
int
|
||||
test_keyframe_transition_main (int argc, char *argv[]);
|
||||
|
||||
static void
|
||||
on_transition_stopped (ClutterActor *actor,
|
||||
const gchar *transition_name,
|
||||
gboolean is_finished)
|
||||
{
|
||||
g_print ("%s: transition stopped: %s (finished: %s)\n",
|
||||
clutter_actor_get_name (actor),
|
||||
transition_name,
|
||||
is_finished ? "yes" : "no");
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_keyframe_transition_describe (void)
|
||||
{
|
||||
return "Demonstrate the keyframe transition.";
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_keyframe_transition_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
int i;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Keyframe Transitions");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
ClutterTransition *transition, *group;
|
||||
ClutterActor *rect;
|
||||
float cur_x, cur_y;
|
||||
float new_x, new_y;
|
||||
gchar *name;
|
||||
|
||||
cur_x = PADDING;
|
||||
cur_y = PADDING + ((SIZE + PADDING) * i);
|
||||
|
||||
new_x = clutter_actor_get_width (stage) - PADDING - SIZE;
|
||||
new_y = g_random_double_range (PADDING, clutter_actor_get_height (stage) - PADDING - SIZE);
|
||||
|
||||
name = g_strdup_printf ("rect%02d", i);
|
||||
|
||||
rect = clutter_actor_new ();
|
||||
|
||||
clutter_actor_set_name (rect, name);
|
||||
clutter_actor_set_background_color (rect, &colors[i]);
|
||||
clutter_actor_set_size (rect, SIZE, SIZE);
|
||||
clutter_actor_set_position (rect, PADDING, cur_y);
|
||||
clutter_actor_add_child (stage, rect);
|
||||
|
||||
group = clutter_transition_group_new ();
|
||||
clutter_timeline_set_duration (CLUTTER_TIMELINE (group), 2000);
|
||||
clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (group), 1);
|
||||
clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (group), TRUE);
|
||||
|
||||
transition = clutter_keyframe_transition_new ("x");
|
||||
clutter_transition_set_from (transition, G_TYPE_FLOAT, cur_x);
|
||||
clutter_transition_set_to (transition, G_TYPE_FLOAT, new_x);
|
||||
|
||||
clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (transition),
|
||||
G_TYPE_FLOAT, 1,
|
||||
0.5, new_x / 2.0f, CLUTTER_EASE_OUT_EXPO);
|
||||
clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), transition);
|
||||
g_object_unref (transition);
|
||||
|
||||
transition = clutter_keyframe_transition_new ("y");
|
||||
clutter_transition_set_from (transition, G_TYPE_FLOAT, cur_y);
|
||||
clutter_transition_set_to (transition, G_TYPE_FLOAT, cur_y);
|
||||
|
||||
clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (transition),
|
||||
G_TYPE_FLOAT, 1,
|
||||
0.5, new_y, CLUTTER_EASE_OUT_EXPO);
|
||||
clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), transition);
|
||||
g_object_unref (transition);
|
||||
|
||||
clutter_actor_add_transition (rect, "rectAnimation", group);
|
||||
|
||||
g_signal_connect (rect, "transition-stopped",
|
||||
G_CALLBACK (on_transition_stopped),
|
||||
NULL);
|
||||
g_object_unref (group);
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
693
src/tests/clutter/interactive/test-layout.c
Normal file
693
src/tests/clutter/interactive/test-layout.c
Normal file
@ -0,0 +1,693 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <gmodule.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
/* layout actor, by Lucas Rocha */
|
||||
|
||||
#define MY_TYPE_THING (my_thing_get_type ())
|
||||
#define MY_THING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_THING, MyThing))
|
||||
#define MY_IS_THING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_THING))
|
||||
#define MY_THING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MY_TYPE_THING, MyThingClass))
|
||||
#define MY_IS_THING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_TYPE_THING))
|
||||
#define MY_THING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MY_TYPE_THING, MyThingClass))
|
||||
|
||||
typedef struct _MyThing MyThing;
|
||||
typedef struct _MyThingPrivate MyThingPrivate;
|
||||
typedef struct _MyThingClass MyThingClass;
|
||||
|
||||
struct _MyThing
|
||||
{
|
||||
ClutterActor parent_instance;
|
||||
|
||||
MyThingPrivate *priv;
|
||||
};
|
||||
|
||||
struct _MyThingClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_SPACING,
|
||||
PROP_PADDING,
|
||||
PROP_USE_TRANSFORMED_BOX
|
||||
};
|
||||
|
||||
struct _MyThingPrivate
|
||||
{
|
||||
gfloat spacing;
|
||||
gfloat padding;
|
||||
|
||||
guint use_transformed_box : 1;
|
||||
};
|
||||
|
||||
GType my_thing_get_type (void);
|
||||
|
||||
int
|
||||
test_layout_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_layout_describe (void);
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MyThing, my_thing, CLUTTER_TYPE_ACTOR)
|
||||
|
||||
#define MY_THING_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MY_TYPE_THING, MyThingPrivate))
|
||||
|
||||
static void
|
||||
my_thing_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MyThingPrivate *priv = MY_THING (gobject)->priv;
|
||||
gboolean needs_relayout = TRUE;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SPACING:
|
||||
priv->spacing = g_value_get_float (value);
|
||||
break;
|
||||
|
||||
case PROP_PADDING:
|
||||
priv->padding = g_value_get_float (value);
|
||||
break;
|
||||
|
||||
case PROP_USE_TRANSFORMED_BOX:
|
||||
priv->use_transformed_box = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
needs_relayout = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* setting spacing or padding queues a relayout
|
||||
because they are supposed to change the internal
|
||||
allocation of children */
|
||||
if (needs_relayout)
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (gobject));
|
||||
}
|
||||
|
||||
static void
|
||||
my_thing_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MyThingPrivate *priv = MY_THING (gobject)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SPACING:
|
||||
g_value_set_float (value, priv->spacing);
|
||||
break;
|
||||
|
||||
case PROP_PADDING:
|
||||
g_value_set_float (value, priv->padding);
|
||||
break;
|
||||
|
||||
case PROP_USE_TRANSFORMED_BOX:
|
||||
g_value_set_boolean (value, priv->use_transformed_box);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
my_thing_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
gfloat min_left, min_right;
|
||||
gfloat natural_left, natural_right;
|
||||
|
||||
min_left = 0;
|
||||
min_right = 0;
|
||||
natural_left = 0;
|
||||
natural_right = 0;
|
||||
|
||||
clutter_actor_iter_init (&iter, self);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
gfloat child_x, child_min, child_natural;
|
||||
|
||||
child_x = clutter_actor_get_x (child);
|
||||
|
||||
clutter_actor_get_preferred_size (child,
|
||||
&child_min, NULL,
|
||||
&child_natural, NULL);
|
||||
|
||||
if (child == clutter_actor_get_first_child (self))
|
||||
{
|
||||
/* First child */
|
||||
min_left = child_x;
|
||||
natural_left = child_x;
|
||||
min_right = min_left + child_min;
|
||||
natural_right = natural_left + child_natural;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Union of extents with previous children */
|
||||
if (child_x < min_left)
|
||||
min_left = child_x;
|
||||
|
||||
if (child_x < natural_left)
|
||||
natural_left = child_x;
|
||||
|
||||
if (child_x + child_min > min_right)
|
||||
min_right = child_x + child_min;
|
||||
|
||||
if (child_x + child_natural > natural_right)
|
||||
natural_right = child_x + child_natural;
|
||||
}
|
||||
}
|
||||
|
||||
if (min_left < 0)
|
||||
min_left = 0;
|
||||
|
||||
if (natural_left < 0)
|
||||
natural_left = 0;
|
||||
|
||||
if (min_right < 0)
|
||||
min_right = 0;
|
||||
|
||||
if (natural_right < 0)
|
||||
natural_right = 0;
|
||||
|
||||
g_assert (min_right >= min_left);
|
||||
g_assert (natural_right >= natural_left);
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p = min_right - min_left;
|
||||
|
||||
if (natural_width_p)
|
||||
*natural_width_p = natural_right - min_left;
|
||||
}
|
||||
|
||||
static void
|
||||
my_thing_get_preferred_height (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
gfloat min_top, min_bottom;
|
||||
gfloat natural_top, natural_bottom;
|
||||
|
||||
min_top = 0;
|
||||
min_bottom = 0;
|
||||
natural_top = 0;
|
||||
natural_bottom = 0;
|
||||
|
||||
clutter_actor_iter_init (&iter, self);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
gfloat child_y, child_min, child_natural;
|
||||
|
||||
child_y = clutter_actor_get_y (child);
|
||||
|
||||
clutter_actor_get_preferred_size (child,
|
||||
NULL, &child_min,
|
||||
NULL, &child_natural);
|
||||
|
||||
if (child == clutter_actor_get_first_child (self))
|
||||
{
|
||||
/* First child */
|
||||
min_top = child_y;
|
||||
natural_top = child_y;
|
||||
min_bottom = min_top + child_min;
|
||||
natural_bottom = natural_top + child_natural;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Union of extents with previous children */
|
||||
if (child_y < min_top)
|
||||
min_top = child_y;
|
||||
|
||||
if (child_y < natural_top)
|
||||
natural_top = child_y;
|
||||
|
||||
if (child_y + child_min > min_bottom)
|
||||
min_bottom = child_y + child_min;
|
||||
|
||||
if (child_y + child_natural > natural_bottom)
|
||||
natural_bottom = child_y + child_natural;
|
||||
}
|
||||
}
|
||||
|
||||
if (min_top < 0)
|
||||
min_top = 0;
|
||||
|
||||
if (natural_top < 0)
|
||||
natural_top = 0;
|
||||
|
||||
if (min_bottom < 0)
|
||||
min_bottom = 0;
|
||||
|
||||
if (natural_bottom < 0)
|
||||
natural_bottom = 0;
|
||||
|
||||
g_assert (min_bottom >= min_top);
|
||||
g_assert (natural_bottom >= natural_top);
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p = min_bottom - min_top;
|
||||
|
||||
if (natural_height_p)
|
||||
*natural_height_p = natural_bottom - min_top;
|
||||
}
|
||||
|
||||
static void
|
||||
my_thing_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
MyThingPrivate *priv;
|
||||
gfloat current_x, current_y, max_row_height;
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
|
||||
clutter_actor_set_allocation (self, box, flags);
|
||||
|
||||
priv = MY_THING (self)->priv;
|
||||
|
||||
current_x = priv->padding;
|
||||
current_y = priv->padding;
|
||||
max_row_height = 0;
|
||||
|
||||
/* The allocation logic here is to horizontally place children
|
||||
* side-by-side and reflow into a new row when we run out of
|
||||
* space
|
||||
*/
|
||||
clutter_actor_iter_init (&iter, self);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
gfloat natural_width, natural_height;
|
||||
ClutterActorBox child_box;
|
||||
|
||||
clutter_actor_get_preferred_size (child,
|
||||
NULL, NULL,
|
||||
&natural_width,
|
||||
&natural_height);
|
||||
|
||||
/* if it fits in the current row, keep it there; otherwise
|
||||
* reflow into another row
|
||||
*/
|
||||
if (current_x + natural_width > box->x2 - box->x1 - priv->padding)
|
||||
{
|
||||
current_x = priv->padding;
|
||||
current_y += max_row_height + priv->spacing;
|
||||
max_row_height = 0;
|
||||
}
|
||||
|
||||
child_box.x1 = current_x;
|
||||
child_box.y1 = current_y;
|
||||
child_box.x2 = child_box.x1 + natural_width;
|
||||
child_box.y2 = child_box.y1 + natural_height;
|
||||
|
||||
clutter_actor_allocate (child, &child_box, flags);
|
||||
|
||||
/* if we take into account the transformation of the children
|
||||
* then we first check if it's transformed; then we get the
|
||||
* onscreen coordinates of the two points of the bounding box
|
||||
* of the actor (origin(x, y) and (origin + size)(x,y)) and
|
||||
* we update the coordinates and area given to the next child
|
||||
*/
|
||||
if (priv->use_transformed_box)
|
||||
{
|
||||
if (clutter_actor_is_scaled (child) ||
|
||||
clutter_actor_is_rotated (child))
|
||||
{
|
||||
ClutterVertex v1 = { 0, }, v2 = { 0, };
|
||||
ClutterActorBox transformed_box = { 0, };
|
||||
|
||||
/* origin */
|
||||
if (!(flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED))
|
||||
{
|
||||
v1.x = 0;
|
||||
v1.y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
v1.x = box->x1;
|
||||
v1.y = box->y1;
|
||||
}
|
||||
|
||||
clutter_actor_apply_transform_to_point (child, &v1, &v2);
|
||||
transformed_box.x1 = v2.x;
|
||||
transformed_box.y1 = v2.y;
|
||||
|
||||
/* size */
|
||||
v1.x = natural_width;
|
||||
v1.y = natural_height;
|
||||
clutter_actor_apply_transform_to_point (child, &v1, &v2);
|
||||
transformed_box.x2 = v2.x;
|
||||
transformed_box.y2 = v2.y;
|
||||
|
||||
natural_width = transformed_box.x2 - transformed_box.x1;
|
||||
natural_height = transformed_box.y2 - transformed_box.y1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Record the maximum child height on current row to know
|
||||
* what's the increment that should be used for the next
|
||||
* row
|
||||
*/
|
||||
if (natural_height > max_row_height)
|
||||
max_row_height = natural_height;
|
||||
|
||||
current_x += natural_width + priv->spacing;
|
||||
}
|
||||
}
|
||||
|
||||
#define MIN_SIZE 24
|
||||
#define MAX_SIZE 64
|
||||
|
||||
static void
|
||||
my_thing_class_init (MyThingClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = my_thing_set_property;
|
||||
gobject_class->get_property = my_thing_get_property;
|
||||
|
||||
actor_class->get_preferred_width = my_thing_get_preferred_width;
|
||||
actor_class->get_preferred_height = my_thing_get_preferred_height;
|
||||
actor_class->allocate = my_thing_allocate;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SPACING,
|
||||
g_param_spec_float ("spacing",
|
||||
"Spacing",
|
||||
"Spacing of the thing",
|
||||
0, G_MAXFLOAT,
|
||||
0,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PADDING,
|
||||
g_param_spec_float ("padding",
|
||||
"Padding",
|
||||
"Padding around the thing",
|
||||
0, G_MAXFLOAT,
|
||||
0,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_USE_TRANSFORMED_BOX,
|
||||
g_param_spec_boolean ("use-transformed-box",
|
||||
"Use Transformed Box",
|
||||
"Use transformed box when allocating",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
static void
|
||||
my_thing_init (MyThing *thing)
|
||||
{
|
||||
thing->priv = MY_THING_GET_PRIVATE (thing);
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
my_thing_new (gfloat padding,
|
||||
gfloat spacing)
|
||||
{
|
||||
return g_object_new (MY_TYPE_THING,
|
||||
"padding", padding,
|
||||
"spacing", spacing,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* test code */
|
||||
|
||||
static ClutterActor *box = NULL;
|
||||
static ClutterActor *icon = NULL;
|
||||
static ClutterTimeline *main_timeline = NULL;
|
||||
|
||||
static void
|
||||
toggle_property_value (ClutterActor *actor,
|
||||
const gchar *property_name)
|
||||
{
|
||||
gboolean value;
|
||||
|
||||
g_object_get (actor, property_name, &value, NULL);
|
||||
|
||||
value = !value;
|
||||
|
||||
g_object_set (box, property_name, value, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
increase_property_value (ClutterActor *actor,
|
||||
const char *property_name)
|
||||
{
|
||||
gfloat value;
|
||||
|
||||
g_object_get (actor, property_name, &value, NULL);
|
||||
|
||||
value = value + 10.0;
|
||||
|
||||
g_object_set (box, property_name, value, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
decrease_property_value (ClutterActor *actor,
|
||||
const char *property_name)
|
||||
{
|
||||
gfloat value;
|
||||
|
||||
g_object_get (actor, property_name, &value, NULL);
|
||||
|
||||
value = MAX (0, value - 10.0);
|
||||
|
||||
g_object_set (box, property_name, value, NULL);
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
create_item (void)
|
||||
{
|
||||
ClutterActor *clone = clutter_clone_new (icon);
|
||||
|
||||
gint32 size = g_random_int_range (MIN_SIZE, MAX_SIZE);
|
||||
|
||||
clutter_actor_set_size (clone, size, size);
|
||||
clutter_actor_animate_with_timeline (clone, CLUTTER_EASE_OUT_CUBIC,
|
||||
main_timeline,
|
||||
"scale-x", 2.0,
|
||||
"scale-y", 2.0,
|
||||
"fixed::scale-gravity", CLUTTER_GRAVITY_CENTER,
|
||||
NULL);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
keypress_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
switch (clutter_event_get_key_symbol (event))
|
||||
{
|
||||
case CLUTTER_KEY_q:
|
||||
clutter_main_quit ();
|
||||
break;
|
||||
|
||||
case CLUTTER_KEY_a:
|
||||
{
|
||||
if (icon != NULL)
|
||||
{
|
||||
ClutterActor *clone = create_item ();
|
||||
|
||||
/* Add one item to container */
|
||||
clutter_actor_add_child (box, clone);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CLUTTER_KEY_d:
|
||||
{
|
||||
ClutterActor *last_child;
|
||||
|
||||
last_child = clutter_actor_get_last_child (box);
|
||||
if (last_child != NULL)
|
||||
{
|
||||
/* Remove last item on container */
|
||||
clutter_actor_remove_child (box, last_child);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CLUTTER_KEY_w:
|
||||
{
|
||||
decrease_property_value (box, "padding");
|
||||
break;
|
||||
}
|
||||
|
||||
case CLUTTER_KEY_e:
|
||||
{
|
||||
increase_property_value (box, "padding");
|
||||
break;
|
||||
}
|
||||
|
||||
case CLUTTER_KEY_r:
|
||||
{
|
||||
decrease_property_value (box, "spacing");
|
||||
break;
|
||||
}
|
||||
|
||||
case CLUTTER_KEY_s:
|
||||
{
|
||||
toggle_property_value (box, "use-transformed-box");
|
||||
break;
|
||||
}
|
||||
|
||||
case CLUTTER_KEY_t:
|
||||
{
|
||||
increase_property_value (box, "spacing");
|
||||
break;
|
||||
}
|
||||
|
||||
case CLUTTER_KEY_z:
|
||||
{
|
||||
if (clutter_timeline_is_playing (main_timeline))
|
||||
clutter_timeline_pause (main_timeline);
|
||||
else
|
||||
clutter_timeline_start (main_timeline);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
relayout_on_frame (ClutterTimeline *timeline)
|
||||
{
|
||||
gboolean use_transformed_box;
|
||||
|
||||
/* if we care about transformations updating the layout, we need to inform
|
||||
* the layout that a transformation is happening; this is either done by
|
||||
* attaching a notification on the transformation properties or by simply
|
||||
* queuing a relayout on each frame of the timeline used to drive the
|
||||
* behaviour. for simplicity's sake, we used the latter
|
||||
*/
|
||||
|
||||
g_object_get (G_OBJECT (box),
|
||||
"use-transformed-box", &use_transformed_box,
|
||||
NULL);
|
||||
|
||||
if (use_transformed_box)
|
||||
clutter_actor_queue_relayout (box);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_layout_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *instructions;
|
||||
gint i, size;
|
||||
GError *error = NULL;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (stage, 800, 600);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Layout");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
main_timeline = clutter_timeline_new (2000);
|
||||
clutter_timeline_set_repeat_count (main_timeline, -1);
|
||||
clutter_timeline_set_auto_reverse (main_timeline, TRUE);
|
||||
g_signal_connect (main_timeline, "new-frame",
|
||||
G_CALLBACK (relayout_on_frame),
|
||||
NULL);
|
||||
|
||||
|
||||
box = my_thing_new (10, 10);
|
||||
|
||||
clutter_actor_set_position (box, 20, 20);
|
||||
clutter_actor_set_size (box, 350, -1);
|
||||
|
||||
icon = clutter_texture_new_from_file (TESTS_DATADIR
|
||||
G_DIR_SEPARATOR_S
|
||||
"redhand.png",
|
||||
&error);
|
||||
if (error)
|
||||
g_error ("Unable to load 'redhand.png': %s", error->message);
|
||||
|
||||
size = g_random_int_range (MIN_SIZE, MAX_SIZE);
|
||||
clutter_actor_set_size (icon, size, size);
|
||||
clutter_actor_add_child (box, icon);
|
||||
clutter_actor_animate_with_timeline (icon, CLUTTER_EASE_OUT_CUBIC,
|
||||
main_timeline,
|
||||
"scale-x", 2.0,
|
||||
"scale-y", 2.0,
|
||||
"fixed::scale-gravity", CLUTTER_GRAVITY_CENTER,
|
||||
NULL);
|
||||
|
||||
for (i = 1; i < 33; i++)
|
||||
{
|
||||
ClutterActor *clone = create_item ();
|
||||
|
||||
clutter_actor_add_child (box, clone);
|
||||
}
|
||||
|
||||
clutter_actor_add_child (stage, box);
|
||||
|
||||
instructions = clutter_text_new_with_text (NULL,
|
||||
"<b>Instructions:</b>\n"
|
||||
"a - add a new item\n"
|
||||
"d - remove last item\n"
|
||||
"z - start/pause behaviour\n"
|
||||
"w - decrease padding\n"
|
||||
"e - increase padding\n"
|
||||
"r - decrease spacing\n"
|
||||
"t - increase spacing\n"
|
||||
"s - use transformed box\n"
|
||||
"q - quit");
|
||||
|
||||
clutter_text_set_use_markup (CLUTTER_TEXT (instructions), TRUE);
|
||||
clutter_actor_set_position (instructions, 450, 10);
|
||||
clutter_actor_add_child (stage, instructions);
|
||||
|
||||
g_signal_connect (stage, "key-release-event",
|
||||
G_CALLBACK (keypress_cb),
|
||||
NULL);
|
||||
|
||||
clutter_timeline_stop (main_timeline);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_object_unref (main_timeline);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_layout_describe (void)
|
||||
{
|
||||
return "Container implementing a layout policy.";
|
||||
}
|
221
src/tests/clutter/interactive/test-main.c
Normal file
221
src/tests/clutter/interactive/test-main.c
Normal file
@ -0,0 +1,221 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#include "test-unit-names.h"
|
||||
|
||||
#define MAX_DESC_SIZE 72
|
||||
|
||||
static GModule *module = NULL;
|
||||
|
||||
static gpointer
|
||||
get_symbol_with_suffix (const char *unit_name,
|
||||
const char *suffix)
|
||||
{
|
||||
char *main_symbol_name;
|
||||
gpointer func;
|
||||
|
||||
main_symbol_name = g_strconcat (unit_name, "_", suffix, NULL);
|
||||
main_symbol_name = g_strdelimit (main_symbol_name, "-", '_');
|
||||
|
||||
g_module_symbol (module, main_symbol_name, &func);
|
||||
|
||||
g_free (main_symbol_name);
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
get_unit_name_main (const char *unit_name)
|
||||
{
|
||||
return get_symbol_with_suffix (unit_name, "main");
|
||||
}
|
||||
static char *
|
||||
get_unit_name_description (const char *unit_name,
|
||||
gssize max_len)
|
||||
{
|
||||
const char *description;
|
||||
gpointer func;
|
||||
char *retval;
|
||||
|
||||
func = get_symbol_with_suffix (unit_name, "describe");
|
||||
if (func == NULL)
|
||||
description = "No description found";
|
||||
else
|
||||
{
|
||||
const char *(* unit_test_describe) (void);
|
||||
|
||||
unit_test_describe = func;
|
||||
|
||||
description = unit_test_describe ();
|
||||
}
|
||||
|
||||
if (max_len > 0 && strlen (description) >= max_len)
|
||||
{
|
||||
GString *buf = g_string_sized_new (max_len);
|
||||
char *newline;
|
||||
|
||||
newline = strchr (description, '\n');
|
||||
if (newline != NULL)
|
||||
{
|
||||
g_string_append_len (buf, description,
|
||||
MIN (newline - description - 1, max_len - 3));
|
||||
}
|
||||
else
|
||||
g_string_append_len (buf, description, max_len - 3);
|
||||
|
||||
g_string_append (buf, "...");
|
||||
|
||||
retval = g_string_free (buf, FALSE);
|
||||
}
|
||||
else
|
||||
retval = g_strdup (description);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean list_all = FALSE;
|
||||
static gboolean describe = FALSE;
|
||||
static char **unit_names = NULL;
|
||||
|
||||
static GOptionEntry entries[] = {
|
||||
{
|
||||
"describe", 'd',
|
||||
0,
|
||||
G_OPTION_ARG_NONE, &describe,
|
||||
"Describe the interactive unit test", NULL,
|
||||
},
|
||||
{
|
||||
"list-all", 'l',
|
||||
0,
|
||||
G_OPTION_ARG_NONE, &list_all,
|
||||
"List all available units", NULL,
|
||||
},
|
||||
{
|
||||
G_OPTION_REMAINING, 0,
|
||||
0,
|
||||
G_OPTION_ARG_STRING_ARRAY, &unit_names,
|
||||
"The interactive unit test", "UNIT_NAME"
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int ret, i, n_unit_names;
|
||||
GOptionContext *context;
|
||||
|
||||
context = g_option_context_new (" - Interactive test suite");
|
||||
g_option_context_add_main_entries (context, entries, NULL);
|
||||
g_option_context_set_help_enabled (context, TRUE);
|
||||
g_option_context_set_ignore_unknown_options (context, TRUE);
|
||||
if (!g_option_context_parse (context, &argc, &argv, NULL))
|
||||
{
|
||||
g_print ("Usage: test-interactive <unit_test>\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
g_option_context_free (context);
|
||||
|
||||
module = g_module_open (NULL, 0);
|
||||
if (!module)
|
||||
g_error ("*** Failed to open self for symbol lookup");
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
|
||||
if (list_all)
|
||||
{
|
||||
g_print ("* Available unit tests:\n");
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_unit_names); i++)
|
||||
{
|
||||
char *str;
|
||||
gsize len;
|
||||
|
||||
len = MAX_DESC_SIZE - strlen (test_unit_names[i]);
|
||||
str = get_unit_name_description (test_unit_names[i], len - 2);
|
||||
|
||||
g_print (" - %s:%*s%s\n",
|
||||
test_unit_names[i],
|
||||
(int) (len - strlen (str)), " ",
|
||||
str);
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (unit_names != NULL)
|
||||
n_unit_names = g_strv_length (unit_names);
|
||||
else
|
||||
{
|
||||
g_print ("Usage: test-interactive <unit_test>\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_unit_names; i++)
|
||||
{
|
||||
const char *unit_name = unit_names[i];
|
||||
char *unit_test = NULL;
|
||||
gboolean found;
|
||||
int j;
|
||||
|
||||
unit_test = g_path_get_basename (unit_name);
|
||||
|
||||
found = FALSE;
|
||||
for (j = 0; j < G_N_ELEMENTS (test_unit_names); j++)
|
||||
{
|
||||
if (strcmp (test_unit_names[j], unit_test) == 0)
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
g_error ("*** Unit '%s' does not exist", unit_test);
|
||||
|
||||
if (describe)
|
||||
{
|
||||
char *str;
|
||||
|
||||
str = get_unit_name_description (unit_test, -1);
|
||||
|
||||
g_print ("* %s:\n%s\n\n", unit_test, str);
|
||||
|
||||
g_free (str);
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
int (* unit_test_main) (int argc, char **argv);
|
||||
gpointer func;
|
||||
|
||||
func = get_unit_name_main (unit_test);
|
||||
if (func == NULL)
|
||||
g_error ("*** Unable to find the main entry point for '%s'", unit_test);
|
||||
|
||||
unit_test_main = func;
|
||||
|
||||
ret = unit_test_main (n_unit_names, unit_names);
|
||||
|
||||
g_free (unit_test);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (unit_test);
|
||||
}
|
||||
|
||||
out:
|
||||
g_module_close (module);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
376
src/tests/clutter/interactive/test-paint-wrapper.c
Normal file
376
src/tests/clutter/interactive/test-paint-wrapper.c
Normal file
@ -0,0 +1,376 @@
|
||||
#include <gmodule.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#if defined (_MSC_VER) && !defined (_USE_MATH_DEFINES)
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef CLUTTER_WINDOWING_X11
|
||||
#include "clutter/x11/clutter-x11.h"
|
||||
#endif
|
||||
|
||||
#define NHANDS 6
|
||||
|
||||
typedef struct SuperOH
|
||||
{
|
||||
ClutterActor **hand, *bgtex;
|
||||
ClutterActor *real_hand;
|
||||
ClutterActor *group;
|
||||
ClutterActor *stage;
|
||||
|
||||
gint stage_width;
|
||||
gint stage_height;
|
||||
gfloat radius;
|
||||
|
||||
ClutterBehaviour *scaler_1;
|
||||
ClutterBehaviour *scaler_2;
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
guint frame_id;
|
||||
|
||||
gboolean *paint_guards;
|
||||
} SuperOH;
|
||||
|
||||
static gint n_hands = NHANDS;
|
||||
static gint use_alpha = 255;
|
||||
|
||||
static GOptionEntry super_oh_entries[] = {
|
||||
{
|
||||
"num-hands", 'n',
|
||||
0,
|
||||
G_OPTION_ARG_INT, &n_hands,
|
||||
"Number of hands", "HANDS"
|
||||
},
|
||||
{
|
||||
"use-alpha", 'a',
|
||||
0,
|
||||
G_OPTION_ARG_INT, &use_alpha,
|
||||
"Stage opacity", "VALUE"
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
int
|
||||
test_paint_wrapper_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_paint_wrapper_describe (void);
|
||||
|
||||
static gboolean
|
||||
on_button_press_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
SuperOH *oh)
|
||||
{
|
||||
gfloat x, y;
|
||||
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
|
||||
g_print ("*** button press event (button:%d) at %.2f, %.2f ***\n",
|
||||
clutter_event_get_button (event),
|
||||
x, y);
|
||||
|
||||
clutter_actor_hide (actor);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
input_cb (ClutterActor *stage,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
SuperOH *oh = data;
|
||||
|
||||
if (event->type == CLUTTER_KEY_RELEASE)
|
||||
{
|
||||
g_print ("*** key press event (key:%c) ***\n",
|
||||
clutter_event_get_key_symbol (event));
|
||||
|
||||
if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_q)
|
||||
{
|
||||
clutter_main_quit ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_r)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < n_hands; i++)
|
||||
clutter_actor_show (oh->hand[i]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Timeline handler */
|
||||
static void
|
||||
frame_cb (ClutterTimeline *timeline,
|
||||
gint msecs,
|
||||
gpointer data)
|
||||
{
|
||||
SuperOH *oh = data;
|
||||
gint i;
|
||||
float rotation = clutter_timeline_get_progress (timeline) * 360.0f;
|
||||
|
||||
/* Rotate everything clockwise about stage center*/
|
||||
|
||||
clutter_actor_set_rotation (oh->group,
|
||||
CLUTTER_Z_AXIS,
|
||||
rotation,
|
||||
oh->stage_width / 2,
|
||||
oh->stage_height / 2,
|
||||
0);
|
||||
|
||||
for (i = 0; i < n_hands; i++)
|
||||
{
|
||||
/* Rotate each hand around there centers - to get this we need
|
||||
* to take into account any scaling.
|
||||
*/
|
||||
clutter_actor_set_rotation (oh->hand[i],
|
||||
CLUTTER_Z_AXIS,
|
||||
-6.0 * rotation,
|
||||
0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static gdouble
|
||||
my_sine_wave (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
|
||||
gdouble progress = clutter_timeline_get_progress (timeline);
|
||||
|
||||
return sin (progress * G_PI);
|
||||
}
|
||||
|
||||
static void
|
||||
hand_pre_paint (ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
SuperOH *oh = user_data;
|
||||
gfloat w, h;
|
||||
int actor_num;
|
||||
|
||||
for (actor_num = 0; oh->hand[actor_num] != actor; actor_num++)
|
||||
;
|
||||
|
||||
g_assert (oh->paint_guards[actor_num] == FALSE);
|
||||
|
||||
clutter_actor_get_size (actor, &w, &h);
|
||||
|
||||
cogl_set_source_color4ub (255, 0, 0, 128);
|
||||
cogl_rectangle (0, 0, w / 2, h / 2);
|
||||
|
||||
oh->paint_guards[actor_num] = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
hand_post_paint (ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
SuperOH *oh = user_data;
|
||||
gfloat w, h;
|
||||
int actor_num;
|
||||
|
||||
for (actor_num = 0; oh->hand[actor_num] != actor; actor_num++)
|
||||
;
|
||||
|
||||
g_assert (oh->paint_guards[actor_num] == TRUE);
|
||||
|
||||
clutter_actor_get_size (actor, &w, &h);
|
||||
|
||||
cogl_set_source_color4ub (0, 255, 0, 128);
|
||||
cogl_rectangle (w / 2, h / 2, w, h);
|
||||
|
||||
oh->paint_guards[actor_num] = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
stop_and_quit (ClutterActor *actor,
|
||||
SuperOH *oh)
|
||||
{
|
||||
g_signal_handler_disconnect (oh->timeline, oh->frame_id);
|
||||
clutter_timeline_stop (oh->timeline);
|
||||
|
||||
clutter_main_quit ();
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_paint_wrapper_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterAlpha *alpha;
|
||||
ClutterActor *stage;
|
||||
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
||||
SuperOH *oh;
|
||||
gint i;
|
||||
GError *error;
|
||||
ClutterActor *real_hand;
|
||||
|
||||
error = NULL;
|
||||
|
||||
#ifdef CLUTTER_WINDOWING_X11
|
||||
clutter_x11_set_use_argb_visual (TRUE);
|
||||
#endif
|
||||
|
||||
if (clutter_init_with_args (&argc, &argv,
|
||||
NULL,
|
||||
super_oh_entries,
|
||||
NULL,
|
||||
&error) != CLUTTER_INIT_SUCCESS)
|
||||
{
|
||||
g_warning ("Unable to initialise Clutter:\n%s",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
oh = g_new(SuperOH, 1);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (stage, 800, 600);
|
||||
|
||||
if (use_alpha != 255)
|
||||
{
|
||||
clutter_stage_set_use_alpha (CLUTTER_STAGE (stage), TRUE);
|
||||
clutter_actor_set_opacity (stage, use_alpha);
|
||||
}
|
||||
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Paint Test");
|
||||
clutter_actor_set_background_color (stage, &stage_color);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (stop_and_quit), oh);
|
||||
|
||||
oh->stage = stage;
|
||||
|
||||
/* Create a timeline to manage animation */
|
||||
oh->timeline = clutter_timeline_new (6000);
|
||||
clutter_timeline_set_repeat_count (oh->timeline, -1);
|
||||
|
||||
/* fire a callback for frame change */
|
||||
oh->frame_id =
|
||||
g_signal_connect (oh->timeline, "new-frame", G_CALLBACK (frame_cb), oh);
|
||||
|
||||
/* Set up some behaviours to handle scaling */
|
||||
alpha = clutter_alpha_new_with_func (oh->timeline, my_sine_wave, NULL, NULL);
|
||||
|
||||
oh->scaler_1 = clutter_behaviour_scale_new (alpha, 0.5, 0.5, 1.0, 1.0);
|
||||
oh->scaler_2 = clutter_behaviour_scale_new (alpha, 1.0, 1.0, 0.5, 0.5);
|
||||
|
||||
real_hand = clutter_texture_new_from_file (TESTS_DATADIR
|
||||
G_DIR_SEPARATOR_S
|
||||
"redhand.png",
|
||||
&error);
|
||||
if (real_hand == NULL)
|
||||
{
|
||||
g_error ("image load failed: %s", error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* create a new group to hold multiple actors in a group */
|
||||
oh->group = clutter_group_new();
|
||||
|
||||
oh->hand = g_new (ClutterActor*, n_hands);
|
||||
|
||||
oh->stage_width = clutter_actor_get_width (stage);
|
||||
oh->stage_height = clutter_actor_get_height (stage);
|
||||
oh->radius = (oh->stage_width + oh->stage_height)
|
||||
/ n_hands;
|
||||
|
||||
for (i = 0; i < n_hands; i++)
|
||||
{
|
||||
gint x, y, w, h;
|
||||
|
||||
if (i == 0)
|
||||
oh->hand[i] = real_hand;
|
||||
else
|
||||
oh->hand[i] = clutter_clone_new (real_hand);
|
||||
|
||||
clutter_actor_set_reactive (oh->hand[i], TRUE);
|
||||
|
||||
clutter_actor_set_size (oh->hand[i], 200, 213);
|
||||
|
||||
/* Place around a circle */
|
||||
w = clutter_actor_get_width (oh->hand[i]);
|
||||
h = clutter_actor_get_height (oh->hand[i]);
|
||||
|
||||
x = oh->stage_width / 2
|
||||
+ oh->radius
|
||||
* cos (i * G_PI / (n_hands / 2))
|
||||
- w / 2;
|
||||
|
||||
y = oh->stage_height / 2
|
||||
+ oh->radius
|
||||
* sin (i * G_PI / (n_hands / 2))
|
||||
- h / 2;
|
||||
|
||||
clutter_actor_set_position (oh->hand[i], x, y);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (oh->hand[i],
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
g_signal_connect (oh->hand[i], "button-press-event",
|
||||
G_CALLBACK (on_button_press_event),
|
||||
oh);
|
||||
|
||||
/* paint something before each hand */
|
||||
g_signal_connect (oh->hand[i],
|
||||
"paint", G_CALLBACK (hand_pre_paint),
|
||||
oh);
|
||||
|
||||
/* paint something after each hand */
|
||||
g_signal_connect_after (oh->hand[i],
|
||||
"paint", G_CALLBACK (hand_post_paint),
|
||||
oh);
|
||||
|
||||
/* Add to our group group */
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (oh->group), oh->hand[i]);
|
||||
|
||||
if (i % 2)
|
||||
clutter_behaviour_apply (oh->scaler_1, oh->hand[i]);
|
||||
else
|
||||
clutter_behaviour_apply (oh->scaler_2, oh->hand[i]);
|
||||
}
|
||||
|
||||
oh->paint_guards = g_malloc0 (sizeof (gboolean) * n_hands);
|
||||
|
||||
/* Add the group to the stage */
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage),
|
||||
CLUTTER_ACTOR (oh->group));
|
||||
|
||||
/* Show everying ( and map window ) */
|
||||
clutter_actor_show (stage);
|
||||
|
||||
g_signal_connect (stage, "key-release-event",
|
||||
G_CALLBACK (input_cb),
|
||||
oh);
|
||||
|
||||
/* and start it */
|
||||
clutter_timeline_start (oh->timeline);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_object_unref (oh->scaler_1);
|
||||
g_object_unref (oh->scaler_2);
|
||||
g_object_unref (oh->timeline);
|
||||
g_free (oh->paint_guards);
|
||||
g_free (oh->hand);
|
||||
g_free (oh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_paint_wrapper_describe (void)
|
||||
{
|
||||
return "Wrap an actor's paint cycle for pre and post processing.";
|
||||
}
|
137
src/tests/clutter/interactive/test-path-constraint.c
Normal file
137
src/tests/clutter/interactive/test-path-constraint.c
Normal file
@ -0,0 +1,137 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define PATH_DESCRIPTION \
|
||||
"M 0, 0 " \
|
||||
"L 0, 300 " \
|
||||
"L 300, 300 " \
|
||||
"L 300, 0 " \
|
||||
"L 0, 0"
|
||||
|
||||
static gboolean toggled = FALSE;
|
||||
|
||||
int
|
||||
test_path_constraint_main (int argc,
|
||||
char *argv[]);
|
||||
|
||||
static gboolean
|
||||
on_button_press (ClutterActor *actor,
|
||||
const ClutterEvent *event,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
if (!toggled)
|
||||
clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 500,
|
||||
"@constraints.path.offset", 1.0,
|
||||
NULL);
|
||||
else
|
||||
clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 500,
|
||||
"@constraints.path.offset", 0.0,
|
||||
NULL);
|
||||
|
||||
toggled = !toggled;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
node_to_string (const ClutterPathNode *node)
|
||||
{
|
||||
GString *buffer = g_string_sized_new (256);
|
||||
gsize len = 0, i;
|
||||
|
||||
switch (node->type)
|
||||
{
|
||||
case CLUTTER_PATH_MOVE_TO:
|
||||
g_string_append (buffer, "move-to ");
|
||||
len = 1;
|
||||
break;
|
||||
|
||||
case CLUTTER_PATH_LINE_TO:
|
||||
g_string_append (buffer, "line-to ");
|
||||
len = 1;
|
||||
break;
|
||||
|
||||
case CLUTTER_PATH_CURVE_TO:
|
||||
g_string_append (buffer, "curve-to ");
|
||||
len = 3;
|
||||
break;
|
||||
|
||||
case CLUTTER_PATH_CLOSE:
|
||||
g_string_append (buffer, "close");
|
||||
len = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
g_string_append (buffer, "[ ");
|
||||
|
||||
g_string_append_printf (buffer, "[ %d, %d ]",
|
||||
node->points[i].x,
|
||||
node->points[i].y);
|
||||
|
||||
if (i == len - 1)
|
||||
g_string_append (buffer, " ]");
|
||||
}
|
||||
|
||||
return g_string_free (buffer, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_node_reached (ClutterPathConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
guint index_)
|
||||
{
|
||||
ClutterPath *path = clutter_path_constraint_get_path (constraint);
|
||||
ClutterPathNode node;
|
||||
gchar *str;
|
||||
|
||||
clutter_path_get_node (path, index_, &node);
|
||||
|
||||
str = node_to_string (&node);
|
||||
g_print ("Node %d reached: %s\n", index_, str);
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_path_constraint_main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *rect;
|
||||
ClutterPath *path;
|
||||
ClutterColor rect_color = { 0xcc, 0x00, 0x00, 0xff };
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Path Constraint");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
path = clutter_path_new ();
|
||||
clutter_path_set_description (path, PATH_DESCRIPTION);
|
||||
|
||||
rect = clutter_rectangle_new ();
|
||||
clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color);
|
||||
clutter_actor_set_size (rect, 128, 128);
|
||||
clutter_actor_set_reactive (rect, TRUE);
|
||||
clutter_actor_add_constraint_with_name (rect, "path", clutter_path_constraint_new (path, 0.0));
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
|
||||
|
||||
g_signal_connect (rect, "button-press-event", G_CALLBACK (on_button_press), NULL);
|
||||
g_signal_connect (clutter_actor_get_constraint (rect, "path"),
|
||||
"node-reached",
|
||||
G_CALLBACK (on_node_reached),
|
||||
NULL);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
99
src/tests/clutter/interactive/test-rotate-zoom.c
Normal file
99
src/tests/clutter/interactive/test-rotate-zoom.c
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#define STAGE_WIDTH 800
|
||||
#define STAGE_HEIGHT 550
|
||||
|
||||
int
|
||||
test_rotate_zoom_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_rotate_zoom_describe (void);
|
||||
|
||||
static ClutterActor *
|
||||
create_hand (void)
|
||||
{
|
||||
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png", NULL);
|
||||
ClutterContent *image = clutter_image_new ();
|
||||
ClutterActor *actor = clutter_actor_new ();
|
||||
|
||||
clutter_image_set_data (CLUTTER_IMAGE (image),
|
||||
gdk_pixbuf_get_pixels (pixbuf),
|
||||
gdk_pixbuf_get_has_alpha (pixbuf)
|
||||
? COGL_PIXEL_FORMAT_RGBA_8888
|
||||
: COGL_PIXEL_FORMAT_RGB_888,
|
||||
gdk_pixbuf_get_width (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf),
|
||||
gdk_pixbuf_get_rowstride (pixbuf),
|
||||
NULL);
|
||||
clutter_actor_set_content (actor, image);
|
||||
clutter_actor_set_size (actor,
|
||||
gdk_pixbuf_get_width (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf));
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_rotate_zoom_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *actor;
|
||||
gfloat width, height;
|
||||
|
||||
/* initialize Clutter */
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
/* create a resizable stage */
|
||||
stage = clutter_stage_new ();
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Rotate and Zoom actions");
|
||||
clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT);
|
||||
clutter_actor_set_reactive (stage, FALSE);
|
||||
clutter_actor_show (stage);
|
||||
|
||||
actor = create_hand ();
|
||||
clutter_actor_add_action (actor, clutter_rotate_action_new ());
|
||||
clutter_actor_add_action (actor, clutter_zoom_action_new ());
|
||||
clutter_actor_add_child (stage, actor);
|
||||
|
||||
clutter_actor_get_size (actor, &width, &height);
|
||||
clutter_actor_set_position (actor,
|
||||
STAGE_WIDTH / 2 - width / 2,
|
||||
STAGE_HEIGHT / 2 - height / 2);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_rotate_zoom_describe (void)
|
||||
{
|
||||
return "Rotates and zooms an actor using touch events";
|
||||
}
|
125
src/tests/clutter/interactive/test-scale.c
Normal file
125
src/tests/clutter/interactive/test-scale.c
Normal file
@ -0,0 +1,125 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static const ClutterGravity gravities[] = {
|
||||
CLUTTER_GRAVITY_NORTH_EAST,
|
||||
CLUTTER_GRAVITY_NORTH,
|
||||
CLUTTER_GRAVITY_NORTH_WEST,
|
||||
CLUTTER_GRAVITY_WEST,
|
||||
CLUTTER_GRAVITY_SOUTH_WEST,
|
||||
CLUTTER_GRAVITY_SOUTH,
|
||||
CLUTTER_GRAVITY_SOUTH_EAST,
|
||||
CLUTTER_GRAVITY_EAST,
|
||||
CLUTTER_GRAVITY_CENTER,
|
||||
CLUTTER_GRAVITY_NONE
|
||||
};
|
||||
|
||||
static gint gindex = 0;
|
||||
static ClutterActor *label;
|
||||
|
||||
int
|
||||
test_scale_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_scale_describe (void);
|
||||
|
||||
static void
|
||||
set_next_gravity (ClutterActor *actor)
|
||||
{
|
||||
ClutterGravity gravity = gravities[gindex];
|
||||
GEnumClass *eclass;
|
||||
GEnumValue *evalue;
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor, gravities[gindex]);
|
||||
|
||||
eclass = g_type_class_ref (CLUTTER_TYPE_GRAVITY);
|
||||
evalue = g_enum_get_value (eclass, gravity);
|
||||
clutter_text_set_text (CLUTTER_TEXT (label), evalue->value_nick);
|
||||
g_type_class_unref (eclass);
|
||||
|
||||
if (++gindex >= G_N_ELEMENTS (gravities))
|
||||
gindex = 0;
|
||||
}
|
||||
|
||||
static gdouble
|
||||
my_ramp_func (ClutterAlpha *alpha,
|
||||
gpointer unused)
|
||||
{
|
||||
ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
|
||||
|
||||
return clutter_timeline_get_progress (timeline);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_scale_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *rect;
|
||||
ClutterColor rect_color = { 0xff, 0xff, 0xff, 0x99 };
|
||||
ClutterTimeline *timeline;
|
||||
ClutterAlpha *alpha;
|
||||
ClutterBehaviour *behave;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Scaling");
|
||||
clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black);
|
||||
clutter_actor_set_size (stage, 300, 300);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
rect = clutter_rectangle_new_with_color (&rect_color);
|
||||
clutter_actor_set_size (rect, 100, 100);
|
||||
clutter_actor_set_position (rect, 100, 100);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
|
||||
|
||||
label = clutter_text_new_with_text ("Sans 20px", "");
|
||||
clutter_text_set_color (CLUTTER_TEXT (label), CLUTTER_COLOR_White);
|
||||
clutter_actor_set_position (label,
|
||||
clutter_actor_get_x (rect),
|
||||
clutter_actor_get_y (rect)
|
||||
+ clutter_actor_get_height (rect));
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), label);
|
||||
|
||||
rect_color.alpha = 0xff;
|
||||
rect = clutter_rectangle_new_with_color (&rect_color);
|
||||
clutter_actor_set_position (rect, 100, 100);
|
||||
clutter_actor_set_size (rect, 100, 100);
|
||||
set_next_gravity (rect);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
|
||||
|
||||
timeline = clutter_timeline_new (750);
|
||||
alpha = clutter_alpha_new_with_func (timeline,
|
||||
my_ramp_func,
|
||||
NULL, NULL);
|
||||
|
||||
behave = clutter_behaviour_scale_new (alpha,
|
||||
0.0, 0.0, /* scale start */
|
||||
1.0, 1.0); /* scale end */
|
||||
|
||||
clutter_behaviour_apply (behave, rect);
|
||||
|
||||
clutter_timeline_set_repeat_count (timeline, -1);
|
||||
g_signal_connect_swapped (timeline, "completed",
|
||||
G_CALLBACK (set_next_gravity), rect);
|
||||
clutter_timeline_start (timeline);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main();
|
||||
|
||||
g_object_unref (timeline);
|
||||
g_object_unref (behave);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_scale_describe (void)
|
||||
{
|
||||
return "Scaling animation and scaling center changes";
|
||||
}
|
68
src/tests/clutter/interactive/test-script-signals.json
Normal file
68
src/tests/clutter/interactive/test-script-signals.json
Normal file
@ -0,0 +1,68 @@
|
||||
[
|
||||
{
|
||||
"id" : "button",
|
||||
"type" : "ClutterRectangle",
|
||||
|
||||
"width" : "16 em",
|
||||
"height" : "6 em",
|
||||
|
||||
"color" : "rgb(255, 0, 0)",
|
||||
"opacity" : 128,
|
||||
|
||||
"scale-gravity" : "center",
|
||||
|
||||
"reactive" : true,
|
||||
|
||||
"signals" : [
|
||||
{
|
||||
"name" : "button-press-event",
|
||||
"handler" : "on_button_press"
|
||||
},
|
||||
{ "name" : "enter-event", "states" : "button-states", "target-state" : "hover" },
|
||||
{ "name" : "leave-event", "states" : "button-states", "target-state" : "base" },
|
||||
{ "name" : "button-press-event", "states" : "button-states", "target-state" : "active" },
|
||||
{ "name" : "button-release-event", "states" : "button-states", "target-state" : "hover" }
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"id" : "button-states",
|
||||
"type" : "ClutterState",
|
||||
|
||||
"duration" : 250,
|
||||
|
||||
"transitions" : [
|
||||
{
|
||||
"source" : null,
|
||||
"target" : "base",
|
||||
|
||||
"keys" : [
|
||||
[ "button", "opacity", "linear", 128 ],
|
||||
[ "button", "scale-x", "ease-in-cubic", 1.0 ],
|
||||
[ "button", "scale-y", "ease-in-cubic", 1.0 ],
|
||||
[ "button", "color", "linear", "rgb(255, 0, 0)" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"source" : null,
|
||||
"target" : "hover",
|
||||
|
||||
"keys" : [
|
||||
[ "button", "opacity", "linear", 255 ],
|
||||
[ "button", "scale-x", "ease-out-bounce", 1.4 ],
|
||||
[ "button", "scale-y", "ease-out-bounce", 1.4 ],
|
||||
[ "button", "color", "linear", "rgb(0, 255, 0)" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"source" : null,
|
||||
"target" : "active",
|
||||
|
||||
"keys" : [
|
||||
[ "button", "opacity", "linear", 255 ],
|
||||
[ "button", "color", "linear", "rgb(0, 0, 255)" ]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
188
src/tests/clutter/interactive/test-script.c
Normal file
188
src/tests/clutter/interactive/test-script.c
Normal file
@ -0,0 +1,188 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static ClutterScript *script = NULL;
|
||||
static guint merge_id = 0;
|
||||
|
||||
int
|
||||
test_script_main (int argc, char *argv[]);
|
||||
|
||||
static const gchar *test_unmerge =
|
||||
"["
|
||||
" {"
|
||||
" \"id\" : \"main-stage\","
|
||||
" \"type\" : \"ClutterStage\","
|
||||
" \"children\" : [ \"blue-button\" ]"
|
||||
" },"
|
||||
" {"
|
||||
" \"id\" : \"blue-button\","
|
||||
" \"type\" : \"ClutterRectangle\","
|
||||
" \"color\" : \"#0000ffff\","
|
||||
" \"x\" : 350,"
|
||||
" \"y\" : 50,"
|
||||
" \"width\" : 100,"
|
||||
" \"height\" : 100,"
|
||||
" \"visible\" : true,"
|
||||
" \"reactive\" : true"
|
||||
" }"
|
||||
"]";
|
||||
|
||||
static const gchar *test_behaviour =
|
||||
"["
|
||||
" {"
|
||||
" \"id\" : \"main-timeline\","
|
||||
" \"type\" : \"ClutterTimeline\","
|
||||
" \"duration\" : 5000,"
|
||||
" \"loop\" : true"
|
||||
" },"
|
||||
" {"
|
||||
" \"id\" : \"sine-alpha\","
|
||||
" \"type\" : \"ClutterAlpha\","
|
||||
" \"function\" : \"sine_alpha\","
|
||||
" \"timeline\" : \"main-timeline\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\" : \"path-behaviour\","
|
||||
" \"type\" : \"ClutterBehaviourPath\","
|
||||
" \"path\" : \"M 50 50 L 100 100\","
|
||||
" \"alpha\" : {"
|
||||
" \"timeline\" : \"main-timeline\","
|
||||
" \"function\" : \"double_ramp_alpha\""
|
||||
" }"
|
||||
" },"
|
||||
" {"
|
||||
" \"id\" : \"rotate-behaviour\","
|
||||
" \"type\" : \"ClutterBehaviourRotate\","
|
||||
" \"angle-start\" : 0.0,"
|
||||
" \"angle-end\" : 360.0,"
|
||||
" \"axis\" : \"y-axis\","
|
||||
" \"alpha\" : \"sine-alpha\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\" : \"fade-behaviour\","
|
||||
" \"type\" : \"ClutterBehaviourOpacity\","
|
||||
" \"opacity-start\" : 255,"
|
||||
" \"opacity-end\" : 0,"
|
||||
" \"alpha\" : {"
|
||||
" \"id\" : \"fade-alpha\","
|
||||
" \"type\" : \"ClutterAlpha\","
|
||||
" \"timeline\" : \"main-timeline\","
|
||||
" \"mode\" : \"linear\""
|
||||
" }"
|
||||
" }"
|
||||
"]";
|
||||
|
||||
static gboolean
|
||||
blue_button_press (ClutterActor *actor,
|
||||
ClutterButtonEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
g_print ("[*] Pressed '%s'\n", clutter_get_script_id (G_OBJECT (actor)));
|
||||
g_print ("[*] Unmerging objects with merge id: %d\n", merge_id);
|
||||
|
||||
clutter_script_unmerge_objects (script, merge_id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
red_button_press (ClutterActor *actor,
|
||||
ClutterButtonEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
GObject *timeline;
|
||||
|
||||
g_print ("[*] Pressed '%s'\n", clutter_get_script_id (G_OBJECT (actor)));
|
||||
|
||||
timeline = clutter_script_get_object (script, "main-timeline");
|
||||
g_assert (CLUTTER_IS_TIMELINE (timeline));
|
||||
|
||||
if (!clutter_timeline_is_playing (CLUTTER_TIMELINE (timeline)))
|
||||
clutter_timeline_start (CLUTTER_TIMELINE (timeline));
|
||||
else
|
||||
clutter_timeline_pause (CLUTTER_TIMELINE (timeline));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_script_main (int argc, char *argv[])
|
||||
{
|
||||
GObject *stage, *blue_button, *red_button;
|
||||
GError *error = NULL;
|
||||
gchar *file;
|
||||
gint res;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
script = clutter_script_new ();
|
||||
g_assert (CLUTTER_IS_SCRIPT (script));
|
||||
|
||||
clutter_script_load_from_data (script, test_behaviour, -1, &error);
|
||||
if (error)
|
||||
{
|
||||
g_print ("*** Error:\n"
|
||||
"*** %s\n", error->message);
|
||||
g_error_free (error);
|
||||
g_object_unref (script);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
file = g_build_filename (TESTS_DATADIR, "test-script.json", NULL);
|
||||
clutter_script_load_from_file (script, file, &error);
|
||||
if (error)
|
||||
{
|
||||
g_print ("*** Error:\n"
|
||||
"*** %s\n", error->message);
|
||||
g_error_free (error);
|
||||
g_object_unref (script);
|
||||
g_free (file);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
g_free (file);
|
||||
|
||||
merge_id = clutter_script_load_from_data (script, test_unmerge, -1, &error);
|
||||
if (error)
|
||||
{
|
||||
g_print ("*** Error:\n"
|
||||
"*** %s\n", error->message);
|
||||
g_error_free (error);
|
||||
g_object_unref (script);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
clutter_script_connect_signals (script, NULL);
|
||||
|
||||
res = clutter_script_get_objects (script,
|
||||
"main-stage", &stage,
|
||||
"red-button", &red_button,
|
||||
"blue-button", &blue_button,
|
||||
NULL);
|
||||
g_assert (res == 3);
|
||||
|
||||
clutter_actor_show (CLUTTER_ACTOR (stage));
|
||||
|
||||
g_signal_connect (red_button,
|
||||
"button-press-event",
|
||||
G_CALLBACK (red_button_press),
|
||||
NULL);
|
||||
|
||||
g_signal_connect (blue_button,
|
||||
"button-press-event",
|
||||
G_CALLBACK (blue_button_press),
|
||||
NULL);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_object_unref (script);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
74
src/tests/clutter/interactive/test-script.json
Normal file
74
src/tests/clutter/interactive/test-script.json
Normal file
@ -0,0 +1,74 @@
|
||||
{
|
||||
"My Scene" : {
|
||||
"id" : "main-stage",
|
||||
"type" : "ClutterStage",
|
||||
"title" : { "translatable" : true, "string" : "ClutterScript test" },
|
||||
"color" : "white",
|
||||
"signals" : [
|
||||
{ "name" : "key-press-event", "handler" : "clutter_main_quit" },
|
||||
{ "name" : "destroy", "handler" : "clutter_main_quit" }
|
||||
],
|
||||
"children" : [
|
||||
{
|
||||
"id" : "red-button",
|
||||
"type" : "ClutterRectangle",
|
||||
"color" : "#ff0000ff",
|
||||
"x" : 50, "y" : 50, "width" : 100, "height" : 100,
|
||||
"reactive" : true,
|
||||
"rotation" : [
|
||||
{ "z-axis" : [ 45.0, [ 75, 75 ] ] }
|
||||
],
|
||||
"behaviours" : [ "fade-behaviour", "path-behaviour" ]
|
||||
},
|
||||
{
|
||||
"id" : "green-button",
|
||||
"type" : "ClutterRectangle",
|
||||
"color" : "#00ff00ff",
|
||||
"border-width" : 5,
|
||||
"border-color" : "#00cc00ff",
|
||||
"position" : [ 200.0, 50.0 ],
|
||||
"size" : { "width" : 100.0, "height" : 100.0 },
|
||||
"depth" : -200.0,
|
||||
"reactive" : true,
|
||||
"signals" : [
|
||||
{ "name" : "button-press-event", "handler" : "clutter_main_quit" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "red-hand",
|
||||
"type" : "ClutterTexture",
|
||||
"filename" : "redhand.png",
|
||||
"position" : { "x" : 100.0, "y" : 100.0 },
|
||||
"width" : "20 mm",
|
||||
"keep-aspect-ratio" : true,
|
||||
"anchor-x" : "5 em",
|
||||
"anchor-y" : "5 pt",
|
||||
"opacity" : 100,
|
||||
"behaviours" : [ "rotate-behaviour", "fade-behaviour" ]
|
||||
},
|
||||
{
|
||||
"id" : "red-hand-clone",
|
||||
"type" : "ClutterClone",
|
||||
"source" : "red-hand",
|
||||
"position" : [ 250.0, 150.0 ],
|
||||
"opacity" : 100
|
||||
},
|
||||
{
|
||||
"id" : "label",
|
||||
"type" : "ClutterText",
|
||||
"x" : 50,
|
||||
"y" : 200,
|
||||
"text" : { "translatable" : true, "string" : "Clutter Script" },
|
||||
"font-name" : "Sans 24px",
|
||||
"color" : "black",
|
||||
"line-alignment" : "center",
|
||||
"line-wrap" : false,
|
||||
"ellipsize" : "none",
|
||||
"rotation" : [
|
||||
{ "y-axis" : [ 60.0, [ 275, 100 ] ] },
|
||||
{ "z-axis" : [ 45.0, [ 75, 75 ] ] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
137
src/tests/clutter/interactive/test-scrolling.c
Normal file
137
src/tests/clutter/interactive/test-scrolling.c
Normal file
@ -0,0 +1,137 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define RECT_WIDTH 400
|
||||
#define RECT_HEIGHT 300
|
||||
#define N_RECTS 7
|
||||
|
||||
static const gchar *rect_color[N_RECTS] = {
|
||||
"#edd400",
|
||||
"#f57900",
|
||||
"#c17d11",
|
||||
"#73d216",
|
||||
"#3465a4",
|
||||
"#75507b",
|
||||
"#cc0000"
|
||||
};
|
||||
|
||||
static ClutterActor *rectangle[N_RECTS];
|
||||
static ClutterActor *viewport = NULL;
|
||||
|
||||
int
|
||||
test_scrolling_main (int argc, char *argv[]);
|
||||
|
||||
static void
|
||||
on_drag_end (ClutterDragAction *action,
|
||||
ClutterActor *actor,
|
||||
gfloat event_x,
|
||||
gfloat event_y,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
gfloat viewport_x = clutter_actor_get_x (viewport);
|
||||
gfloat offset_x;
|
||||
gint child_visible;
|
||||
|
||||
/* check if we're at the viewport edges */
|
||||
if (viewport_x > 0)
|
||||
{
|
||||
clutter_actor_save_easing_state (viewport);
|
||||
clutter_actor_set_easing_mode (viewport, CLUTTER_EASE_OUT_BOUNCE);
|
||||
clutter_actor_set_x (viewport, 0);
|
||||
clutter_actor_restore_easing_state (viewport);
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewport_x < (-1.0f * (RECT_WIDTH * (N_RECTS - 1))))
|
||||
{
|
||||
clutter_actor_save_easing_state (viewport);
|
||||
clutter_actor_set_easing_mode (viewport, CLUTTER_EASE_OUT_BOUNCE);
|
||||
clutter_actor_set_x (viewport, -1.0f * (RECT_WIDTH * (N_RECTS - 1)));
|
||||
clutter_actor_restore_easing_state (viewport);
|
||||
return;
|
||||
}
|
||||
|
||||
/* animate the viewport to fully show the child once we pass
|
||||
* a certain threshold with the dragging action
|
||||
*/
|
||||
offset_x = fabsf (viewport_x) / RECT_WIDTH + 0.5f;
|
||||
if (offset_x > (RECT_WIDTH * 0.33))
|
||||
child_visible = (int) offset_x + 1;
|
||||
else
|
||||
child_visible = (int) offset_x;
|
||||
|
||||
/* sanity check on the children number */
|
||||
child_visible = CLAMP (child_visible, 0, N_RECTS);
|
||||
|
||||
clutter_actor_save_easing_state (viewport);
|
||||
clutter_actor_set_x (viewport, -1.0f * RECT_WIDTH * child_visible);
|
||||
clutter_actor_restore_easing_state (viewport);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_scrolling_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *scroll;
|
||||
ClutterAction *action;
|
||||
gint i;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Scrolling");
|
||||
clutter_actor_set_size (stage, 800, 600);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* scroll: the group that contains the scrolling viewport; we set its
|
||||
* size to be the same as one rectangle, position it in the middle of
|
||||
* the stage and set it to clip its contents to the allocated size
|
||||
*/
|
||||
scroll = clutter_actor_new ();
|
||||
clutter_actor_add_child (stage, scroll);
|
||||
clutter_actor_set_size (scroll, RECT_WIDTH, RECT_HEIGHT);
|
||||
clutter_actor_add_constraint (scroll, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
|
||||
clutter_actor_set_clip_to_allocation (scroll, TRUE);
|
||||
|
||||
/* viewport: the actual container for the children; we scroll it using
|
||||
* the Drag action constrained to the horizontal axis, and every time
|
||||
* the dragging ends we check whether we're dragging past the end of
|
||||
* the viewport
|
||||
*/
|
||||
viewport = clutter_actor_new ();
|
||||
clutter_actor_set_layout_manager (viewport, clutter_box_layout_new ());
|
||||
clutter_actor_add_child (scroll, viewport);
|
||||
|
||||
/* add dragging capabilities to the viewport; the heavy lifting is
|
||||
* all done by the DragAction itself, plus the ::drag-end signal
|
||||
* handler in our code
|
||||
*/
|
||||
action = clutter_drag_action_new ();
|
||||
clutter_actor_add_action (viewport, action);
|
||||
clutter_drag_action_set_drag_axis (CLUTTER_DRAG_ACTION (action),
|
||||
CLUTTER_DRAG_X_AXIS);
|
||||
g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL);
|
||||
clutter_actor_set_reactive (viewport, TRUE);
|
||||
|
||||
/* children of the viewport */
|
||||
for (i = 0; i < N_RECTS; i++)
|
||||
{
|
||||
ClutterColor color;
|
||||
|
||||
clutter_color_from_string (&color, rect_color[i]);
|
||||
|
||||
rectangle[i] = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (rectangle[i], &color);
|
||||
clutter_actor_add_child (viewport, rectangle[i]);
|
||||
clutter_actor_set_size (rectangle[i], RECT_WIDTH, RECT_HEIGHT);
|
||||
}
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
86
src/tests/clutter/interactive/test-shader-effects.c
Normal file
86
src/tests/clutter/interactive/test-shader-effects.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
int
|
||||
test_shader_effects_main (int argc, char *argv[]);
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_shader_effects_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterTimeline *timeline;
|
||||
ClutterActor *stage, *hand, *label, *rect;
|
||||
gchar *file;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
/* Make a timeline */
|
||||
timeline = clutter_timeline_new (7692);
|
||||
clutter_timeline_set_repeat_count (timeline, -1);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Rotations");
|
||||
clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium3);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* Make a hand */
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
hand = clutter_texture_new_from_file (file, NULL);
|
||||
if (!hand)
|
||||
g_error("Unable to load '%s'", file);
|
||||
|
||||
g_free (file);
|
||||
|
||||
clutter_actor_set_position (hand, 326, 265);
|
||||
clutter_actor_add_effect_with_name (hand, "desaturate", clutter_desaturate_effect_new (0.75));
|
||||
clutter_actor_add_effect_with_name (hand, "blur", clutter_blur_effect_new ());
|
||||
clutter_actor_animate_with_timeline (hand, CLUTTER_LINEAR, timeline,
|
||||
"@effects.desaturate.factor", 1.0,
|
||||
"rotation-angle-z", 360.0,
|
||||
"fixed::anchor-x", 86.0,
|
||||
"fixed::anchor-y", 125.0,
|
||||
"opacity", 128,
|
||||
NULL);
|
||||
|
||||
rect = clutter_rectangle_new_with_color (CLUTTER_COLOR_DarkOrange);
|
||||
clutter_actor_add_effect_with_name (rect, "blur", clutter_blur_effect_new ());
|
||||
clutter_actor_set_position (rect, 415, 215);
|
||||
clutter_actor_set_size (rect, 150, 150);
|
||||
clutter_actor_animate_with_timeline (rect, CLUTTER_LINEAR, timeline,
|
||||
"rotation-angle-z", 360.0,
|
||||
"fixed::anchor-x", 75.0,
|
||||
"fixed::anchor-y", 75.0,
|
||||
NULL);
|
||||
|
||||
label = clutter_text_new_with_text ("Mono 16",
|
||||
"The Wonder\n"
|
||||
"of the\n"
|
||||
"Spinning Hand");
|
||||
clutter_text_set_line_alignment (CLUTTER_TEXT (label), PANGO_ALIGN_CENTER);
|
||||
clutter_actor_set_position (label, 336, 275);
|
||||
clutter_actor_set_size (label, 500, 100);
|
||||
clutter_actor_animate_with_timeline (label, CLUTTER_LINEAR, timeline,
|
||||
"rotation-angle-z", 360.0,
|
||||
"fixed::anchor-x", 86.0,
|
||||
"fixed::anchor-y", 125.0,
|
||||
NULL);
|
||||
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage), rect, hand, label, NULL);
|
||||
|
||||
/* start the timeline and thus the animations */
|
||||
clutter_timeline_start (timeline);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main();
|
||||
|
||||
g_object_unref (timeline);
|
||||
|
||||
return 0;
|
||||
}
|
174
src/tests/clutter/interactive/test-stage-read-pixels.c
Normal file
174
src/tests/clutter/interactive/test-stage-read-pixels.c
Normal file
@ -0,0 +1,174 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
int
|
||||
test_stage_read_pixels_main (int argc, char **argv);
|
||||
|
||||
const char *
|
||||
test_stage_read_pixels_describe (void);
|
||||
|
||||
static ClutterActor *
|
||||
make_label (void)
|
||||
{
|
||||
ClutterActor *label;
|
||||
gchar *text;
|
||||
const char *argv[] = { "ls", "--help", NULL };
|
||||
|
||||
label = clutter_text_new ();
|
||||
clutter_text_set_font_name (CLUTTER_TEXT (label), "Sans 10");
|
||||
|
||||
if (g_spawn_sync (NULL, (char **) 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.";
|
||||
}
|
88
src/tests/clutter/interactive/test-stage-sizing.c
Normal file
88
src/tests/clutter/interactive/test-stage-sizing.c
Normal file
@ -0,0 +1,88 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
int
|
||||
test_stage_sizing_main (int argc, char *argv[]);
|
||||
|
||||
const char *
|
||||
test_stage_sizing_describe (void);
|
||||
|
||||
static gboolean
|
||||
shrink_clicked_cb (ClutterActor *stage)
|
||||
{
|
||||
gfloat width, height;
|
||||
clutter_actor_get_size (stage, &width, &height);
|
||||
clutter_actor_set_size (stage, MAX (0, width - 10.f), MAX (0, height - 10.f));
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
expand_clicked_cb (ClutterActor *stage)
|
||||
{
|
||||
gfloat width, height;
|
||||
clutter_actor_get_size (stage, &width, &height);
|
||||
clutter_actor_set_size (stage, width + 10.f, height + 10.f);
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_stage_sizing_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *rect, *label, *box;
|
||||
ClutterMargin margin = { 12.f, 12.f, 6.f, 6.f };
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Stage Sizing");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
box = clutter_actor_new ();
|
||||
clutter_actor_set_layout_manager (box, clutter_box_layout_new ());
|
||||
clutter_actor_add_constraint (box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
|
||||
clutter_actor_add_child (stage, box);
|
||||
|
||||
rect = clutter_actor_new ();
|
||||
clutter_actor_set_layout_manager (rect,
|
||||
clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER));
|
||||
clutter_actor_set_background_color (rect, CLUTTER_COLOR_SkyBlue);
|
||||
clutter_actor_set_reactive (rect, TRUE);
|
||||
g_signal_connect_swapped (rect, "button-press-event",
|
||||
G_CALLBACK (shrink_clicked_cb), stage);
|
||||
label = clutter_text_new_with_text ("Sans 16", "Shrink");
|
||||
clutter_actor_set_margin (label, &margin);
|
||||
clutter_actor_add_child (rect, label);
|
||||
clutter_actor_add_child (box, rect);
|
||||
|
||||
rect = clutter_actor_new ();
|
||||
clutter_actor_set_layout_manager (rect,
|
||||
clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER));
|
||||
clutter_actor_set_background_color (rect, CLUTTER_COLOR_Butter);
|
||||
clutter_actor_set_reactive (rect, TRUE);
|
||||
g_signal_connect_swapped (rect, "button-press-event",
|
||||
G_CALLBACK (expand_clicked_cb), stage);
|
||||
label = clutter_text_new_with_text ("Sans 16", "Expand");
|
||||
clutter_actor_set_margin (label, &margin);
|
||||
clutter_actor_add_child (rect, label);
|
||||
clutter_actor_add_child (box, rect);
|
||||
|
||||
clutter_stage_set_minimum_size (CLUTTER_STAGE (stage),
|
||||
clutter_actor_get_width (box),
|
||||
clutter_actor_get_height (box));
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_stage_sizing_describe (void)
|
||||
{
|
||||
return "Check stage sizing policies.";
|
||||
}
|
45
src/tests/clutter/interactive/test-state-script.c
Normal file
45
src/tests/clutter/interactive/test-state-script.c
Normal file
@ -0,0 +1,45 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define TEST_STATE_SCRIPT_FILE "test-script-signals.json"
|
||||
|
||||
int
|
||||
test_state_script_main (int argc, char *argv[]);
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_state_script_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *button;
|
||||
ClutterScript *script;
|
||||
GError *error = NULL;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
script = clutter_script_new ();
|
||||
clutter_script_load_from_file (script, TEST_STATE_SCRIPT_FILE, &error);
|
||||
if (error != NULL)
|
||||
g_error ("Unable to load '%s': %s\n",
|
||||
TEST_STATE_SCRIPT_FILE,
|
||||
error->message);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "State Script");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
clutter_actor_show (stage);
|
||||
|
||||
button = CLUTTER_ACTOR (clutter_script_get_object (script, "button"));
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button);
|
||||
clutter_actor_add_constraint (button, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
|
||||
|
||||
clutter_script_connect_signals (script, NULL);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_object_unref (script);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
212
src/tests/clutter/interactive/test-state.c
Normal file
212
src/tests/clutter/interactive/test-state.c
Normal file
@ -0,0 +1,212 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define STAGE_WIDTH 1024
|
||||
#define STAGE_HEIGHT 768
|
||||
|
||||
#define ACTOR_WIDTH 128
|
||||
#define ACTOR_HEIGHT 128
|
||||
|
||||
#define COLS (STAGE_WIDTH/ACTOR_WIDTH)
|
||||
#define ROWS (STAGE_HEIGHT/ACTOR_HEIGHT)
|
||||
#define TOTAL (ROWS*COLS)
|
||||
|
||||
gint
|
||||
test_state_main (gint argc,
|
||||
gchar **argv);
|
||||
|
||||
const char *
|
||||
test_state_describe (void);
|
||||
|
||||
static gboolean press_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterState *state = CLUTTER_STATE (user_data);
|
||||
clutter_state_set_state (state, "right");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean release_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterState *state = CLUTTER_STATE (user_data);
|
||||
clutter_state_set_state (state, "active");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean enter_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterState *state = CLUTTER_STATE (user_data);
|
||||
clutter_state_set_state (state, "hover");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean leave_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterState *state = CLUTTER_STATE (user_data);
|
||||
clutter_state_set_state (state, "normal");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void completed (ClutterState *state,
|
||||
gpointer data)
|
||||
{
|
||||
g_print ("Completed transitioning to state: %s\n",
|
||||
clutter_state_get_state (state));
|
||||
|
||||
if (g_str_equal (clutter_state_get_state (state), "right"))
|
||||
{
|
||||
/* skip straight to left state when reaching right */
|
||||
clutter_state_warp_to_state (state, "left");
|
||||
}
|
||||
}
|
||||
|
||||
static ClutterActor *new_rect (gint r,
|
||||
gint g,
|
||||
gint b,
|
||||
gint a)
|
||||
{
|
||||
GError *error = NULL;
|
||||
ClutterColor *color = clutter_color_new (r, g, b, a);
|
||||
ClutterActor *group = clutter_actor_new ();
|
||||
ClutterActor *rectangle = clutter_actor_new ();
|
||||
ClutterActor *hand = NULL;
|
||||
|
||||
gchar *file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
|
||||
hand = clutter_texture_new_from_file (file, &error);
|
||||
if (rectangle == NULL)
|
||||
g_error ("image load failed: %s", error->message);
|
||||
g_free (file);
|
||||
clutter_actor_set_size (hand, ACTOR_WIDTH,ACTOR_HEIGHT);
|
||||
|
||||
clutter_actor_set_background_color (rectangle, color);
|
||||
clutter_actor_set_size (rectangle, ACTOR_WIDTH,ACTOR_HEIGHT);
|
||||
clutter_color_free (color);
|
||||
|
||||
clutter_actor_add_child (group, rectangle);
|
||||
clutter_actor_add_child (group, hand);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT gint
|
||||
test_state_main (gint argc,
|
||||
gchar **argv)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterState *layout_state;
|
||||
gint i;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
layout_state = clutter_state_new ();
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "State Machine");
|
||||
clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
g_signal_connect (stage, "button-press-event",
|
||||
G_CALLBACK (press_event), layout_state);
|
||||
g_signal_connect (stage, "button-release-event",
|
||||
G_CALLBACK (release_event), layout_state);
|
||||
|
||||
for (i = 0; i < TOTAL; i++)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
ClutterState *a_state;
|
||||
|
||||
int row = i/COLS;
|
||||
int col = i%COLS;
|
||||
|
||||
actor = new_rect (255 * (1.0 * col / COLS), 50,
|
||||
255 * (1.0 * row / ROWS), 255);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
|
||||
clutter_actor_set_position (actor, 320.0, 240.0);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
clutter_actor_add_effect_with_name (actor, "fade",
|
||||
clutter_desaturate_effect_new (0.0));
|
||||
|
||||
|
||||
clutter_state_set (layout_state, NULL, "active",
|
||||
actor, "delayed::x", CLUTTER_LINEAR,
|
||||
ACTOR_WIDTH * 1.0 * ((TOTAL-1-i) % COLS),
|
||||
((row*1.0/ROWS))/2, (1.0-(row*1.0/ROWS))/2,
|
||||
actor, "delayed::y", CLUTTER_LINEAR,
|
||||
ACTOR_HEIGHT * 1.0 * ((TOTAL-1-i) / COLS),
|
||||
((row*1.0/ROWS))/2, 0.0,
|
||||
actor, "rotation-angle-x", CLUTTER_LINEAR, 0.0,
|
||||
actor, "rotation-angle-y", CLUTTER_LINEAR, 0.0,
|
||||
NULL);
|
||||
|
||||
clutter_state_set (layout_state, NULL, "right",
|
||||
actor, "delayed::x", CLUTTER_LINEAR, STAGE_WIDTH * 1.0,
|
||||
((row*1.0/ROWS))/2,
|
||||
(1.0-(row*1.0/ROWS))/2,
|
||||
actor, "delayed::y", CLUTTER_LINEAR, STAGE_HEIGHT * 1.0,
|
||||
((row*1.0/ROWS))/2,
|
||||
0.0,
|
||||
NULL);
|
||||
|
||||
clutter_state_set (layout_state, NULL, "left",
|
||||
actor, "rotation-angle-x", CLUTTER_LINEAR, 45.0,
|
||||
actor, "rotation-angle-y", CLUTTER_LINEAR, 5.0,
|
||||
actor, "x", CLUTTER_LINEAR, 0-64.0,
|
||||
actor, "y", CLUTTER_LINEAR, 0-64.0,
|
||||
NULL);
|
||||
|
||||
a_state = clutter_state_new ();
|
||||
g_object_set_data_full (G_OBJECT (actor), "hover-state-machine",
|
||||
a_state, g_object_unref);
|
||||
g_signal_connect (actor, "enter-event",
|
||||
G_CALLBACK (enter_event), a_state);
|
||||
g_signal_connect (actor, "leave-event",
|
||||
G_CALLBACK (leave_event), a_state);
|
||||
|
||||
clutter_state_set (a_state, NULL, "normal",
|
||||
actor, "opacity", CLUTTER_LINEAR, 0x77,
|
||||
actor, "rotation-angle-z", CLUTTER_LINEAR, 0.0,
|
||||
actor, "@effects.fade.factor", CLUTTER_LINEAR, 0.0,
|
||||
NULL);
|
||||
clutter_state_set (a_state, NULL, "hover",
|
||||
actor, "opacity", CLUTTER_LINEAR, 0xff,
|
||||
actor, "rotation-angle-z", CLUTTER_LINEAR, 10.0,
|
||||
actor, "@effects.fade.factor", CLUTTER_LINEAR, 1.0,
|
||||
NULL);
|
||||
clutter_actor_set_opacity (actor, 0x77);
|
||||
|
||||
clutter_state_set_duration (a_state, NULL, NULL, 500);
|
||||
}
|
||||
|
||||
clutter_state_set_duration (layout_state, NULL, NULL, 1000);
|
||||
clutter_state_set_duration (layout_state, "active", "left", 1400);
|
||||
|
||||
g_signal_connect (layout_state, "completed", G_CALLBACK (completed), NULL);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_state_warp_to_state (layout_state, "left");
|
||||
clutter_state_set_state (layout_state, "active");
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_object_unref (layout_state);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_state_describe (void)
|
||||
{
|
||||
return "Animating using the State class.";
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user