1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <math.h>
21 
22 #include <gegl.h>
23 #include <gtk/gtk.h>
24 
25 #ifdef G_OS_WIN32
26 #include <windef.h>
27 #include <winbase.h>
28 #include <windows.h>
29 #endif
30 
31 #ifdef GDK_WINDOWING_QUARTZ
32 #import <AppKit/AppKit.h>
33 #include <gdk/gdkquartz.h>
34 #endif /* !GDK_WINDOWING_QUARTZ */
35 
36 #include "libgimpmath/gimpmath.h"
37 #include "libgimpcolor/gimpcolor.h"
38 #include "libgimpwidgets/gimpwidgets.h"
39 
40 #include "display-types.h"
41 
42 #include "config/gimpguiconfig.h"
43 
44 #include "core/gimp.h"
45 #include "core/gimpcontext.h"
46 #include "core/gimpimage.h"
47 #include "core/gimpprogress.h"
48 #include "core/gimpcontainer.h"
49 
50 #include "widgets/gimpactiongroup.h"
51 #include "widgets/gimpdialogfactory.h"
52 #include "widgets/gimpdock.h"
53 #include "widgets/gimpdockbook.h"
54 #include "widgets/gimpdockcolumns.h"
55 #include "widgets/gimpdockcontainer.h"
56 #include "widgets/gimphelp-ids.h"
57 #include "widgets/gimpmenufactory.h"
58 #include "widgets/gimpsessioninfo.h"
59 #include "widgets/gimpsessioninfo-aux.h"
60 #include "widgets/gimpsessionmanaged.h"
61 #include "widgets/gimpsessioninfo-dock.h"
62 #include "widgets/gimptoolbox.h"
63 #include "widgets/gimpuimanager.h"
64 #include "widgets/gimpview.h"
65 #include "widgets/gimpviewrenderer.h"
66 #include "widgets/gimpwidgets-utils.h"
67 
68 #include "gimpdisplay.h"
69 #include "gimpdisplay-foreach.h"
70 #include "gimpdisplayshell.h"
71 #include "gimpdisplayshell-appearance.h"
72 #include "gimpdisplayshell-close.h"
73 #include "gimpdisplayshell-scale.h"
74 #include "gimpdisplayshell-scroll.h"
75 #include "gimpdisplayshell-tool-events.h"
76 #include "gimpdisplayshell-transform.h"
77 #include "gimpimagewindow.h"
78 #include "gimpstatusbar.h"
79 
80 #include "gimp-log.h"
81 #include "gimp-priorities.h"
82 
83 #include "gimp-intl.h"
84 
85 
86 #define GIMP_EMPTY_IMAGE_WINDOW_ENTRY_ID   "gimp-empty-image-window"
87 #define GIMP_SINGLE_IMAGE_WINDOW_ENTRY_ID  "gimp-single-image-window"
88 
89 /* The width of the left and right dock areas */
90 #define GIMP_IMAGE_WINDOW_LEFT_DOCKS_WIDTH  "left-docks-width"
91 #define GIMP_IMAGE_WINDOW_RIGHT_DOCKS_WIDTH "right-docks-width"
92 
93 /* deprecated property: GtkPaned position of the right docks area */
94 #define GIMP_IMAGE_WINDOW_RIGHT_DOCKS_POS  "right-docks-position"
95 
96 /* Whether the window's maximized or not */
97 #define GIMP_IMAGE_WINDOW_MAXIMIZED        "maximized"
98 
99 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
100 #define NSWindowCollectionBehaviorFullScreenAuxiliary (1 << 8)
101 #endif
102 
103 
104 enum
105 {
106   PROP_0,
107   PROP_GIMP,
108   PROP_DIALOG_FACTORY,
109   PROP_INITIAL_SCREEN,
110   PROP_INITIAL_MONITOR
111 };
112 
113 
114 typedef struct _GimpImageWindowPrivate GimpImageWindowPrivate;
115 
116 struct _GimpImageWindowPrivate
117 {
118   Gimp              *gimp;
119   GimpUIManager     *menubar_manager;
120   GimpDialogFactory *dialog_factory;
121 
122   GList             *shells;
123   GimpDisplayShell  *active_shell;
124 
125   GtkWidget         *main_vbox;
126   GtkWidget         *menubar;
127   GtkWidget         *hbox;
128   GtkWidget         *left_hpane;
129   GtkWidget         *left_docks;
130   GtkWidget         *right_hpane;
131   GtkWidget         *notebook;
132   GtkWidget         *right_docks;
133 
134   GdkWindowState     window_state;
135 
136   const gchar       *entry_id;
137 
138   GdkScreen         *initial_screen;
139   gint               initial_monitor;
140 
141   gint               suspend_keep_pos;
142 
143   gint               update_ui_manager_idle_id;
144 };
145 
146 typedef struct
147 {
148   gint canvas_x;
149   gint canvas_y;
150   gint window_x;
151   gint window_y;
152 } PosCorrectionData;
153 
154 
155 #define GIMP_IMAGE_WINDOW_GET_PRIVATE(window) \
156         ((GimpImageWindowPrivate *) gimp_image_window_get_instance_private ((GimpImageWindow *) (window)))
157 
158 
159 /*  local function prototypes  */
160 
161 static void      gimp_image_window_dock_container_iface_init
162                                                        (GimpDockContainerInterface
163                                                                             *iface);
164 static void      gimp_image_window_session_managed_iface_init
165                                                        (GimpSessionManagedInterface
166                                                                             *iface);
167 static void      gimp_image_window_constructed         (GObject             *object);
168 static void      gimp_image_window_dispose             (GObject             *object);
169 static void      gimp_image_window_finalize            (GObject             *object);
170 static void      gimp_image_window_set_property        (GObject             *object,
171                                                         guint                property_id,
172                                                         const GValue        *value,
173                                                         GParamSpec          *pspec);
174 static void      gimp_image_window_get_property        (GObject             *object,
175                                                         guint                property_id,
176                                                         GValue              *value,
177                                                         GParamSpec          *pspec);
178 
179 static void      gimp_image_window_map                 (GtkWidget           *widget);
180 static gboolean  gimp_image_window_delete_event        (GtkWidget           *widget,
181                                                         GdkEventAny         *event);
182 static gboolean  gimp_image_window_configure_event     (GtkWidget           *widget,
183                                                         GdkEventConfigure   *event);
184 static gboolean  gimp_image_window_window_state_event  (GtkWidget           *widget,
185                                                         GdkEventWindowState *event);
186 static void      gimp_image_window_style_set           (GtkWidget           *widget,
187                                                         GtkStyle            *prev_style);
188 
189 static void      gimp_image_window_monitor_changed     (GimpWindow          *window,
190                                                         GdkScreen           *screen,
191                                                         gint                 monitor);
192 
193 static GList *   gimp_image_window_get_docks           (GimpDockContainer   *dock_container);
194 static GimpDialogFactory *
195                  gimp_image_window_dock_container_get_dialog_factory
196                                                        (GimpDockContainer   *dock_container);
197 static GimpUIManager *
198                  gimp_image_window_dock_container_get_ui_manager
199                                                        (GimpDockContainer   *dock_container);
200 static void      gimp_image_window_add_dock            (GimpDockContainer   *dock_container,
201                                                         GimpDock            *dock,
202                                                         GimpSessionInfoDock *dock_info);
203 static GimpAlignmentType
204                  gimp_image_window_get_dock_side       (GimpDockContainer   *dock_container,
205                                                         GimpDock            *dock);
206 static GList   * gimp_image_window_get_aux_info        (GimpSessionManaged  *session_managed);
207 static void      gimp_image_window_set_aux_info        (GimpSessionManaged  *session_managed,
208                                                         GList               *aux_info);
209 
210 static void      gimp_image_window_config_notify       (GimpImageWindow     *window,
211                                                         GParamSpec          *pspec,
212                                                         GimpGuiConfig       *config);
213 static void      gimp_image_window_session_clear       (GimpImageWindow     *window);
214 static void      gimp_image_window_session_apply       (GimpImageWindow     *window,
215                                                         const gchar         *entry_id,
216                                                         GdkScreen           *screen,
217                                                         gint                 monitor);
218 static void      gimp_image_window_session_update      (GimpImageWindow     *window,
219                                                         GimpDisplay         *new_display,
220                                                         const gchar         *new_entry_id,
221                                                         GdkScreen           *screen,
222                                                         gint                 monitor);
223 static const gchar *
224                  gimp_image_window_config_to_entry_id  (GimpGuiConfig       *config);
225 static void      gimp_image_window_show_tooltip        (GimpUIManager       *manager,
226                                                         const gchar         *tooltip,
227                                                         GimpImageWindow     *window);
228 static void      gimp_image_window_hide_tooltip        (GimpUIManager       *manager,
229                                                         GimpImageWindow     *window);
230 static gboolean  gimp_image_window_update_ui_manager_idle
231                                                        (GimpImageWindow     *window);
232 static void      gimp_image_window_update_ui_manager   (GimpImageWindow     *window);
233 
234 static void      gimp_image_window_shell_size_allocate (GimpDisplayShell    *shell,
235                                                         GtkAllocation       *allocation,
236                                                         PosCorrectionData   *data);
237 static gboolean  gimp_image_window_shell_events        (GtkWidget           *widget,
238                                                         GdkEvent            *event,
239                                                         GimpImageWindow     *window);
240 
241 static void      gimp_image_window_switch_page         (GtkNotebook         *notebook,
242                                                         gpointer             page,
243                                                         gint                 page_num,
244                                                         GimpImageWindow     *window);
245 static void      gimp_image_window_page_removed        (GtkNotebook         *notebook,
246                                                         GtkWidget           *widget,
247                                                         gint                 page_num,
248                                                         GimpImageWindow     *window);
249 static void      gimp_image_window_page_reordered      (GtkNotebook         *notebook,
250                                                         GtkWidget           *widget,
251                                                         gint                 page_num,
252                                                         GimpImageWindow     *window);
253 static void      gimp_image_window_disconnect_from_active_shell
254                                                        (GimpImageWindow *window);
255 
256 static void      gimp_image_window_image_notify        (GimpDisplay         *display,
257                                                         const GParamSpec    *pspec,
258                                                         GimpImageWindow     *window);
259 static void      gimp_image_window_shell_scaled        (GimpDisplayShell    *shell,
260                                                         GimpImageWindow     *window);
261 static void      gimp_image_window_shell_rotated       (GimpDisplayShell    *shell,
262                                                         GimpImageWindow     *window);
263 static void      gimp_image_window_shell_title_notify  (GimpDisplayShell    *shell,
264                                                         const GParamSpec    *pspec,
265                                                         GimpImageWindow     *window);
266 static void      gimp_image_window_shell_icon_notify   (GimpDisplayShell    *shell,
267                                                         const GParamSpec    *pspec,
268                                                         GimpImageWindow     *window);
269 static GtkWidget *
270                  gimp_image_window_create_tab_label    (GimpImageWindow     *window,
271                                                         GimpDisplayShell    *shell);
272 static void      gimp_image_window_update_tab_labels   (GimpImageWindow     *window);
273 
274 
275 G_DEFINE_TYPE_WITH_CODE (GimpImageWindow, gimp_image_window, GIMP_TYPE_WINDOW,
276                          G_ADD_PRIVATE (GimpImageWindow)
277                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCK_CONTAINER,
278                                                 gimp_image_window_dock_container_iface_init)
279                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_SESSION_MANAGED,
280                                                 gimp_image_window_session_managed_iface_init))
281 
282 #define parent_class gimp_image_window_parent_class
283 
284 
285 static const gchar image_window_rc_style[] =
286   "style \"fullscreen-menubar-style\"\n"
287   "{\n"
288   "  GtkMenuBar::shadow-type      = none\n"
289   "  GtkMenuBar::internal-padding = 0\n"
290   "}\n"
291   "widget \"*.gimp-menubar-fullscreen\" style \"fullscreen-menubar-style\"\n";
292 
293 static void
gimp_image_window_class_init(GimpImageWindowClass * klass)294 gimp_image_window_class_init (GimpImageWindowClass *klass)
295 {
296   GObjectClass    *object_class = G_OBJECT_CLASS (klass);
297   GtkWidgetClass  *widget_class = GTK_WIDGET_CLASS (klass);
298   GimpWindowClass *window_class = GIMP_WINDOW_CLASS (klass);
299 
300   object_class->constructed        = gimp_image_window_constructed;
301   object_class->dispose            = gimp_image_window_dispose;
302   object_class->finalize           = gimp_image_window_finalize;
303   object_class->set_property       = gimp_image_window_set_property;
304   object_class->get_property       = gimp_image_window_get_property;
305 
306   widget_class->map                = gimp_image_window_map;
307   widget_class->delete_event       = gimp_image_window_delete_event;
308   widget_class->configure_event    = gimp_image_window_configure_event;
309   widget_class->window_state_event = gimp_image_window_window_state_event;
310   widget_class->style_set          = gimp_image_window_style_set;
311 
312   window_class->monitor_changed    = gimp_image_window_monitor_changed;
313 
314   g_object_class_install_property (object_class, PROP_GIMP,
315                                    g_param_spec_object ("gimp",
316                                                         NULL, NULL,
317                                                         GIMP_TYPE_GIMP,
318                                                         GIMP_PARAM_WRITABLE |
319                                                         G_PARAM_CONSTRUCT_ONLY));
320 
321   g_object_class_install_property (object_class, PROP_DIALOG_FACTORY,
322                                    g_param_spec_object ("dialog-factory",
323                                                         NULL, NULL,
324                                                         GIMP_TYPE_DIALOG_FACTORY,
325                                                         GIMP_PARAM_READWRITE |
326                                                         G_PARAM_CONSTRUCT_ONLY));
327 
328   g_object_class_install_property (object_class, PROP_INITIAL_SCREEN,
329                                    g_param_spec_object ("initial-screen",
330                                                         NULL, NULL,
331                                                         GDK_TYPE_SCREEN,
332                                                         GIMP_PARAM_READWRITE |
333                                                         G_PARAM_CONSTRUCT_ONLY));
334   g_object_class_install_property (object_class, PROP_INITIAL_MONITOR,
335                                    g_param_spec_int ("initial-monitor",
336                                                      NULL, NULL,
337                                                      0, 16, 0,
338                                                      GIMP_PARAM_READWRITE |
339                                                      G_PARAM_CONSTRUCT_ONLY));
340 
341   gtk_rc_parse_string (image_window_rc_style);
342 }
343 
344 static void
gimp_image_window_init(GimpImageWindow * window)345 gimp_image_window_init (GimpImageWindow *window)
346 {
347   static gint  role_serial = 1;
348   gchar       *role;
349 
350   role = g_strdup_printf ("gimp-image-window-%d", role_serial++);
351   gtk_window_set_role (GTK_WINDOW (window), role);
352   g_free (role);
353 
354   gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
355 }
356 
357 static void
gimp_image_window_dock_container_iface_init(GimpDockContainerInterface * iface)358 gimp_image_window_dock_container_iface_init (GimpDockContainerInterface *iface)
359 {
360   iface->get_docks          = gimp_image_window_get_docks;
361   iface->get_dialog_factory = gimp_image_window_dock_container_get_dialog_factory;
362   iface->get_ui_manager     = gimp_image_window_dock_container_get_ui_manager;
363   iface->add_dock           = gimp_image_window_add_dock;
364   iface->get_dock_side      = gimp_image_window_get_dock_side;
365 }
366 
367 static void
gimp_image_window_session_managed_iface_init(GimpSessionManagedInterface * iface)368 gimp_image_window_session_managed_iface_init (GimpSessionManagedInterface *iface)
369 {
370   iface->get_aux_info = gimp_image_window_get_aux_info;
371   iface->set_aux_info = gimp_image_window_set_aux_info;
372 }
373 
374 static void
gimp_image_window_constructed(GObject * object)375 gimp_image_window_constructed (GObject *object)
376 {
377   GimpImageWindow        *window  = GIMP_IMAGE_WINDOW (object);
378   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
379   GimpMenuFactory        *menu_factory;
380   GimpGuiConfig          *config;
381 
382   G_OBJECT_CLASS (parent_class)->constructed (object);
383 
384   gimp_assert (GIMP_IS_GIMP (private->gimp));
385   gimp_assert (GIMP_IS_DIALOG_FACTORY (private->dialog_factory));
386 
387   menu_factory = gimp_dialog_factory_get_menu_factory (private->dialog_factory);
388 
389   private->menubar_manager = gimp_menu_factory_manager_new (menu_factory,
390                                                             "<Image>",
391                                                             window,
392                                                             FALSE);
393 
394   g_signal_connect_object (private->dialog_factory, "dock-window-added",
395                            G_CALLBACK (gimp_image_window_update_ui_manager),
396                            window, G_CONNECT_SWAPPED);
397   g_signal_connect_object (private->dialog_factory, "dock-window-removed",
398                            G_CALLBACK (gimp_image_window_update_ui_manager),
399                            window, G_CONNECT_SWAPPED);
400 
401   gtk_window_add_accel_group (GTK_WINDOW (window),
402                               gimp_ui_manager_get_accel_group (private->menubar_manager));
403 
404   g_signal_connect (private->menubar_manager, "show-tooltip",
405                     G_CALLBACK (gimp_image_window_show_tooltip),
406                     window);
407   g_signal_connect (private->menubar_manager, "hide-tooltip",
408                     G_CALLBACK (gimp_image_window_hide_tooltip),
409                     window);
410 
411   config = GIMP_GUI_CONFIG (private->gimp->config);
412 
413   /* Create the window toplevel container */
414   private->main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
415   gtk_container_add (GTK_CONTAINER (window), private->main_vbox);
416   gtk_widget_show (private->main_vbox);
417 
418   /* Create the menubar */
419 #ifndef GDK_WINDOWING_QUARTZ
420   private->menubar = gimp_ui_manager_get_widget (private->menubar_manager,
421                                                  "/image-menubar");
422 #endif /* !GDK_WINDOWING_QUARTZ */
423   if (private->menubar)
424     {
425       gtk_box_pack_start (GTK_BOX (private->main_vbox),
426                           private->menubar, FALSE, FALSE, 0);
427 
428       /*  make sure we can activate accels even if the menubar is invisible
429        *  (see https://bugzilla.gnome.org/show_bug.cgi?id=137151)
430        */
431       g_signal_connect (private->menubar, "can-activate-accel",
432                         G_CALLBACK (gtk_true),
433                         NULL);
434 
435       /*  active display callback  */
436       g_signal_connect (private->menubar, "button-press-event",
437                         G_CALLBACK (gimp_image_window_shell_events),
438                         window);
439       g_signal_connect (private->menubar, "button-release-event",
440                         G_CALLBACK (gimp_image_window_shell_events),
441                         window);
442       g_signal_connect (private->menubar, "key-press-event",
443                         G_CALLBACK (gimp_image_window_shell_events),
444                         window);
445     }
446 
447   /* Create the hbox that contains docks and images */
448   private->hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
449   gtk_box_pack_start (GTK_BOX (private->main_vbox), private->hbox,
450                       TRUE, TRUE, 0);
451   gtk_widget_show (private->hbox);
452 
453   /* Create the left pane */
454   private->left_hpane = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
455   gtk_box_pack_start (GTK_BOX (private->hbox), private->left_hpane,
456                       TRUE, TRUE, 0);
457   gtk_widget_show (private->left_hpane);
458 
459   /* Create the left dock columns widget */
460   private->left_docks =
461     gimp_dock_columns_new (gimp_get_user_context (private->gimp),
462                            private->dialog_factory,
463                            private->menubar_manager);
464   gtk_paned_pack1 (GTK_PANED (private->left_hpane), private->left_docks,
465                    FALSE, FALSE);
466   gtk_widget_set_visible (private->left_docks, config->single_window_mode);
467 
468   /* Create the right pane */
469   private->right_hpane = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
470   gtk_paned_pack2 (GTK_PANED (private->left_hpane), private->right_hpane,
471                    TRUE, FALSE);
472   gtk_widget_show (private->right_hpane);
473 
474   /* Create notebook that contains images */
475   private->notebook = gtk_notebook_new ();
476   gtk_notebook_set_scrollable (GTK_NOTEBOOK (private->notebook), TRUE);
477   gtk_notebook_set_show_border (GTK_NOTEBOOK (private->notebook), FALSE);
478   gtk_notebook_set_show_tabs (GTK_NOTEBOOK (private->notebook), FALSE);
479   gtk_notebook_set_tab_pos (GTK_NOTEBOOK (private->notebook), GTK_POS_TOP);
480 
481   gtk_paned_pack1 (GTK_PANED (private->right_hpane), private->notebook,
482                    TRUE, TRUE);
483 
484   g_signal_connect (private->notebook, "switch-page",
485                     G_CALLBACK (gimp_image_window_switch_page),
486                     window);
487   g_signal_connect (private->notebook, "page-removed",
488                     G_CALLBACK (gimp_image_window_page_removed),
489                     window);
490   g_signal_connect (private->notebook, "page-reordered",
491                     G_CALLBACK (gimp_image_window_page_reordered),
492                     window);
493   gtk_widget_show (private->notebook);
494 
495   /* Create the right dock columns widget */
496   private->right_docks =
497     gimp_dock_columns_new (gimp_get_user_context (private->gimp),
498                            private->dialog_factory,
499                            private->menubar_manager);
500   gtk_paned_pack2 (GTK_PANED (private->right_hpane), private->right_docks,
501                    FALSE, FALSE);
502   gtk_widget_set_visible (private->right_docks, config->single_window_mode);
503 
504   g_signal_connect_object (config, "notify::single-window-mode",
505                            G_CALLBACK (gimp_image_window_config_notify),
506                            window, G_CONNECT_SWAPPED);
507   g_signal_connect_object (config, "notify::show-tabs",
508                            G_CALLBACK (gimp_image_window_config_notify),
509                            window, G_CONNECT_SWAPPED);
510   g_signal_connect_object (config, "notify::hide-docks",
511                            G_CALLBACK (gimp_image_window_config_notify),
512                            window, G_CONNECT_SWAPPED);
513   g_signal_connect_object (config, "notify::tabs-position",
514                            G_CALLBACK (gimp_image_window_config_notify),
515                            window, G_CONNECT_SWAPPED);
516 
517   gimp_image_window_session_update (window,
518                                     NULL /*new_display*/,
519                                     gimp_image_window_config_to_entry_id (config),
520                                     private->initial_screen,
521                                     private->initial_monitor);
522 }
523 
524 static void
gimp_image_window_dispose(GObject * object)525 gimp_image_window_dispose (GObject *object)
526 {
527   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (object);
528 
529   if (private->dialog_factory)
530     {
531       g_signal_handlers_disconnect_by_func (private->dialog_factory,
532                                             gimp_image_window_update_ui_manager,
533                                             object);
534       private->dialog_factory = NULL;
535     }
536 
537   g_clear_object (&private->menubar_manager);
538 
539   if (private->update_ui_manager_idle_id)
540     {
541       g_source_remove (private->update_ui_manager_idle_id);
542       private->update_ui_manager_idle_id = 0;
543     }
544 
545   G_OBJECT_CLASS (parent_class)->dispose (object);
546 }
547 
548 static void
gimp_image_window_finalize(GObject * object)549 gimp_image_window_finalize (GObject *object)
550 {
551   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (object);
552 
553   if (private->shells)
554     {
555       g_list_free (private->shells);
556       private->shells = NULL;
557     }
558 
559   G_OBJECT_CLASS (parent_class)->finalize (object);
560 }
561 
562 static void
gimp_image_window_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)563 gimp_image_window_set_property (GObject      *object,
564                                 guint         property_id,
565                                 const GValue *value,
566                                 GParamSpec   *pspec)
567 {
568   GimpImageWindow        *window  = GIMP_IMAGE_WINDOW (object);
569   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
570 
571   switch (property_id)
572     {
573     case PROP_GIMP:
574       private->gimp = g_value_get_object (value);
575       break;
576     case PROP_DIALOG_FACTORY:
577       private->dialog_factory = g_value_get_object (value);
578       break;
579     case PROP_INITIAL_SCREEN:
580       private->initial_screen = g_value_get_object (value);
581       break;
582     case PROP_INITIAL_MONITOR:
583       private->initial_monitor = g_value_get_int (value);
584       break;
585 
586     default:
587       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
588       break;
589     }
590 }
591 
592 static void
gimp_image_window_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)593 gimp_image_window_get_property (GObject    *object,
594                                 guint       property_id,
595                                 GValue     *value,
596                                 GParamSpec *pspec)
597 {
598   GimpImageWindow        *window  = GIMP_IMAGE_WINDOW (object);
599   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
600 
601   switch (property_id)
602     {
603     case PROP_GIMP:
604       g_value_set_object (value, private->gimp);
605       break;
606     case PROP_DIALOG_FACTORY:
607       g_value_set_object (value, private->dialog_factory);
608       break;
609     case PROP_INITIAL_SCREEN:
610       g_value_set_object (value, private->initial_screen);
611       break;
612     case PROP_INITIAL_MONITOR:
613       g_value_set_int (value, private->initial_monitor);
614       break;
615 
616     default:
617       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
618       break;
619     }
620 }
621 
622 static void
gimp_image_window_map(GtkWidget * widget)623 gimp_image_window_map (GtkWidget *widget)
624 {
625 #ifdef GDK_WINDOWING_QUARTZ
626   GdkWindow *gdk_window;
627   NSWindow  *ns_window;
628 #endif /* !GDK_WINDOWING_QUARTZ */
629 
630   GTK_WIDGET_CLASS (parent_class)->map (widget);
631 
632 #ifdef GDK_WINDOWING_QUARTZ
633   gdk_window = gtk_widget_get_window (GTK_WIDGET (widget));
634   ns_window = gdk_quartz_window_get_nswindow (gdk_window);
635 
636   /* Disable the new-style full screen mode. For now only the "old-style"
637    * full screen mode, via the "View" menu, is supported. In the future, and
638    * as soon as GTK+ has proper support for this, we will migrate to the
639    * new-style full screen mode.
640    */
641   ns_window.collectionBehavior |= NSWindowCollectionBehaviorFullScreenAuxiliary;
642 #endif /* !GDK_WINDOWING_QUARTZ */
643 }
644 
645 static gboolean
gimp_image_window_delete_event(GtkWidget * widget,GdkEventAny * event)646 gimp_image_window_delete_event (GtkWidget   *widget,
647                                 GdkEventAny *event)
648 {
649   GimpImageWindow        *window  = GIMP_IMAGE_WINDOW (widget);
650   GimpDisplayShell       *shell   = gimp_image_window_get_active_shell (window);
651   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
652   GimpGuiConfig          *config  = GIMP_GUI_CONFIG (private->gimp->config);
653 
654   if (config->single_window_mode)
655     gimp_ui_manager_activate_action (gimp_image_window_get_ui_manager (window),
656                                      "file", "file-quit");
657   else if (shell)
658     gimp_display_shell_close (shell, FALSE);
659 
660   return TRUE;
661 }
662 
663 static gboolean
gimp_image_window_configure_event(GtkWidget * widget,GdkEventConfigure * event)664 gimp_image_window_configure_event (GtkWidget         *widget,
665                                    GdkEventConfigure *event)
666 {
667   GimpImageWindow *window = GIMP_IMAGE_WINDOW (widget);
668   GtkAllocation    allocation;
669   gint             current_width;
670   gint             current_height;
671 
672   gtk_widget_get_allocation (widget, &allocation);
673 
674   /* Grab the size before we run the parent implementation */
675   current_width  = allocation.width;
676   current_height = allocation.height;
677 
678   /* Run the parent implementation */
679   if (GTK_WIDGET_CLASS (parent_class)->configure_event)
680     GTK_WIDGET_CLASS (parent_class)->configure_event (widget, event);
681 
682   /* If the window size has changed, make sure additoinal logic is run
683    * in the display shell's size-allocate
684    */
685   if (event->width  != current_width ||
686       event->height != current_height)
687     {
688       /* FIXME multiple shells */
689       GimpDisplayShell *shell = gimp_image_window_get_active_shell (window);
690 
691       if (shell && gimp_display_get_image (shell->display))
692         shell->size_allocate_from_configure_event = TRUE;
693     }
694 
695   return TRUE;
696 }
697 
698 static gboolean
gimp_image_window_window_state_event(GtkWidget * widget,GdkEventWindowState * event)699 gimp_image_window_window_state_event (GtkWidget           *widget,
700                                       GdkEventWindowState *event)
701 {
702   GimpImageWindow        *window  = GIMP_IMAGE_WINDOW (widget);
703   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
704   GimpDisplayShell       *shell   = gimp_image_window_get_active_shell (window);
705 
706   if (! shell)
707     return FALSE;
708 
709   private->window_state = event->new_window_state;
710 
711   if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
712     {
713       gboolean fullscreen = gimp_image_window_get_fullscreen (window);
714 
715       GIMP_LOG (WM, "Image window '%s' [%p] set fullscreen %s",
716                 gtk_window_get_title (GTK_WINDOW (widget)),
717                 widget,
718                 fullscreen ? "TRUE" : "FALSE");
719 
720       if (private->menubar)
721         gtk_widget_set_name (private->menubar,
722                              fullscreen ? "gimp-menubar-fullscreen" : NULL);
723 
724       gimp_image_window_suspend_keep_pos (window);
725       gimp_display_shell_appearance_update (shell);
726       gimp_image_window_resume_keep_pos (window);
727     }
728 
729   if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED)
730     {
731       GimpStatusbar *statusbar = gimp_display_shell_get_statusbar (shell);
732       gboolean       iconified = gimp_image_window_is_iconified (window);
733 
734       GIMP_LOG (WM, "Image window '%s' [%p] set %s",
735                 gtk_window_get_title (GTK_WINDOW (widget)),
736                 widget,
737                 iconified ? "iconified" : "uniconified");
738 
739       if (iconified)
740         {
741           if (gimp_displays_get_num_visible (private->gimp) == 0)
742             {
743               GIMP_LOG (WM, "No displays visible any longer");
744 
745               gimp_dialog_factory_hide_with_display (private->dialog_factory);
746             }
747         }
748       else
749         {
750           gimp_dialog_factory_show_with_display (private->dialog_factory);
751         }
752 
753       if (gimp_progress_is_active (GIMP_PROGRESS (statusbar)))
754         {
755           if (iconified)
756             gimp_statusbar_override_window_title (statusbar);
757           else
758             gtk_window_set_title (GTK_WINDOW (window), shell->title);
759         }
760     }
761 
762   return FALSE;
763 }
764 
765 static void
gimp_image_window_style_set(GtkWidget * widget,GtkStyle * prev_style)766 gimp_image_window_style_set (GtkWidget *widget,
767                              GtkStyle  *prev_style)
768 {
769   GimpImageWindow        *window        = GIMP_IMAGE_WINDOW (widget);
770   GimpImageWindowPrivate *private       = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
771   GimpDisplayShell       *shell         = gimp_image_window_get_active_shell (window);
772   GimpStatusbar          *statusbar     = NULL;
773   GtkRequisition          requisition   = { 0, };
774   GdkGeometry             geometry      = { 0, };
775   GdkWindowHints          geometry_mask = 0;
776 
777   GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
778 
779   if (! shell)
780     return;
781 
782   statusbar = gimp_display_shell_get_statusbar (shell);
783 
784   gtk_widget_size_request (GTK_WIDGET (statusbar), &requisition);
785 
786   geometry.min_height = 23;
787 
788   geometry.min_width   = requisition.width;
789   geometry.min_height += requisition.height;
790 
791   if (private->menubar)
792     {
793       gtk_widget_size_request (private->menubar, &requisition);
794 
795       geometry.min_height += requisition.height;
796     }
797 
798   geometry_mask = GDK_HINT_MIN_SIZE;
799 
800   /*  Only set user pos on the empty display because it gets a pos
801    *  set by gimp. All other displays should be placed by the window
802    *  manager. See https://bugzilla.gnome.org/show_bug.cgi?id=559580
803    */
804   if (! gimp_display_get_image (shell->display))
805     geometry_mask |= GDK_HINT_USER_POS;
806 
807   gtk_window_set_geometry_hints (GTK_WINDOW (widget), NULL,
808                                  &geometry, geometry_mask);
809 
810   gimp_dialog_factory_set_has_min_size (GTK_WINDOW (widget), TRUE);
811 }
812 
813 static void
gimp_image_window_monitor_changed(GimpWindow * window,GdkScreen * screen,gint monitor)814 gimp_image_window_monitor_changed (GimpWindow *window,
815                                    GdkScreen  *screen,
816                                    gint        monitor)
817 {
818   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
819   GList                  *list;
820 
821   for (list = private->shells; list; list = g_list_next (list))
822     {
823       /*  hack, this should live here, and screen_changed call
824        *  monitor_changed
825        */
826       g_signal_emit_by_name (list->data, "screen-changed",
827                              gtk_widget_get_screen (list->data));
828 
829       /*  make it fetch the new monitor's resolution  */
830       gimp_display_shell_scale_update (GIMP_DISPLAY_SHELL (list->data));
831 
832       /*  make it fetch the right monitor profile  */
833       gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (list->data));
834     }
835 }
836 
837 static GList *
gimp_image_window_get_docks(GimpDockContainer * dock_container)838 gimp_image_window_get_docks (GimpDockContainer *dock_container)
839 {
840   GimpImageWindowPrivate *private;
841   GList                  *iter;
842   GList                  *all_docks = NULL;
843 
844   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (dock_container), FALSE);
845 
846   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (dock_container);
847 
848   for (iter = gimp_dock_columns_get_docks (GIMP_DOCK_COLUMNS (private->left_docks));
849        iter;
850        iter = g_list_next (iter))
851     {
852       all_docks = g_list_append (all_docks, GIMP_DOCK (iter->data));
853     }
854 
855   for (iter = gimp_dock_columns_get_docks (GIMP_DOCK_COLUMNS (private->right_docks));
856        iter;
857        iter = g_list_next (iter))
858     {
859       all_docks = g_list_append (all_docks, GIMP_DOCK (iter->data));
860     }
861 
862   return all_docks;
863 }
864 
865 static GimpDialogFactory *
gimp_image_window_dock_container_get_dialog_factory(GimpDockContainer * dock_container)866 gimp_image_window_dock_container_get_dialog_factory (GimpDockContainer *dock_container)
867 {
868   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (dock_container);
869 
870   return private->dialog_factory;
871 }
872 
873 static GimpUIManager *
gimp_image_window_dock_container_get_ui_manager(GimpDockContainer * dock_container)874 gimp_image_window_dock_container_get_ui_manager (GimpDockContainer *dock_container)
875 {
876   GimpImageWindow *window = GIMP_IMAGE_WINDOW (dock_container);
877 
878   return gimp_image_window_get_ui_manager (window);
879 }
880 
881 void
gimp_image_window_add_dock(GimpDockContainer * dock_container,GimpDock * dock,GimpSessionInfoDock * dock_info)882 gimp_image_window_add_dock (GimpDockContainer   *dock_container,
883                             GimpDock            *dock,
884                             GimpSessionInfoDock *dock_info)
885 {
886   GimpImageWindow        *window;
887   GimpDisplayShell       *active_shell;
888   GimpImageWindowPrivate *private;
889 
890   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (dock_container));
891 
892   window  = GIMP_IMAGE_WINDOW (dock_container);
893   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
894 
895   if (dock_info->side == GIMP_ALIGN_LEFT)
896     {
897       gimp_dock_columns_add_dock (GIMP_DOCK_COLUMNS (private->left_docks),
898                                   dock,
899                                   -1 /*index*/);
900     }
901   else
902     {
903       gimp_dock_columns_add_dock (GIMP_DOCK_COLUMNS (private->right_docks),
904                                   dock,
905                                   -1 /*index*/);
906     }
907 
908   active_shell = gimp_image_window_get_active_shell (window);
909   if (active_shell)
910     gimp_display_shell_appearance_update (active_shell);
911 }
912 
913 static GimpAlignmentType
gimp_image_window_get_dock_side(GimpDockContainer * dock_container,GimpDock * dock)914 gimp_image_window_get_dock_side (GimpDockContainer *dock_container,
915                                  GimpDock          *dock)
916 {
917   GimpAlignmentType       side = -1;
918   GimpImageWindowPrivate *private;
919   GList                  *iter;
920 
921   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (dock_container), FALSE);
922 
923   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (dock_container);
924 
925   for (iter = gimp_dock_columns_get_docks (GIMP_DOCK_COLUMNS (private->left_docks));
926        iter && side == -1;
927        iter = g_list_next (iter))
928     {
929       GimpDock *dock_iter = GIMP_DOCK (iter->data);
930 
931       if (dock_iter == dock)
932         side = GIMP_ALIGN_LEFT;
933     }
934 
935   for (iter = gimp_dock_columns_get_docks (GIMP_DOCK_COLUMNS (private->right_docks));
936        iter && side == -1;
937        iter = g_list_next (iter))
938     {
939       GimpDock *dock_iter = GIMP_DOCK (iter->data);
940 
941       if (dock_iter == dock)
942         side = GIMP_ALIGN_RIGHT;
943     }
944 
945   return side;
946 }
947 
948 static GList *
gimp_image_window_get_aux_info(GimpSessionManaged * session_managed)949 gimp_image_window_get_aux_info (GimpSessionManaged *session_managed)
950 {
951   GList                  *aux_info = NULL;
952   GimpImageWindowPrivate *private;
953   GimpGuiConfig          *config;
954 
955   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (session_managed), NULL);
956 
957   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (session_managed);
958   config  = GIMP_GUI_CONFIG (private->gimp->config);
959 
960   if (config->single_window_mode)
961     {
962       GimpSessionInfoAux *aux;
963       GtkAllocation       allocation;
964       gchar               widthbuf[128];
965 
966       g_snprintf (widthbuf, sizeof (widthbuf), "%d",
967                   gtk_paned_get_position (GTK_PANED (private->left_hpane)));
968       aux = gimp_session_info_aux_new (GIMP_IMAGE_WINDOW_LEFT_DOCKS_WIDTH,
969                                        widthbuf);
970       aux_info = g_list_append (aux_info, aux);
971 
972       gtk_widget_get_allocation (private->right_hpane, &allocation);
973 
974       g_snprintf (widthbuf, sizeof (widthbuf), "%d",
975                   allocation.width -
976                   gtk_paned_get_position (GTK_PANED (private->right_hpane)));
977       aux = gimp_session_info_aux_new (GIMP_IMAGE_WINDOW_RIGHT_DOCKS_WIDTH,
978                                        widthbuf);
979       aux_info = g_list_append (aux_info, aux);
980 
981       aux = gimp_session_info_aux_new (GIMP_IMAGE_WINDOW_MAXIMIZED,
982                                        gimp_image_window_is_maximized (GIMP_IMAGE_WINDOW (session_managed)) ?
983                                        "yes" : "no");
984       aux_info = g_list_append (aux_info, aux);
985     }
986 
987   return aux_info;
988 }
989 
990 static void
gimp_image_window_set_right_docks_width(GtkPaned * paned,GtkAllocation * allocation,void * data)991 gimp_image_window_set_right_docks_width (GtkPaned      *paned,
992                                          GtkAllocation *allocation,
993                                          void          *data)
994 {
995   gint width = GPOINTER_TO_INT (data);
996 
997   g_return_if_fail (GTK_IS_PANED (paned));
998 
999   if (width > 0)
1000     gtk_paned_set_position (paned, allocation->width - width);
1001   else
1002     gtk_paned_set_position (paned, - width);
1003 
1004   g_signal_handlers_disconnect_by_func (paned,
1005                                         gimp_image_window_set_right_docks_width,
1006                                         data);
1007 }
1008 
1009 static void
gimp_image_window_set_aux_info(GimpSessionManaged * session_managed,GList * aux_info)1010 gimp_image_window_set_aux_info (GimpSessionManaged *session_managed,
1011                                 GList              *aux_info)
1012 {
1013   GimpImageWindowPrivate *private;
1014   GList                  *iter;
1015   gint                    left_docks_width      = G_MININT;
1016   gint                    right_docks_width     = G_MININT;
1017   gboolean                wait_with_right_docks = FALSE;
1018   gboolean                maximized             = FALSE;
1019 #ifdef G_OS_WIN32
1020   STARTUPINFO             StartupInfo;
1021 
1022   GetStartupInfo (&StartupInfo);
1023 #endif
1024 
1025   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (session_managed));
1026 
1027   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (session_managed);
1028 
1029   for (iter = aux_info; iter; iter = g_list_next (iter))
1030     {
1031       GimpSessionInfoAux *aux   = iter->data;
1032       gint               *width = NULL;
1033 
1034       if (! strcmp (aux->name, GIMP_IMAGE_WINDOW_LEFT_DOCKS_WIDTH))
1035         width = &left_docks_width;
1036       else if (! strcmp (aux->name, GIMP_IMAGE_WINDOW_RIGHT_DOCKS_WIDTH))
1037         width = &right_docks_width;
1038       else if (! strcmp (aux->name, GIMP_IMAGE_WINDOW_RIGHT_DOCKS_POS))
1039         width = &right_docks_width;
1040       else if (! strcmp (aux->name, GIMP_IMAGE_WINDOW_MAXIMIZED))
1041         if (! g_ascii_strcasecmp (aux->value, "yes"))
1042           maximized = TRUE;
1043 
1044       if (width)
1045         sscanf (aux->value, "%d", width);
1046 
1047       /* compat handling for right docks */
1048       if (! strcmp (aux->name, GIMP_IMAGE_WINDOW_RIGHT_DOCKS_POS))
1049         {
1050           /* negate the value because negative docks pos means docks width,
1051            * also use the negativenes of a real docks pos as condition below.
1052            */
1053           *width = - *width;
1054         }
1055     }
1056 
1057   if (left_docks_width != G_MININT &&
1058       gtk_paned_get_position (GTK_PANED (private->left_hpane)) !=
1059       left_docks_width)
1060     {
1061       gtk_paned_set_position (GTK_PANED (private->left_hpane), left_docks_width);
1062 
1063       /* We can't set the position of the right docks, because it will
1064        * be undesirably adjusted when its get a new size
1065        * allocation. We must wait until after the size allocation.
1066        */
1067       wait_with_right_docks = TRUE;
1068     }
1069 
1070   if (right_docks_width != G_MININT &&
1071       gtk_paned_get_position (GTK_PANED (private->right_hpane)) !=
1072       right_docks_width)
1073     {
1074       if (wait_with_right_docks || right_docks_width > 0)
1075         {
1076           /* We must wait for a size allocation before we can set the
1077            * position
1078            */
1079           g_signal_connect_data (private->right_hpane, "size-allocate",
1080                                  G_CALLBACK (gimp_image_window_set_right_docks_width),
1081                                  GINT_TO_POINTER (right_docks_width), NULL,
1082                                  G_CONNECT_AFTER);
1083         }
1084       else
1085         {
1086           /* We can set the position directly, because we didn't
1087            * change the left hpane position, and we got the old compat
1088            * dock pos property.
1089            */
1090           gtk_paned_set_position (GTK_PANED (private->right_hpane),
1091                                   - right_docks_width);
1092         }
1093     }
1094 
1095 #ifdef G_OS_WIN32
1096   /* On Windows, user can provide startup hints to have a program
1097    * maximized/minimized on startup. This can be done through command
1098    * line: `start /max gimp-2.9.exe` or with the shortcut's "run"
1099    * property.
1100    * When such a hint is given, we should follow it and bypass the
1101    * session's information.
1102    */
1103   if (StartupInfo.wShowWindow == SW_SHOWMAXIMIZED)
1104     gtk_window_maximize (GTK_WINDOW (session_managed));
1105   else if (StartupInfo.wShowWindow == SW_SHOWMINIMIZED   ||
1106            StartupInfo.wShowWindow == SW_SHOWMINNOACTIVE ||
1107            StartupInfo.wShowWindow == SW_MINIMIZE)
1108     /* XXX Iconification does not seem to work. I see the
1109      * window being iconified and immediately re-raised.
1110      * I leave this piece of code for later improvement. */
1111     gtk_window_iconify (GTK_WINDOW (session_managed));
1112   else
1113     /* Another show property not relevant to min/max.
1114      * Defaults is: SW_SHOWNORMAL
1115      */
1116 #endif
1117     if (maximized)
1118       gtk_window_maximize (GTK_WINDOW (session_managed));
1119     else
1120       gtk_window_unmaximize (GTK_WINDOW (session_managed));
1121 }
1122 
1123 
1124 /*  public functions  */
1125 
1126 GimpImageWindow *
gimp_image_window_new(Gimp * gimp,GimpImage * image,GimpDialogFactory * dialog_factory,GdkScreen * screen,gint monitor)1127 gimp_image_window_new (Gimp              *gimp,
1128                        GimpImage         *image,
1129                        GimpDialogFactory *dialog_factory,
1130                        GdkScreen         *screen,
1131                        gint               monitor)
1132 {
1133   GimpImageWindow        *window;
1134   GimpImageWindowPrivate *private;
1135 
1136   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
1137   g_return_val_if_fail (image == NULL || GIMP_IS_IMAGE (image), NULL);
1138   g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (dialog_factory), NULL);
1139   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1140 
1141   window = g_object_new (GIMP_TYPE_IMAGE_WINDOW,
1142                          "gimp",            gimp,
1143                          "dialog-factory",  dialog_factory,
1144                          "initial-screen",  screen,
1145                          "initial-monitor", monitor,
1146                          /* The window position will be overridden by the
1147                           * dialog factory, it is only really used on first
1148                           * startup.
1149                           */
1150                          image ? NULL : "window-position",
1151                          GTK_WIN_POS_CENTER,
1152                          NULL);
1153 
1154   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1155 
1156   gimp->image_windows = g_list_append (gimp->image_windows, window);
1157 
1158   if (! GIMP_GUI_CONFIG (private->gimp->config)->single_window_mode)
1159     {
1160       GdkScreen *pointer_screen;
1161       gint       pointer_monitor;
1162 
1163       pointer_monitor = gimp_get_monitor_at_pointer (&pointer_screen);
1164 
1165       /*  If we are supposed to go to a monitor other than where the
1166        *  pointer is, place the window on that monitor manually,
1167        *  otherwise simply let the window manager place the window on
1168        *  the poiner's monitor.
1169        */
1170       if (pointer_screen  != screen ||
1171           pointer_monitor != monitor)
1172         {
1173           GdkRectangle rect;
1174           gchar        geom[32];
1175 
1176           gdk_screen_get_monitor_workarea (screen, monitor, &rect);
1177 
1178           /*  FIXME: image window placement
1179            *
1180            *  This is ugly beyond description but better than showing
1181            *  the window on the wrong monitor
1182            */
1183           g_snprintf (geom, sizeof (geom), "%+d%+d",
1184                       rect.x + 300, rect.y + 30);
1185           gtk_window_parse_geometry (GTK_WINDOW (window), geom);
1186         }
1187     }
1188 
1189   return window;
1190 }
1191 
1192 void
gimp_image_window_destroy(GimpImageWindow * window)1193 gimp_image_window_destroy (GimpImageWindow *window)
1194 {
1195   GimpImageWindowPrivate *private;
1196 
1197   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1198 
1199   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1200 
1201   private->gimp->image_windows = g_list_remove (private->gimp->image_windows,
1202                                                 window);
1203 
1204   gtk_widget_destroy (GTK_WIDGET (window));
1205 }
1206 
1207 GimpUIManager *
gimp_image_window_get_ui_manager(GimpImageWindow * window)1208 gimp_image_window_get_ui_manager (GimpImageWindow *window)
1209 {
1210   GimpImageWindowPrivate *private;
1211 
1212   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), FALSE);
1213 
1214   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1215 
1216   return private->menubar_manager;
1217 }
1218 
1219 GimpDockColumns  *
gimp_image_window_get_left_docks(GimpImageWindow * window)1220 gimp_image_window_get_left_docks (GimpImageWindow  *window)
1221 {
1222   GimpImageWindowPrivate *private;
1223 
1224   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), FALSE);
1225 
1226   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1227 
1228   return GIMP_DOCK_COLUMNS (private->left_docks);
1229 }
1230 
1231 GimpDockColumns  *
gimp_image_window_get_right_docks(GimpImageWindow * window)1232 gimp_image_window_get_right_docks (GimpImageWindow  *window)
1233 {
1234   GimpImageWindowPrivate *private;
1235 
1236   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), FALSE);
1237 
1238   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1239 
1240   return GIMP_DOCK_COLUMNS (private->right_docks);
1241 }
1242 
1243 void
gimp_image_window_add_shell(GimpImageWindow * window,GimpDisplayShell * shell)1244 gimp_image_window_add_shell (GimpImageWindow  *window,
1245                              GimpDisplayShell *shell)
1246 {
1247   GimpImageWindowPrivate *private;
1248   GtkWidget              *tab_label;
1249 
1250   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1251   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
1252 
1253   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1254 
1255   g_return_if_fail (g_list_find (private->shells, shell) == NULL);
1256 
1257   private->shells = g_list_append (private->shells, shell);
1258 
1259   tab_label = gimp_image_window_create_tab_label (window, shell);
1260 
1261   gtk_notebook_append_page (GTK_NOTEBOOK (private->notebook),
1262                             GTK_WIDGET (shell), tab_label);
1263   gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (private->notebook),
1264                                     GTK_WIDGET (shell), TRUE);
1265 
1266   gtk_widget_show (GTK_WIDGET (shell));
1267 
1268   /*  make it fetch the right monitor profile  */
1269   gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (shell));
1270 }
1271 
1272 GimpDisplayShell *
gimp_image_window_get_shell(GimpImageWindow * window,gint index)1273 gimp_image_window_get_shell (GimpImageWindow *window,
1274                              gint             index)
1275 {
1276   GimpImageWindowPrivate *private;
1277 
1278   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), NULL);
1279 
1280   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1281 
1282   return g_list_nth_data (private->shells, index);
1283 }
1284 
1285 void
gimp_image_window_remove_shell(GimpImageWindow * window,GimpDisplayShell * shell)1286 gimp_image_window_remove_shell (GimpImageWindow  *window,
1287                                 GimpDisplayShell *shell)
1288 {
1289   GimpImageWindowPrivate *private;
1290 
1291   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1292   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
1293 
1294   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1295 
1296   g_return_if_fail (g_list_find (private->shells, shell) != NULL);
1297 
1298   private->shells = g_list_remove (private->shells, shell);
1299 
1300   gtk_container_remove (GTK_CONTAINER (private->notebook),
1301                         GTK_WIDGET (shell));
1302 }
1303 
1304 gint
gimp_image_window_get_n_shells(GimpImageWindow * window)1305 gimp_image_window_get_n_shells (GimpImageWindow *window)
1306 {
1307   GimpImageWindowPrivate *private;
1308 
1309   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), 0);
1310 
1311   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1312 
1313   return g_list_length (private->shells);
1314 }
1315 
1316 void
gimp_image_window_set_active_shell(GimpImageWindow * window,GimpDisplayShell * shell)1317 gimp_image_window_set_active_shell (GimpImageWindow  *window,
1318                                     GimpDisplayShell *shell)
1319 {
1320   GimpImageWindowPrivate *private;
1321   gint                    page_num;
1322 
1323   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1324   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
1325 
1326   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1327 
1328   g_return_if_fail (g_list_find (private->shells, shell));
1329 
1330   page_num = gtk_notebook_page_num (GTK_NOTEBOOK (private->notebook),
1331                                     GTK_WIDGET (shell));
1332 
1333   gtk_notebook_set_current_page (GTK_NOTEBOOK (private->notebook), page_num);
1334 }
1335 
1336 GimpDisplayShell *
gimp_image_window_get_active_shell(GimpImageWindow * window)1337 gimp_image_window_get_active_shell (GimpImageWindow *window)
1338 {
1339   GimpImageWindowPrivate *private;
1340 
1341   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), NULL);
1342 
1343   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1344 
1345   return private->active_shell;
1346 }
1347 
1348 void
gimp_image_window_set_fullscreen(GimpImageWindow * window,gboolean fullscreen)1349 gimp_image_window_set_fullscreen (GimpImageWindow *window,
1350                                   gboolean         fullscreen)
1351 {
1352   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1353 
1354   if (fullscreen != gimp_image_window_get_fullscreen (window))
1355     {
1356       if (fullscreen)
1357         gtk_window_fullscreen (GTK_WINDOW (window));
1358       else
1359         gtk_window_unfullscreen (GTK_WINDOW (window));
1360     }
1361 }
1362 
1363 gboolean
gimp_image_window_get_fullscreen(GimpImageWindow * window)1364 gimp_image_window_get_fullscreen (GimpImageWindow *window)
1365 {
1366   GimpImageWindowPrivate *private;
1367 
1368   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), FALSE);
1369 
1370   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1371 
1372   return (private->window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
1373 }
1374 
1375 void
gimp_image_window_set_show_menubar(GimpImageWindow * window,gboolean show)1376 gimp_image_window_set_show_menubar (GimpImageWindow *window,
1377                                     gboolean         show)
1378 {
1379   GimpImageWindowPrivate *private;
1380 
1381   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1382 
1383   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1384 
1385   if (private->menubar)
1386     gtk_widget_set_visible (private->menubar, show);
1387 }
1388 
1389 gboolean
gimp_image_window_get_show_menubar(GimpImageWindow * window)1390 gimp_image_window_get_show_menubar (GimpImageWindow *window)
1391 {
1392   GimpImageWindowPrivate *private;
1393 
1394   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), FALSE);
1395 
1396   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1397 
1398   if (private->menubar)
1399     return gtk_widget_get_visible (private->menubar);
1400 
1401   return FALSE;
1402 }
1403 
1404 gboolean
gimp_image_window_is_iconified(GimpImageWindow * window)1405 gimp_image_window_is_iconified (GimpImageWindow *window)
1406 {
1407   GimpImageWindowPrivate *private;
1408 
1409   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), FALSE);
1410 
1411   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1412 
1413   return (private->window_state & GDK_WINDOW_STATE_ICONIFIED) != 0;
1414 }
1415 
1416 gboolean
gimp_image_window_is_maximized(GimpImageWindow * window)1417 gimp_image_window_is_maximized (GimpImageWindow *window)
1418 {
1419   GimpImageWindowPrivate *private;
1420 
1421   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), FALSE);
1422 
1423   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1424 
1425   return (private->window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
1426 }
1427 
1428 /**
1429  * gimp_image_window_has_toolbox:
1430  * @window:
1431  *
1432  * Returns: %TRUE if the image window contains a GimpToolbox.
1433  **/
1434 gboolean
gimp_image_window_has_toolbox(GimpImageWindow * window)1435 gimp_image_window_has_toolbox (GimpImageWindow *window)
1436 {
1437   GimpImageWindowPrivate *private;
1438   GList                  *iter = NULL;
1439 
1440   g_return_val_if_fail (GIMP_IS_IMAGE_WINDOW (window), FALSE);
1441 
1442   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1443 
1444   for (iter = gimp_dock_columns_get_docks (GIMP_DOCK_COLUMNS (private->left_docks));
1445        iter;
1446        iter = g_list_next (iter))
1447     {
1448       if (GIMP_IS_TOOLBOX (iter->data))
1449         return TRUE;
1450     }
1451 
1452   for (iter = gimp_dock_columns_get_docks (GIMP_DOCK_COLUMNS (private->right_docks));
1453        iter;
1454        iter = g_list_next (iter))
1455     {
1456       if (GIMP_IS_TOOLBOX (iter->data))
1457         return TRUE;
1458     }
1459 
1460   return FALSE;
1461 }
1462 
1463 void
gimp_image_window_shrink_wrap(GimpImageWindow * window,gboolean grow_only)1464 gimp_image_window_shrink_wrap (GimpImageWindow *window,
1465                                gboolean         grow_only)
1466 {
1467   GimpDisplayShell *active_shell;
1468   GtkWidget        *widget;
1469   GtkAllocation     allocation;
1470   GdkScreen        *screen;
1471   GdkRectangle      rect;
1472   gint              monitor;
1473   gint              disp_width, disp_height;
1474   gint              width, height;
1475   gint              max_auto_width, max_auto_height;
1476   gint              border_width, border_height;
1477   gboolean          resize = FALSE;
1478 
1479   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1480 
1481   if (! gtk_widget_get_realized (GTK_WIDGET (window)))
1482     return;
1483 
1484   /* FIXME this so needs cleanup and shell/window separation */
1485 
1486   active_shell = gimp_image_window_get_active_shell (window);
1487 
1488   if (!active_shell)
1489     return;
1490 
1491   widget = GTK_WIDGET (window);
1492   screen = gtk_widget_get_screen (widget);
1493 
1494   gtk_widget_get_allocation (widget, &allocation);
1495 
1496   monitor = gdk_screen_get_monitor_at_window (screen,
1497                                               gtk_widget_get_window (widget));
1498   gdk_screen_get_monitor_workarea (screen, monitor, &rect);
1499 
1500   if (! gimp_display_shell_get_infinite_canvas (active_shell))
1501     {
1502       gimp_display_shell_scale_get_image_size (active_shell,
1503                                                &width, &height);
1504     }
1505   else
1506     {
1507       gimp_display_shell_scale_get_image_bounding_box (active_shell,
1508                                                        NULL,   NULL,
1509                                                        &width, &height);
1510     }
1511 
1512   disp_width  = active_shell->disp_width;
1513   disp_height = active_shell->disp_height;
1514 
1515 
1516   /* As long as the disp_width/disp_height is larger than 1 we
1517    * can reliably depend on it to calculate the
1518    * border_width/border_height because that means there is enough
1519    * room in the top-level for the canvas as well as the rulers and
1520    * scrollbars. If it is 1 or smaller it is likely that the rulers
1521    * and scrollbars are overlapping each other and thus we cannot use
1522    * the normal approach to border size, so special case that.
1523    */
1524   if (disp_width > 1 || !active_shell->vsb)
1525     {
1526       border_width = allocation.width - disp_width;
1527     }
1528   else
1529     {
1530       GtkAllocation vsb_allocation;
1531 
1532       gtk_widget_get_allocation (active_shell->vsb, &vsb_allocation);
1533 
1534       border_width = allocation.width - disp_width + vsb_allocation.width;
1535     }
1536 
1537   if (disp_height > 1 || !active_shell->hsb)
1538     {
1539       border_height = allocation.height - disp_height;
1540     }
1541   else
1542     {
1543       GtkAllocation hsb_allocation;
1544 
1545       gtk_widget_get_allocation (active_shell->hsb, &hsb_allocation);
1546 
1547       border_height = allocation.height - disp_height + hsb_allocation.height;
1548     }
1549 
1550 
1551   max_auto_width  = (rect.width  - border_width)  * 0.75;
1552   max_auto_height = (rect.height - border_height) * 0.75;
1553 
1554   /* If one of the display dimensions has changed and one of the
1555    * dimensions fits inside the screen
1556    */
1557   if (((width  + border_width)  < rect.width ||
1558        (height + border_height) < rect.height) &&
1559       (width  != disp_width ||
1560        height != disp_height))
1561     {
1562       width  = ((width  + border_width)  < rect.width)  ? width  : max_auto_width;
1563       height = ((height + border_height) < rect.height) ? height : max_auto_height;
1564 
1565       resize = TRUE;
1566     }
1567 
1568   /*  If the projected dimension is greater than current, but less than
1569    *  3/4 of the screen size, expand automagically
1570    */
1571   else if ((width  > disp_width ||
1572             height > disp_height) &&
1573            (disp_width  < max_auto_width ||
1574             disp_height < max_auto_height))
1575     {
1576       width  = MIN (max_auto_width,  width);
1577       height = MIN (max_auto_height, height);
1578 
1579       resize = TRUE;
1580     }
1581 
1582   if (resize)
1583     {
1584       GimpStatusbar *statusbar = gimp_display_shell_get_statusbar (active_shell);
1585       gint           statusbar_width;
1586 
1587       gtk_widget_get_size_request (GTK_WIDGET (statusbar),
1588                                    &statusbar_width, NULL);
1589 
1590       if (width < statusbar_width)
1591         width = statusbar_width;
1592 
1593       width  = width  + border_width;
1594       height = height + border_height;
1595 
1596       if (grow_only)
1597         {
1598           if (width < allocation.width)
1599             width = allocation.width;
1600 
1601           if (height < allocation.height)
1602             height = allocation.height;
1603         }
1604 
1605       gtk_window_resize (GTK_WINDOW (window), width, height);
1606     }
1607 
1608   /* A wrap always means that we should center the image too. If the
1609    * window changes size another center will be done in
1610    * GimpDisplayShell::configure_event().
1611    */
1612   /* FIXME multiple shells */
1613   gimp_display_shell_scroll_center_content (active_shell, TRUE, TRUE);
1614 }
1615 
1616 static GtkWidget *
gimp_image_window_get_first_dockbook(GimpDockColumns * columns)1617 gimp_image_window_get_first_dockbook (GimpDockColumns *columns)
1618 {
1619   GList *dock_iter;
1620 
1621   for (dock_iter = gimp_dock_columns_get_docks (columns);
1622        dock_iter;
1623        dock_iter = g_list_next (dock_iter))
1624     {
1625       GimpDock *dock      = GIMP_DOCK (dock_iter->data);
1626       GList    *dockbooks = gimp_dock_get_dockbooks (dock);
1627 
1628       if (dockbooks)
1629         return GTK_WIDGET (dockbooks->data);
1630     }
1631 
1632   return NULL;
1633 }
1634 
1635 /**
1636  * gimp_image_window_get_default_dockbook:
1637  * @window:
1638  *
1639  * Gets the default dockbook, which is the dockbook in which new
1640  * dockables should be put in single-window mode.
1641  *
1642  * Returns: The default dockbook for new dockables, or NULL if no
1643  *          dockbook were available.
1644  **/
1645 GtkWidget *
gimp_image_window_get_default_dockbook(GimpImageWindow * window)1646 gimp_image_window_get_default_dockbook (GimpImageWindow  *window)
1647 {
1648   GimpImageWindowPrivate *private;
1649   GimpDockColumns        *dock_columns;
1650   GtkWidget              *dockbook = NULL;
1651 
1652   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1653 
1654   /* First try the first dockbook in the right docks */
1655   dock_columns = GIMP_DOCK_COLUMNS (private->right_docks);
1656   dockbook     = gimp_image_window_get_first_dockbook (dock_columns);
1657 
1658   /* Then the left docks */
1659   if (! dockbook)
1660     {
1661       dock_columns = GIMP_DOCK_COLUMNS (private->left_docks);
1662       dockbook     = gimp_image_window_get_first_dockbook (dock_columns);
1663     }
1664 
1665   return dockbook;
1666 }
1667 
1668 /**
1669  * gimp_image_window_keep_canvas_pos:
1670  * @window:
1671  *
1672  * Stores the coordinates of the current image canvas origin relatively
1673  * its GtkWindow; and on the first size-allocate sets the offsets in
1674  * the shell so that the image origin remains the same (even on another
1675  * GtkWindow).
1676  *
1677  * Example use case: The user hides docks attached to the side of image
1678  * windows. You want the image to remain fixed on the screen though,
1679  * so you use this function to keep the image fixed after the docks
1680  * have been hidden.
1681  **/
1682 void
gimp_image_window_keep_canvas_pos(GimpImageWindow * window)1683 gimp_image_window_keep_canvas_pos (GimpImageWindow *window)
1684 {
1685   GimpImageWindowPrivate *private;
1686   GimpDisplayShell       *shell;
1687   gint                    canvas_x;
1688   gint                    canvas_y;
1689   gint                    window_x;
1690   gint                    window_y;
1691 
1692   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1693 
1694   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1695 
1696   if (private->suspend_keep_pos > 0)
1697     return;
1698 
1699   shell = gimp_image_window_get_active_shell (window);
1700 
1701   gimp_display_shell_transform_xy (shell, 0.0, 0.0, &canvas_x, &canvas_y);
1702 
1703   if (gtk_widget_translate_coordinates (GTK_WIDGET (shell->canvas),
1704                                         GTK_WIDGET (window),
1705                                         canvas_x, canvas_y,
1706                                         &window_x, &window_y))
1707     {
1708       PosCorrectionData *data = g_new0 (PosCorrectionData, 1);
1709 
1710       data->canvas_x = canvas_x;
1711       data->canvas_y = canvas_y;
1712       data->window_x = window_x;
1713       data->window_y = window_y;
1714 
1715       g_signal_connect_data (shell, "size-allocate",
1716                              G_CALLBACK (gimp_image_window_shell_size_allocate),
1717                              data, (GClosureNotify) g_free,
1718                              G_CONNECT_AFTER);
1719     }
1720 }
1721 
1722 void
gimp_image_window_suspend_keep_pos(GimpImageWindow * window)1723 gimp_image_window_suspend_keep_pos (GimpImageWindow  *window)
1724 {
1725   GimpImageWindowPrivate *private;
1726 
1727   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1728 
1729   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1730 
1731   private->suspend_keep_pos++;
1732 }
1733 
1734 void
gimp_image_window_resume_keep_pos(GimpImageWindow * window)1735 gimp_image_window_resume_keep_pos (GimpImageWindow  *window)
1736 {
1737   GimpImageWindowPrivate *private;
1738 
1739   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1740 
1741   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1742 
1743   g_return_if_fail (private->suspend_keep_pos > 0);
1744 
1745   private->suspend_keep_pos--;
1746 }
1747 
1748 /**
1749  * gimp_image_window_update_tabs:
1750  * @window: the Image Window to update.
1751  *
1752  * Holds the logics of whether shell tabs are to be shown or not in the
1753  * Image Window @window. This function should be called after every
1754  * change to @window where one might expect tab visibility to change.
1755  *
1756  * No direct call to gtk_notebook_set_show_tabs() should ever be made.
1757  * If we change the logics of tab hiding, we should only change this
1758  * procedure instead.
1759  **/
1760 void
gimp_image_window_update_tabs(GimpImageWindow * window)1761 gimp_image_window_update_tabs (GimpImageWindow *window)
1762 {
1763   GimpImageWindowPrivate *private;
1764   GimpGuiConfig          *config;
1765   GtkPositionType         position;
1766 
1767   g_return_if_fail (GIMP_IS_IMAGE_WINDOW (window));
1768 
1769   private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1770   config = GIMP_GUI_CONFIG (private->gimp->config);
1771 
1772   /* Tab visibility. */
1773   gtk_notebook_set_show_tabs (GTK_NOTEBOOK (private->notebook),
1774                               config->single_window_mode &&
1775                               config->show_tabs          &&
1776                               ! config->hide_docks       &&
1777                               ((private->active_shell          &&
1778                                 private->active_shell->display &&
1779                                 gimp_display_get_image (private->active_shell->display)) ||
1780                                g_list_length (private->shells) > 1));
1781 
1782   /* Tab position. */
1783   switch (config->tabs_position)
1784     {
1785     case GIMP_POSITION_TOP:
1786       position = GTK_POS_TOP;
1787       break;
1788     case GIMP_POSITION_BOTTOM:
1789       position = GTK_POS_BOTTOM;
1790       break;
1791     case GIMP_POSITION_LEFT:
1792       position = GTK_POS_LEFT;
1793       break;
1794     case GIMP_POSITION_RIGHT:
1795       position = GTK_POS_RIGHT;
1796       break;
1797     default:
1798       /* If we have any strange value, just reset to default. */
1799       position = GTK_POS_TOP;
1800       break;
1801     }
1802 
1803   gtk_notebook_set_tab_pos (GTK_NOTEBOOK (private->notebook), position);
1804 }
1805 
1806 
1807 /*  private functions  */
1808 
1809 static void
gimp_image_window_show_tooltip(GimpUIManager * manager,const gchar * tooltip,GimpImageWindow * window)1810 gimp_image_window_show_tooltip (GimpUIManager   *manager,
1811                                 const gchar     *tooltip,
1812                                 GimpImageWindow *window)
1813 {
1814   GimpDisplayShell *shell     = gimp_image_window_get_active_shell (window);
1815   GimpStatusbar    *statusbar = NULL;
1816 
1817   if (! shell)
1818     return;
1819 
1820   statusbar = gimp_display_shell_get_statusbar (shell);
1821 
1822   gimp_statusbar_push (statusbar, "menu-tooltip",
1823                        NULL, "%s", tooltip);
1824 }
1825 
1826 static void
gimp_image_window_config_notify(GimpImageWindow * window,GParamSpec * pspec,GimpGuiConfig * config)1827 gimp_image_window_config_notify (GimpImageWindow *window,
1828                                  GParamSpec      *pspec,
1829                                  GimpGuiConfig   *config)
1830 {
1831   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1832 
1833   /* Dock column visibility */
1834   if (strcmp (pspec->name, "single-window-mode") == 0 ||
1835       strcmp (pspec->name, "hide-docks")         == 0 ||
1836       strcmp (pspec->name, "show-tabs")          == 0 ||
1837       strcmp (pspec->name, "tabs-position")      == 0)
1838     {
1839       if (strcmp (pspec->name, "single-window-mode") == 0 ||
1840           strcmp (pspec->name, "hide-docks")         == 0)
1841         {
1842           gboolean show_docks = (config->single_window_mode &&
1843                                  ! config->hide_docks);
1844 
1845           gimp_image_window_keep_canvas_pos (window);
1846           gtk_widget_set_visible (private->left_docks, show_docks);
1847           gtk_widget_set_visible (private->right_docks, show_docks);
1848 
1849           /* If docks are being shown, and we are in multi-window-mode,
1850            * and this is the window of the active display, try to set
1851            * the keyboard focus to this window because it might have
1852            * been stolen by a dock. See bug #567333.
1853            */
1854           if (strcmp (pspec->name, "hide-docks") == 0 &&
1855               ! config->single_window_mode            &&
1856               ! config->hide_docks)
1857             {
1858               GimpDisplayShell *shell;
1859               GimpContext      *user_context;
1860 
1861               shell        = gimp_image_window_get_active_shell (window);
1862               user_context = gimp_get_user_context (private->gimp);
1863 
1864               if (gimp_context_get_display (user_context) == shell->display)
1865                 {
1866                   GdkWindow *w = gtk_widget_get_window (GTK_WIDGET (window));
1867 
1868                   if (w)
1869                     gdk_window_focus (w, gtk_get_current_event_time ());
1870                 }
1871             }
1872         }
1873 
1874       gimp_image_window_update_tabs (window);
1875     }
1876 
1877   /* Session management */
1878   if (strcmp (pspec->name, "single-window-mode") == 0)
1879     {
1880       gimp_image_window_session_update (window,
1881                                         NULL /*new_display*/,
1882                                         gimp_image_window_config_to_entry_id (config),
1883                                         gtk_widget_get_screen (GTK_WIDGET (window)),
1884                                         gimp_widget_get_monitor (GTK_WIDGET (window)));
1885     }
1886 }
1887 
1888 static void
gimp_image_window_hide_tooltip(GimpUIManager * manager,GimpImageWindow * window)1889 gimp_image_window_hide_tooltip (GimpUIManager   *manager,
1890                                 GimpImageWindow *window)
1891 {
1892   GimpDisplayShell *shell     = gimp_image_window_get_active_shell (window);
1893   GimpStatusbar    *statusbar = NULL;
1894 
1895   if (! shell)
1896     return;
1897 
1898   statusbar = gimp_display_shell_get_statusbar (shell);
1899 
1900   gimp_statusbar_pop (statusbar, "menu-tooltip");
1901 }
1902 
1903 static gboolean
gimp_image_window_update_ui_manager_idle(GimpImageWindow * window)1904 gimp_image_window_update_ui_manager_idle (GimpImageWindow *window)
1905 {
1906   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1907 
1908   gimp_assert (private->active_shell != NULL);
1909 
1910   gimp_ui_manager_update (private->menubar_manager,
1911                           private->active_shell->display);
1912 
1913   private->update_ui_manager_idle_id = 0;
1914 
1915   return G_SOURCE_REMOVE;
1916 }
1917 
1918 static void
gimp_image_window_update_ui_manager(GimpImageWindow * window)1919 gimp_image_window_update_ui_manager (GimpImageWindow *window)
1920 {
1921   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1922 
1923   if (! private->update_ui_manager_idle_id)
1924     {
1925       private->update_ui_manager_idle_id =
1926         g_idle_add_full (GIMP_PRIORITY_IMAGE_WINDOW_UPDATE_UI_MANAGER_IDLE,
1927                          (GSourceFunc) gimp_image_window_update_ui_manager_idle,
1928                          window,
1929                          NULL);
1930     }
1931 }
1932 
1933 static void
gimp_image_window_shell_size_allocate(GimpDisplayShell * shell,GtkAllocation * allocation,PosCorrectionData * data)1934 gimp_image_window_shell_size_allocate (GimpDisplayShell  *shell,
1935                                        GtkAllocation     *allocation,
1936                                        PosCorrectionData *data)
1937 {
1938   GimpImageWindow *window = gimp_display_shell_get_window (shell);
1939   gint             new_window_x;
1940   gint             new_window_y;
1941 
1942   if (gtk_widget_translate_coordinates (GTK_WIDGET (shell->canvas),
1943                                         GTK_WIDGET (window),
1944                                         data->canvas_x, data->canvas_y,
1945                                         &new_window_x, &new_window_y))
1946     {
1947       gint off_x = new_window_x - data->window_x;
1948       gint off_y = new_window_y - data->window_y;
1949 
1950       if (off_x || off_y)
1951         gimp_display_shell_scroll (shell, off_x, off_y);
1952     }
1953 
1954   g_signal_handlers_disconnect_by_func (shell,
1955                                         gimp_image_window_shell_size_allocate,
1956                                         data);
1957 }
1958 
1959 static gboolean
gimp_image_window_shell_events(GtkWidget * widget,GdkEvent * event,GimpImageWindow * window)1960 gimp_image_window_shell_events (GtkWidget       *widget,
1961                                 GdkEvent        *event,
1962                                 GimpImageWindow *window)
1963 {
1964   GimpDisplayShell *shell = gimp_image_window_get_active_shell (window);
1965 
1966   if (! shell)
1967     return FALSE;
1968 
1969   return gimp_display_shell_events (widget, event, shell);
1970 }
1971 
1972 static void
gimp_image_window_switch_page(GtkNotebook * notebook,gpointer page,gint page_num,GimpImageWindow * window)1973 gimp_image_window_switch_page (GtkNotebook     *notebook,
1974                                gpointer         page,
1975                                gint             page_num,
1976                                GimpImageWindow *window)
1977 {
1978   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
1979   GimpDisplayShell       *shell;
1980   GimpDisplay            *active_display;
1981 
1982   shell = GIMP_DISPLAY_SHELL (gtk_notebook_get_nth_page (notebook, page_num));
1983 
1984   if (shell == private->active_shell)
1985     return;
1986 
1987   gimp_image_window_disconnect_from_active_shell (window);
1988 
1989   GIMP_LOG (WM, "GimpImageWindow %p, private->active_shell = %p; \n",
1990             window, shell);
1991   private->active_shell = shell;
1992 
1993   gimp_window_set_primary_focus_widget (GIMP_WINDOW (window),
1994                                         shell->canvas);
1995 
1996   active_display = private->active_shell->display;
1997 
1998   g_signal_connect (active_display, "notify::image",
1999                     G_CALLBACK (gimp_image_window_image_notify),
2000                     window);
2001 
2002   g_signal_connect (private->active_shell, "scaled",
2003                     G_CALLBACK (gimp_image_window_shell_scaled),
2004                     window);
2005   g_signal_connect (private->active_shell, "rotated",
2006                     G_CALLBACK (gimp_image_window_shell_rotated),
2007                     window);
2008   g_signal_connect (private->active_shell, "notify::title",
2009                     G_CALLBACK (gimp_image_window_shell_title_notify),
2010                     window);
2011   g_signal_connect (private->active_shell, "notify::icon",
2012                     G_CALLBACK (gimp_image_window_shell_icon_notify),
2013                     window);
2014 
2015   gtk_window_set_title (GTK_WINDOW (window), shell->title);
2016   gtk_window_set_icon (GTK_WINDOW (window), shell->icon);
2017 
2018   gimp_display_shell_appearance_update (private->active_shell);
2019 
2020   if (gtk_widget_get_window (GTK_WIDGET (window)))
2021     {
2022       /*  we are fully initialized, use the window's current monitor
2023        */
2024       gimp_image_window_session_update (window,
2025                                         active_display,
2026                                         NULL /*new_entry_id*/,
2027                                         gtk_widget_get_screen (GTK_WIDGET (window)),
2028                                         gimp_widget_get_monitor (GTK_WIDGET (window)));
2029     }
2030   else
2031     {
2032       /*  we are in construction, use the initial monitor; calling
2033        *  gimp_widget_get_monitor() would get us the monitor where the
2034        *  pointer is
2035        */
2036       gimp_image_window_session_update (window,
2037                                         active_display,
2038                                         NULL /*new_entry_id*/,
2039                                         private->initial_screen,
2040                                         private->initial_monitor);
2041     }
2042 
2043   gimp_context_set_display (gimp_get_user_context (private->gimp),
2044                             active_display);
2045 
2046   gimp_image_window_update_ui_manager (window);
2047 
2048   gimp_image_window_update_tab_labels (window);
2049 }
2050 
2051 static void
gimp_image_window_page_removed(GtkNotebook * notebook,GtkWidget * widget,gint page_num,GimpImageWindow * window)2052 gimp_image_window_page_removed (GtkNotebook     *notebook,
2053                                 GtkWidget       *widget,
2054                                 gint             page_num,
2055                                 GimpImageWindow *window)
2056 {
2057   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
2058 
2059   if (GTK_WIDGET (private->active_shell) == widget)
2060     {
2061       GIMP_LOG (WM, "GimpImageWindow %p, private->active_shell = %p; \n",
2062                 window, NULL);
2063       gimp_image_window_disconnect_from_active_shell (window);
2064       private->active_shell = NULL;
2065     }
2066 }
2067 
2068 static void
gimp_image_window_page_reordered(GtkNotebook * notebook,GtkWidget * widget,gint page_num,GimpImageWindow * window)2069 gimp_image_window_page_reordered (GtkNotebook     *notebook,
2070                                   GtkWidget       *widget,
2071                                   gint             page_num,
2072                                   GimpImageWindow *window)
2073 {
2074   GimpImageWindowPrivate *private  = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
2075   GimpContainer          *displays = private->gimp->displays;
2076   gint                    index    = g_list_index (private->shells, widget);
2077 
2078   if (index != page_num)
2079     {
2080       private->shells = g_list_remove (private->shells, widget);
2081       private->shells = g_list_insert (private->shells, widget, page_num);
2082     }
2083 
2084   /* We need to reorder the displays as well in order to update the
2085    * numbered accelerators (alt-1, alt-2, etc.).
2086    */
2087   gimp_container_reorder (displays,
2088                           GIMP_OBJECT (GIMP_DISPLAY_SHELL (widget)->display),
2089                           page_num);
2090 
2091   gtk_notebook_reorder_child (notebook, widget, page_num);
2092 }
2093 
2094 static void
gimp_image_window_disconnect_from_active_shell(GimpImageWindow * window)2095 gimp_image_window_disconnect_from_active_shell (GimpImageWindow *window)
2096 {
2097   GimpImageWindowPrivate *private        = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
2098   GimpDisplay            *active_display = NULL;
2099 
2100   if (! private->active_shell)
2101     return;
2102 
2103   active_display = private->active_shell->display;
2104 
2105   if (active_display)
2106     g_signal_handlers_disconnect_by_func (active_display,
2107                                           gimp_image_window_image_notify,
2108                                           window);
2109 
2110   g_signal_handlers_disconnect_by_func (private->active_shell,
2111                                         gimp_image_window_shell_scaled,
2112                                         window);
2113   g_signal_handlers_disconnect_by_func (private->active_shell,
2114                                         gimp_image_window_shell_rotated,
2115                                         window);
2116   g_signal_handlers_disconnect_by_func (private->active_shell,
2117                                         gimp_image_window_shell_title_notify,
2118                                         window);
2119   g_signal_handlers_disconnect_by_func (private->active_shell,
2120                                         gimp_image_window_shell_icon_notify,
2121                                         window);
2122 
2123   if (private->menubar_manager)
2124     gimp_image_window_hide_tooltip (private->menubar_manager, window);
2125 
2126   if (private->update_ui_manager_idle_id)
2127     {
2128       g_source_remove (private->update_ui_manager_idle_id);
2129       private->update_ui_manager_idle_id = 0;
2130     }
2131 }
2132 
2133 static void
gimp_image_window_image_notify(GimpDisplay * display,const GParamSpec * pspec,GimpImageWindow * window)2134 gimp_image_window_image_notify (GimpDisplay      *display,
2135                                 const GParamSpec *pspec,
2136                                 GimpImageWindow  *window)
2137 {
2138   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
2139   GtkWidget              *tab_label;
2140   GList                  *children;
2141   GtkWidget              *view;
2142 
2143   gimp_image_window_session_update (window,
2144                                     display,
2145                                     NULL /*new_entry_id*/,
2146                                     gtk_widget_get_screen (GTK_WIDGET (window)),
2147                                     gimp_widget_get_monitor (GTK_WIDGET (window)));
2148 
2149   tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (private->notebook),
2150                                           GTK_WIDGET (gimp_display_get_shell (display)));
2151   children  = gtk_container_get_children (GTK_CONTAINER (tab_label));
2152   view      = GTK_WIDGET (children->data);
2153   g_list_free (children);
2154 
2155   gimp_view_set_viewable (GIMP_VIEW (view),
2156                           GIMP_VIEWABLE (gimp_display_get_image (display)));
2157 
2158   gimp_image_window_update_ui_manager (window);
2159 }
2160 
2161 static void
gimp_image_window_session_clear(GimpImageWindow * window)2162 gimp_image_window_session_clear (GimpImageWindow *window)
2163 {
2164   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
2165   GtkWidget              *widget  = GTK_WIDGET (window);
2166 
2167   if (gimp_dialog_factory_from_widget (widget, NULL))
2168     gimp_dialog_factory_remove_dialog (private->dialog_factory,
2169                                        widget);
2170 }
2171 
2172 static void
gimp_image_window_session_apply(GimpImageWindow * window,const gchar * entry_id,GdkScreen * screen,gint monitor)2173 gimp_image_window_session_apply (GimpImageWindow *window,
2174                                  const gchar     *entry_id,
2175                                  GdkScreen       *screen,
2176                                  gint             monitor)
2177 {
2178   GimpImageWindowPrivate *private      = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
2179   GimpSessionInfo        *session_info = NULL;
2180   gint                    width        = -1;
2181   gint                    height       = -1;
2182 
2183   gtk_window_unfullscreen (GTK_WINDOW (window));
2184 
2185   /*  get the NIW size before adding the display to the dialog
2186    *  factory so the window's current size doesn't affect the
2187    *  stored session info entry.
2188    */
2189   session_info =
2190     gimp_dialog_factory_find_session_info (private->dialog_factory, entry_id);
2191 
2192   if (session_info)
2193     {
2194       width  = gimp_session_info_get_width  (session_info);
2195       height = gimp_session_info_get_height (session_info);
2196     }
2197   else
2198     {
2199       GtkAllocation allocation;
2200 
2201       gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
2202 
2203       width  = allocation.width;
2204       height = allocation.height;
2205     }
2206 
2207   gimp_dialog_factory_add_foreign (private->dialog_factory,
2208                                    entry_id,
2209                                    GTK_WIDGET (window),
2210                                    screen,
2211                                    monitor);
2212 
2213   gtk_window_unmaximize (GTK_WINDOW (window));
2214   gtk_window_resize (GTK_WINDOW (window), width, height);
2215 }
2216 
2217 static void
gimp_image_window_session_update(GimpImageWindow * window,GimpDisplay * new_display,const gchar * new_entry_id,GdkScreen * screen,gint monitor)2218 gimp_image_window_session_update (GimpImageWindow *window,
2219                                   GimpDisplay     *new_display,
2220                                   const gchar     *new_entry_id,
2221                                   GdkScreen       *screen,
2222                                   gint             monitor)
2223 {
2224   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
2225 
2226   /* Handle changes to the entry id */
2227   if (new_entry_id)
2228     {
2229       if (! private->entry_id)
2230         {
2231           /* We're initializing. If we're in single-window mode, this
2232            * will be the only window, so start to session manage
2233            * it. If we're in multi-window mode, we will find out if we
2234            * should session manage ourselves when we get a display
2235            */
2236           if (strcmp (new_entry_id, GIMP_SINGLE_IMAGE_WINDOW_ENTRY_ID) == 0)
2237             {
2238               gimp_image_window_session_apply (window, new_entry_id,
2239                                                screen, monitor);
2240             }
2241         }
2242       else if (strcmp (private->entry_id, new_entry_id) != 0)
2243         {
2244           /* The entry id changed, immediately and always stop session
2245            * managing the old entry
2246            */
2247           gimp_image_window_session_clear (window);
2248 
2249           if (strcmp (new_entry_id, GIMP_EMPTY_IMAGE_WINDOW_ENTRY_ID) == 0)
2250             {
2251               /* If there is only one imageless display, we shall
2252                * become the empty image window
2253                */
2254               if (private->active_shell &&
2255                   private->active_shell->display &&
2256                   ! gimp_display_get_image (private->active_shell->display) &&
2257                   g_list_length (private->shells) <= 1)
2258                 {
2259                   gimp_image_window_session_apply (window, new_entry_id,
2260                                                    screen, monitor);
2261                 }
2262             }
2263           else if (strcmp (new_entry_id, GIMP_SINGLE_IMAGE_WINDOW_ENTRY_ID) == 0)
2264             {
2265               /* As soon as we become the single image window, we
2266                * shall session manage ourself until single-window mode
2267                * is exited
2268                */
2269               gimp_image_window_session_apply (window, new_entry_id,
2270                                                screen, monitor);
2271             }
2272         }
2273 
2274       private->entry_id = new_entry_id;
2275     }
2276 
2277   /* Handle changes to the displays. When in single-window mode, we
2278    * just keep session managing the single image window. We only need
2279    * to care about the multi-window mode case here
2280    */
2281   if (new_display &&
2282       strcmp (private->entry_id, GIMP_EMPTY_IMAGE_WINDOW_ENTRY_ID) == 0)
2283     {
2284       if (gimp_display_get_image (new_display))
2285         {
2286           /* As soon as we have an image we should not affect the size of the
2287            * empty image window
2288            */
2289           gimp_image_window_session_clear (window);
2290         }
2291       else if (! gimp_display_get_image (new_display) &&
2292                g_list_length (private->shells) <= 1)
2293         {
2294           /* As soon as we have no image (and no other shells that may
2295            * contain images) we should become the empty image window
2296            */
2297           gimp_image_window_session_apply (window, private->entry_id,
2298                                            screen, monitor);
2299         }
2300     }
2301 }
2302 
2303 static const gchar *
gimp_image_window_config_to_entry_id(GimpGuiConfig * config)2304 gimp_image_window_config_to_entry_id (GimpGuiConfig *config)
2305 {
2306   return (config->single_window_mode ?
2307           GIMP_SINGLE_IMAGE_WINDOW_ENTRY_ID :
2308           GIMP_EMPTY_IMAGE_WINDOW_ENTRY_ID);
2309 }
2310 
2311 static void
gimp_image_window_shell_scaled(GimpDisplayShell * shell,GimpImageWindow * window)2312 gimp_image_window_shell_scaled (GimpDisplayShell *shell,
2313                                 GimpImageWindow  *window)
2314 {
2315   /* update the <Image>/View/Zoom menu */
2316   gimp_image_window_update_ui_manager (window);
2317 }
2318 
2319 static void
gimp_image_window_shell_rotated(GimpDisplayShell * shell,GimpImageWindow * window)2320 gimp_image_window_shell_rotated (GimpDisplayShell *shell,
2321                                  GimpImageWindow  *window)
2322 {
2323   /* update the <Image>/View/Rotate menu */
2324   gimp_image_window_update_ui_manager (window);
2325 }
2326 
2327 static void
gimp_image_window_shell_title_notify(GimpDisplayShell * shell,const GParamSpec * pspec,GimpImageWindow * window)2328 gimp_image_window_shell_title_notify (GimpDisplayShell *shell,
2329                                       const GParamSpec *pspec,
2330                                       GimpImageWindow  *window)
2331 {
2332   gtk_window_set_title (GTK_WINDOW (window), shell->title);
2333 }
2334 
2335 static void
gimp_image_window_shell_icon_notify(GimpDisplayShell * shell,const GParamSpec * pspec,GimpImageWindow * window)2336 gimp_image_window_shell_icon_notify (GimpDisplayShell *shell,
2337                                      const GParamSpec *pspec,
2338                                      GimpImageWindow  *window)
2339 {
2340   gtk_window_set_icon (GTK_WINDOW (window), shell->icon);
2341 }
2342 
2343 static void
gimp_image_window_shell_close_button_callback(GimpDisplayShell * shell)2344 gimp_image_window_shell_close_button_callback (GimpDisplayShell *shell)
2345 {
2346   if (shell)
2347     gimp_display_shell_close (shell, FALSE);
2348 }
2349 
2350 static GtkWidget *
gimp_image_window_create_tab_label(GimpImageWindow * window,GimpDisplayShell * shell)2351 gimp_image_window_create_tab_label (GimpImageWindow  *window,
2352                                     GimpDisplayShell *shell)
2353 {
2354   GtkWidget *hbox;
2355   GtkWidget *view;
2356   GimpImage *image;
2357   GtkWidget *button;
2358   GtkWidget *gtk_image;
2359 
2360   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
2361   gtk_widget_show (hbox);
2362 
2363   view = gimp_view_new_by_types (gimp_get_user_context (shell->display->gimp),
2364                                  GIMP_TYPE_VIEW, GIMP_TYPE_IMAGE,
2365                                  GIMP_VIEW_SIZE_LARGE, 0, FALSE);
2366   gtk_widget_set_size_request (view, GIMP_VIEW_SIZE_LARGE, -1);
2367   gimp_view_renderer_set_color_config (GIMP_VIEW (view)->renderer,
2368                                        gimp_display_shell_get_color_config (shell));
2369   gtk_box_pack_start (GTK_BOX (hbox), view, FALSE, FALSE, 0);
2370   gtk_widget_show (view);
2371 
2372   image = gimp_display_get_image (shell->display);
2373   if (image)
2374     gimp_view_set_viewable (GIMP_VIEW (view), GIMP_VIEWABLE (image));
2375 
2376   button = gtk_button_new ();
2377   gtk_widget_set_can_focus (button, FALSE);
2378   gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2379   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
2380   gtk_widget_show (button);
2381 
2382   gtk_image = gtk_image_new_from_icon_name (GIMP_ICON_CLOSE,
2383                                             GTK_ICON_SIZE_MENU);
2384   gtk_container_add (GTK_CONTAINER (button), gtk_image);
2385   gtk_widget_show (gtk_image);
2386 
2387   g_signal_connect_swapped (button, "clicked",
2388                             G_CALLBACK (gimp_image_window_shell_close_button_callback),
2389                             shell);
2390 
2391   g_object_set_data (G_OBJECT (hbox), "close-button", button);
2392 
2393   return hbox;
2394 }
2395 
2396 static void
gimp_image_window_update_tab_labels(GimpImageWindow * window)2397 gimp_image_window_update_tab_labels (GimpImageWindow *window)
2398 {
2399   GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
2400   GList                  *children;
2401   GList                  *list;
2402 
2403   children = gtk_container_get_children (GTK_CONTAINER (private->notebook));
2404 
2405   for (list = children; list; list = g_list_next (list))
2406     {
2407       GtkWidget *shell = list->data;
2408       GtkWidget *tab_widget;
2409       GtkWidget *close_button;
2410 
2411       tab_widget = gtk_notebook_get_tab_label (GTK_NOTEBOOK (private->notebook),
2412                                                shell);
2413 
2414       close_button = g_object_get_data (G_OBJECT (tab_widget), "close-button");
2415 
2416       if (gimp_context_get_display (gimp_get_user_context (private->gimp)) ==
2417           GIMP_DISPLAY_SHELL (shell)->display)
2418         {
2419           gtk_widget_show (close_button);
2420         }
2421       else
2422         {
2423           gtk_widget_hide (close_button);
2424         }
2425     }
2426 
2427   g_list_free (children);
2428 }
2429