Instead of including dialogs/dialogs.h everywhere, introduce gimp_dialog_factory_get_singleton(). The dialog factory singleton is still initialized by dialogs.c though. Right now the assumption is that we never will have another dialog factory instance around. There were so many problems before when we had four of them, so let's just keep one of them around.
532 lines
20 KiB
C
532 lines
20 KiB
C
/* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
#include "libgimpmath/gimpmath.h"
|
|
|
|
#include "dialogs/dialogs-types.h"
|
|
|
|
#include "display/gimpdisplay.h"
|
|
#include "display/gimpdisplayshell.h"
|
|
#include "display/gimpdisplayshell-transform.h"
|
|
#include "display/gimpimagewindow.h"
|
|
|
|
#include "widgets/gimpdialogfactory.h"
|
|
#include "widgets/gimpdocked.h"
|
|
#include "widgets/gimpdockwindow.h"
|
|
#include "widgets/gimphelp-ids.h"
|
|
#include "widgets/gimpsessioninfo.h"
|
|
#include "widgets/gimptooloptionseditor.h"
|
|
#include "widgets/gimpuimanager.h"
|
|
|
|
#include "core/gimp.h"
|
|
#include "core/gimpcontext.h"
|
|
#include "core/gimptoolinfo.h"
|
|
#include "core/gimptooloptions.h"
|
|
|
|
#include "tests.h"
|
|
|
|
#include "gimp-app-test-utils.h"
|
|
|
|
|
|
#define GIMP_UI_WINDOW_POSITION_EPSILON 10
|
|
#define GIMP_UI_WINDOW_POSITION_EPSILON 10
|
|
#define GIMP_UI_POSITION_EPSILON 1
|
|
#define GIMP_UI_POSITION_EPSILON 1
|
|
|
|
|
|
typedef struct
|
|
{
|
|
int avoid_sizeof_zero;
|
|
} GimpTestFixture;
|
|
|
|
|
|
static void gimp_ui_tool_options_editor_updates (GimpTestFixture *fixture,
|
|
gconstpointer data);
|
|
static void gimp_ui_create_new_image_via_dialog (GimpTestFixture *fixture,
|
|
gconstpointer data);
|
|
static void gimp_ui_restore_recently_closed_dock (GimpTestFixture *fixture,
|
|
gconstpointer data);
|
|
static void gimp_ui_tab_toggle_dont_change_position (GimpTestFixture *fixture,
|
|
gconstpointer data);
|
|
static void gimp_ui_switch_to_single_window_mode (GimpTestFixture *fixture,
|
|
gconstpointer data);
|
|
static void gimp_ui_hide_docks_in_single_window_mode (GimpTestFixture *fixture,
|
|
gconstpointer data);
|
|
static void gimp_ui_show_docks_in_single_window_mode (GimpTestFixture *fixture,
|
|
gconstpointer data);
|
|
static void gimp_ui_switch_back_to_multi_window_mode (GimpTestFixture *fixture,
|
|
gconstpointer data);
|
|
static GimpUIManager * gimp_ui_get_ui_manager (Gimp *gimp);
|
|
static void gimp_ui_synthesize_delete_event (GtkWidget *widget);
|
|
static GtkWidget * gimp_ui_find_non_toolbox_dock_window (GimpDialogFactory *dialog_factory);
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
Gimp *gimp = NULL;
|
|
gint result = -1;
|
|
|
|
g_type_init ();
|
|
gtk_init (&argc, &argv);
|
|
g_test_init (&argc, &argv, NULL);
|
|
|
|
gimp_test_utils_set_gimp2_directory ("GIMP_TESTING_ABS_TOP_SRCDIR",
|
|
"app/tests/gimpdir");
|
|
gimp_test_utils_setup_menus_dir ();
|
|
|
|
/* Start up GIMP */
|
|
gimp = gimp_init_for_gui_testing (FALSE, TRUE);
|
|
gimp_test_run_mainloop_until_idle ();
|
|
|
|
/* Setup the tests */
|
|
g_test_add ("/gimp-ui/tool-options-editor-updates",
|
|
GimpTestFixture,
|
|
gimp,
|
|
NULL,
|
|
gimp_ui_tool_options_editor_updates,
|
|
NULL);
|
|
g_test_add ("/gimp-ui/create-new-image-via-dialog",
|
|
GimpTestFixture,
|
|
gimp,
|
|
NULL,
|
|
gimp_ui_create_new_image_via_dialog,
|
|
NULL);
|
|
g_test_add ("/gimp-ui/restore-recently-closed-dock",
|
|
GimpTestFixture,
|
|
gimp,
|
|
NULL,
|
|
gimp_ui_restore_recently_closed_dock,
|
|
NULL);
|
|
g_test_add ("/gimp-ui/tab-toggle-dont-change-dock-window-position",
|
|
GimpTestFixture,
|
|
gimp,
|
|
NULL,
|
|
gimp_ui_tab_toggle_dont_change_position,
|
|
NULL);
|
|
g_test_add ("/gimp-ui/switch-to-single-window-mode",
|
|
GimpTestFixture,
|
|
gimp,
|
|
NULL,
|
|
gimp_ui_switch_to_single_window_mode,
|
|
NULL);
|
|
g_test_add ("/gimp-ui/hide-docks-in-single-window-mode",
|
|
GimpTestFixture,
|
|
gimp,
|
|
NULL,
|
|
gimp_ui_hide_docks_in_single_window_mode,
|
|
NULL);
|
|
g_test_add ("/gimp-ui/show-docks-in-single-window-mode",
|
|
GimpTestFixture,
|
|
gimp,
|
|
NULL,
|
|
gimp_ui_show_docks_in_single_window_mode,
|
|
NULL);
|
|
g_test_add ("/gimp-ui/switch-back-to-multi-window-mode",
|
|
GimpTestFixture,
|
|
gimp,
|
|
NULL,
|
|
gimp_ui_switch_back_to_multi_window_mode,
|
|
NULL);
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/**
|
|
* gimp_ui_tool_options_editor_updates:
|
|
* @fixture:
|
|
* @data:
|
|
*
|
|
* Makes sure that the tool options editor is updated when the tool
|
|
* changes.
|
|
**/
|
|
static void
|
|
gimp_ui_tool_options_editor_updates (GimpTestFixture *fixture,
|
|
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-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 void
|
|
gimp_ui_create_new_image_via_dialog (GimpTestFixture *fixture,
|
|
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 *new_image_dialog = NULL;
|
|
guint n_initial_images = g_list_length (gimp_get_image_iter (gimp));
|
|
guint n_images = -1;
|
|
gint tries_left = 100;
|
|
|
|
/* Bring up the new image dialog */
|
|
gimp_ui_manager_activate_action (ui_manager,
|
|
"image",
|
|
"image-new");
|
|
gimp_test_run_mainloop_until_idle ();
|
|
|
|
/* Get the GtkWindow of the dialog */
|
|
new_image_dialog =
|
|
gimp_dialog_factory_dialog_raise (gimp_dialog_factory_get_singleton (),
|
|
gtk_widget_get_screen (GTK_WIDGET (shell)),
|
|
"gimp-image-new-dialog",
|
|
-1 /*view_size*/);
|
|
|
|
/* Press the focused widget, it should be the Ok button. It will
|
|
* take a while for the image to be created to loop for a while
|
|
*/
|
|
gtk_widget_activate (gtk_window_get_focus (GTK_WINDOW (new_image_dialog)));
|
|
do
|
|
{
|
|
g_usleep (20 * 1000);
|
|
gimp_test_run_mainloop_until_idle ();
|
|
n_images = g_list_length (gimp_get_image_iter (gimp));
|
|
}
|
|
while (tries_left-- &&
|
|
n_images != n_initial_images + 1);
|
|
|
|
/* Make sure there now is one image more than initially */
|
|
g_assert_cmpint (n_images,
|
|
==,
|
|
n_initial_images + 1);
|
|
}
|
|
|
|
static void
|
|
gimp_ui_restore_recently_closed_dock (GimpTestFixture *fixture,
|
|
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_non_toolbox_dock_window (gimp_dialog_factory_get_singleton ());
|
|
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);
|
|
|
|
/* Restore the (only avaiable) closed dock and make sure the session
|
|
* infos in the global dock factory are increased again
|
|
*/
|
|
gimp_ui_manager_activate_action (gimp_ui_get_ui_manager (gimp),
|
|
"windows",
|
|
/* FIXME: This is severly 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);
|
|
}
|
|
|
|
/**
|
|
* gimp_ui_tab_toggle_dont_change_position:
|
|
* @fixture:
|
|
* @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
|
|
gimp_ui_tab_toggle_dont_change_position (GimpTestFixture *fixture,
|
|
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_non_toolbox_dock_window (gimp_dialog_factory_get_singleton ());
|
|
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_ui_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_ui_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
|
|
gimp_ui_switch_to_single_window_mode (GimpTestFixture *fixture,
|
|
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_manager_activate_action (gimp_ui_get_ui_manager (gimp),
|
|
"windows",
|
|
"windows-use-single-window-mode");
|
|
gimp_test_run_mainloop_until_idle ();
|
|
}
|
|
|
|
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,
|
|
FALSE /*use_offsets*/);
|
|
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_ui_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,
|
|
FALSE /*use_offsets*/);
|
|
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
|
|
gimp_ui_hide_docks_in_single_window_mode (GimpTestFixture *fixture,
|
|
gconstpointer data)
|
|
{
|
|
Gimp *gimp = GIMP (data);
|
|
gimp_ui_toggle_docks_in_single_window_mode (gimp);
|
|
}
|
|
|
|
static void
|
|
gimp_ui_show_docks_in_single_window_mode (GimpTestFixture *fixture,
|
|
gconstpointer data)
|
|
{
|
|
Gimp *gimp = GIMP (data);
|
|
gimp_ui_toggle_docks_in_single_window_mode (gimp);
|
|
}
|
|
|
|
static void
|
|
gimp_ui_switch_back_to_multi_window_mode (GimpTestFixture *fixture,
|
|
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_manager_activate_action (gimp_ui_get_ui_manager (gimp),
|
|
"windows",
|
|
"windows-use-single-window-mode");
|
|
gimp_test_run_mainloop_until_idle ();
|
|
}
|
|
|
|
static GimpUIManager *
|
|
gimp_ui_get_ui_manager (Gimp *gimp)
|
|
{
|
|
GimpDisplay *display = NULL;
|
|
GimpDisplayShell *shell = NULL;
|
|
GtkWidget *toplevel = NULL;
|
|
GimpImageWindow *image_window = NULL;
|
|
GimpUIManager *ui_manager = NULL;
|
|
|
|
display = GIMP_DISPLAY (gimp_get_empty_display (gimp));
|
|
|
|
/* If there were not empty display, assume that there is at least
|
|
* one image display and use that
|
|
*/
|
|
if (! display)
|
|
display = GIMP_DISPLAY (gimp_get_display_iter (gimp)->data);
|
|
|
|
shell = gimp_display_get_shell (display);
|
|
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell));
|
|
image_window = GIMP_IMAGE_WINDOW (toplevel);
|
|
ui_manager = gimp_image_window_get_ui_manager (image_window);
|
|
|
|
return ui_manager;
|
|
}
|
|
|
|
/**
|
|
* 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 GtkWidget *
|
|
gimp_ui_find_non_toolbox_dock_window (GimpDialogFactory *dialog_factory)
|
|
{
|
|
GList *iter = NULL;
|
|
GtkWidget *dock_window = 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 (GIMP_IS_DOCK_WINDOW (widget) &&
|
|
! gimp_dock_window_has_toolbox (GIMP_DOCK_WINDOW (widget)))
|
|
{
|
|
dock_window = widget;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return dock_window;
|
|
}
|