mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 20:32:16 +00:00
c4e6f74f29
Even if the test has been successfully compiled against the X11 backend, we need to ensure that it is actually running against it, otherwise bad things will happen.
319 lines
8.8 KiB
C
319 lines
8.8 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <gmodule.h>
|
|
|
|
#include <cairo.h>
|
|
|
|
#ifdef CAIRO_HAS_XLIB_SURFACE
|
|
#include <cairo-xlib.h>
|
|
#endif
|
|
|
|
#undef CLUTTER_DISABLE_DEPRECATED
|
|
#include <clutter/clutter.h>
|
|
|
|
#ifdef CLUTTER_WINDOWING_X11
|
|
#include <X11/Xlib.h>
|
|
#include <X11/extensions/Xcomposite.h>
|
|
|
|
#include <clutter/x11/clutter-x11.h>
|
|
#include <clutter/x11/clutter-x11-texture-pixmap.h>
|
|
#endif
|
|
|
|
#define IMAGE TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png"
|
|
|
|
static gboolean disable_x11 = FALSE;
|
|
static gboolean disable_animation = FALSE;
|
|
|
|
static GOptionEntry g_options[] =
|
|
{
|
|
{ "disable-x11",
|
|
0, 0,
|
|
G_OPTION_ARG_NONE,
|
|
&disable_x11,
|
|
"Disable redirection through X11 pixmap",
|
|
NULL },
|
|
{ "disable-animation",
|
|
0, 0,
|
|
G_OPTION_ARG_NONE,
|
|
&disable_animation,
|
|
"Disable the animations",
|
|
NULL },
|
|
|
|
{ NULL }
|
|
};
|
|
|
|
static void
|
|
toggle_texture_quality (ClutterActor *actor)
|
|
{
|
|
if (CLUTTER_IS_CONTAINER (actor))
|
|
clutter_container_foreach (CLUTTER_CONTAINER (actor),
|
|
(ClutterCallback) toggle_texture_quality,
|
|
NULL);
|
|
|
|
if (CLUTTER_IS_TEXTURE (actor))
|
|
{
|
|
ClutterTextureQuality quality;
|
|
|
|
quality = clutter_texture_get_filter_quality (CLUTTER_TEXTURE (actor));
|
|
|
|
if (quality == CLUTTER_TEXTURE_QUALITY_HIGH)
|
|
quality = CLUTTER_TEXTURE_QUALITY_MEDIUM;
|
|
else
|
|
quality = CLUTTER_TEXTURE_QUALITY_HIGH;
|
|
|
|
g_print ("switching to quality %s for %p\n",
|
|
quality == CLUTTER_TEXTURE_QUALITY_HIGH
|
|
? "high" : "medium",
|
|
actor);
|
|
|
|
clutter_texture_set_filter_quality (CLUTTER_TEXTURE (actor), quality);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
stage_key_release_cb (ClutterActor *actor,
|
|
ClutterEvent *event,
|
|
gpointer data)
|
|
{
|
|
switch (clutter_event_get_key_symbol (event))
|
|
{
|
|
case CLUTTER_KEY_q:
|
|
case CLUTTER_KEY_Q:
|
|
clutter_main_quit ();
|
|
break;
|
|
|
|
case CLUTTER_KEY_m:
|
|
toggle_texture_quality (actor);
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
draw_arc (Pixmap pixmap)
|
|
{
|
|
Display *dpy = clutter_x11_get_default_display ();
|
|
static GC gc = None;
|
|
static int x = 100, y = 100;
|
|
|
|
if (gc == None)
|
|
{
|
|
XGCValues gc_values = { 0 };
|
|
|
|
gc_values.line_width = 12;
|
|
/* This is an attempt to get a black pixel will full
|
|
opacity. Seemingly the BlackPixel macro and the default GC
|
|
value are a fully transparent color */
|
|
gc_values.foreground = 0xff000000;
|
|
|
|
gc = XCreateGC (dpy,
|
|
pixmap,
|
|
GCLineWidth | GCForeground,
|
|
&gc_values);
|
|
}
|
|
|
|
XDrawArc (dpy, pixmap, gc, x, y, 100, 100, 0, 360 * 64);
|
|
|
|
x -= 5;
|
|
y -= 5;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
stage_button_press_cb (ClutterActor *actor,
|
|
ClutterEvent *event,
|
|
gpointer data)
|
|
{
|
|
draw_arc ((Pixmap)data);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
Pixmap
|
|
create_pixmap (guint *width, guint *height, guint *depth)
|
|
{
|
|
Display *dpy = clutter_x11_get_default_display ();
|
|
cairo_surface_t *image;
|
|
Pixmap pixmap;
|
|
XVisualInfo xvisinfo;
|
|
XVisualInfo *xvisinfos;
|
|
int n;
|
|
cairo_surface_t *xlib_surface;
|
|
cairo_t *cr;
|
|
guint w, h;
|
|
|
|
image = cairo_image_surface_create_from_png (IMAGE);
|
|
if (cairo_surface_status (image) != CAIRO_STATUS_SUCCESS)
|
|
g_error ("Failed to load %s", IMAGE);
|
|
|
|
w = cairo_image_surface_get_width (image);
|
|
h = cairo_image_surface_get_height (image);
|
|
|
|
pixmap = XCreatePixmap (dpy,
|
|
DefaultRootWindow (dpy),
|
|
w, h,
|
|
32);
|
|
|
|
xvisinfo.depth = 32;
|
|
xvisinfos = XGetVisualInfo (dpy, VisualDepthMask, &xvisinfo, &n);
|
|
if (!xvisinfos)
|
|
g_error ("Failed to find a 32bit X Visual");
|
|
|
|
xlib_surface =
|
|
cairo_xlib_surface_create (dpy,
|
|
pixmap,
|
|
xvisinfos->visual,
|
|
w, h);
|
|
XFree (xvisinfos);
|
|
|
|
cr = cairo_create (xlib_surface);
|
|
cairo_set_source_surface (cr, image, 0, 0);
|
|
cairo_paint (cr);
|
|
cairo_surface_destroy (image);
|
|
|
|
if (width)
|
|
*width = w;
|
|
if (height)
|
|
*height = h;
|
|
if (depth)
|
|
*depth = 32;
|
|
|
|
return pixmap;
|
|
}
|
|
|
|
/* each time the timeline animating the label completes, swap the direction */
|
|
static void
|
|
timeline_completed (ClutterTimeline *timeline,
|
|
gpointer user_data)
|
|
{
|
|
clutter_timeline_set_direction (timeline,
|
|
!clutter_timeline_get_direction (timeline));
|
|
clutter_timeline_start (timeline);
|
|
}
|
|
|
|
G_MODULE_EXPORT int
|
|
test_pixmap_main (int argc, char **argv)
|
|
{
|
|
GOptionContext *context;
|
|
Display *xdpy;
|
|
int screen;
|
|
ClutterActor *group = NULL, *label, *stage, *tex;
|
|
Pixmap pixmap;
|
|
const ClutterColor gry = { 0x99, 0x99, 0x99, 0xFF };
|
|
Window win_remote;
|
|
guint w, h, d;
|
|
GC gc;
|
|
ClutterTimeline *timeline;
|
|
ClutterAlpha *alpha;
|
|
ClutterBehaviour *depth_behavior;
|
|
int i;
|
|
int row_height;
|
|
|
|
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
|
return 1;
|
|
|
|
#ifdef CLUTTER_WINDOWING_X11
|
|
if (!clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
|
|
g_error ("test-pixmap requires the X11 Clutter backend.");
|
|
#endif
|
|
|
|
xdpy = clutter_x11_get_default_display ();
|
|
XSynchronize (xdpy, True);
|
|
|
|
context = g_option_context_new (" - test-pixmap options");
|
|
g_option_context_add_main_entries (context, g_options, NULL);
|
|
g_option_context_parse (context, &argc, &argv, NULL);
|
|
|
|
pixmap = create_pixmap (&w, &h, &d);
|
|
|
|
screen = DefaultScreen(xdpy);
|
|
win_remote = XCreateSimpleWindow (xdpy, DefaultRootWindow(xdpy),
|
|
0, 0, 200, 200,
|
|
0,
|
|
WhitePixel(xdpy, screen),
|
|
WhitePixel(xdpy, screen));
|
|
|
|
XMapWindow (xdpy, win_remote);
|
|
|
|
stage = clutter_stage_get_default ();
|
|
clutter_actor_set_position (stage, 0, 150);
|
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &gry);
|
|
|
|
timeline = clutter_timeline_new (5000);
|
|
g_signal_connect (timeline,
|
|
"completed", G_CALLBACK (timeline_completed),
|
|
NULL);
|
|
|
|
alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR);
|
|
depth_behavior = clutter_behaviour_depth_new (alpha, -2500, 400);
|
|
|
|
if (!disable_x11)
|
|
{
|
|
group = clutter_group_new ();
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
|
|
label = clutter_text_new_with_text ("fixed",
|
|
"ClutterX11Texture (Window)");
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (group), label);
|
|
tex = clutter_x11_texture_pixmap_new_with_window (win_remote);
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (group), tex);
|
|
clutter_actor_set_position (tex, 0, 20);
|
|
clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (tex),
|
|
TRUE);
|
|
clutter_texture_set_filter_quality (CLUTTER_TEXTURE (tex),
|
|
CLUTTER_TEXTURE_QUALITY_HIGH);
|
|
clutter_actor_set_position (group, 0, 0);
|
|
if (!disable_animation)
|
|
clutter_behaviour_apply (depth_behavior, group);
|
|
}
|
|
|
|
if (group)
|
|
row_height = clutter_actor_get_height (group);
|
|
else
|
|
row_height = 0;
|
|
|
|
/* NB: We only draw on the window after being redirected, so we dont
|
|
* have to worry about handling expose events... */
|
|
gc = XCreateGC (xdpy, win_remote, 0, NULL);
|
|
XSetForeground (xdpy, gc, BlackPixel (xdpy, screen));
|
|
XSetLineAttributes(xdpy, gc, 5, LineSolid, CapButt, JoinMiter);
|
|
|
|
for (i = 0; i < 10; i++)
|
|
XDrawLine (xdpy, win_remote, gc, 0+i*20, 0, 10+i*20+i, 200);
|
|
|
|
|
|
group = clutter_group_new ();
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
|
|
label = clutter_text_new_with_text ("fixed", "ClutterX11Texture (Pixmap)");
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (group), label);
|
|
tex = clutter_x11_texture_pixmap_new_with_pixmap (pixmap);
|
|
clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (tex),
|
|
TRUE);
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (group), tex);
|
|
clutter_actor_set_position (tex, 0, 20);
|
|
clutter_texture_set_filter_quality (CLUTTER_TEXTURE (tex),
|
|
CLUTTER_TEXTURE_QUALITY_HIGH);
|
|
/* oddly, the actor's size is 0 until it is realized, even though
|
|
pixmap-height is set */
|
|
clutter_actor_set_position (group, 0, row_height);
|
|
if (!disable_animation)
|
|
clutter_behaviour_apply (depth_behavior, group);
|
|
|
|
|
|
g_signal_connect (stage, "key-release-event",
|
|
G_CALLBACK (stage_key_release_cb), (gpointer)pixmap);
|
|
g_signal_connect (stage, "button-press-event",
|
|
G_CALLBACK (stage_button_press_cb), (gpointer)pixmap);
|
|
|
|
clutter_actor_show (stage);
|
|
|
|
if (!disable_animation)
|
|
clutter_timeline_start (timeline);
|
|
|
|
g_timeout_add_seconds (1, (GSourceFunc)draw_arc, GUINT_TO_POINTER (pixmap));
|
|
|
|
clutter_main ();
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|