909 lines
32 KiB
C
909 lines
32 KiB
C
/* PIKA - Photo and Image Kooker Application
|
|
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
|
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
|
*
|
|
* Original copyright, applying to most contents (license remains unchanged):
|
|
* 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 "libpikabase/pikabase.h"
|
|
#include "libpikamath/pikamath.h"
|
|
#include "libpikawidgets/pikawidgets.h"
|
|
|
|
#include "dialogs/dialogs-types.h"
|
|
|
|
#include "display/pikadisplay.h"
|
|
#include "display/pikadisplayshell.h"
|
|
#include "display/pikadisplayshell-scale.h"
|
|
#include "display/pikadisplayshell-transform.h"
|
|
#include "display/pikaimagewindow.h"
|
|
|
|
#include "menus/menus.h"
|
|
|
|
#include "widgets/pikadialogfactory.h"
|
|
#include "widgets/pikadock.h"
|
|
#include "widgets/pikadockable.h"
|
|
#include "widgets/pikadockbook.h"
|
|
#include "widgets/pikadockcontainer.h"
|
|
#include "widgets/pikadocked.h"
|
|
#include "widgets/pikadockwindow.h"
|
|
#include "widgets/pikahelp-ids.h"
|
|
#include "widgets/pikasessioninfo.h"
|
|
#include "widgets/pikasessioninfo-aux.h"
|
|
#include "widgets/pikasessionmanaged.h"
|
|
#include "widgets/pikatoolbox.h"
|
|
#include "widgets/pikatooloptionseditor.h"
|
|
#include "widgets/pikauimanager.h"
|
|
#include "widgets/pikawidgets-utils.h"
|
|
|
|
#include "core/pika.h"
|
|
#include "core/pikachannel.h"
|
|
#include "core/pikacontext.h"
|
|
#include "core/pikaimage.h"
|
|
#include "core/pikalayer.h"
|
|
#include "core/pikalayer-new.h"
|
|
#include "core/pikatoolinfo.h"
|
|
#include "core/pikatooloptions.h"
|
|
|
|
#include "pikacoreapp.h"
|
|
|
|
#include "pika-app-test-utils.h"
|
|
#include "tests.h"
|
|
|
|
|
|
#define PIKA_UI_WINDOW_POSITION_EPSILON 30
|
|
#define PIKA_UI_POSITION_EPSILON 1
|
|
#define PIKA_UI_ZOOM_EPSILON 0.01
|
|
|
|
#define ADD_TEST(function) \
|
|
g_test_add_data_func ("/pika-ui/" #function, pika, 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 PIKA_PAUSE (g_usleep (20 * 1000 * 1000))
|
|
|
|
|
|
typedef gboolean (*PikaUiTestFunc) (GObject *object);
|
|
|
|
|
|
static void pika_ui_synthesize_delete_event (GtkWidget *widget);
|
|
static gboolean pika_ui_synthesize_click (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
gint button,
|
|
GdkModifierType modifiers);
|
|
static GtkWidget * pika_ui_find_window (PikaDialogFactory *dialog_factory,
|
|
PikaUiTestFunc predicate);
|
|
static gboolean pika_ui_not_toolbox_window (GObject *object);
|
|
static gboolean pika_ui_multicolumn_not_toolbox_window (GObject *object);
|
|
static gboolean pika_ui_is_pika_layer_list (GObject *object);
|
|
static int pika_ui_aux_data_eqiuvalent (gconstpointer _a,
|
|
gconstpointer _b);
|
|
static void pika_ui_switch_window_mode (Pika *pika);
|
|
|
|
|
|
/**
|
|
* 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)
|
|
{
|
|
Pika *pika = PIKA (data);
|
|
PikaDisplay *display = PIKA_DISPLAY (pika_get_empty_display (pika));
|
|
PikaDisplayShell *shell = pika_display_get_shell (display);
|
|
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell));
|
|
PikaUIManager *ui_manager = menus_get_image_manager_singleton (pika);
|
|
GtkWidget *dockable = pika_dialog_factory_dialog_new (pika_dialog_factory_get_singleton (),
|
|
pika_widget_get_monitor (toplevel),
|
|
NULL /*ui_manager*/,
|
|
toplevel,
|
|
"pika-tool-options",
|
|
-1 /*view_size*/,
|
|
FALSE /*present*/);
|
|
PikaToolOptionsEditor *editor = PIKA_TOOL_OPTIONS_EDITOR (gtk_bin_get_child (GTK_BIN (dockable)));
|
|
|
|
/* First select the rect select tool */
|
|
pika_ui_manager_activate_action (ui_manager,
|
|
"tools",
|
|
"tools-rect-select");
|
|
g_assert_cmpstr (PIKA_HELP_TOOL_RECT_SELECT,
|
|
==,
|
|
pika_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
|
|
*/
|
|
pika_ui_manager_activate_action (ui_manager,
|
|
"tools",
|
|
"tools-ellipse-select");
|
|
g_assert_cmpstr (PIKA_HELP_TOOL_ELLIPSE_SELECT,
|
|
==,
|
|
pika_tool_options_editor_get_tool_options (editor)->
|
|
tool_info->help_id);
|
|
}
|
|
|
|
static void
|
|
create_new_image_via_dialog (gconstpointer data)
|
|
{
|
|
Pika *pika = PIKA (data);
|
|
PikaImage *image;
|
|
PikaLayer *layer;
|
|
|
|
image = pika_test_utils_create_image_from_dialog (pika);
|
|
|
|
/* Add a layer to the image to make it more useful in later tests */
|
|
layer = pika_layer_new (image,
|
|
pika_image_get_width (image),
|
|
pika_image_get_height (image),
|
|
pika_image_get_layer_format (image, TRUE),
|
|
"Layer for testing",
|
|
PIKA_OPACITY_OPAQUE,
|
|
PIKA_LAYER_MODE_NORMAL);
|
|
|
|
pika_image_add_layer (image, layer,
|
|
PIKA_IMAGE_ACTIVE_PARENT, -1, TRUE);
|
|
pika_test_run_mainloop_until_idle ();
|
|
}
|
|
|
|
static void
|
|
keyboard_zoom_focus (gconstpointer data)
|
|
{
|
|
Pika *pika = PIKA (data);
|
|
PikaDisplay *display = PIKA_DISPLAY (pika_get_display_iter (pika)->data);
|
|
PikaDisplayShell *shell = pika_display_get_shell (display);
|
|
PikaImageWindow *window = pika_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.
|
|
*/
|
|
pika_display_shell_transform_xy (shell,
|
|
image_x,
|
|
image_y,
|
|
&shell_x_before_zoom,
|
|
&shell_y_before_zoom);
|
|
pika_display_shell_push_zoom_focus_pointer_pos (shell,
|
|
shell_x_before_zoom,
|
|
shell_y_before_zoom);
|
|
factor_before_zoom = pika_zoom_model_get_factor (shell->zoom);
|
|
|
|
/* Do the zoom */
|
|
pika_test_utils_synthesize_key_event (GTK_WIDGET (window), GDK_KEY_plus);
|
|
pika_test_run_mainloop_until_idle ();
|
|
|
|
/* Make sure the zoom focus point remained fixed */
|
|
pika_display_shell_transform_xy (shell,
|
|
image_x,
|
|
image_y,
|
|
&shell_x_after_zoom,
|
|
&shell_y_after_zoom);
|
|
factor_after_zoom = pika_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),
|
|
>=,
|
|
PIKA_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),
|
|
<=,
|
|
PIKA_UI_POSITION_EPSILON);
|
|
g_assert_cmpint (ABS (shell_y_after_zoom - shell_y_before_zoom),
|
|
<=,
|
|
PIKA_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
|
|
Pika *pika = PIKA (data);
|
|
PikaImage *image = PIKA_IMAGE (pika_get_image_iter (pika)->data);
|
|
PikaChannel *selection = pika_image_get_mask (image);
|
|
GList *selected_layers;
|
|
GList *iter;
|
|
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 PIKA_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
|
|
*/
|
|
selected_layers = pika_image_get_selected_layers (image);
|
|
selected_layers = g_list_copy (selected_layers);
|
|
|
|
/* 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 = pika_ui_find_window (pika_dialog_factory_get_singleton (),
|
|
pika_ui_is_pika_layer_list);
|
|
gtk_tree_view = gtk_test_find_widget (dockable,
|
|
"Lock:",
|
|
GTK_TYPE_TREE_VIEW);
|
|
|
|
/* First make sure there is no selection */
|
|
g_assert (pika_channel_is_empty (selection));
|
|
|
|
/* Now simulate alt-click on the background layer */
|
|
g_assert (pika_ui_synthesize_click (gtk_tree_view,
|
|
assumed_layer_x,
|
|
assumed_background_layer_y,
|
|
1 /*button*/,
|
|
GDK_MOD1_MASK));
|
|
pika_test_run_mainloop_until_idle ();
|
|
|
|
/* Make sure we got a selection and that the active layer didn't
|
|
* change
|
|
*/
|
|
g_assert (! pika_channel_is_empty (selection));
|
|
g_assert (g_list_length (pika_image_get_selected_layers (image)) ==
|
|
g_list_length (selected_layers));
|
|
for (iter = selected_layers; iter; iter = iter->next)
|
|
g_assert (g_list_find (pika_image_get_selected_layers (image), iter->data));
|
|
|
|
/* Now simulate alt-click on the empty layer */
|
|
g_assert (pika_ui_synthesize_click (gtk_tree_view,
|
|
assumed_layer_x,
|
|
assumed_empty_layer_y,
|
|
1 /*button*/,
|
|
GDK_MOD1_MASK));
|
|
pika_test_run_mainloop_until_idle ();
|
|
|
|
/* Make sure that emptied the selection and that the active layer
|
|
* still didn't change
|
|
*/
|
|
g_assert (pika_channel_is_empty (selection));
|
|
g_assert (g_list_length (pika_image_get_selected_layers (image)) ==
|
|
g_list_length (selected_layers));
|
|
for (iter = selected_layers; iter; iter = iter->next)
|
|
g_assert (g_list_find (pika_image_get_selected_layers (image), iter->data));
|
|
|
|
g_list_free (selected_layers);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
restore_recently_closed_multi_column_dock (gconstpointer data)
|
|
{
|
|
Pika *pika = PIKA (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 = pika_ui_find_window (pika_dialog_factory_get_singleton (),
|
|
pika_ui_multicolumn_not_toolbox_window);
|
|
g_assert (dock_window != NULL);
|
|
|
|
/* Count number of docks */
|
|
session_infos = pika_dialog_factory_get_session_infos (pika_dialog_factory_get_singleton ());
|
|
n_session_infos_before_close = g_list_length (session_infos);
|
|
|
|
/* Close one of the dock windows */
|
|
pika_ui_synthesize_delete_event (GTK_WIDGET (dock_window));
|
|
pika_test_run_mainloop_until_idle ();
|
|
|
|
/* Make sure the number of session infos went down */
|
|
session_infos = pika_dialog_factory_get_session_infos (pika_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 available) closed dock and make sure the session
|
|
* infos in the global dock factory are increased again
|
|
*/
|
|
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
|
|
"windows",
|
|
/* FIXME: This is severely hardcoded */
|
|
"windows-recent-0003");
|
|
pika_test_run_mainloop_until_idle ();
|
|
session_infos = pika_dialog_factory_get_session_infos (pika_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);
|
|
}
|
|
|
|
/**
|
|
* 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)
|
|
{
|
|
Pika *pika = PIKA (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 = pika_ui_find_window (pika_dialog_factory_get_singleton (),
|
|
pika_ui_not_toolbox_window);
|
|
g_assert (dock_window != NULL);
|
|
g_assert (gtk_widget_get_visible (dock_window));
|
|
|
|
/* Get the position and size */
|
|
pika_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 */
|
|
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
|
|
"windows",
|
|
"windows-hide-docks");
|
|
pika_test_run_mainloop_until_idle ();
|
|
g_assert (! gtk_widget_get_visible (dock_window));
|
|
|
|
/* Show them again */
|
|
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
|
|
"windows",
|
|
"windows-hide-docks");
|
|
pika_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), <=, PIKA_UI_WINDOW_POSITION_EPSILON);
|
|
g_assert_cmpint ((int)abs (y_before_hide - y_after_show), <=, PIKA_UI_WINDOW_POSITION_EPSILON);
|
|
g_assert_cmpint ((int)abs (w_before_hide - w_after_show), <=, PIKA_UI_WINDOW_POSITION_EPSILON);
|
|
g_assert_cmpint ((int)abs (h_before_hide - h_after_show), <=, PIKA_UI_WINDOW_POSITION_EPSILON);
|
|
}
|
|
|
|
static void
|
|
switch_to_single_window_mode (gconstpointer data)
|
|
{
|
|
Pika *pika = PIKA (data);
|
|
|
|
/* Switch to single-window mode. We consider this test as passed if
|
|
* we don't get any GLib warnings/errors
|
|
*/
|
|
pika_ui_switch_window_mode (pika);
|
|
}
|
|
|
|
static void
|
|
pika_ui_toggle_docks_in_single_window_mode (Pika *pika)
|
|
{
|
|
PikaDisplay *display = PIKA_DISPLAY (pika_get_display_iter (pika)->data);
|
|
PikaDisplayShell *shell = pika_display_get_shell (display);
|
|
GtkWidget *toplevel = GTK_WIDGET (pika_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 */
|
|
pika_test_run_mainloop_until_idle ();
|
|
pika_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 */
|
|
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
|
|
"windows",
|
|
"windows-hide-docks");
|
|
pika_test_run_mainloop_until_idle ();
|
|
|
|
/* Get toplevel coordinate of image origin */
|
|
pika_test_run_mainloop_until_idle ();
|
|
pika_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), <=, PIKA_UI_POSITION_EPSILON);
|
|
g_assert_cmpint ((int)abs (y_after_hide - y_before_hide), <=, PIKA_UI_POSITION_EPSILON);
|
|
}
|
|
|
|
static void
|
|
hide_docks_in_single_window_mode (gconstpointer data)
|
|
{
|
|
Pika *pika = PIKA (data);
|
|
pika_ui_toggle_docks_in_single_window_mode (pika);
|
|
}
|
|
|
|
static void
|
|
show_docks_in_single_window_mode (gconstpointer data)
|
|
{
|
|
Pika *pika = PIKA (data);
|
|
pika_ui_toggle_docks_in_single_window_mode (pika);
|
|
}
|
|
|
|
static void
|
|
maximize_state_in_aux_data (gconstpointer data)
|
|
{
|
|
Pika *pika = PIKA (data);
|
|
PikaDisplay *display = PIKA_DISPLAY (pika_get_display_iter (pika)->data);
|
|
PikaDisplayShell *shell = pika_display_get_shell (display);
|
|
PikaImageWindow *window = pika_display_shell_get_window (shell);
|
|
gint i;
|
|
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
GList *aux_info = NULL;
|
|
PikaSessionInfoAux *target_info;
|
|
gboolean target_max_state;
|
|
|
|
if (i == 0)
|
|
{
|
|
target_info = pika_session_info_aux_new ("maximized" , "yes");
|
|
target_max_state = TRUE;
|
|
}
|
|
else
|
|
{
|
|
target_info = pika_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);
|
|
pika_session_managed_set_aux_info (PIKA_SESSION_MANAGED (window), aux_info);
|
|
g_list_free (aux_info);
|
|
|
|
/* Give the WM a chance to maximize/unmaximize us */
|
|
pika_test_run_mainloop_until_idle ();
|
|
g_usleep (500 * 1000);
|
|
pika_test_run_mainloop_until_idle ();
|
|
|
|
/* Make sure the maximize/unmaximize happened */
|
|
g_assert (pika_image_window_is_maximized (window) == target_max_state);
|
|
|
|
/* Make sure we can read out the window state again */
|
|
aux_info = pika_session_managed_get_aux_info (PIKA_SESSION_MANAGED (window));
|
|
g_assert (g_list_find_custom (aux_info, target_info, pika_ui_aux_data_eqiuvalent));
|
|
g_list_free_full (aux_info,
|
|
(GDestroyNotify) pika_session_info_aux_free);
|
|
|
|
pika_session_info_aux_free (target_info);
|
|
}
|
|
}
|
|
|
|
static void
|
|
switch_back_to_multi_window_mode (gconstpointer data)
|
|
{
|
|
Pika *pika = PIKA (data);
|
|
|
|
/* Switch back to multi-window mode. We consider this test as passed
|
|
* if we don't get any GLib warnings/errors
|
|
*/
|
|
pika_ui_switch_window_mode (pika);
|
|
}
|
|
|
|
static void
|
|
close_image (gconstpointer data)
|
|
{
|
|
Pika *pika = PIKA (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--)
|
|
{
|
|
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
|
|
"edit",
|
|
"edit-undo");
|
|
pika_test_run_mainloop_until_idle ();
|
|
}
|
|
|
|
/* Close the image */
|
|
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
|
|
"view",
|
|
"view-close");
|
|
pika_test_run_mainloop_until_idle ();
|
|
|
|
/* Did it really disappear? */
|
|
g_assert_cmpint (g_list_length (pika_get_image_iter (pika)), ==, 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
|
|
Pika *pika = PIKA (data);
|
|
PikaDisplay *display = PIKA_DISPLAY (pika_get_empty_display (pika));
|
|
PikaDisplayShell *shell = pika_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 */
|
|
pika_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 */
|
|
pika_ui_switch_window_mode (pika);
|
|
|
|
/* 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 */
|
|
pika_ui_switch_window_mode (pika);
|
|
|
|
/* 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... */
|
|
pika_ui_switch_window_mode (pika);
|
|
|
|
/* 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
|
|
*/
|
|
pika_ui_switch_window_mode (pika);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* window_roles:
|
|
* @data:
|
|
*
|
|
* Makes sure that different windows have the right roles specified.
|
|
**/
|
|
static void
|
|
window_roles (gconstpointer data)
|
|
{
|
|
GdkMonitor *monitor = NULL;
|
|
GtkWidget *dock = NULL;
|
|
GtkWidget *toolbox = NULL;
|
|
PikaDockWindow *dock_window = NULL;
|
|
PikaDockWindow *toolbox_window = NULL;
|
|
|
|
monitor = gdk_display_get_primary_monitor (gdk_display_get_default ());
|
|
dock = pika_dock_with_window_new (pika_dialog_factory_get_singleton (),
|
|
monitor,
|
|
FALSE /*toolbox*/);
|
|
toolbox = pika_dock_with_window_new (pika_dialog_factory_get_singleton (),
|
|
monitor,
|
|
TRUE /*toolbox*/);
|
|
dock_window = pika_dock_window_from_dock (PIKA_DOCK (dock));
|
|
toolbox_window = pika_dock_window_from_dock (PIKA_DOCK (toolbox));
|
|
|
|
g_assert_cmpint (g_str_has_prefix (gtk_window_get_role (GTK_WINDOW (dock_window)), "pika-dock-"), ==,
|
|
TRUE);
|
|
g_assert_cmpint (g_str_has_prefix (gtk_window_get_role (GTK_WINDOW (toolbox_window)), "pika-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)
|
|
{
|
|
Pika *pika = PIKA (data);
|
|
PikaContext *user_context = pika_get_user_context (pika);
|
|
PikaToolInfo *tool_info = pika_context_get_tool (user_context);
|
|
|
|
g_assert_cmpstr (tool_info->help_id,
|
|
==,
|
|
"pika-tool-paintbrush");
|
|
}
|
|
|
|
/**
|
|
* pika_ui_synthesize_delete_event:
|
|
* @widget:
|
|
*
|
|
* Synthesize a delete event to @widget.
|
|
**/
|
|
static void
|
|
pika_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
|
|
pika_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 *
|
|
pika_ui_find_window (PikaDialogFactory *dialog_factory,
|
|
PikaUiTestFunc predicate)
|
|
{
|
|
GList *iter = NULL;
|
|
GtkWidget *dock_window = NULL;
|
|
|
|
g_return_val_if_fail (predicate != NULL, NULL);
|
|
|
|
for (iter = pika_dialog_factory_get_session_infos (dialog_factory);
|
|
iter;
|
|
iter = g_list_next (iter))
|
|
{
|
|
GtkWidget *widget = pika_session_info_get_widget (iter->data);
|
|
|
|
if (predicate (G_OBJECT (widget)))
|
|
{
|
|
dock_window = widget;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return dock_window;
|
|
}
|
|
|
|
static gboolean
|
|
pika_ui_not_toolbox_window (GObject *object)
|
|
{
|
|
return (PIKA_IS_DOCK_WINDOW (object) &&
|
|
! pika_dock_window_has_toolbox (PIKA_DOCK_WINDOW (object)));
|
|
}
|
|
|
|
static gboolean
|
|
pika_ui_multicolumn_not_toolbox_window (GObject *object)
|
|
{
|
|
gboolean not_toolbox_window;
|
|
PikaDockWindow *dock_window;
|
|
PikaDockContainer *dock_container;
|
|
GList *docks;
|
|
|
|
if (! PIKA_IS_DOCK_WINDOW (object))
|
|
return FALSE;
|
|
|
|
dock_window = PIKA_DOCK_WINDOW (object);
|
|
dock_container = PIKA_DOCK_CONTAINER (object);
|
|
docks = pika_dock_container_get_docks (dock_container);
|
|
|
|
not_toolbox_window = (! pika_dock_window_has_toolbox (dock_window) &&
|
|
g_list_length (docks) > 1);
|
|
|
|
g_list_free (docks);
|
|
|
|
return not_toolbox_window;
|
|
}
|
|
|
|
static gboolean
|
|
pika_ui_is_pika_layer_list (GObject *object)
|
|
{
|
|
PikaDialogFactoryEntry *entry = NULL;
|
|
|
|
if (! GTK_IS_WIDGET (object))
|
|
return FALSE;
|
|
|
|
pika_dialog_factory_from_widget (GTK_WIDGET (object), &entry);
|
|
|
|
return strcmp (entry->identifier, "pika-layer-list") == 0;
|
|
}
|
|
|
|
static int
|
|
pika_ui_aux_data_eqiuvalent (gconstpointer _a, gconstpointer _b)
|
|
{
|
|
PikaSessionInfoAux *a = (PikaSessionInfoAux*) _a;
|
|
PikaSessionInfoAux *b = (PikaSessionInfoAux*) _b;
|
|
return (strcmp (a->name, b->name) || strcmp (a->value, b->value));
|
|
}
|
|
|
|
static void
|
|
pika_ui_switch_window_mode (Pika *pika)
|
|
{
|
|
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
|
|
"windows",
|
|
"windows-use-single-window-mode");
|
|
pika_test_run_mainloop_until_idle ();
|
|
|
|
/* Add a small sleep to let things stabilize */
|
|
g_usleep (500 * 1000);
|
|
pika_test_run_mainloop_until_idle ();
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
Pika *pika = NULL;
|
|
gint result = -1;
|
|
|
|
pika_test_bail_if_no_display ();
|
|
gtk_test_init (&argc, &argv, NULL);
|
|
|
|
pika_test_utils_setup_menus_path ();
|
|
|
|
/* Start up PIKA */
|
|
pika = pika_init_for_gui_testing (TRUE /*show_gui*/);
|
|
pika_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 (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 */
|
|
g_application_run (pika->app, 0, NULL);
|
|
result = pika_core_app_get_exit_status (PIKA_CORE_APP (pika->app));
|
|
|
|
g_application_quit (G_APPLICATION (pika->app));
|
|
g_clear_object (&pika->app);
|
|
|
|
return result;
|
|
}
|