gimpsessioninfo.c 20.7 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
2 3 4
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * gimpsessioninfo.c
5
 * Copyright (C) 2001-2008 Michael Natterer <mitch@gimp.org>
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10 11 12 13 14 15 16 17
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 20 21 22 23 24 25 26
 */

#include "config.h"

#include <string.h>

#include <gtk/gtk.h>

27
#include "libgimpconfig/gimpconfig.h"
28

29
#include "widgets-types.h"
30 31 32 33

#include "gimpdialogfactory.h"
#include "gimpdock.h"
#include "gimpsessioninfo.h"
34 35 36
#include "gimpsessioninfo-aux.h"
#include "gimpsessioninfo-book.h"
#include "gimpsessioninfo-dock.h"
37
#include "gimpsessioninfo-private.h"
38

39 40
#include "gimp-log.h"

41 42 43 44 45 46 47

enum
{
  SESSION_INFO_POSITION,
  SESSION_INFO_SIZE,
  SESSION_INFO_OPEN,
  SESSION_INFO_AUX,
48
  SESSION_INFO_DOCK
49 50
};

51 52
#define DEFAULT_SCREEN  -1

53

54
static void     gimp_session_info_config_iface_init (GimpConfigInterface *iface);
55

56
static void     gimp_session_info_finalize          (GObject          *object);
57

58 59
static gint64   gimp_session_info_get_memsize       (GimpObject       *object,
                                                     gint64           *gui_size);
60

61 62 63 64 65 66 67
static gboolean gimp_session_info_serialize         (GimpConfig       *config,
                                                     GimpConfigWriter *writer,
                                                     gpointer          data);
static gboolean gimp_session_info_deserialize       (GimpConfig       *config,
                                                     GScanner         *scanner,
                                                     gint              nest_level,
                                                     gpointer          data);
68
static gboolean gimp_session_info_is_for_dock       (GimpSessionInfo  *info);
69 70 71 72 73


G_DEFINE_TYPE_WITH_CODE (GimpSessionInfo, gimp_session_info, GIMP_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,
                                                gimp_session_info_config_iface_init))
74 75 76 77 78 79

#define parent_class gimp_session_info_parent_class


static void
gimp_session_info_class_init (GimpSessionInfoClass *klass)
Michael Natterer's avatar
Michael Natterer committed
80
{
81 82 83 84 85 86
  GObjectClass    *object_class      = G_OBJECT_CLASS (klass);
  GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);

  object_class->finalize         = gimp_session_info_finalize;

  gimp_object_class->get_memsize = gimp_session_info_get_memsize;
87 88

  g_type_class_add_private (klass, sizeof (GimpSessionInfoPrivate));
Michael Natterer's avatar
Michael Natterer committed
89 90
}

91 92
static void
gimp_session_info_init (GimpSessionInfo *info)
93
{
94 95 96 97
  info->p = G_TYPE_INSTANCE_GET_PRIVATE (info,
                                         GIMP_TYPE_SESSION_INFO,
                                         GimpSessionInfoPrivate);
  info->p->screen = DEFAULT_SCREEN;
98 99 100 101 102 103 104
}

static void
gimp_session_info_config_iface_init (GimpConfigInterface *iface)
{
  iface->serialize   = gimp_session_info_serialize;
  iface->deserialize = gimp_session_info_deserialize;
105 106 107 108 109 110
}

static void
gimp_session_info_finalize (GObject *object)
{
  GimpSessionInfo *info = GIMP_SESSION_INFO (object);
111

112
  gimp_session_info_clear_info (info);
113

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static gint64
gimp_session_info_get_memsize (GimpObject *object,
                               gint64     *gui_size)
{
#if 0
  GimpSessionInfo *info    = GIMP_SESSION_INFO (object);
#endif
  gint64           memsize = 0;

  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
                                                                  gui_size);
}

130 131 132 133
static gboolean
gimp_session_info_serialize (GimpConfig       *config,
                             GimpConfigWriter *writer,
                             gpointer          data)
134
{
135
  GimpSessionInfo *info = GIMP_SESSION_INFO (config);
136 137

  gimp_config_writer_open (writer, "position");
138
  gimp_config_writer_printf (writer, "%d %d", info->p->x, info->p->y);
139 140
  gimp_config_writer_close (writer);

141
  if (info->p->width > 0 && info->p->height > 0)
142 143
    {
      gimp_config_writer_open (writer, "size");
144
      gimp_config_writer_printf (writer, "%d %d", info->p->width, info->p->height);
145 146 147
      gimp_config_writer_close (writer);
    }

148
  if (info->p->open)
149 150
    {
      gimp_config_writer_open (writer, "open-on-exit");
151

152 153
      if (info->p->screen != DEFAULT_SCREEN)
        gimp_config_writer_printf (writer, "%d", info->p->screen);
154

155 156 157
      gimp_config_writer_close (writer);
    }

158 159
  if (info->p->aux_info)
    gimp_session_info_aux_serialize (writer, info->p->aux_info);
160

161 162
  if (info->p->books)
    gimp_session_info_dock_serialize (writer, info->p->books);
163

164
  return TRUE;
165 166
}

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
/*
 * This function is just like gimp_scanner_parse_int(), but it is allows
 * to detect the special value '-0'. This is used as in X geometry strings.
 */
static gboolean
gimp_session_info_parse_offset (GScanner *scanner,
                                gint     *dest,
                                gboolean *negative)
{
  if (g_scanner_peek_next_token (scanner) == '-')
    {
      *negative = TRUE;
      g_scanner_get_next_token (scanner);
    }
  else
    {
      *negative = FALSE;
    }

  if (g_scanner_peek_next_token (scanner) != G_TOKEN_INT)
    return FALSE;

  g_scanner_get_next_token (scanner);

  if (*negative)
    *dest = -scanner->value.v_int64;
  else
    *dest = scanner->value.v_int64;

  return TRUE;
}

199 200 201 202 203
static gboolean
gimp_session_info_deserialize (GimpConfig *config,
                               GScanner   *scanner,
                               gint        nest_level,
                               gpointer    data)
204
{
205 206 207 208
  GimpSessionInfo *info = GIMP_SESSION_INFO (config);
  GTokenType       token;
  guint            scope_id;
  guint            old_scope_id;
209

210 211
  scope_id = g_type_qname (G_TYPE_FROM_INSTANCE (config));
  old_scope_id = g_scanner_set_scope (scanner, scope_id);
212

213
  g_scanner_scope_add_symbol (scanner, scope_id, "position",
214
                              GINT_TO_POINTER (SESSION_INFO_POSITION));
215
  g_scanner_scope_add_symbol (scanner, scope_id, "size",
216
                              GINT_TO_POINTER (SESSION_INFO_SIZE));
217
  g_scanner_scope_add_symbol (scanner, scope_id, "open-on-exit",
218
                              GINT_TO_POINTER (SESSION_INFO_OPEN));
219
  g_scanner_scope_add_symbol (scanner, scope_id, "aux-info",
220
                              GINT_TO_POINTER (SESSION_INFO_AUX));
221
  g_scanner_scope_add_symbol (scanner, scope_id, "dock",
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
                              GINT_TO_POINTER (SESSION_INFO_DOCK));

  token = G_TOKEN_LEFT_PAREN;

  while (g_scanner_peek_next_token (scanner) == token)
    {
      token = g_scanner_get_next_token (scanner);

      switch (token)
        {
        case G_TOKEN_LEFT_PAREN:
          token = G_TOKEN_SYMBOL;
          break;

        case G_TOKEN_SYMBOL:
          switch (GPOINTER_TO_INT (scanner->value.v_symbol))
            {
            case SESSION_INFO_POSITION:
              token = G_TOKEN_INT;
241
              if (! gimp_session_info_parse_offset (scanner,
242 243
                                                    &info->p->x,
                                                    &info->p->right_align))
244
                goto error;
245
              if (! gimp_session_info_parse_offset (scanner,
246 247
                                                    &info->p->y,
                                                    &info->p->bottom_align))
248 249 250 251 252
                goto error;
              break;

            case SESSION_INFO_SIZE:
              token = G_TOKEN_INT;
253
              if (! gimp_scanner_parse_int (scanner, &info->p->width))
254
                goto error;
255
              if (! gimp_scanner_parse_int (scanner, &info->p->height))
256 257 258 259
                goto error;
              break;

            case SESSION_INFO_OPEN:
260
              info->p->open = TRUE;
261

262
              /*  the screen number is optional  */
263 264 265
              if (g_scanner_peek_next_token (scanner) == G_TOKEN_RIGHT_PAREN)
                break;

266
              token = G_TOKEN_INT;
267
              if (! gimp_scanner_parse_int (scanner, &info->p->screen))
268
                goto error;
269 270 271
              break;

            case SESSION_INFO_AUX:
Michael Natterer's avatar
Michael Natterer committed
272
              token = gimp_session_info_aux_deserialize (scanner,
273
                                                         &info->p->aux_info);
274 275
              if (token != G_TOKEN_LEFT_PAREN)
                goto error;
276 277 278
              break;

            case SESSION_INFO_DOCK:
279
              if (info->p->factory_entry)
280 281
                goto error;

282 283
              g_scanner_set_scope (scanner, scope_id + 1);
              token = gimp_session_info_dock_deserialize (scanner, scope_id + 1,
284
                                                          info);
285 286

              if (token == G_TOKEN_LEFT_PAREN)
287
                g_scanner_set_scope (scanner, scope_id);
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
              else
                goto error;

              break;

            default:
              break;
            }
          token = G_TOKEN_RIGHT_PAREN;
          break;

        case G_TOKEN_RIGHT_PAREN:
          token = G_TOKEN_LEFT_PAREN;
          break;

        default:
          break;
        }
    }

308
 error:
309

310 311 312 313 314 315 316 317 318 319
  g_scanner_scope_remove_symbol (scanner, scope_id, "position");
  g_scanner_scope_remove_symbol (scanner, scope_id, "size");
  g_scanner_scope_remove_symbol (scanner, scope_id, "open-on-exit");
  g_scanner_scope_remove_symbol (scanner, scope_id, "aux-info");
  g_scanner_scope_remove_symbol (scanner, scope_id, "dock");

  g_scanner_set_scope (scanner, old_scope_id);

  return gimp_config_deserialize_return (scanner, token, nest_level);
}
320

321 322 323 324 325 326 327 328 329 330 331 332 333
/**
 * gimp_session_info_is_for_dock:
 * @info:
 *
 * Helper function to determine if the session info is for a dock. It
 * uses the dialog factory entry state and the associated widget state
 * if any to determine that.
 *
 * Returns: %TRUE if session info is for a dock, %FALSE otherwise.
 **/
static gboolean
gimp_session_info_is_for_dock (GimpSessionInfo *info)
{
334 335 336
  gboolean entry_state_for_dock  =  info->p->factory_entry == NULL;
  gboolean widget_state_for_dock = (info->p->widget == NULL ||
                                    GIMP_IS_DOCK (info->p->widget));
337 338 339 340

  return entry_state_for_dock && widget_state_for_dock;
}

341

342 343 344 345 346 347
/*  public functions  */

GimpSessionInfo *
gimp_session_info_new (void)
{
  return g_object_new (GIMP_TYPE_SESSION_INFO, NULL);
348 349 350 351 352 353
}

void
gimp_session_info_restore (GimpSessionInfo   *info,
                           GimpDialogFactory *factory)
{
354
  GdkDisplay *display;
355
  GdkScreen  *screen = NULL;
356

357
  g_return_if_fail (GIMP_IS_SESSION_INFO (info));
358 359
  g_return_if_fail (GIMP_IS_DIALOG_FACTORY (factory));

360 361
  display = gdk_display_get_default ();

362 363
  if (info->p->screen != DEFAULT_SCREEN)
    screen = gdk_display_get_screen (display, info->p->screen);
364 365 366 367

  if (! screen)
    screen = gdk_display_get_default_screen (display);

368 369
  info->p->open   = FALSE;
  info->p->screen = DEFAULT_SCREEN;
370

371
  if (info->p->factory_entry && ! info->p->factory_entry->dockable)
372 373 374
    {
      GtkWidget *dialog;

375 376 377 378
      GIMP_LOG (DIALOG_FACTORY, "restoring toplevel \"%s\" (info %p)",
                info->p->factory_entry->identifier,
                info);

379
      dialog =
380
        gimp_dialog_factory_dialog_new (factory, screen,
381 382
                                        info->p->factory_entry->identifier,
                                        info->p->factory_entry->view_size,
383
                                        TRUE);
384

385 386
      if (dialog && info->p->aux_info)
        gimp_session_info_aux_set_list (dialog, info->p->aux_info);
387 388 389
    }
  else
    {
390 391 392
      GIMP_LOG (DIALOG_FACTORY, "restoring dock  (info %p)",
                info);

393
      gimp_session_info_dock_restore (info, factory, screen);
394 395 396
    }
}

397 398 399
/* This function mostly lifted from
 * gtk+/gdk/gdkscreen.c:gdk_screen_get_monitor_at_window()
 */
400
static gint
401 402 403 404 405
gimp_session_info_get_appropriate_monitor (GdkScreen *screen,
                                           gint       x,
                                           gint       y,
                                           gint       w,
                                           gint       h)
406 407
{
  GdkRectangle rect;
408 409 410 411 412 413 414 415
  gint         area    = 0;
  gint         monitor = -1;
  gint         num_monitors;
  gint         i;

  rect.x      = x;
  rect.y      = y;
  rect.width  = w;
416 417 418
  rect.height = h;

  num_monitors = gdk_screen_get_n_monitors (screen);
419

420 421
  for (i = 0; i < num_monitors; i++)
    {
422 423 424 425 426 427 428 429
      GdkRectangle geometry;

      gdk_screen_get_monitor_geometry (screen, i, &geometry);

      if (gdk_rectangle_intersect (&rect, &geometry, &geometry) &&
          geometry.width * geometry.height > area)
        {
          area = geometry.width * geometry.height;
430 431 432
          monitor = i;
        }
    }
433

434 435 436 437 438 439 440 441
  if (monitor >= 0)
    return monitor;
  else
    return gdk_screen_get_monitor_at_point (screen,
                                            rect.x + rect.width / 2,
                                            rect.y + rect.height / 2);
}

442 443 444 445 446 447 448
/**
 * gimp_session_info_apply_geometry:
 * @info:
 *
 * Apply the geometry stored in the session info object to the
 * associated widget.
 **/
449
void
450
gimp_session_info_apply_geometry (GimpSessionInfo *info)
451
{
452
  GdkScreen   *screen;
453
  GdkRectangle rect;
454
  gchar        geom[32];
455 456
  gint         monitor;
  gboolean     use_size;
457

458
  g_return_if_fail (GIMP_IS_SESSION_INFO (info));
459
  g_return_if_fail (GTK_IS_WINDOW (info->p->widget));
460

461
  screen = gtk_widget_get_screen (info->p->widget);
462

463
  use_size = (gimp_session_info_get_remember_size (info) &&
464 465
              info->p->width  > 0 &&
              info->p->height > 0);
466 467

  if (use_size)
468
    {
469
      monitor = gimp_session_info_get_appropriate_monitor (screen,
470 471 472 473
                                                           info->p->x,
                                                           info->p->y,
                                                           info->p->width,
                                                           info->p->height);
474 475 476
    }
  else
    {
477
      monitor = gdk_screen_get_monitor_at_point (screen, info->p->x, info->p->y);
478
    }
479

480
  gdk_screen_get_monitor_geometry (screen, monitor, &rect);
481

482
  info->p->x = CLAMP (info->p->x,
483
                   rect.x,
484 485 486
                   rect.x + rect.width - (info->p->width > 0 ?
                                          info->p->width : 128));
  info->p->y = CLAMP (info->p->y,
487
                   rect.y,
488 489
                   rect.y + rect.height - (info->p->height > 0 ?
                                           info->p->height : 128));
490

491
  if (info->p->right_align && info->p->bottom_align)
492 493
    {
      g_strlcpy (geom, "-0-0", sizeof (geom));
494
    }
495
  else if (info->p->right_align)
496
    {
497
      g_snprintf (geom, sizeof (geom), "-0%+d", info->p->y);
498
    }
499
  else if (info->p->bottom_align)
500
    {
501
      g_snprintf (geom, sizeof (geom), "%+d-0", info->p->x);
502 503 504
    }
  else
    {
505
      g_snprintf (geom, sizeof (geom), "%+d%+d", info->p->x, info->p->y);
506 507
    }

508
  gtk_window_parse_geometry (GTK_WINDOW (info->p->widget), geom);
509 510

  if (use_size)
511 512
    gtk_window_set_default_size (GTK_WINDOW (info->p->widget),
                                 info->p->width, info->p->height);
513 514
}

515 516 517 518 519 520
/**
 * gimp_session_info_read_geometry:
 * @info:
 *
 * Read geometry related information from the associated widget.
 **/
521
void
522
gimp_session_info_read_geometry (GimpSessionInfo *info)
523
{
524 525
  GdkWindow *window;

526
  g_return_if_fail (GIMP_IS_SESSION_INFO (info));
527
  g_return_if_fail (GTK_IS_WINDOW (info->p->widget));
528

529
  window = gtk_widget_get_window (info->p->widget);
530 531

  if (window)
532
    {
533 534
      gint x, y;

535
      gdk_window_get_root_origin (window, &x, &y);
536 537 538 539 540

      /* Don't write negative values to the sessionrc, they are
       * interpreted as relative to the right, respective bottom edge
       * of the screen.
       */
541 542
      info->p->x = MAX (0, x);
      info->p->y = MAX (0, y);
543

544
      if (gimp_session_info_get_remember_size (info))
545
        {
546
          gdk_drawable_get_size (GDK_DRAWABLE (window),
547
                                 &info->p->width, &info->p->height);
548
        }
549
      else
550
        {
551 552
          info->p->width  = 0;
          info->p->height = 0;
553
        }
554 555
    }

556
  info->p->open = FALSE;
557

558
  if (gimp_session_info_get_remember_if_open (info))
559 560 561 562
    {
      GimpDialogVisibilityState visibility;

      visibility =
563
        GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info->p->widget),
564 565 566 567 568
                                            GIMP_DIALOG_VISIBILITY_KEY));

      switch (visibility)
        {
        case GIMP_DIALOG_VISIBILITY_UNKNOWN:
569
          info->p->open = GTK_WIDGET_VISIBLE (info->p->widget);
570 571 572
          break;

        case GIMP_DIALOG_VISIBILITY_INVISIBLE:
573
          info->p->open = FALSE;
574 575 576
          break;

        case GIMP_DIALOG_VISIBILITY_VISIBLE:
577
          info->p->open = TRUE;
578 579 580
          break;
        }
    }
581

582
  info->p->screen = DEFAULT_SCREEN;
583

584
  if (info->p->open)
585
    {
586 587
      GdkDisplay *display = gtk_widget_get_display (info->p->widget);
      GdkScreen  *screen  = gtk_widget_get_screen (info->p->widget);
588 589

      if (screen != gdk_display_get_default_screen (display))
590
        info->p->screen = gdk_screen_get_number (screen);
591
    }
592
}
593 594 595 596 597

void
gimp_session_info_get_info (GimpSessionInfo *info)
{
  g_return_if_fail (GIMP_IS_SESSION_INFO (info));
598
  g_return_if_fail (GTK_IS_WIDGET (info->p->widget));
599

600
  gimp_session_info_read_geometry (info);
601

602
  info->p->aux_info = gimp_session_info_aux_get_list (info->p->widget);
603

604 605 606 607
  if (info->p->factory_entry == NULL ||
      (info->p->factory_entry &&
       info->p->factory_entry->dockable))
    info->p->books = gimp_session_info_dock_from_widget (GIMP_DOCK (info->p->widget));
608 609 610 611 612 613 614
}

void
gimp_session_info_clear_info (GimpSessionInfo *info)
{
  g_return_if_fail (GIMP_IS_SESSION_INFO (info));

615
  if (info->p->aux_info)
616
    {
617
      g_list_foreach (info->p->aux_info,
618
                      (GFunc) gimp_session_info_aux_free, NULL);
619 620
      g_list_free (info->p->aux_info);
      info->p->aux_info = NULL;
621 622
    }

623
   if (info->p->books)
624
     {
625
       g_list_foreach (info->p->books,
626
                       (GFunc) gimp_session_info_book_free, NULL);
627 628
       g_list_free (info->p->books);
       info->p->books = NULL;
629 630
     }
}
631 632 633 634 635 636 637

gboolean
gimp_session_info_is_singleton (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), FALSE);

  return (! gimp_session_info_is_for_dock (info) &&
638 639
          info->p->factory_entry &&
          info->p->factory_entry->singleton);
640 641 642 643 644 645 646 647
}

gboolean
gimp_session_info_is_session_managed (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), FALSE);

  return (gimp_session_info_is_for_dock (info) ||
648 649
          (info->p->factory_entry &&
           info->p->factory_entry->session_managed));
650 651 652 653 654 655 656 657 658
}


gboolean
gimp_session_info_get_remember_size (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), FALSE);

  return (gimp_session_info_is_for_dock (info) ||
659 660
          (info->p->factory_entry &&
           info->p->factory_entry->remember_size));
661 662 663 664 665 666 667 668
}

gboolean
gimp_session_info_get_remember_if_open (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), FALSE);

  return (gimp_session_info_is_for_dock (info) ||
669 670
          (info->p->factory_entry &&
           info->p->factory_entry->remember_if_open));
671
}
672 673 674 675 676 677

GtkWidget *
gimp_session_info_get_widget (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), FALSE);

678
  return info->p->widget;
679 680 681 682 683 684 685 686
}

void
gimp_session_info_set_widget (GimpSessionInfo *info,
                              GtkWidget       *widget)
{
  g_return_if_fail (GIMP_IS_SESSION_INFO (info));

687
  info->p->widget = widget;
688 689 690 691 692 693 694
}

GimpDialogFactoryEntry *
gimp_session_info_get_factory_entry (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), FALSE);

695
  return info->p->factory_entry;
696 697 698 699 700 701 702 703
}

void
gimp_session_info_set_factory_entry (GimpSessionInfo        *info,
                                     GimpDialogFactoryEntry *entry)
{
  g_return_if_fail (GIMP_IS_SESSION_INFO (info));

704
  info->p->factory_entry = entry;
705 706 707 708 709 710 711
}

gboolean
gimp_session_info_get_open (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), FALSE);

712
  return info->p->open;
713 714 715 716 717 718 719
}

gint
gimp_session_info_get_x (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), 0);

720
  return info->p->x;
721 722 723 724 725 726 727
}

gint
gimp_session_info_get_y (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), 0);

728
  return info->p->y;
729 730 731 732 733 734 735
}

gint
gimp_session_info_get_width (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), 0);

736
  return info->p->width;
737 738 739 740 741 742 743
}

gint
gimp_session_info_get_height (GimpSessionInfo *info)
{
  g_return_val_if_fail (GIMP_IS_SESSION_INFO (info), 0);

744
  return info->p->height;
745
}