[gimp] Bug 602223 - Can't hide docks with Tab in single-window mode



commit 18f3be6bd3438c828648a93174595ebd3f4a632c
Author: Martin Nordholts <martinn src gnome org>
Date:   Tue Feb 23 20:21:08 2010 +0100

    Bug 602223 - Can't hide docks with Tab in single-window mode
    
    Add a "hide-docks" config and connect the Windows->Hide docks menu
    item to it. Also connect the image window to the config property so it
    can hide/show its docks when it needs to.
    
    Also add and use a utility function
    gimp_image_window_keep_canvas_pos() to ensure that the image in the
    window remains fixed when toggling visiblity of docks. One problem:
    When GimpDrawTool is active on the canvas, there is flicker. The end
    position is correct though.
    
    Also add regression testing for this fix to test-ui.c

 app/actions/windows-actions.c  |    3 +-
 app/actions/windows-commands.c |    9 ++++
 app/config/gimpguiconfig.c     |   12 +++++
 app/config/gimpguiconfig.h     |    1 +
 app/config/gimprc-blurbs.h     |    3 +
 app/display/gimpimagewindow.c  |   95 ++++++++++++++++++++++++++++++++++++++-
 app/tests/test-ui.c            |   94 +++++++++++++++++++++++++++++++++++++--
 7 files changed, 207 insertions(+), 10 deletions(-)
---
diff --git a/app/actions/windows-actions.c b/app/actions/windows-actions.c
index 8a9832c..bb4dc37 100644
--- a/app/actions/windows-actions.c
+++ b/app/actions/windows-actions.c
@@ -201,8 +201,7 @@ windows_actions_update (GimpActionGroup *group,
         gimp_action_group_set_action_active (group, action, (condition) != 0)
 
   SET_ACTIVE ("windows-use-single-window-mode", config->single_window_mode);
-  SET_ACTIVE ("windows-hide-docks", (gimp_dialog_factories_get_state () !=
-                                     GIMP_DIALOGS_SHOWN));
+  SET_ACTIVE ("windows-hide-docks", config->hide_docks);
 
 #undef SET_ACTIVE
 }
diff --git a/app/actions/windows-commands.c b/app/actions/windows-commands.c
index 7525c44..4c6890c 100644
--- a/app/actions/windows-commands.c
+++ b/app/actions/windows-commands.c
@@ -56,6 +56,11 @@ windows_hide_docks_cmd_callback (GtkAction *action,
   gboolean         active    = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
   GimpDialogsState state     = gimp_dialog_factories_get_state ();
   GimpDialogsState new_state = state;
+  Gimp            *gimp      = NULL;
+  return_if_no_gimp (gimp, data);
+
+  if (GIMP_GUI_CONFIG (gimp->config)->hide_docks == active)
+    return;
 
   /* Make sure the state and toggle action are in sync */
   if (active && state == GIMP_DIALOGS_SHOWN)
@@ -65,6 +70,10 @@ windows_hide_docks_cmd_callback (GtkAction *action,
 
   if (state != new_state)
     gimp_dialog_factories_set_state (new_state);
+
+  g_object_set (gimp->config,
+                "hide-docks", active,
+                NULL);
 }
 
 void
diff --git a/app/config/gimpguiconfig.c b/app/config/gimpguiconfig.c
index 287dfca..d69aef2 100644
--- a/app/config/gimpguiconfig.c
+++ b/app/config/gimpguiconfig.c
@@ -52,6 +52,7 @@ enum
   PROP_RESTORE_SESSION,
   PROP_SAVE_TOOL_OPTIONS,
   PROP_SHOW_TOOLTIPS,
+  PROP_HIDE_DOCKS,
   PROP_SINGLE_WINDOW_MODE,
   PROP_TEAROFF_MENUS,
   PROP_CAN_CHANGE_ACCELS,
@@ -154,6 +155,11 @@ gimp_gui_config_class_init (GimpGuiConfigClass *klass)
                                     TRUE,
                                     GIMP_PARAM_STATIC_STRINGS |
                                     GIMP_CONFIG_PARAM_RESTART);
+  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_HIDE_DOCKS,
+                                    "hide-docks", HIDE_DOCKS_BLURB,
+                                    FALSE,
+                                    GIMP_PARAM_STATIC_STRINGS |
+                                    GIMP_CONFIG_PARAM_RESTART);
   GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_SINGLE_WINDOW_MODE,
                                     "single-window-mode", SINGLE_WINDOW_MODE_BLURB,
                                     FALSE,
@@ -353,6 +359,9 @@ gimp_gui_config_set_property (GObject      *object,
     case PROP_SHOW_TOOLTIPS:
       gui_config->show_tooltips = g_value_get_boolean (value);
       break;
+    case PROP_HIDE_DOCKS:
+      gui_config->hide_docks = g_value_get_boolean (value);
+      break;
     case PROP_SINGLE_WINDOW_MODE:
       gui_config->single_window_mode = g_value_get_boolean (value);
       break;
@@ -474,6 +483,9 @@ gimp_gui_config_get_property (GObject    *object,
     case PROP_SHOW_TOOLTIPS:
       g_value_set_boolean (value, gui_config->show_tooltips);
       break;
+    case PROP_HIDE_DOCKS:
+      g_value_set_boolean (value, gui_config->hide_docks);
+      break;
     case PROP_SINGLE_WINDOW_MODE:
       g_value_set_boolean (value, gui_config->single_window_mode);
       break;
diff --git a/app/config/gimpguiconfig.h b/app/config/gimpguiconfig.h
index 1e6d7f7..5126c65 100644
--- a/app/config/gimpguiconfig.h
+++ b/app/config/gimpguiconfig.h
@@ -46,6 +46,7 @@ struct _GimpGuiConfig
   gboolean             restore_session;
   gboolean             save_tool_options;
   gboolean             show_tooltips;
+  gboolean             hide_docks;
   gboolean             single_window_mode;
   gboolean             tearoff_menus;
   gboolean             can_change_accels;
diff --git a/app/config/gimprc-blurbs.h b/app/config/gimprc-blurbs.h
index 6a269af..746ee82 100644
--- a/app/config/gimprc-blurbs.h
+++ b/app/config/gimprc-blurbs.h
@@ -361,6 +361,9 @@ N_("Show a tooltip when the pointer hovers over an item.")
 #define SINGLE_WINDOW_MODE_BLURB \
 N_("Use GIMP in a single-window mode.")
 
+#define HIDE_DOCKS_BLURB \
+N_("Hide docks and other windows, leaving only image windows.")
+
 #define SPACE_BAR_ACTION_BLURB \
 N_("What to do when the space bar is pressed in the image window.")
 
diff --git a/app/display/gimpimagewindow.c b/app/display/gimpimagewindow.c
index 425fd8b..e242d68 100644
--- a/app/display/gimpimagewindow.c
+++ b/app/display/gimpimagewindow.c
@@ -50,6 +50,7 @@
 #include "gimpdisplayshell-callbacks.h"
 #include "gimpdisplayshell-close.h"
 #include "gimpdisplayshell-scroll.h"
+#include "gimpdisplayshell-transform.h"
 #include "gimpimagewindow.h"
 #include "gimpstatusbar.h"
 
@@ -90,6 +91,14 @@ struct _GimpImageWindowPrivate
   gboolean           is_empty;
 };
 
+typedef struct
+{
+  GimpImageWindow *window;
+  gint             x;
+  gint             y;
+} PosCorrectionData;
+
+
 #define GIMP_IMAGE_WINDOW_GET_PRIVATE(window) \
         G_TYPE_INSTANCE_GET_PRIVATE (window, \
                                      GIMP_TYPE_IMAGE_WINDOW, \
@@ -131,6 +140,10 @@ static void      gimp_image_window_show_tooltip        (GimpUIManager       *man
 static void      gimp_image_window_hide_tooltip        (GimpUIManager       *manager,
                                                         GimpImageWindow     *window);
 
+static void      gimp_image_window_keep_canvas_pos     (GimpImageWindow     *window);
+static void      gimp_image_window_shell_size_allocate (GimpDisplayShell    *shell,
+                                                        GtkAllocation       *allocation,
+                                                        PosCorrectionData   *data);
 static gboolean  gimp_image_window_shell_events        (GtkWidget           *widget,
                                                         GdkEvent            *event,
                                                         GimpImageWindow     *window);
@@ -344,6 +357,9 @@ gimp_image_window_constructor (GType                  type,
   g_signal_connect_object (config, "notify::single-window-mode",
                            G_CALLBACK (gimp_image_window_config_notify),
                            window, G_CONNECT_SWAPPED);
+  g_signal_connect_object (config, "notify::hide-docks",
+                           G_CALLBACK (gimp_image_window_config_notify),
+                           window, G_CONNECT_SWAPPED);
   return object;
 }
 
@@ -1045,10 +1061,15 @@ gimp_image_window_config_notify (GimpImageWindow *window,
 {
   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
 
-  if (strcmp (pspec->name, "single-window-mode") == 0)
+  if (strcmp (pspec->name, "single-window-mode") == 0 ||
+      strcmp (pspec->name, "hide-docks")         == 0)
     {
-      gtk_widget_set_visible (private->left_docks, config->single_window_mode);
-      gtk_widget_set_visible (private->right_docks, config->single_window_mode);
+      gboolean show_docks = (config->single_window_mode &&
+                             ! config->hide_docks);
+
+      gimp_image_window_keep_canvas_pos (window);
+      gtk_widget_set_visible (private->left_docks, show_docks);
+      gtk_widget_set_visible (private->right_docks, show_docks);
     }
 }
 
@@ -1067,6 +1088,74 @@ gimp_image_window_hide_tooltip (GimpUIManager   *manager,
   gimp_statusbar_pop (statusbar, "menu-tooltip");
 }
 
+/**
+ * gimp_image_window_keep_canvas_pos:
+ * @window:
+ *
+ * Stores the coordinate of the current shell image origin in
+ * GtkWindow coordinates and on the first size-allocate sets the
+ * offsets in the shell so the image origin remains the same in
+ * GtkWindow coordinates.
+ *
+ * Exampe use case: The user hides docks attached to the side of image
+ * windows. You want the image to remain fixed on the screen though,
+ * so you use this function to keep the image fixed after the docks
+ * have been hidden.
+ **/
+static void
+gimp_image_window_keep_canvas_pos (GimpImageWindow *window)
+{
+  GimpDisplayShell  *shell                 = gimp_image_window_get_active_shell (window);
+  gint               image_origin_shell_x  = -1;
+  gint               image_origin_shell_y  = -1;
+  gint               image_origin_window_x = -1;
+  gint               image_origin_window_y = -1;
+  PosCorrectionData *data                  = NULL;
+
+  gimp_display_shell_transform_xy (shell,
+                                   0.0, 0.0,
+                                   &image_origin_shell_x, &image_origin_shell_y,
+                                   FALSE /*use_offsets*/);
+  gtk_widget_translate_coordinates (GTK_WIDGET (shell),
+                                    GTK_WIDGET (window),
+                                    image_origin_shell_x, image_origin_shell_y,
+                                    &image_origin_window_x, &image_origin_window_y);
+
+  data         = g_new0 (PosCorrectionData, 1);
+  data->window = window;
+  data->x      = image_origin_window_x;
+  data->y      = image_origin_window_y;
+  g_signal_connect_data (shell, "size-allocate",
+                         G_CALLBACK (gimp_image_window_shell_size_allocate),
+                         data, (GClosureNotify) g_free,
+                         G_CONNECT_AFTER);
+}
+
+static void
+gimp_image_window_shell_size_allocate (GimpDisplayShell  *shell,
+                                         GtkAllocation     *allocation,
+                                         PosCorrectionData *data)
+{
+  GimpImageWindow *window               = data->window;
+  gint             image_origin_shell_x = -1;
+  gint             image_origin_shell_y = -1;
+
+  gtk_widget_translate_coordinates (GTK_WIDGET (window),
+                                    GTK_WIDGET (shell),
+                                    data->x, data->y,
+                                    &image_origin_shell_x, &image_origin_shell_y);
+
+  /* Note that the shell offset isn't the offset of the image into the
+   * shell, but the offset of the shell relative to the image,
+   * therefor we need to negate
+   */
+  gimp_display_shell_scroll_set_offset (shell, -image_origin_shell_x, -image_origin_shell_y);
+
+  g_signal_handlers_disconnect_by_func (shell,
+                                        gimp_image_window_shell_size_allocate,
+                                        data);
+}
+
 static gboolean
 gimp_image_window_shell_events (GtkWidget       *widget,
                                 GdkEvent        *event,
diff --git a/app/tests/test-ui.c b/app/tests/test-ui.c
index 83da321..ef9cd8a 100644
--- a/app/tests/test-ui.c
+++ b/app/tests/test-ui.c
@@ -28,6 +28,8 @@
 #include "dialogs/dialogs.h"
 
 #include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimpdisplayshell-transform.h"
 #include "display/gimpimagewindow.h"
 
 #include "widgets/gimpdialogfactory.h"
@@ -48,7 +50,10 @@
 #include "gimp-app-test-utils.h"
 
 
-#define GIMP_UI_POSITION_EPSILON 10
+#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
@@ -67,6 +72,10 @@ static void            gimp_ui_tab_toggle_dont_change_position  (GimpTestFixture
                                                                  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);
@@ -122,6 +131,18 @@ int main(int argc, char **argv)
               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,
@@ -345,10 +366,10 @@ gimp_ui_tab_toggle_dont_change_position (GimpTestFixture *fixture,
   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_POSITION_EPSILON);
-  g_assert_cmpint ((int)abs (y_before_hide - y_after_show), <, GIMP_UI_POSITION_EPSILON);
-  g_assert_cmpint ((int)abs (w_before_hide - w_after_show), <, GIMP_UI_POSITION_EPSILON);
-  g_assert_cmpint ((int)abs (h_before_hide - h_after_show), <, GIMP_UI_POSITION_EPSILON);
+  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
@@ -367,6 +388,69 @@ gimp_ui_switch_to_single_window_mode (GimpTestFixture *fixture,
 }
 
 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)
 {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]