gtkviewport.c 34.8 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
Javier Jardón's avatar
Javier Jardón committed
15
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
16
 */
17 18

/*
19
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20 21 22 23 24
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

25
#include "config.h"
26 27

#include "gtkviewport.h"
28

29
#include "gtkadjustment.h"
Alexander Larsson's avatar
Alexander Larsson committed
30
#include "gtkintl.h"
31
#include "gtkmarshalers.h"
32
#include "gtkpixelcacheprivate.h"
33
#include "gtkprivate.h"
34
#include "gtkscrollable.h"
35
#include "gtkrender.h"
36
#include "gtktypebuiltins.h"
37
#include "gtkwidgetprivate.h"
38

Elliot Lee's avatar
Elliot Lee committed
39

40 41 42 43 44 45 46 47 48
/**
 * SECTION:gtkviewport
 * @Short_description: An adapter which makes widgets scrollable
 * @Title: GtkViewport
 * @See_also:#GtkScrolledWindow, #GtkAdjustment
 *
 * The #GtkViewport widget acts as an adaptor class, implementing
 * scrollability for child widgets that lack their own scrolling
 * capabilities. Use #GtkViewport to scroll child widgets such as
49
 * #GtkGrid, #GtkBox, and so on.
50 51
 *
 * If a widget has native scrolling abilities, such as #GtkTextView,
52
 * #GtkTreeView or #GtkIconView, it can be added to a #GtkScrolledWindow
53 54
 * with gtk_container_add(). If a widget does not, you must first add the
 * widget to a #GtkViewport, then add the viewport to the scrolled window.
55 56 57
 * gtk_container_add() does this automatically if a child that does not
 * implement #GtkScrollable is added to a #GtkScrolledWindow, so you can
 * ignore the presence of the viewport.
58 59
 *
 * The #GtkViewport will start scrolling content only if allocated less
60
 * than the child widget’s minimum size in a given orientation.
61 62
 */

63
struct _GtkViewportPrivate
64 65 66 67 68 69 70
{
  GtkAdjustment  *hadjustment;
  GtkAdjustment  *vadjustment;
  GtkShadowType   shadow_type;

  GdkWindow      *bin_window;
  GdkWindow      *view_window;
71

72 73
  GtkPixelCache *pixel_cache;

74 75 76 77
  /* GtkScrollablePolicy needs to be checked when
   * driving the scrollable adjustment values */
  guint hscroll_policy : 1;
  guint vscroll_policy : 1;
78 79
};

80
enum {
Alexander Larsson's avatar
Alexander Larsson committed
81 82 83
  PROP_0,
  PROP_HADJUSTMENT,
  PROP_VADJUSTMENT,
84 85
  PROP_HSCROLL_POLICY,
  PROP_VSCROLL_POLICY,
Alexander Larsson's avatar
Alexander Larsson committed
86
  PROP_SHADOW_TYPE
87 88 89
};


Alexander Larsson's avatar
Alexander Larsson committed
90 91 92 93 94 95 96 97
static void gtk_viewport_set_property             (GObject         *object,
						   guint            prop_id,
						   const GValue    *value,
						   GParamSpec      *pspec);
static void gtk_viewport_get_property             (GObject         *object,
						   guint            prop_id,
						   GValue          *value,
						   GParamSpec      *pspec);
98
static void gtk_viewport_destroy                  (GtkWidget        *widget);
Elliot Lee's avatar
Elliot Lee committed
99 100
static void gtk_viewport_realize                  (GtkWidget        *widget);
static void gtk_viewport_unrealize                (GtkWidget        *widget);
101 102
static void gtk_viewport_map                      (GtkWidget        *widget);
static void gtk_viewport_unmap                    (GtkWidget        *widget);
103 104
static gint gtk_viewport_draw                     (GtkWidget        *widget,
						   cairo_t          *cr);
105 106
static void gtk_viewport_add                      (GtkContainer     *container,
						   GtkWidget        *widget);
Elliot Lee's avatar
Elliot Lee committed
107 108 109 110 111
static void gtk_viewport_size_allocate            (GtkWidget        *widget,
						   GtkAllocation    *allocation);
static void gtk_viewport_adjustment_value_changed (GtkAdjustment    *adjustment,
						   gpointer          data);

112 113 114 115 116 117
static void gtk_viewport_get_preferred_width      (GtkWidget        *widget,
						   gint             *minimum_size,
						   gint             *natural_size);
static void gtk_viewport_get_preferred_height     (GtkWidget        *widget,
						   gint             *minimum_size,
						   gint             *natural_size);
118 119 120 121 122 123 124 125
static void gtk_viewport_get_preferred_width_for_height (GtkWidget  *widget,
                                                   gint              height,
						   gint             *minimum_size,
						   gint             *natural_size);
static void gtk_viewport_get_preferred_height_for_width (GtkWidget  *widget,
                                                   gint              width,
						   gint             *minimum_size,
						   gint             *natural_size);
126

127 128 129
static void viewport_set_adjustment               (GtkViewport      *viewport,
                                                   GtkOrientation    orientation,
                                                   GtkAdjustment    *adjustment);
130 131
static void gtk_viewport_queue_draw_region        (GtkWidget        *widget,
						   const cairo_region_t *region);
132

133
G_DEFINE_TYPE_WITH_CODE (GtkViewport, gtk_viewport, GTK_TYPE_BIN,
134
                         G_ADD_PRIVATE (GtkViewport)
135
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
Elliot Lee's avatar
Elliot Lee committed
136 137 138 139

static void
gtk_viewport_class_init (GtkViewportClass *class)
{
Alexander Larsson's avatar
Alexander Larsson committed
140
  GObjectClass   *gobject_class;
Elliot Lee's avatar
Elliot Lee committed
141 142 143
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;

Alexander Larsson's avatar
Alexander Larsson committed
144
  gobject_class = G_OBJECT_CLASS (class);
Elliot Lee's avatar
Elliot Lee committed
145 146
  widget_class = (GtkWidgetClass*) class;
  container_class = (GtkContainerClass*) class;
Manish Singh's avatar
Manish Singh committed
147

Alexander Larsson's avatar
Alexander Larsson committed
148 149
  gobject_class->set_property = gtk_viewport_set_property;
  gobject_class->get_property = gtk_viewport_get_property;
150 151

  widget_class->destroy = gtk_viewport_destroy;
Elliot Lee's avatar
Elliot Lee committed
152 153
  widget_class->realize = gtk_viewport_realize;
  widget_class->unrealize = gtk_viewport_unrealize;
154 155
  widget_class->map = gtk_viewport_map;
  widget_class->unmap = gtk_viewport_unmap;
156
  widget_class->draw = gtk_viewport_draw;
Elliot Lee's avatar
Elliot Lee committed
157
  widget_class->size_allocate = gtk_viewport_size_allocate;
158 159
  widget_class->get_preferred_width = gtk_viewport_get_preferred_width;
  widget_class->get_preferred_height = gtk_viewport_get_preferred_height;
160 161
  widget_class->get_preferred_width_for_height = gtk_viewport_get_preferred_width_for_height;
  widget_class->get_preferred_height_for_width = gtk_viewport_get_preferred_height_for_width;
162
  widget_class->queue_draw_region = gtk_viewport_queue_draw_region;
163
  
164 165
  gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_VIEWPORT);

166 167
  container_class->add = gtk_viewport_add;

168
  /* GtkScrollable implementation */
169 170 171 172
  g_object_class_override_property (gobject_class, PROP_HADJUSTMENT,    "hadjustment");
  g_object_class_override_property (gobject_class, PROP_VADJUSTMENT,    "vadjustment");
  g_object_class_override_property (gobject_class, PROP_HSCROLL_POLICY, "hscroll-policy");
  g_object_class_override_property (gobject_class, PROP_VSCROLL_POLICY, "vscroll-policy");
Alexander Larsson's avatar
Alexander Larsson committed
173 174 175

  g_object_class_install_property (gobject_class,
                                   PROP_SHADOW_TYPE,
176
                                   g_param_spec_enum ("shadow-type",
177 178
						      P_("Shadow type"),
						      P_("Determines how the shadowed box around the viewport is drawn"),
Alexander Larsson's avatar
Alexander Larsson committed
179 180
						      GTK_TYPE_SHADOW_TYPE,
						      GTK_SHADOW_IN,
181
						      GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
Elliot Lee's avatar
Elliot Lee committed
182 183
}

184
static void
Alexander Larsson's avatar
Alexander Larsson committed
185 186 187 188
gtk_viewport_set_property (GObject         *object,
			   guint            prop_id,
			   const GValue    *value,
			   GParamSpec      *pspec)
189 190 191 192 193
{
  GtkViewport *viewport;

  viewport = GTK_VIEWPORT (object);

Alexander Larsson's avatar
Alexander Larsson committed
194
  switch (prop_id)
195
    {
Alexander Larsson's avatar
Alexander Larsson committed
196
    case PROP_HADJUSTMENT:
197
      viewport_set_adjustment (viewport, GTK_ORIENTATION_HORIZONTAL, g_value_get_object (value));
198
      break;
Alexander Larsson's avatar
Alexander Larsson committed
199
    case PROP_VADJUSTMENT:
200
      viewport_set_adjustment (viewport, GTK_ORIENTATION_VERTICAL, g_value_get_object (value));
201
      break;
202
    case PROP_HSCROLL_POLICY:
203 204 205 206 207 208
      if (viewport->priv->hscroll_policy != g_value_get_enum (value))
        {
          viewport->priv->hscroll_policy = g_value_get_enum (value);
          gtk_widget_queue_resize (GTK_WIDGET (viewport));
          g_object_notify_by_pspec (object, pspec);
        }
209 210
      break;
    case PROP_VSCROLL_POLICY:
211 212 213 214 215 216
      if (viewport->priv->vscroll_policy != g_value_get_enum (value))
        {
          viewport->priv->vscroll_policy = g_value_get_enum (value);
          gtk_widget_queue_resize (GTK_WIDGET (viewport));
          g_object_notify_by_pspec (object, pspec);
        }
217
      break;
Alexander Larsson's avatar
Alexander Larsson committed
218 219
    case PROP_SHADOW_TYPE:
      gtk_viewport_set_shadow_type (viewport, g_value_get_enum (value));
220
      break;
221
    default:
Alexander Larsson's avatar
Alexander Larsson committed
222
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
223 224 225 226 227
      break;
    }
}

static void
Alexander Larsson's avatar
Alexander Larsson committed
228 229 230 231
gtk_viewport_get_property (GObject         *object,
			   guint            prop_id,
			   GValue          *value,
			   GParamSpec      *pspec)
232
{
233
  GtkViewport *viewport = GTK_VIEWPORT (object);
234
  GtkViewportPrivate *priv = viewport->priv;
235

Alexander Larsson's avatar
Alexander Larsson committed
236
  switch (prop_id)
237
    {
Alexander Larsson's avatar
Alexander Larsson committed
238
    case PROP_HADJUSTMENT:
239
      g_value_set_object (value, priv->hadjustment);
240
      break;
Alexander Larsson's avatar
Alexander Larsson committed
241
    case PROP_VADJUSTMENT:
242
      g_value_set_object (value, priv->vadjustment);
243
      break;
244 245 246 247 248 249
    case PROP_HSCROLL_POLICY:
      g_value_set_enum (value, priv->hscroll_policy);
      break;
    case PROP_VSCROLL_POLICY:
      g_value_set_enum (value, priv->vscroll_policy);
      break;
Alexander Larsson's avatar
Alexander Larsson committed
250
    case PROP_SHADOW_TYPE:
251
      g_value_set_enum (value, priv->shadow_type);
252 253
      break;
    default:
Alexander Larsson's avatar
Alexander Larsson committed
254
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
255 256 257 258
      break;
    }
}

Elliot Lee's avatar
Elliot Lee committed
259 260 261
static void
gtk_viewport_init (GtkViewport *viewport)
{
262
  GtkViewportPrivate *priv;
263

264
  viewport->priv = gtk_viewport_get_instance_private (viewport);
265 266
  priv = viewport->priv;

267
  gtk_widget_set_has_window (GTK_WIDGET (viewport), TRUE);
Elliot Lee's avatar
Elliot Lee committed
268

269
  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (viewport), FALSE);
270 271 272 273 274 275

  priv->shadow_type = GTK_SHADOW_IN;
  priv->view_window = NULL;
  priv->bin_window = NULL;
  priv->hadjustment = NULL;
  priv->vadjustment = NULL;
276

277 278
  priv->pixel_cache = _gtk_pixel_cache_new ();

279
  gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (viewport)), GTK_STYLE_CLASS_FRAME);
280 281
  viewport_set_adjustment (viewport, GTK_ORIENTATION_HORIZONTAL, NULL);
  viewport_set_adjustment (viewport, GTK_ORIENTATION_VERTICAL, NULL);
Elliot Lee's avatar
Elliot Lee committed
282 283
}

Matthias Clasen's avatar
Matthias Clasen committed
284 285
/**
 * gtk_viewport_new:
286 287
 * @hadjustment: (allow-none): horizontal adjustment
 * @vadjustment: (allow-none): vertical adjustment
Matthias Clasen's avatar
Matthias Clasen committed
288
 *
289 290
 * Creates a new #GtkViewport with the given adjustments, or with default
 * adjustments if none are given.
Matthias Clasen's avatar
Matthias Clasen committed
291
 *
Matthias Clasen's avatar
Matthias Clasen committed
292 293
 * Returns: a new #GtkViewport
 */
Elliot Lee's avatar
Elliot Lee committed
294 295 296 297
GtkWidget*
gtk_viewport_new (GtkAdjustment *hadjustment,
		  GtkAdjustment *vadjustment)
{
298 299
  GtkWidget *viewport;

300
  viewport = g_object_new (GTK_TYPE_VIEWPORT,
301 302 303 304 305 306
			     "hadjustment", hadjustment,
			     "vadjustment", vadjustment,
			     NULL);

  return viewport;
}
Elliot Lee's avatar
Elliot Lee committed
307

308 309
#define ADJUSTMENT_POINTER(viewport, orientation)         \
  (((orientation) == GTK_ORIENTATION_HORIZONTAL) ?        \
310
     &(viewport)->priv->hadjustment : &(viewport)->priv->vadjustment)
311

312
static void
313 314
viewport_disconnect_adjustment (GtkViewport    *viewport,
				GtkOrientation  orientation)
315
{
316
  GtkAdjustment **adjustmentp = ADJUSTMENT_POINTER (viewport, orientation);
Elliot Lee's avatar
Elliot Lee committed
317

318
  if (*adjustmentp)
319
    {
320
      g_signal_handlers_disconnect_by_func (*adjustmentp,
Manish Singh's avatar
Manish Singh committed
321 322
					    gtk_viewport_adjustment_value_changed,
					    viewport);
323 324
      g_object_unref (*adjustmentp);
      *adjustmentp = NULL;
325
    }
326 327 328
}

static void
329
gtk_viewport_destroy (GtkWidget *widget)
330
{
331
  GtkViewport *viewport = GTK_VIEWPORT (widget);
332
  GtkViewportPrivate *priv = viewport->priv;
333 334 335

  viewport_disconnect_adjustment (viewport, GTK_ORIENTATION_HORIZONTAL);
  viewport_disconnect_adjustment (viewport, GTK_ORIENTATION_VERTICAL);
336

337 338 339 340
  if (priv->pixel_cache)
    _gtk_pixel_cache_free (priv->pixel_cache);
  priv->pixel_cache = NULL;

341
  GTK_WIDGET_CLASS (gtk_viewport_parent_class)->destroy (widget);
342 343
}

344 345 346 347 348 349 350
static void
viewport_get_view_allocation (GtkViewport   *viewport,
			      GtkAllocation *view_allocation)
{
  GtkViewportPrivate *priv = viewport->priv;
  GtkWidget *widget = GTK_WIDGET (viewport);
  GtkAllocation allocation;
351 352 353
  GtkStyleContext *context;
  GtkStateFlags state;
  GtkBorder padding, border;
354
  gint border_width;
355 356 357 358 359 360 361

  gtk_widget_get_allocation (widget, &allocation);
  border_width = gtk_container_get_border_width (GTK_CONTAINER (viewport));

  view_allocation->x = 0;
  view_allocation->y = 0;

362 363
  context = gtk_widget_get_style_context (widget);
  state = gtk_widget_get_state_flags (widget);
364

365 366 367
  gtk_style_context_get_padding (context, state, &padding);
  gtk_style_context_get_border (context, state, &border);

368 369
  if (priv->shadow_type != GTK_SHADOW_NONE)
    {
370 371
      view_allocation->x = border.left;
      view_allocation->y = border.top;
372 373
    }

374
  view_allocation->x += padding.left;
375
  view_allocation->y += padding.top;
376 377 378 379 380 381 382 383
  view_allocation->width = MAX (1, allocation.width - padding.left - padding.right - border_width * 2);
  view_allocation->height = MAX (1, allocation.height - padding.top - padding.bottom - border_width * 2);

  if (priv->shadow_type != GTK_SHADOW_NONE)
    {
      view_allocation->width = MAX (1, view_allocation->width - border.left - border.right);
      view_allocation->height = MAX (1, view_allocation->height - border.top - border.bottom);
    }
384 385
}

Matthias Clasen's avatar
Matthias Clasen committed
386 387 388
/**
 * gtk_viewport_get_hadjustment:
 * @viewport: a #GtkViewport.
389
 *
Matthias Clasen's avatar
Matthias Clasen committed
390 391
 * Returns the horizontal adjustment of the viewport.
 *
392
 * Returns: (transfer none): the horizontal adjustment of @viewport.
393 394
 *
 * Deprecated: 3.0: Use gtk_scrollable_get_hadjustment()
Matthias Clasen's avatar
Matthias Clasen committed
395
 **/
Elliot Lee's avatar
Elliot Lee committed
396 397 398 399 400
GtkAdjustment*
gtk_viewport_get_hadjustment (GtkViewport *viewport)
{
  g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);

401
  return viewport->priv->hadjustment;
Elliot Lee's avatar
Elliot Lee committed
402 403
}

Matthias Clasen's avatar
Matthias Clasen committed
404 405 406 407 408 409
/**
 * gtk_viewport_get_vadjustment:
 * @viewport: a #GtkViewport.
 * 
 * Returns the vertical adjustment of the viewport.
 *
410
 * Returns: (transfer none): the vertical adjustment of @viewport.
411 412
 *
 * Deprecated: 3.0: Use gtk_scrollable_get_vadjustment()
Matthias Clasen's avatar
Matthias Clasen committed
413
 **/
Elliot Lee's avatar
Elliot Lee committed
414 415 416 417 418
GtkAdjustment*
gtk_viewport_get_vadjustment (GtkViewport *viewport)
{
  g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);

419
  return viewport->priv->vadjustment;
Elliot Lee's avatar
Elliot Lee committed
420 421
}

422
static void
423
viewport_set_hadjustment_values (GtkViewport *viewport)
424 425 426
{
  GtkBin *bin = GTK_BIN (viewport);
  GtkAllocation view_allocation;
427
  GtkAdjustment *hadjustment = viewport->priv->hadjustment;
Javier Jardón's avatar
Javier Jardón committed
428
  GtkWidget *child;
429
  gdouble upper, value;
430
  
431 432
  viewport_get_view_allocation (viewport, &view_allocation);  

Javier Jardón's avatar
Javier Jardón committed
433 434
  child = gtk_bin_get_child (bin);
  if (child && gtk_widget_get_visible (child))
435
    {
436 437 438 439 440 441 442
      gint minimum_width, natural_width;
      gint scroll_height;
      
      if (viewport->priv->vscroll_policy == GTK_SCROLL_MINIMUM)
	gtk_widget_get_preferred_height (child, &scroll_height, NULL);
      else
	gtk_widget_get_preferred_height (child, NULL, &scroll_height);
443

444
      gtk_widget_get_preferred_width_for_height (child,
445
                                                 MAX (view_allocation.height, scroll_height),
446
                                                 &minimum_width,
447 448 449
                                                 &natural_width);

      if (viewport->priv->hscroll_policy == GTK_SCROLL_MINIMUM)
450
	upper = MAX (minimum_width, view_allocation.width);
451
      else
452
	upper = MAX (natural_width, view_allocation.width);
453 454
    }
  else
455
    upper = view_allocation.width;
456

457 458 459
  value = gtk_adjustment_get_value (hadjustment);
  /* We clamp to the left in RTL mode */
  if (gtk_widget_get_direction (GTK_WIDGET (viewport)) == GTK_TEXT_DIR_RTL)
460
    {
461 462 463 464
      gdouble dist = gtk_adjustment_get_upper (hadjustment)
                     - value
                     - gtk_adjustment_get_page_size (hadjustment);
      value = upper - dist - view_allocation.width;
465
    }
466 467 468 469 470 471 472 473

  gtk_adjustment_configure (hadjustment,
                            value,
                            0,
                            upper,
                            view_allocation.width * 0.1,
                            view_allocation.width * 0.9,
                            view_allocation.width);
474 475 476
}

static void
477
viewport_set_vadjustment_values (GtkViewport *viewport)
478 479 480
{
  GtkBin *bin = GTK_BIN (viewport);
  GtkAllocation view_allocation;
481
  GtkAdjustment *vadjustment = viewport->priv->vadjustment;
Javier Jardón's avatar
Javier Jardón committed
482
  GtkWidget *child;
483
  gdouble upper;
484 485 486

  viewport_get_view_allocation (viewport, &view_allocation);  

Javier Jardón's avatar
Javier Jardón committed
487 488
  child = gtk_bin_get_child (bin);
  if (child && gtk_widget_get_visible (child))
489
    {
490 491 492 493 494 495 496
      gint minimum_height, natural_height;
      gint scroll_width;

      if (viewport->priv->hscroll_policy == GTK_SCROLL_MINIMUM)
	gtk_widget_get_preferred_width (child, &scroll_width, NULL);
      else
	gtk_widget_get_preferred_width (child, NULL, &scroll_width);
Javier Jardón's avatar
Javier Jardón committed
497

498
      gtk_widget_get_preferred_height_for_width (child,
499
                                                 MAX (view_allocation.width, scroll_width),
500
                                                 &minimum_height,
501
                                                 &natural_height);
502

503
      if (viewport->priv->vscroll_policy == GTK_SCROLL_MINIMUM)
504
	upper = MAX (minimum_height, view_allocation.height);
505
      else
506
	upper = MAX (natural_height, view_allocation.height);
507 508
    }
  else
509 510 511 512 513 514 515 516 517
    upper = view_allocation.height;

  gtk_adjustment_configure (vadjustment,
                            gtk_adjustment_get_value (vadjustment),
                            0,
                            upper,
                            view_allocation.height * 0.1,
                            view_allocation.height * 0.9,
                            view_allocation.height);
518 519 520 521 522 523 524 525 526
}

static void
viewport_set_adjustment (GtkViewport    *viewport,
			 GtkOrientation  orientation,
			 GtkAdjustment  *adjustment)
{
  GtkAdjustment **adjustmentp = ADJUSTMENT_POINTER (viewport, orientation);

527
  if (adjustment && adjustment == *adjustmentp)
528 529 530
    return;

  if (!adjustment)
Javier Jardón's avatar
Javier Jardón committed
531
    adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
532
  viewport_disconnect_adjustment (viewport, orientation);
533
  *adjustmentp = adjustment;
534
  g_object_ref_sink (adjustment);
535 536

  if (orientation == GTK_ORIENTATION_HORIZONTAL)
537
    viewport_set_hadjustment_values (viewport);
538
  else
539
    viewport_set_vadjustment_values (viewport);
540

541
  g_signal_connect (adjustment, "value-changed",
542 543 544
		    G_CALLBACK (gtk_viewport_adjustment_value_changed),
		    viewport);

545
  gtk_viewport_adjustment_value_changed (adjustment, viewport);
546 547
}

Matthias Clasen's avatar
Matthias Clasen committed
548 549 550
/**
 * gtk_viewport_set_hadjustment:
 * @viewport: a #GtkViewport.
551 552
 * @adjustment: (allow-none): a #GtkAdjustment.
 *
Matthias Clasen's avatar
Matthias Clasen committed
553
 * Sets the horizontal adjustment of the viewport.
554 555
 *
 * Deprecated: 3.0: Use gtk_scrollable_set_hadjustment()
Matthias Clasen's avatar
Matthias Clasen committed
556
 **/
Elliot Lee's avatar
Elliot Lee committed
557 558 559 560 561
void
gtk_viewport_set_hadjustment (GtkViewport   *viewport,
			      GtkAdjustment *adjustment)
{
  g_return_if_fail (GTK_IS_VIEWPORT (viewport));
562 563
  if (adjustment)
    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
Elliot Lee's avatar
Elliot Lee committed
564

565
  viewport_set_adjustment (viewport, GTK_ORIENTATION_HORIZONTAL, adjustment);
Alexander Larsson's avatar
Alexander Larsson committed
566 567

  g_object_notify (G_OBJECT (viewport), "hadjustment");
Elliot Lee's avatar
Elliot Lee committed
568 569
}

Matthias Clasen's avatar
Matthias Clasen committed
570 571 572
/**
 * gtk_viewport_set_vadjustment:
 * @viewport: a #GtkViewport.
573 574
 * @adjustment: (allow-none): a #GtkAdjustment.
 *
Matthias Clasen's avatar
Matthias Clasen committed
575
 * Sets the vertical adjustment of the viewport.
576 577
 *
 * Deprecated: 3.0: Use gtk_scrollable_set_vadjustment()
Matthias Clasen's avatar
Matthias Clasen committed
578
 **/
Elliot Lee's avatar
Elliot Lee committed
579 580 581 582 583
void
gtk_viewport_set_vadjustment (GtkViewport   *viewport,
			      GtkAdjustment *adjustment)
{
  g_return_if_fail (GTK_IS_VIEWPORT (viewport));
584 585
  if (adjustment)
    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
Elliot Lee's avatar
Elliot Lee committed
586

587
  viewport_set_adjustment (viewport, GTK_ORIENTATION_VERTICAL, adjustment);
Alexander Larsson's avatar
Alexander Larsson committed
588

589
  g_object_notify (G_OBJECT (viewport), "vadjustment");
Elliot Lee's avatar
Elliot Lee committed
590 591
}

Matthias Clasen's avatar
Matthias Clasen committed
592 593 594 595 596 597 598
/** 
 * gtk_viewport_set_shadow_type:
 * @viewport: a #GtkViewport.
 * @type: the new shadow type.
 *
 * Sets the shadow type of the viewport.
 **/ 
Elliot Lee's avatar
Elliot Lee committed
599 600 601 602
void
gtk_viewport_set_shadow_type (GtkViewport   *viewport,
			      GtkShadowType  type)
{
603
  GtkViewportPrivate *priv;
604
  GtkWidget *widget;
605
  GtkStyleContext *context;
606

Elliot Lee's avatar
Elliot Lee committed
607 608
  g_return_if_fail (GTK_IS_VIEWPORT (viewport));

609
  widget = GTK_WIDGET (viewport);
610 611 612
  priv = viewport->priv;

  if ((GtkShadowType) priv->shadow_type != type)
Elliot Lee's avatar
Elliot Lee committed
613
    {
614
      priv->shadow_type = type;
Elliot Lee's avatar
Elliot Lee committed
615

616 617 618 619 620 621
      context = gtk_widget_get_style_context (widget);
      if (type != GTK_SHADOW_NONE)
        gtk_style_context_add_class (context, GTK_STYLE_CLASS_FRAME);
      else
        gtk_style_context_remove_class (context, GTK_STYLE_CLASS_FRAME);
 
622
      gtk_widget_queue_resize (widget);
Alexander Larsson's avatar
Alexander Larsson committed
623

624
      g_object_notify (G_OBJECT (viewport), "shadow-type");
625
    }
Elliot Lee's avatar
Elliot Lee committed
626 627
}

628 629 630 631 632 633
/**
 * gtk_viewport_get_shadow_type:
 * @viewport: a #GtkViewport
 *
 * Gets the shadow type of the #GtkViewport. See
 * gtk_viewport_set_shadow_type().
634
 *
635
 * Returns: the shadow type 
636 637 638 639 640 641
 **/
GtkShadowType
gtk_viewport_get_shadow_type (GtkViewport *viewport)
{
  g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), GTK_SHADOW_NONE);

642
  return viewport->priv->shadow_type;
643
}
Elliot Lee's avatar
Elliot Lee committed
644

645 646 647 648 649 650
/**
 * gtk_viewport_get_bin_window:
 * @viewport: a #GtkViewport
 *
 * Gets the bin window of the #GtkViewport.
 *
651
 * Returns: (transfer none): a #GdkWindow
652 653 654 655 656 657 658 659
 *
 * Since: 2.20
 **/
GdkWindow*
gtk_viewport_get_bin_window (GtkViewport *viewport)
{
  g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);

660
  return viewport->priv->bin_window;
661 662
}

663 664 665 666 667 668
/**
 * gtk_viewport_get_view_window:
 * @viewport: a #GtkViewport
 *
 * Gets the view window of the #GtkViewport.
 *
669
 * Returns: (transfer none): a #GdkWindow
670 671 672 673 674 675 676 677
 *
 * Since: 2.22
 **/
GdkWindow*
gtk_viewport_get_view_window (GtkViewport *viewport)
{
  g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);

678
  return viewport->priv->view_window;
679 680
}

681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
static void
gtk_viewport_bin_window_invalidate_handler (GdkWindow *window,
					    cairo_region_t *region)
{
  gpointer widget;
  GtkViewport *viewport;
  GtkViewportPrivate *priv;

  gdk_window_get_user_data (window, &widget);
  viewport = GTK_VIEWPORT (widget);
  priv = viewport->priv;

  _gtk_pixel_cache_invalidate (priv->pixel_cache, region);
}

static void
gtk_viewport_queue_draw_region (GtkWidget *widget,
				const cairo_region_t *region)
{
  GtkViewport *viewport = GTK_VIEWPORT (widget);
  GtkViewportPrivate *priv = viewport->priv;

  /* There is no way we can know if a region targets the
     not-currently-visible but in pixel cache region, so we
     always just invalidate the whole thing whenever the
     tree view gets a queue draw. This doesn't normally happen
     in normal scrolling cases anyway. */
  _gtk_pixel_cache_invalidate (priv->pixel_cache, NULL);

  GTK_WIDGET_CLASS (gtk_viewport_parent_class)->queue_draw_region (widget,
								   region);
}


Elliot Lee's avatar
Elliot Lee committed
715 716 717
static void
gtk_viewport_realize (GtkWidget *widget)
{
718
  GtkViewport *viewport = GTK_VIEWPORT (widget);
719
  GtkViewportPrivate *priv = viewport->priv;
720
  GtkBin *bin = GTK_BIN (widget);
721 722
  GtkAdjustment *hadjustment = priv->hadjustment;
  GtkAdjustment *vadjustment = priv->vadjustment;
723
  GtkAllocation allocation;
724
  GtkAllocation view_allocation;
Javier Jardón's avatar
Javier Jardón committed
725
  GtkWidget *child;
726
  GdkWindow *window;
Elliot Lee's avatar
Elliot Lee committed
727 728
  GdkWindowAttr attributes;
  gint attributes_mask;
729
  gint event_mask;
Javier Jardón's avatar
Javier Jardón committed
730
  guint border_width;
Elliot Lee's avatar
Elliot Lee committed
731

732 733
  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));

734
  gtk_widget_set_realized (widget, TRUE);
Elliot Lee's avatar
Elliot Lee committed
735

736 737 738 739 740 741
  gtk_widget_get_allocation (widget, &allocation);

  attributes.x = allocation.x + border_width;
  attributes.y = allocation.y + border_width;
  attributes.width = allocation.width - border_width * 2;
  attributes.height = allocation.height - border_width * 2;
Elliot Lee's avatar
Elliot Lee committed
742 743 744
  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (widget);
745 746

  event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
747 748

  attributes.event_mask = event_mask | GDK_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SMOOTH_SCROLL_MASK;
Elliot Lee's avatar
Elliot Lee committed
749

750
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
Elliot Lee's avatar
Elliot Lee committed
751

752 753 754
  window = gdk_window_new (gtk_widget_get_parent_window (widget),
                           &attributes, attributes_mask);
  gtk_widget_set_window (widget, window);
755
  gtk_widget_register_window (widget, window);
Elliot Lee's avatar
Elliot Lee committed
756

757 758 759 760 761 762
  viewport_get_view_allocation (viewport, &view_allocation);
  
  attributes.x = view_allocation.x;
  attributes.y = view_allocation.y;
  attributes.width = view_allocation.width;
  attributes.height = view_allocation.height;
763
  attributes.event_mask = 0;
Elliot Lee's avatar
Elliot Lee committed
764

765 766
  priv->view_window = gdk_window_new (window,
                                      &attributes, attributes_mask);
767
  gtk_widget_register_window (widget, priv->view_window);
Elliot Lee's avatar
Elliot Lee committed
768

769 770 771 772
  attributes.x = - gtk_adjustment_get_value (hadjustment);
  attributes.y = - gtk_adjustment_get_value (vadjustment);
  attributes.width = gtk_adjustment_get_upper (hadjustment);
  attributes.height = gtk_adjustment_get_upper (vadjustment);
773
  
774
  attributes.event_mask = event_mask;
Elliot Lee's avatar
Elliot Lee committed
775

776
  priv->bin_window = gdk_window_new (priv->view_window, &attributes, attributes_mask);
777
  gtk_widget_register_window (widget, priv->bin_window);
778 779
  gdk_window_set_invalidate_handler (priv->bin_window,
				     gtk_viewport_bin_window_invalidate_handler);
780

Javier Jardón's avatar
Javier Jardón committed
781 782
  child = gtk_bin_get_child (bin);
  if (child)
783
    gtk_widget_set_parent_window (child, priv->bin_window);
Elliot Lee's avatar
Elliot Lee committed
784

785 786
  gdk_window_show (priv->bin_window);
  gdk_window_show (priv->view_window);
Elliot Lee's avatar
Elliot Lee committed
787 788 789 790 791
}

static void
gtk_viewport_unrealize (GtkWidget *widget)
{
792
  GtkViewport *viewport = GTK_VIEWPORT (widget);
793
  GtkViewportPrivate *priv = viewport->priv;
Elliot Lee's avatar
Elliot Lee committed
794

795
  gtk_widget_unregister_window (widget, priv->view_window);
796 797
  gdk_window_destroy (priv->view_window);
  priv->view_window = NULL;
798

799
  gtk_widget_unregister_window (widget, priv->bin_window);
800 801
  gdk_window_destroy (priv->bin_window);
  priv->bin_window = NULL;
802

803
  GTK_WIDGET_CLASS (gtk_viewport_parent_class)->unrealize (widget);
Elliot Lee's avatar
Elliot Lee committed
804 805
}

806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
static void
gtk_viewport_map (GtkWidget *widget)
{
  GtkViewport *viewport = GTK_VIEWPORT (widget);
  GtkViewportPrivate *priv = viewport->priv;

  _gtk_pixel_cache_map (priv->pixel_cache);

  GTK_WIDGET_CLASS (gtk_viewport_parent_class)->map (widget);
}

static void
gtk_viewport_unmap (GtkWidget *widget)
{
  GtkViewport *viewport = GTK_VIEWPORT (widget);
  GtkViewportPrivate *priv = viewport->priv;

  GTK_WIDGET_CLASS (gtk_viewport_parent_class)->unmap (widget);

  _gtk_pixel_cache_unmap (priv->pixel_cache);
}

828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
static void
draw_bin (cairo_t *cr,
	  gpointer user_data)
{
  GtkWidget *widget = GTK_WIDGET (user_data);
  GtkViewport *viewport = GTK_VIEWPORT (widget);
  GtkViewportPrivate *priv = viewport->priv;
  GtkStyleContext *context;
  int x, y;

  context = gtk_widget_get_style_context (widget);

  gdk_window_get_position (priv->bin_window, &x, &y);
  gtk_render_background (context, cr, x, y,
			 gdk_window_get_width (priv->bin_window),
			 gdk_window_get_height (priv->bin_window));
  GTK_WIDGET_CLASS (gtk_viewport_parent_class)->draw (widget, cr);
}

Elliot Lee's avatar
Elliot Lee committed
847
static gint
848 849
gtk_viewport_draw (GtkWidget *widget,
                   cairo_t   *cr)
Elliot Lee's avatar
Elliot Lee committed
850
{
851 852
  GtkViewport *viewport = GTK_VIEWPORT (widget);
  GtkViewportPrivate *priv = viewport->priv;
853
  GtkStyleContext *context;
854

855 856
  context = gtk_widget_get_style_context (widget);

857
  if (gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
858 859 860 861 862 863 864 865
    {
      gtk_render_background (context, cr, 0, 0,
                             gdk_window_get_width (gtk_widget_get_window (widget)),
                             gdk_window_get_height (gtk_widget_get_window (widget)));
      gtk_render_frame (context, cr, 0, 0,
                        gdk_window_get_width (gtk_widget_get_window (widget)),
                        gdk_window_get_height (gtk_widget_get_window (widget)));
    }
866

867 868
  if (gtk_cairo_should_draw_window (cr, priv->bin_window))
    {
869 870 871 872 873 874 875 876 877 878
      cairo_rectangle_int_t view_rect;
      cairo_rectangle_int_t canvas_rect;

      gdk_window_get_position (priv->view_window, &view_rect.x, &view_rect.y);
      view_rect.width = gdk_window_get_width (priv->view_window);
      view_rect.height = gdk_window_get_height (priv->view_window);

      gdk_window_get_position (priv->bin_window, &canvas_rect.x, &canvas_rect.y);
      canvas_rect.width = gdk_window_get_width (priv->bin_window);
      canvas_rect.height = gdk_window_get_height (priv->bin_window);
879

880 881 882
      _gtk_pixel_cache_draw (priv->pixel_cache, cr, priv->bin_window,
			     &view_rect, &canvas_rect,
			     draw_bin, widget);
Elliot Lee's avatar
Elliot Lee committed
883 884 885 886 887
    }

  return FALSE;
}

888 889
static void
gtk_viewport_add (GtkContainer *container,
890
		  GtkWidget    *child)
891
{
892
  GtkBin *bin = GTK_BIN (container);
893
  GtkViewport *viewport = GTK_VIEWPORT (bin);
894
  GtkViewportPrivate *priv = viewport->priv;
895

Javier Jardón's avatar
Javier Jardón committed
896
  g_return_if_fail (gtk_bin_get_child (bin) == NULL);
897

898
  gtk_widget_set_parent_window (child, priv->bin_window);
899

Matthias Clasen's avatar
Matthias Clasen committed
900
  GTK_CONTAINER_CLASS (gtk_viewport_parent_class)->add (container, child);
901 902
}

Elliot Lee's avatar
Elliot Lee committed
903 904 905 906
static void
gtk_viewport_size_allocate (GtkWidget     *widget,
			    GtkAllocation *allocation)
{
907
  GtkAllocation widget_allocation;
908
  GtkViewport *viewport = GTK_VIEWPORT (widget);
909
  GtkViewportPrivate *priv = viewport->priv;
910
  GtkBin *bin = GTK_BIN (widget);
911
  guint border_width;
912 913
  GtkAdjustment *hadjustment = priv->hadjustment;
  GtkAdjustment *vadjustment = priv->vadjustment;
914
  GtkAllocation child_allocation;
Javier Jardón's avatar
Javier Jardón committed
915
  GtkWidget *child;
916

917 918
  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));

919 920 921
  /* If our size changed, and we have a shadow, queue a redraw on widget->window to
   * redraw the shadow correctly.
   */
922
  gtk_widget_get_allocation (widget, &widget_allocation);
923
  if (gtk_widget_get_mapped (widget) &&
924
      priv->shadow_type != GTK_SHADOW_NONE &&
925 926 927 928 929 930
      (widget_allocation.width != allocation->width ||
       widget_allocation.height != allocation->height))
    gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE);

  gtk_widget_set_allocation (widget, allocation);

931 932 933 934 935
  g_object_freeze_notify (G_OBJECT (hadjustment));
  g_object_freeze_notify (G_OBJECT (vadjustment));

  viewport_set_hadjustment_values (viewport);
  viewport_set_vadjustment_values (viewport);
936

937 938
  child_allocation.x = 0;
  child_allocation.y = 0;
939 940
  child_allocation.width = gtk_adjustment_get_upper (hadjustment);
  child_allocation.height = gtk_adjustment_get_upper (vadjustment);
941
  if (gtk_widget_get_realized (widget))
Elliot Lee's avatar
Elliot Lee committed
942
    {
943
      GtkAllocation view_allocation;
944 945

      gdk_window_move_resize (gtk_widget_get_window (widget),
Owen Taylor's avatar
Owen Taylor committed
946 947 948 949
			      allocation->x + border_width,
			      allocation->y + border_width,
			      allocation->width - border_width * 2,
			      allocation->height - border_width * 2);
950 951
      
      viewport_get_view_allocation (viewport, &view_allocation);
952
      gdk_window_move_resize (priv->view_window,
953 954 955 956
			      view_allocation.x,
			      view_allocation.y,
			      view_allocation.width,
			      view_allocation.height);
957
      gdk_window_move_resize (priv->bin_window,
958 959
                              - gtk_adjustment_get_value (hadjustment),
                              - gtk_adjustment_get_value (vadjustment),
960 961
                              child_allocation.width,
                              child_allocation.height);
Elliot Lee's avatar
Elliot Lee committed
962
    }
Javier Jardón's avatar
Javier Jardón committed
963 964 965 966

  child = gtk_bin_get_child (bin);
  if (child && gtk_widget_get_visible (child))
    gtk_widget_size_allocate (child, &child_allocation);
Elliot Lee's avatar
Elliot Lee committed
967

968 969
  g_object_thaw_notify (G_OBJECT (hadjustment));
  g_object_thaw_notify (G_OBJECT (vadjustment));
Elliot Lee's avatar
Elliot Lee committed
970 971 972 973 974 975
}

static void
gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
				       gpointer       data)
{
976
  GtkViewport *viewport = GTK_VIEWPORT (data);
977
  GtkViewportPrivate *priv = viewport->priv;
978
  GtkBin *bin = GTK_BIN (data);
Javier Jardón's avatar
Javier Jardón committed
979
  GtkWidget *child;
Elliot Lee's avatar
Elliot Lee committed
980

Javier Jardón's avatar
Javier Jardón committed
981 982
  child = gtk_bin_get_child (bin);
  if (child && gtk_widget_get_visible (child) &&
983
      gtk_widget_get_realized (GTK_WIDGET (viewport)))
Elliot Lee's avatar
Elliot Lee committed
984
    {
985 986
      GtkAdjustment *hadjustment = priv->hadjustment;
      GtkAdjustment *vadjustment = priv->vadjustment;
987 988
      gint old_x, old_y;
      gint new_x, new_y;
Elliot Lee's avatar
Elliot Lee committed
989

990
      gdk_window_get_position (priv->bin_window, &old_x, &old_y);
991 992
      new_x = - gtk_adjustment_get_value (hadjustment);
      new_y = - gtk_adjustment_get_value (vadjustment);
Elliot Lee's avatar
Elliot Lee committed
993

994
      if (new_x != old_x || new_y != old_y)
995
	gdk_window_move (priv->bin_window, new_x, new_y);
Elliot Lee's avatar
Elliot Lee committed
996 997
    }
}
998

999
static void
1000 1001
gtk_viewport_get_preferred_size (GtkWidget      *widget,
                                 GtkOrientation  orientation,
1002
                                 gint            for_size,
1003 1004
                                 gint           *minimum_size,
                                 gint           *natural_size)
1005
{
1006
  GtkViewport *viewport = GTK_VIEWPORT (widget);
1007
  GtkViewportPrivate *priv = viewport->priv;
1008 1009 1010
  GtkStyleContext *context;
  GtkStateFlags state;
  GtkBorder padding, border;
1011 1012 1013
  GtkWidget *child;
  gint       child_min, child_nat;
  gint       minimum, natural;
1014

1015
  child = gtk_bin_get_child (GTK_BIN (widget));
1016

1017
  minimum = 2 * gtk_container_get_border_width (GTK_CONTAINER (widget));
1018

1019 1020 1021 1022
  context = gtk_widget_get_style_context (GTK_WIDGET (widget));
  state = gtk_widget_get_state_flags (GTK_WIDGET (widget));
  gtk_style_context_get_padding (context, state, &padding);

1023
  if (priv->shadow_type != GTK_SHADOW_NONE)
1024
    {
1025 1026
      gtk_style_context_get_border (context, state, &border);

1027
      if (orientation == GTK_ORIENTATION_HORIZONTAL)
1028
        {
1029 1030
          if (for_size >= 0)
            for_size -= border.top + border.bottom;
1031 1032
          minimum += border.left + border.right;
        }
1033
      else
1034
        {
1035 1036
          if (for_size >= 0)
            for_size -= border.left + border.right;
1037 1038
          minimum += border.top + border.bottom;
        }
1039 1040
    }

1041
  if (orientation == GTK_ORIENTATION_HORIZONTAL)
1042
    {
1043 1044
      if (for_size >= 0)
        for_size -= padding.top + padding.bottom;
1045 1046
      minimum += padding.left + padding.right;
    }
1047
  else
1048
    {
1049 1050
      if (for_size >= 0)
        for_size -= padding.left + padding.right;
1051 1052
      minimum += padding.top + padding.bottom;
    }
1053

1054 1055
  natural = minimum;

1056 1057
  if (child && gtk_widget_get_visible (child))
    {
1058 1059
      _gtk_widget_get_preferred_size_for_size (child,
                                               orientation,
1060
                                               for_size,
1061 1062
                                               &child_min, &child_nat,
                                               NULL, NULL);
1063

1064 1065
      minimum += child_min;
      natural += child_nat;
1066
    }
1067

1068 1069
  *minimum_size = minimum;
  *natural_size = natural;
1070 1071 1072
}

static void
1073 1074 1075
gtk_viewport_get_preferred_width (GtkWidget *widget,
                                  gint      *minimum_size,
                                  gint      *natural_size)
1076
{
1077
  gtk_viewport_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, -1, minimum_size, natural_size);
1078 1079 1080
}

static void
1081 1082 1083
gtk_viewport_get_preferred_height (GtkWidget *widget,
                                   gint      *minimum_size,
                                   gint      *natural_size)
1084
{
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
  gtk_viewport_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, -1, minimum_size, natural_size);
}

static void
gtk_viewport_get_preferred_width_for_height (GtkWidget *widget,
                                             gint       height,
                                             gint      *minimum_size,
                                             gint      *natural_size)
{
  gtk_viewport_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, height, minimum_size, natural_size);
}

static void
gtk_viewport_get_preferred_height_for_width (GtkWidget *widget,
                                             gint       width,
                                             gint      *minimum_size,
                                             gint      *natural_size)
{
  gtk_viewport_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, width, minimum_size, natural_size);
1104
}