diff options
Diffstat (limited to '')
-rw-r--r-- | app/tests/test-ui.c | 980 |
1 files changed, 980 insertions, 0 deletions
diff --git a/app/tests/test-ui.c b/app/tests/test-ui.c new file mode 100644 index 0000000..f67dbc2 --- /dev/null +++ b/app/tests/test-ui.c @@ -0,0 +1,980 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 2009 Martin Nordholts <martinn@src.gnome.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <string.h> + +#include <gegl.h> +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> + +#include "libgimpbase/gimpbase.h" +#include "libgimpmath/gimpmath.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "dialogs/dialogs-types.h" + +#include "display/gimpdisplay.h" +#include "display/gimpdisplayshell.h" +#include "display/gimpdisplayshell-scale.h" +#include "display/gimpdisplayshell-transform.h" +#include "display/gimpimagewindow.h" + +#include "widgets/gimpdialogfactory.h" +#include "widgets/gimpdock.h" +#include "widgets/gimpdockable.h" +#include "widgets/gimpdockbook.h" +#include "widgets/gimpdockcontainer.h" +#include "widgets/gimpdocked.h" +#include "widgets/gimpdockwindow.h" +#include "widgets/gimphelp-ids.h" +#include "widgets/gimpsessioninfo.h" +#include "widgets/gimpsessioninfo-aux.h" +#include "widgets/gimpsessionmanaged.h" +#include "widgets/gimptoolbox.h" +#include "widgets/gimptooloptionseditor.h" +#include "widgets/gimpuimanager.h" +#include "widgets/gimpwidgets-utils.h" + +#include "core/gimp.h" +#include "core/gimpchannel.h" +#include "core/gimpcontext.h" +#include "core/gimpimage.h" +#include "core/gimplayer.h" +#include "core/gimplayer-new.h" +#include "core/gimptoolinfo.h" +#include "core/gimptooloptions.h" + +#include "tests.h" + +#include "gimp-app-test-utils.h" + + +#define GIMP_UI_WINDOW_POSITION_EPSILON 30 +#define GIMP_UI_POSITION_EPSILON 1 +#define GIMP_UI_ZOOM_EPSILON 0.01 + +#define ADD_TEST(function) \ + g_test_add_data_func ("/gimp-ui/" #function, gimp, function); + + +/* Put this in the code below when you want the test to pause so you + * can do measurements of widgets on the screen for example + */ +#define GIMP_PAUSE (g_usleep (20 * 1000 * 1000)) + + +typedef gboolean (*GimpUiTestFunc) (GObject *object); + + +static void gimp_ui_synthesize_delete_event (GtkWidget *widget); +static gboolean gimp_ui_synthesize_click (GtkWidget *widget, + gint x, + gint y, + gint button, + GdkModifierType modifiers); +static GtkWidget * gimp_ui_find_window (GimpDialogFactory *dialog_factory, + GimpUiTestFunc predicate); +static gboolean gimp_ui_not_toolbox_window (GObject *object); +static gboolean gimp_ui_multicolumn_not_toolbox_window (GObject *object); +static gboolean gimp_ui_is_gimp_layer_list (GObject *object); +static int gimp_ui_aux_data_eqiuvalent (gconstpointer _a, + gconstpointer _b); +static void gimp_ui_switch_window_mode (Gimp *gimp); + + +/** + * tool_options_editor_updates: + * @data: + * + * Makes sure that the tool options editor is updated when the tool + * changes. + **/ +static void +tool_options_editor_updates (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + GimpDisplay *display = GIMP_DISPLAY (gimp_get_empty_display (gimp)); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell)); + GimpImageWindow *image_window = GIMP_IMAGE_WINDOW (toplevel); + GimpUIManager *ui_manager = gimp_image_window_get_ui_manager (image_window); + GtkWidget *dockable = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (), + gtk_widget_get_screen (toplevel), + gimp_widget_get_monitor (toplevel), + NULL /*ui_manager*/, + "gimp-tool-options", + -1 /*view_size*/, + FALSE /*present*/); + GimpToolOptionsEditor *editor = GIMP_TOOL_OPTIONS_EDITOR (gtk_bin_get_child (GTK_BIN (dockable))); + + /* First select the rect select tool */ + gimp_ui_manager_activate_action (ui_manager, + "tools", + "tools-rect-select"); + g_assert_cmpstr (GIMP_HELP_TOOL_RECT_SELECT, + ==, + gimp_tool_options_editor_get_tool_options (editor)-> + tool_info->help_id); + + /* Change tool and make sure the change is taken into account by the + * tool options editor + */ + gimp_ui_manager_activate_action (ui_manager, + "tools", + "tools-ellipse-select"); + g_assert_cmpstr (GIMP_HELP_TOOL_ELLIPSE_SELECT, + ==, + gimp_tool_options_editor_get_tool_options (editor)-> + tool_info->help_id); +} + +static GtkWidget * +gimp_ui_get_dialog (const gchar *identifier) +{ + GtkWidget *result = NULL; + GList *iter; + + for (iter = gimp_dialog_factory_get_open_dialogs (gimp_dialog_factory_get_singleton ()); + iter; + iter = g_list_next (iter)) + { + GtkWidget *dialog = GTK_WIDGET (iter->data); + GimpDialogFactoryEntry *entry = NULL; + + gimp_dialog_factory_from_widget (dialog, &entry); + + if (strcmp (entry->identifier, identifier) == 0) + { + result = dialog; + break; + } + } + + return result; +} + +static void +automatic_tab_style (gconstpointer data) +{ + GtkWidget *channel_dockable = gimp_ui_get_dialog ("gimp-channel-list"); + GimpDockable *dockable; + GimpUIManager *ui_manager; + g_assert (channel_dockable != NULL); + + dockable = GIMP_DOCKABLE (channel_dockable); + + gimp_test_run_mainloop_until_idle (); + + /* The channel dockable is the only dockable, it has enough space + * for the icon-blurb + */ + g_assert_cmpint (GIMP_TAB_STYLE_ICON_BLURB, + ==, + gimp_dockable_get_actual_tab_style (dockable)); + + /* Add some dockables to the channel dockable dockbook */ + ui_manager = + gimp_dockbook_get_ui_manager (gimp_dockable_get_dockbook (dockable)); + gimp_ui_manager_activate_action (ui_manager, + "dockable", + "dialogs-sample-points"); + gimp_ui_manager_activate_action (ui_manager, + "dockable", + "dialogs-vectors"); + gimp_test_run_mainloop_until_idle (); + + /* Now there is not enough space to have icon-blurb for channel + * dockable, make sure it's just an icon now + */ + g_assert_cmpint (GIMP_TAB_STYLE_ICON, + ==, + gimp_dockable_get_actual_tab_style (dockable)); + + /* Close the two dockables we added */ + gimp_ui_manager_activate_action (ui_manager, + "dockable", + "dockable-close-tab"); + gimp_ui_manager_activate_action (ui_manager, + "dockable", + "dockable-close-tab"); + gimp_test_run_mainloop_until_idle (); + + /* We should now be back on icon-blurb */ + g_assert_cmpint (GIMP_TAB_STYLE_ICON_BLURB, + ==, + gimp_dockable_get_actual_tab_style (dockable)); +} + +static void +create_new_image_via_dialog (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + GimpImage *image; + GimpLayer *layer; + + image = gimp_test_utils_create_image_from_dialog (gimp); + + /* Add a layer to the image to make it more useful in later tests */ + layer = gimp_layer_new (image, + gimp_image_get_width (image), + gimp_image_get_height (image), + gimp_image_get_layer_format (image, TRUE), + "Layer for testing", + GIMP_OPACITY_OPAQUE, + GIMP_LAYER_MODE_NORMAL); + + gimp_image_add_layer (image, layer, + GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE); + gimp_test_run_mainloop_until_idle (); +} + +static void +keyboard_zoom_focus (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + GimpDisplay *display = GIMP_DISPLAY (gimp_get_display_iter (gimp)->data); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GimpImageWindow *window = gimp_display_shell_get_window (shell); + gint image_x; + gint image_y; + gint shell_x_before_zoom; + gint shell_y_before_zoom; + gdouble factor_before_zoom; + gint shell_x_after_zoom; + gint shell_y_after_zoom; + gdouble factor_after_zoom; + + /* We need to use a point that is within the visible (exposed) part + * of the canvas + */ + image_x = 400; + image_y = 50; + + /* Setup zoom focus on the bottom right part of the image. We avoid + * 0,0 because that's essentially a particularly easy special case. + */ + gimp_display_shell_transform_xy (shell, + image_x, + image_y, + &shell_x_before_zoom, + &shell_y_before_zoom); + gimp_display_shell_push_zoom_focus_pointer_pos (shell, + shell_x_before_zoom, + shell_y_before_zoom); + factor_before_zoom = gimp_zoom_model_get_factor (shell->zoom); + + /* Do the zoom */ + gimp_test_utils_synthesize_key_event (GTK_WIDGET (window), GDK_KEY_plus); + gimp_test_run_mainloop_until_idle (); + + /* Make sure the zoom focus point remained fixed */ + gimp_display_shell_transform_xy (shell, + image_x, + image_y, + &shell_x_after_zoom, + &shell_y_after_zoom); + factor_after_zoom = gimp_zoom_model_get_factor (shell->zoom); + + /* First of all make sure a zoom happened at all. If this assert + * fails, it means that the zoom didn't happen. Possible causes: + * + * * gdk_test_simulate_key() failed to map 'GDK_KEY_plus' to the proper + * 'plus' X keysym, probably because it is mapped to a keycode + * with modifiers like 'shift'. Run "xmodmap -pk | grep plus" to + * find out. Make sure 'plus' is the first keysym for the given + * keycode. If not, use "xmodmap <keycode> = plus" to correct it. + */ + g_assert_cmpfloat (fabs (factor_before_zoom - factor_after_zoom), + >=, + GIMP_UI_ZOOM_EPSILON); + +#ifdef __GNUC__ +#warning disabled zoom test, it fails randomly, no clue how to fix it +#endif +#if 0 + g_assert_cmpint (ABS (shell_x_after_zoom - shell_x_before_zoom), + <=, + GIMP_UI_POSITION_EPSILON); + g_assert_cmpint (ABS (shell_y_after_zoom - shell_y_before_zoom), + <=, + GIMP_UI_POSITION_EPSILON); +#endif +} + +/** + * alt_click_is_layer_to_selection: + * @data: + * + * Makes sure that we can alt-click on a layer to do + * layer-to-selection. Also makes sure that the layer clicked on is + * not set as the active layer. + **/ +static void +alt_click_is_layer_to_selection (gconstpointer data) +{ +#if __GNUC__ +#warning FIXME: please fix alt_click_is_layer_to_selection test +#endif +#if 0 + Gimp *gimp = GIMP (data); + GimpImage *image = GIMP_IMAGE (gimp_get_image_iter (gimp)->data); + GimpChannel *selection = gimp_image_get_mask (image); + GimpLayer *active_layer; + GtkWidget *dockable; + GtkWidget *gtk_tree_view; + gint assumed_layer_x; + gint assumed_empty_layer_y; + gint assumed_background_layer_y; + + /* Hardcode assumptions of where the layers are in the + * GtkTreeView. Doesn't feel worth adding proper API for this. One + * can just use GIMP_PAUSE and re-measure new coordinates if we + * start to layout layers in the GtkTreeView differently + */ + assumed_layer_x = 96; + assumed_empty_layer_y = 16; + assumed_background_layer_y = 42; + + /* Store the active layer, it shall not change during the execution + * of this test + */ + active_layer = gimp_image_get_active_layer (image); + + /* Find the layer tree view to click in. Note that there is a + * potential problem with gtk_test_find_widget and GtkNotebook: it + * will return e.g. a GtkTreeView from another page if that page is + * "on top" of the reference label. + */ + dockable = gimp_ui_find_window (gimp_dialog_factory_get_singleton (), + gimp_ui_is_gimp_layer_list); + gtk_tree_view = gtk_test_find_widget (dockable, + "Lock:", + GTK_TYPE_TREE_VIEW); + + /* First make sure there is no selection */ + g_assert (gimp_channel_is_empty (selection)); + + /* Now simulate alt-click on the background layer */ + g_assert (gimp_ui_synthesize_click (gtk_tree_view, + assumed_layer_x, + assumed_background_layer_y, + 1 /*button*/, + GDK_MOD1_MASK)); + gimp_test_run_mainloop_until_idle (); + + /* Make sure we got a selection and that the active layer didn't + * change + */ + g_assert (! gimp_channel_is_empty (selection)); + g_assert (gimp_image_get_active_layer (image) == active_layer); + + /* Now simulate alt-click on the empty layer */ + g_assert (gimp_ui_synthesize_click (gtk_tree_view, + assumed_layer_x, + assumed_empty_layer_y, + 1 /*button*/, + GDK_MOD1_MASK)); + gimp_test_run_mainloop_until_idle (); + + /* Make sure that emptied the selection and that the active layer + * still didn't change + */ + g_assert (gimp_channel_is_empty (selection)); + g_assert (gimp_image_get_active_layer (image) == active_layer); +#endif +} + +static void +restore_recently_closed_multi_column_dock (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + GtkWidget *dock_window = NULL; + gint n_session_infos_before_close = -1; + gint n_session_infos_after_close = -1; + gint n_session_infos_after_restore = -1; + GList *session_infos = NULL; + + /* Find a non-toolbox dock window */ + dock_window = gimp_ui_find_window (gimp_dialog_factory_get_singleton (), + gimp_ui_multicolumn_not_toolbox_window); + g_assert (dock_window != NULL); + + /* Count number of docks */ + session_infos = gimp_dialog_factory_get_session_infos (gimp_dialog_factory_get_singleton ()); + n_session_infos_before_close = g_list_length (session_infos); + + /* Close one of the dock windows */ + gimp_ui_synthesize_delete_event (GTK_WIDGET (dock_window)); + gimp_test_run_mainloop_until_idle (); + + /* Make sure the number of session infos went down */ + session_infos = gimp_dialog_factory_get_session_infos (gimp_dialog_factory_get_singleton ()); + n_session_infos_after_close = g_list_length (session_infos); + g_assert_cmpint (n_session_infos_before_close, + >, + n_session_infos_after_close); + +#ifdef __GNUC__ +#warning FIXME test disabled until we depend on GTK+ >= 2.24.11 +#endif +#if 0 + /* Restore the (only available) closed dock and make sure the session + * infos in the global dock factory are increased again + */ + gimp_ui_manager_activate_action (gimp_test_utils_get_ui_manager (gimp), + "windows", + /* FIXME: This is severely hardcoded */ + "windows-recent-0003"); + gimp_test_run_mainloop_until_idle (); + session_infos = gimp_dialog_factory_get_session_infos (gimp_dialog_factory_get_singleton ()); + n_session_infos_after_restore = g_list_length (session_infos); + g_assert_cmpint (n_session_infos_after_close, + <, + n_session_infos_after_restore); +#endif +} + +/** + * tab_toggle_dont_change_dock_window_position: + * @data: + * + * Makes sure that when dock windows are hidden with Tab and shown + * again, their positions and sizes are not changed. We don't really + * use Tab though, we only simulate its effect. + **/ +static void +tab_toggle_dont_change_dock_window_position (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + GtkWidget *dock_window = NULL; + gint x_before_hide = -1; + gint y_before_hide = -1; + gint w_before_hide = -1; + gint h_before_hide = -1; + gint x_after_show = -1; + gint y_after_show = -1; + gint w_after_show = -1; + gint h_after_show = -1; + + /* Find a non-toolbox dock window */ + dock_window = gimp_ui_find_window (gimp_dialog_factory_get_singleton (), + gimp_ui_not_toolbox_window); + g_assert (dock_window != NULL); + g_assert (gtk_widget_get_visible (dock_window)); + + /* Get the position and size */ + gimp_test_run_mainloop_until_idle (); + gtk_window_get_position (GTK_WINDOW (dock_window), + &x_before_hide, + &y_before_hide); + gtk_window_get_size (GTK_WINDOW (dock_window), + &w_before_hide, + &h_before_hide); + + /* Hide all dock windows */ + gimp_ui_manager_activate_action (gimp_test_utils_get_ui_manager (gimp), + "windows", + "windows-hide-docks"); + gimp_test_run_mainloop_until_idle (); + g_assert (! gtk_widget_get_visible (dock_window)); + + /* Show them again */ + gimp_ui_manager_activate_action (gimp_test_utils_get_ui_manager (gimp), + "windows", + "windows-hide-docks"); + gimp_test_run_mainloop_until_idle (); + g_assert (gtk_widget_get_visible (dock_window)); + + /* Get the position and size again and make sure it's the same as + * before + */ + gtk_window_get_position (GTK_WINDOW (dock_window), + &x_after_show, + &y_after_show); + gtk_window_get_size (GTK_WINDOW (dock_window), + &w_after_show, + &h_after_show); + g_assert_cmpint ((int)abs (x_before_hide - x_after_show), <=, GIMP_UI_WINDOW_POSITION_EPSILON); + g_assert_cmpint ((int)abs (y_before_hide - y_after_show), <=, GIMP_UI_WINDOW_POSITION_EPSILON); + g_assert_cmpint ((int)abs (w_before_hide - w_after_show), <=, GIMP_UI_WINDOW_POSITION_EPSILON); + g_assert_cmpint ((int)abs (h_before_hide - h_after_show), <=, GIMP_UI_WINDOW_POSITION_EPSILON); +} + +static void +switch_to_single_window_mode (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + + /* Switch to single-window mode. We consider this test as passed if + * we don't get any GLib warnings/errors + */ + gimp_ui_switch_window_mode (gimp); +} + +static void +gimp_ui_toggle_docks_in_single_window_mode (Gimp *gimp) +{ + GimpDisplay *display = GIMP_DISPLAY (gimp_get_display_iter (gimp)->data); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GtkWidget *toplevel = GTK_WIDGET (gimp_display_shell_get_window (shell)); + gint x_temp = -1; + gint y_temp = -1; + gint x_before_hide = -1; + gint y_before_hide = -1; + gint x_after_hide = -1; + gint y_after_hide = -1; + g_assert (shell); + g_assert (toplevel); + + /* Get toplevel coordinate of image origin */ + gimp_test_run_mainloop_until_idle (); + gimp_display_shell_transform_xy (shell, + 0.0, 0.0, + &x_temp, &y_temp); + gtk_widget_translate_coordinates (GTK_WIDGET (shell), + toplevel, + x_temp, y_temp, + &x_before_hide, &y_before_hide); + + /* Hide all dock windows */ + gimp_ui_manager_activate_action (gimp_test_utils_get_ui_manager (gimp), + "windows", + "windows-hide-docks"); + gimp_test_run_mainloop_until_idle (); + + /* Get toplevel coordinate of image origin */ + gimp_test_run_mainloop_until_idle (); + gimp_display_shell_transform_xy (shell, + 0.0, 0.0, + &x_temp, &y_temp); + gtk_widget_translate_coordinates (GTK_WIDGET (shell), + toplevel, + x_temp, y_temp, + &x_after_hide, &y_after_hide); + + g_assert_cmpint ((int)abs (x_after_hide - x_before_hide), <=, GIMP_UI_POSITION_EPSILON); + g_assert_cmpint ((int)abs (y_after_hide - y_before_hide), <=, GIMP_UI_POSITION_EPSILON); +} + +static void +hide_docks_in_single_window_mode (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + gimp_ui_toggle_docks_in_single_window_mode (gimp); +} + +static void +show_docks_in_single_window_mode (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + gimp_ui_toggle_docks_in_single_window_mode (gimp); +} + +static void +maximize_state_in_aux_data (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + GimpDisplay *display = GIMP_DISPLAY (gimp_get_display_iter (gimp)->data); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GimpImageWindow *window = gimp_display_shell_get_window (shell); + gint i; + + for (i = 0; i < 2; i++) + { + GList *aux_info = NULL; + GimpSessionInfoAux *target_info; + gboolean target_max_state; + + if (i == 0) + { + target_info = gimp_session_info_aux_new ("maximized" , "yes"); + target_max_state = TRUE; + } + else + { + target_info = gimp_session_info_aux_new ("maximized", "no"); + target_max_state = FALSE; + } + + /* Set the aux info to out target data */ + aux_info = g_list_append (aux_info, target_info); + gimp_session_managed_set_aux_info (GIMP_SESSION_MANAGED (window), aux_info); + g_list_free (aux_info); + + /* Give the WM a chance to maximize/unmaximize us */ + gimp_test_run_mainloop_until_idle (); + g_usleep (500 * 1000); + gimp_test_run_mainloop_until_idle (); + + /* Make sure the maximize/unmaximize happened */ + g_assert (gimp_image_window_is_maximized (window) == target_max_state); + + /* Make sure we can read out the window state again */ + aux_info = gimp_session_managed_get_aux_info (GIMP_SESSION_MANAGED (window)); + g_assert (g_list_find_custom (aux_info, target_info, gimp_ui_aux_data_eqiuvalent)); + g_list_free_full (aux_info, + (GDestroyNotify) gimp_session_info_aux_free); + + gimp_session_info_aux_free (target_info); + } +} + +static void +switch_back_to_multi_window_mode (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + + /* Switch back to multi-window mode. We consider this test as passed + * if we don't get any GLib warnings/errors + */ + gimp_ui_switch_window_mode (gimp); +} + +static void +close_image (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + int undo_count = 4; + + /* Undo all changes so we don't need to find the 'Do you want to + * save?'-dialog and its 'No' button + */ + while (undo_count--) + { + gimp_ui_manager_activate_action (gimp_test_utils_get_ui_manager (gimp), + "edit", + "edit-undo"); + gimp_test_run_mainloop_until_idle (); + } + + /* Close the image */ + gimp_ui_manager_activate_action (gimp_test_utils_get_ui_manager (gimp), + "view", + "view-close"); + gimp_test_run_mainloop_until_idle (); + + /* Did it really disappear? */ + g_assert_cmpint (g_list_length (gimp_get_image_iter (gimp)), ==, 0); +} + +/** + * repeatedly_switch_window_mode: + * @data: + * + * Makes sure that the size of the image window is properly handled + * when repeatedly switching between window modes. + **/ +static void +repeatedly_switch_window_mode (gconstpointer data) +{ +#ifdef __GNUC__ +#warning FIXME: plesase fix repeatedly_switch_window_mode test +#endif +#if 0 + Gimp *gimp = GIMP (data); + GimpDisplay *display = GIMP_DISPLAY (gimp_get_empty_display (gimp)); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell)); + + gint expected_initial_height; + gint expected_initial_width; + gint expected_second_height; + gint expected_second_width; + gint initial_width; + gint initial_height; + gint second_width; + gint second_height; + + /* We need this for some reason */ + gimp_test_run_mainloop_until_idle (); + + /* Remember the multi-window mode size */ + gtk_window_get_size (GTK_WINDOW (toplevel), + &expected_initial_width, + &expected_initial_height); + + /* Switch to single-window mode */ + gimp_ui_switch_window_mode (gimp); + + /* Remember the single-window mode size */ + gtk_window_get_size (GTK_WINDOW (toplevel), + &expected_second_width, + &expected_second_height); + + /* Make sure they differ, otherwise the test is pointless */ + g_assert_cmpint (expected_initial_width, !=, expected_second_width); + g_assert_cmpint (expected_initial_height, !=, expected_second_height); + + /* Switch back to multi-window mode */ + gimp_ui_switch_window_mode (gimp); + + /* Make sure the size is the same as before */ + gtk_window_get_size (GTK_WINDOW (toplevel), &initial_width, &initial_height); + g_assert_cmpint (expected_initial_width, ==, initial_width); + g_assert_cmpint (expected_initial_height, ==, initial_height); + + /* Switch to single-window mode again... */ + gimp_ui_switch_window_mode (gimp); + + /* Make sure the size is the same as before */ + gtk_window_get_size (GTK_WINDOW (toplevel), &second_width, &second_height); + g_assert_cmpint (expected_second_width, ==, second_width); + g_assert_cmpint (expected_second_height, ==, second_height); + + /* Finally switch back to multi-window mode since that was the mode + * when we started + */ + gimp_ui_switch_window_mode (gimp); +#endif +} + +/** + * window_roles: + * @data: + * + * Makes sure that different windows have the right roles specified. + **/ +static void +window_roles (gconstpointer data) +{ + GtkWidget *dock = NULL; + GtkWidget *toolbox = NULL; + GimpDockWindow *dock_window = NULL; + GimpDockWindow *toolbox_window = NULL; + + dock = gimp_dock_with_window_new (gimp_dialog_factory_get_singleton (), + gdk_screen_get_default (), + 0, + FALSE /*toolbox*/); + toolbox = gimp_dock_with_window_new (gimp_dialog_factory_get_singleton (), + gdk_screen_get_default (), + 0, + TRUE /*toolbox*/); + dock_window = gimp_dock_window_from_dock (GIMP_DOCK (dock)); + toolbox_window = gimp_dock_window_from_dock (GIMP_DOCK (toolbox)); + + g_assert_cmpint (g_str_has_prefix (gtk_window_get_role (GTK_WINDOW (dock_window)), "gimp-dock-"), ==, + TRUE); + g_assert_cmpint (g_str_has_prefix (gtk_window_get_role (GTK_WINDOW (toolbox_window)), "gimp-toolbox-"), ==, + TRUE); + + /* When we get here we have a ref count of one, but the signals we + * emit cause the reference count to become less than zero for some + * reason. So we're lazy and simply ignore to unref these + g_object_unref (toolbox); + g_object_unref (dock); + */ +} + +static void +paintbrush_is_standard_tool (gconstpointer data) +{ + Gimp *gimp = GIMP (data); + GimpContext *user_context = gimp_get_user_context (gimp); + GimpToolInfo *tool_info = gimp_context_get_tool (user_context); + + g_assert_cmpstr (tool_info->help_id, + ==, + "gimp-tool-paintbrush"); +} + +/** + * gimp_ui_synthesize_delete_event: + * @widget: + * + * Synthesize a delete event to @widget. + **/ +static void +gimp_ui_synthesize_delete_event (GtkWidget *widget) +{ + GdkWindow *window = NULL; + GdkEvent *event = NULL; + + window = gtk_widget_get_window (widget); + g_assert (window); + + event = gdk_event_new (GDK_DELETE); + event->any.window = g_object_ref (window); + event->any.send_event = TRUE; + gtk_main_do_event (event); + gdk_event_free (event); +} + +static gboolean +gimp_ui_synthesize_click (GtkWidget *widget, + gint x, + gint y, + gint button, /*1..3*/ + GdkModifierType modifiers) +{ + return (gdk_test_simulate_button (gtk_widget_get_window (widget), + x, y, + button, + modifiers, + GDK_BUTTON_PRESS) && + gdk_test_simulate_button (gtk_widget_get_window (widget), + x, y, + button, + modifiers, + GDK_BUTTON_RELEASE)); +} + +static GtkWidget * +gimp_ui_find_window (GimpDialogFactory *dialog_factory, + GimpUiTestFunc predicate) +{ + GList *iter = NULL; + GtkWidget *dock_window = NULL; + + g_return_val_if_fail (predicate != NULL, NULL); + + for (iter = gimp_dialog_factory_get_session_infos (dialog_factory); + iter; + iter = g_list_next (iter)) + { + GtkWidget *widget = gimp_session_info_get_widget (iter->data); + + if (predicate (G_OBJECT (widget))) + { + dock_window = widget; + break; + } + } + + return dock_window; +} + +static gboolean +gimp_ui_not_toolbox_window (GObject *object) +{ + return (GIMP_IS_DOCK_WINDOW (object) && + ! gimp_dock_window_has_toolbox (GIMP_DOCK_WINDOW (object))); +} + +static gboolean +gimp_ui_multicolumn_not_toolbox_window (GObject *object) +{ + gboolean not_toolbox_window; + GimpDockWindow *dock_window; + GimpDockContainer *dock_container; + GList *docks; + + if (! GIMP_IS_DOCK_WINDOW (object)) + return FALSE; + + dock_window = GIMP_DOCK_WINDOW (object); + dock_container = GIMP_DOCK_CONTAINER (object); + docks = gimp_dock_container_get_docks (dock_container); + + not_toolbox_window = (! gimp_dock_window_has_toolbox (dock_window) && + g_list_length (docks) > 1); + + g_list_free (docks); + + return not_toolbox_window; +} + +static gboolean +gimp_ui_is_gimp_layer_list (GObject *object) +{ + GimpDialogFactoryEntry *entry = NULL; + + if (! GTK_IS_WIDGET (object)) + return FALSE; + + gimp_dialog_factory_from_widget (GTK_WIDGET (object), &entry); + + return strcmp (entry->identifier, "gimp-layer-list") == 0; +} + +static int +gimp_ui_aux_data_eqiuvalent (gconstpointer _a, gconstpointer _b) +{ + GimpSessionInfoAux *a = (GimpSessionInfoAux*) _a; + GimpSessionInfoAux *b = (GimpSessionInfoAux*) _b; + return (strcmp (a->name, b->name) || strcmp (a->value, b->value)); +} + +static void +gimp_ui_switch_window_mode (Gimp *gimp) +{ + gimp_ui_manager_activate_action (gimp_test_utils_get_ui_manager (gimp), + "windows", + "windows-use-single-window-mode"); + gimp_test_run_mainloop_until_idle (); + + /* Add a small sleep to let things stabilize */ + g_usleep (500 * 1000); + gimp_test_run_mainloop_until_idle (); +} + +int main(int argc, char **argv) +{ + Gimp *gimp = NULL; + gint result = -1; + + gimp_test_bail_if_no_display (); + gtk_test_init (&argc, &argv, NULL); + + gimp_test_utils_set_gimp2_directory ("GIMP_TESTING_ABS_TOP_SRCDIR", + "app/tests/gimpdir"); + gimp_test_utils_setup_menus_path (); + + /* Start up GIMP */ + gimp = gimp_init_for_gui_testing (TRUE /*show_gui*/); + gimp_test_run_mainloop_until_idle (); + + /* Add tests. Note that the order matters. For example, + * 'paintbrush_is_standard_tool' can't be after + * 'tool_options_editor_updates' + */ + ADD_TEST (paintbrush_is_standard_tool); + ADD_TEST (tool_options_editor_updates); + ADD_TEST (automatic_tab_style); + ADD_TEST (create_new_image_via_dialog); + ADD_TEST (keyboard_zoom_focus); + ADD_TEST (alt_click_is_layer_to_selection); + ADD_TEST (restore_recently_closed_multi_column_dock); + ADD_TEST (tab_toggle_dont_change_dock_window_position); + ADD_TEST (switch_to_single_window_mode); +#warning FIXME: hide/show docks doesn't work when running make check +#if 0 + ADD_TEST (hide_docks_in_single_window_mode); + ADD_TEST (show_docks_in_single_window_mode); +#endif +#warning FIXME: maximize_state_in_aux_data doesn't work without WM +#if 0 + ADD_TEST (maximize_state_in_aux_data); +#endif + ADD_TEST (switch_back_to_multi_window_mode); + ADD_TEST (close_image); + ADD_TEST (repeatedly_switch_window_mode); + ADD_TEST (window_roles); + + /* Run the tests and return status */ + result = g_test_run (); + + /* Don't write files to the source dir */ + gimp_test_utils_set_gimp2_directory ("GIMP_TESTING_ABS_TOP_BUILDDIR", + "app/tests/gimpdir-output"); + + /* Exit properly so we don't break script-fu plug-in wire */ + gimp_exit (gimp, TRUE); + + return result; +} |