Add vfuncs for gdk_test apis

This commit is contained in:
Matthias Clasen 2010-12-16 01:21:49 -05:00
parent 28abd0c75f
commit afa0ebf36b
9 changed files with 307 additions and 224 deletions

View File

@ -2551,3 +2551,146 @@ gdk_keymap_get_for_display (GdkDisplay *display)
{
return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
}
typedef struct _GdkGlobalErrorTrap GdkGlobalErrorTrap;
struct _GdkGlobalErrorTrap
{
GSList *displays;
};
static GQueue gdk_error_traps = G_QUEUE_INIT;
/**
* gdk_error_trap_push:
*
* This function allows X errors to be trapped instead of the normal
* behavior of exiting the application. It should only be used if it
* is not possible to avoid the X error in any other way. Errors are
* ignored on all #GdkDisplay currently known to the
* #GdkDisplayManager. If you don't care which error happens and just
* want to ignore everything, pop with gdk_error_trap_pop_ignored().
* If you need the error code, use gdk_error_trap_pop() which may have
* to block and wait for the error to arrive from the X server.
*
* This API exists on all platforms but only does anything on X.
*
* You can use gdk_x11_display_error_trap_push() to ignore errors
* on only a single display.
*
* <example>
* <title>Trapping an X error</title>
* <programlisting>
* gdk_error_trap_push (<!-- -->);
*
* // ... Call the X function which may cause an error here ...
*
*
* if (gdk_error_trap_pop (<!-- -->))
* {
* // ... Handle the error here ...
* }
* </programlisting>
* </example>
*/
void
gdk_error_trap_push (void)
{
GdkDisplayManager *manager;
GdkDisplayClass *class;
GdkGlobalErrorTrap *trap;
GSList *l;
manager = gdk_display_manager_get ();
class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager));
if (class->push_error_trap == NULL)
return;
trap = g_slice_new (GdkGlobalErrorTrap);
trap->displays = gdk_display_manager_list_displays (manager);
g_slist_foreach (trap->displays, (GFunc) g_object_ref, NULL);
for (l = trap->displays; l != NULL; l = l->next)
{
class->push_error_trap (l->data);
}
g_queue_push_head (&gdk_error_traps, trap);
}
static gint
gdk_error_trap_pop_internal (gboolean need_code)
{
GdkDisplayManager *manager;
GdkDisplayClass *class;
GdkGlobalErrorTrap *trap;
gint result;
GSList *l;
manager = gdk_display_manager_get ();
class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager));
if (class->pop_error_trap == NULL)
return 0;
trap = g_queue_pop_head (&gdk_error_traps);
g_return_val_if_fail (trap != NULL, 0);
result = 0;
for (l = trap->displays; l != NULL; l = l->next)
{
gint code = 0;
code = class->pop_error_trap (l->data, !need_code);
/* we use the error on the last display listed, why not. */
if (code != 0)
result = code;
}
g_slist_free_full (trap->displays, g_object_unref);
g_slice_free (GdkGlobalErrorTrap, trap);
return result;
}
/**
* gdk_error_trap_pop_ignored:
*
* Removes an error trap pushed with gdk_error_trap_push(), but
* without bothering to wait and see whether an error occurred. If an
* error arrives later asynchronously that was triggered while the
* trap was pushed, that error will be ignored.
*
* Since: 3.0
*/
void
gdk_error_trap_pop_ignored (void)
{
gdk_error_trap_pop_internal (FALSE);
}
/**
* gdk_error_trap_pop:
*
* Removes an error trap pushed with gdk_error_trap_push().
* May block until an error has been definitively received
* or not received from the X server. gdk_error_trap_pop_ignored()
* is preferred if you don't need to know whether an error
* occurred, because it never has to block. If you don't
* need the return value of gdk_error_trap_pop(), use
* gdk_error_trap_pop_ignored().
*
* Prior to GDK 3.0, this function would not automatically
* sync for you, so you had to gdk_flush() if your last
* call to Xlib was not a blocking round trip.
*
* Return value: X error code or 0 on success
*/
gint
gdk_error_trap_pop (void)
{
return gdk_error_trap_pop_internal (TRUE);
}

View File

@ -192,6 +192,9 @@ struct _GdkDisplayClass
gint attributes_mask);
GdkKeymap * (*get_keymap) (GdkDisplay *display);
void (*push_error_trap) (GdkDisplay *display);
gint (*pop_error_trap) (GdkDisplay *display,
gboolean ignore);
/* Signals */
void (*closed) (GdkDisplay *display,

View File

@ -10714,3 +10714,102 @@ gdk_drag_begin_for_device (GdkWindow *window,
{
return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->drag_begin (window, device, targets);
}
/**
* gdk_test_render_sync:
* @window: a mapped #GdkWindow
*
* This function retrieves a pixel from @window to force the windowing
* system to carry out any pending rendering commands.
* This function is intended to be used to syncronize with rendering
* pipelines, to benchmark windowing system rendering operations.
*
* Since: 2.14
**/
void
gdk_test_render_sync (GdkWindow *window)
{
return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->sync_rendering (window);
}
/**
* gdk_test_simulate_key
* @window: a #GdkWindow to simulate a key event for.
* @x: x coordinate within @window for the key event.
* @y: y coordinate within @window for the key event.
* @keyval: A GDK keyboard value.
* @modifiers: Keyboard modifiers the event is setup with.
* @key_pressrelease: either %GDK_KEY_PRESS or %GDK_KEY_RELEASE
*
* This function is intended to be used in GTK+ test programs.
* If (@x,@y) are > (-1,-1), it will warp the mouse pointer to
* the given (@x,@y) corrdinates within @window and simulate a
* key press or release event.
*
* When the mouse pointer is warped to the target location, use
* of this function outside of test programs that run in their
* own virtual windowing system (e.g. Xvfb) is not recommended.
* If (@x,@y) are passed as (-1,-1), the mouse pointer will not
* be warped and @window origin will be used as mouse pointer
* location for the event.
*
* Also, gtk_test_simulate_key() is a fairly low level function,
* for most testing purposes, gtk_test_widget_send_key() is the
* right function to call which will generate a key press event
* followed by its accompanying key release event.
*
* Returns: whether all actions neccessary for a key event simulation
* were carried out successfully.
*
* Since: 2.14
*/
gboolean
gdk_test_simulate_key (GdkWindow *window,
gint x,
gint y,
guint keyval,
GdkModifierType modifiers,
GdkEventType key_pressrelease)
{
return GDK_WINDOW_IMPL_GET_CLASS (window->impl)
->simulate_key (window, x, y, keyval, modifiers, key_pressrelease);
}
/**
* gdk_test_simulate_button
* @window: a #GdkWindow to simulate a button event for.
* @x: x coordinate within @window for the button event.
* @y: y coordinate within @window for the button event.
* @button: Number of the pointer button for the event, usually 1, 2 or 3.
* @modifiers: Keyboard modifiers the event is setup with.
* @button_pressrelease: either %GDK_BUTTON_PRESS or %GDK_BUTTON_RELEASE
*
* This function is intended to be used in GTK+ test programs.
* It will warp the mouse pointer to the given (@x,@y) corrdinates
* within @window and simulate a button press or release event.
* Because the mouse pointer needs to be warped to the target
* location, use of this function outside of test programs that
* run in their own virtual windowing system (e.g. Xvfb) is not
* recommended.
*
* Also, gtk_test_simulate_button() is a fairly low level function,
* for most testing purposes, gtk_test_widget_click() is the right
* function to call which will generate a button press event followed
* by its accompanying button release event.
*
* Returns: whether all actions neccessary for a button event simulation
* were carried out successfully.
*
* Since: 2.14
**/
gboolean
gdk_test_simulate_button (GdkWindow *window,
gint x,
gint y,
guint button, /*1..3*/
GdkModifierType modifiers,
GdkEventType button_pressrelease)
{
return GDK_WINDOW_IMPL_GET_CLASS (window->impl)
->simulate_button (window, x, y, button, modifiers, button_pressrelease);
}

View File

@ -254,6 +254,20 @@ struct _GdkWindowImplClass
void (*process_updates_recurse) (GdkWindow *window,
cairo_region_t *region);
void (*sync_rendering) (GdkWindow *window);
gboolean (*simulate_key) (GdkWindow *window,
gint x,
gint y,
guint keyval,
GdkModifierType modifiers,
GdkEventType event_type);
gboolean (*simulate_button) (GdkWindow *window,
gint x,
gint y,
guint button,
GdkModifierType modifiers,
GdkEventType event_type);
};
/* Interface Functions */

View File

@ -2681,6 +2681,21 @@ gdk_x11_display_event_data_free (GdkDisplay *display,
{
}
static gint
pop_error_trap (GdkDisplay *display,
gboolean ignored)
{
if (ignored)
{
gdk_x11_display_error_trap_pop_ignored (display);
return Success;
}
else
{
return gdk_x11_display_error_trap_pop (display);
}
}
static GdkKeymap *
gdk_x11_display_get_keymap (GdkDisplay *display)
{
@ -2743,4 +2758,6 @@ _gdk_display_x11_class_init (GdkDisplayX11Class * class)
display_class->event_data_free = gdk_x11_display_event_data_free;
display_class->create_window_impl = _gdk_x11_display_create_window_impl;
display_class->get_keymap = gdk_x11_display_get_keymap;
display_class->push_error_trap = gdk_x11_display_error_trap_push;
display_class->pop_error_trap = pop_error_trap;
}

View File

@ -49,7 +49,6 @@
#endif
typedef struct _GdkPredicate GdkPredicate;
typedef struct _GdkGlobalErrorTrap GdkGlobalErrorTrap;
struct _GdkPredicate
{
@ -63,12 +62,7 @@ static GdkXErrorHandler _gdk_old_error_handler;
/* number of times we've pushed the GDK error handler */
static int _gdk_error_handler_push_count = 0;
struct _GdkGlobalErrorTrap
{
GSList *displays;
};
/*
/*
* Private function declarations
*/
@ -83,16 +77,11 @@ static int gdk_x_error (Display *display,
XErrorEvent *error);
static int gdk_x_io_error (Display *display);
/* Private variable declarations
*/
static GQueue gdk_error_traps;
void
_gdk_x11_windowing_init (void)
{
_gdk_x11_initialize_locale ();
g_queue_init (&gdk_error_traps);
XSetErrorHandler (gdk_x_error);
XSetIOErrorHandler (gdk_x_io_error);
}
@ -322,136 +311,6 @@ _gdk_x11_error_handler_pop (void)
}
}
/**
* gdk_error_trap_push:
*
* This function allows X errors to be trapped instead of the normal
* behavior of exiting the application. It should only be used if it
* is not possible to avoid the X error in any other way. Errors are
* ignored on all #GdkDisplay currently known to the
* #GdkDisplayManager. If you don't care which error happens and just
* want to ignore everything, pop with gdk_error_trap_pop_ignored().
* If you need the error code, use gdk_error_trap_pop() which may have
* to block and wait for the error to arrive from the X server.
*
* This API exists on all platforms but only does anything on X.
*
* You can use gdk_x11_display_error_trap_push() to ignore errors
* on only a single display.
*
* <example>
* <title>Trapping an X error</title>
* <programlisting>
* gdk_error_trap_push (<!-- -->);
*
* // ... Call the X function which may cause an error here ...
*
*
* if (gdk_error_trap_pop (<!-- -->))
* {
* // ... Handle the error here ...
* }
* </programlisting>
* </example>
*
*/
void
gdk_error_trap_push (void)
{
GdkGlobalErrorTrap *trap;
GdkDisplayManager *manager;
GSList *tmp_list;
trap = g_slice_new (GdkGlobalErrorTrap);
manager = gdk_display_manager_get ();
trap->displays = gdk_display_manager_list_displays (manager);
g_slist_foreach (trap->displays, (GFunc) g_object_ref, NULL);
for (tmp_list = trap->displays;
tmp_list != NULL;
tmp_list = tmp_list->next)
{
gdk_x11_display_error_trap_push (tmp_list->data);
}
g_queue_push_head (&gdk_error_traps, trap);
}
static gint
gdk_error_trap_pop_internal (gboolean need_code)
{
GdkGlobalErrorTrap *trap;
gint result;
GSList *tmp_list;
trap = g_queue_pop_head (&gdk_error_traps);
g_return_val_if_fail (trap != NULL, Success);
result = Success;
for (tmp_list = trap->displays;
tmp_list != NULL;
tmp_list = tmp_list->next)
{
gint code = Success;
if (need_code)
code = gdk_x11_display_error_trap_pop (tmp_list->data);
else
gdk_x11_display_error_trap_pop_ignored (tmp_list->data);
/* we use the error on the last display listed, why not. */
if (code != Success)
result = code;
}
g_slist_foreach (trap->displays, (GFunc) g_object_unref, NULL);
g_slist_free (trap->displays);
g_slice_free (GdkGlobalErrorTrap, trap);
return result;
}
/**
* gdk_error_trap_pop_ignored:
*
* Removes an error trap pushed with gdk_error_trap_push(), but
* without bothering to wait and see whether an error occurred. If an
* error arrives later asynchronously that was triggered while the
* trap was pushed, that error will be ignored.
*
* Since: 3.0
*/
void
gdk_error_trap_pop_ignored (void)
{
gdk_error_trap_pop_internal (FALSE);
}
/**
* gdk_error_trap_pop:
*
* Removes an error trap pushed with gdk_error_trap_push().
* May block until an error has been definitively received
* or not received from the X server. gdk_error_trap_pop_ignored()
* is preferred if you don't need to know whether an error
* occurred, because it never has to block. If you don't
* need the return value of gdk_error_trap_pop(), use
* gdk_error_trap_pop_ignored().
*
* Prior to GDK 3.0, this function would not automatically
* sync for you, so you had to gdk_flush() if your last
* call to Xlib was not a blocking round trip.
*
* Return value: X error code or 0 on success
*/
gint
gdk_error_trap_pop (void)
{
return gdk_error_trap_pop_internal (TRUE);
}
gint
_gdk_x11_display_send_xevent (GdkDisplay *display,
Window window,

View File

@ -99,6 +99,20 @@ void _gdk_x11_window_process_expose (GdkWindow *window,
gulong serial,
GdkRectangle *area);
void _gdk_x11_window_sync_rendering (GdkWindow *window);
gboolean _gdk_x11_window_simulate_key (GdkWindow *window,
gint x,
gint y,
guint keyval,
GdkModifierType modifiers,
GdkEventType key_pressrelease);
gboolean _gdk_x11_window_simulate_button (GdkWindow *window,
gint x,
gint y,
guint button,
GdkModifierType modifiers,
GdkEventType button_pressrelease);
gboolean _gdk_x11_window_queue_antiexpose (GdkWindow *window,
cairo_region_t *area);
void _gdk_x11_window_translate (GdkWindow *window,

View File

@ -27,19 +27,8 @@
#include <X11/Xlib.h>
/**
* gdk_test_render_sync:
* @window: a mapped #GdkWindow
*
* This function retrieves a pixel from @window to force the windowing
* system to carry out any pending rendering commands.
* This function is intended to be used to syncronize with rendering
* pipelines, to benchmark windowing system rendering operations.
*
* Since: 2.14
**/
void
gdk_test_render_sync (GdkWindow *window)
_gdk_x11_window_sync_rendering (GdkWindow *window)
{
Display *display = GDK_WINDOW_XDISPLAY (window);
XImage *ximage;
@ -53,44 +42,13 @@ gdk_test_render_sync (GdkWindow *window)
XDestroyImage (ximage);
}
/**
* gdk_test_simulate_key
* @window: a #GdkWindow to simulate a key event for.
* @x: x coordinate within @window for the key event.
* @y: y coordinate within @window for the key event.
* @keyval: A GDK keyboard value.
* @modifiers: Keyboard modifiers the event is setup with.
* @key_pressrelease: either %GDK_KEY_PRESS or %GDK_KEY_RELEASE
*
* This function is intended to be used in GTK+ test programs.
* If (@x,@y) are > (-1,-1), it will warp the mouse pointer to
* the given (@x,@y) corrdinates within @window and simulate a
* key press or release event.
*
* When the mouse pointer is warped to the target location, use
* of this function outside of test programs that run in their
* own virtual windowing system (e.g. Xvfb) is not recommended.
* If (@x,@y) are passed as (-1,-1), the mouse pointer will not
* be warped and @window origin will be used as mouse pointer
* location for the event.
*
* Also, gtk_test_simulate_key() is a fairly low level function,
* for most testing purposes, gtk_test_widget_send_key() is the
* right function to call which will generate a key press event
* followed by its accompanying key release event.
*
* Returns: whether all actions neccessary for a key event simulation
* were carried out successfully.
*
* Since: 2.14
**/
gboolean
gdk_test_simulate_key (GdkWindow *window,
gint x,
gint y,
guint keyval,
GdkModifierType modifiers,
GdkEventType key_pressrelease)
_gdk_x11_window_simulate_key (GdkWindow *window,
gint x,
gint y,
guint keyval,
GdkModifierType modifiers,
GdkEventType key_pressrelease)
{
GdkScreen *screen;
GdkKeymapKey *keys = NULL;
@ -162,40 +120,13 @@ gdk_test_simulate_key (GdkWindow *window,
return success;
}
/**
* gdk_test_simulate_button
* @window: a #GdkWindow to simulate a button event for.
* @x: x coordinate within @window for the button event.
* @y: y coordinate within @window for the button event.
* @button: Number of the pointer button for the event, usually 1, 2 or 3.
* @modifiers: Keyboard modifiers the event is setup with.
* @button_pressrelease: either %GDK_BUTTON_PRESS or %GDK_BUTTON_RELEASE
*
* This function is intended to be used in GTK+ test programs.
* It will warp the mouse pointer to the given (@x,@y) corrdinates
* within @window and simulate a button press or release event.
* Because the mouse pointer needs to be warped to the target
* location, use of this function outside of test programs that
* run in their own virtual windowing system (e.g. Xvfb) is not
* recommended.
*
* Also, gtk_test_simulate_button() is a fairly low level function,
* for most testing purposes, gtk_test_widget_click() is the right
* function to call which will generate a button press event followed
* by its accompanying button release event.
*
* Returns: whether all actions neccessary for a button event simulation
* were carried out successfully.
*
* Since: 2.14
**/
gboolean
gdk_test_simulate_button (GdkWindow *window,
gint x,
gint y,
guint button, /*1..3*/
GdkModifierType modifiers,
GdkEventType button_pressrelease)
_gdk_x11_window_simulate_button (GdkWindow *window,
gint x,
gint y,
guint button, /*1..3*/
GdkModifierType modifiers,
GdkEventType button_pressrelease)
{
GdkScreen *screen;
XButtonEvent xev = {

View File

@ -4759,4 +4759,7 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
impl_class->register_dnd = _gdk_x11_window_register_dnd;
impl_class->drag_begin = _gdk_x11_window_drag_begin;
impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
impl_class->simulate_key = _gdk_x11_window_simulate_key;
impl_class->simulate_button = _gdk_x11_window_simulate_button;
}