From afa0ebf36bda82182d8b2c9a28fd777927d93374 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 16 Dec 2010 01:21:49 -0500 Subject: [PATCH] Add vfuncs for gdk_test apis --- gdk/gdkdisplay.c | 143 +++++++++++++++++++++++++++++++++++++ gdk/gdkdisplayprivate.h | 3 + gdk/gdkwindow.c | 99 +++++++++++++++++++++++++ gdk/gdkwindowimpl.h | 14 ++++ gdk/x11/gdkdisplay-x11.c | 17 +++++ gdk/x11/gdkmain-x11.c | 143 +------------------------------------ gdk/x11/gdkprivate-x11.h | 14 ++++ gdk/x11/gdktestutils-x11.c | 95 ++++-------------------- gdk/x11/gdkwindow-x11.c | 3 + 9 files changed, 307 insertions(+), 224 deletions(-) diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index 06b4f5642d..335f7d98dc 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -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. + * +* + * Trapping an X error + * + * gdk_error_trap_push (); + * + * // ... Call the X function which may cause an error here ... + * + * + * if (gdk_error_trap_pop ()) + * { + * // ... Handle the error here ... + * } + * + * + */ +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); +} diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index 2d5630a814..f3e48fb56b 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -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, diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index b0b1fc0aeb..d949e8ba1b 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -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); +} diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h index fe50b7a5ca..0b7695e692 100644 --- a/gdk/gdkwindowimpl.h +++ b/gdk/gdkwindowimpl.h @@ -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 */ diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 3f585623f6..f24614a516 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -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; } diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c index b3de1684ab..f629da16d5 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -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. - * - * - * Trapping an X error - * - * gdk_error_trap_push (); - * - * // ... Call the X function which may cause an error here ... - * - * - * if (gdk_error_trap_pop ()) - * { - * // ... Handle the error here ... - * } - * - * - * - */ -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, diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index ed9513955f..67e23a1e86 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -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, diff --git a/gdk/x11/gdktestutils-x11.c b/gdk/x11/gdktestutils-x11.c index 0068bbea60..7b5916f7ec 100644 --- a/gdk/x11/gdktestutils-x11.c +++ b/gdk/x11/gdktestutils-x11.c @@ -27,19 +27,8 @@ #include -/** - * 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 = { diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 98eabe0d11..07746d0112 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -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; }