gtkscrolledwindow.c 112 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
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
22
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23
24
 */

25
#include "config.h"
26

27
#include "gtkscrolledwindow.h"
28

29
#include "gtkadjustment.h"
30
#include "gtkbindings.h"
31
#include "gtkdnd.h"
32
#include "gtkintl.h"
33
#include "gtkmain.h"
34
#include "gtkmarshalers.h"
35
#include "gtkprivate.h"
36
37
#include "gtkscrollable.h"
#include "gtkscrollbar.h"
Matthias Clasen's avatar
Matthias Clasen committed
38
#include "gtkrangeprivate.h"
39
#include "gtktypebuiltins.h"
40
#include "gtkviewport.h"
41
#include "gtkwidgetprivate.h"
42
#include "gtkwindow.h"
43
#include "a11y/gtkscrolledwindowaccessible.h"
44

45
46
#include <math.h>

47
48
49
50
/**
 * SECTION:gtkscrolledwindow
 * @Short_description: Adds scrollbars to its child widget
 * @Title: GtkScrolledWindow
Tadej Borovšak's avatar
Tadej Borovšak committed
51
 * @See_also: #GtkScrollable, #GtkViewport, #GtkAdjustment
52
 *
53
 * #GtkScrolledWindow is a #GtkBin subclass: it’s a container
54
55
56
57
58
 * the accepts a single child widget. #GtkScrolledWindow adds scrollbars
 * to the child widget and optionally draws a beveled frame around the
 * child widget.
 *
 * The scrolled window can work in two ways. Some widgets have native
Tadej Borovšak's avatar
Tadej Borovšak committed
59
 * scrolling support; these widgets implement the #GtkScrollable interface.
60
61
62
63
64
65
 * Widgets with native scroll support include #GtkTreeView, #GtkTextView,
 * and #GtkLayout.
 *
 * For widgets that lack native scrolling support, the #GtkViewport
 * widget acts as an adaptor class, implementing scrollability for child
 * widgets that lack their own scrolling capabilities. Use #GtkViewport
66
 * to scroll child widgets such as #GtkGrid, #GtkBox, and so on.
67
68
69
70
 *
 * If a widget has native scrolling abilities, it can be added to the
 * #GtkScrolledWindow with gtk_container_add(). If a widget does not, you
 * must first add the widget to a #GtkViewport, then add the #GtkViewport
71
 * to the scrolled window. gtk_container_add() will do this for you for
72
 * widgets that don’t implement #GtkScrollable natively, so you can
73
74
75
76
 * ignore the presence of the viewport.
 *
 * The position of the scrollbars is controlled by the scroll
 * adjustments. See #GtkAdjustment for the fields in an adjustment - for
William Jon McCann's avatar
William Jon McCann committed
77
 * #GtkScrollbar, used by #GtkScrolledWindow, the “value” field
78
 * represents the position of the scrollbar, which must be between the
William Jon McCann's avatar
William Jon McCann committed
79
 * “lower” field and “upper - page_size.” The “page_size” field
80
 * represents the size of the visible scrollable area. The
William Jon McCann's avatar
William Jon McCann committed
81
 * “step_increment” and “page_increment” fields are used when the user
82
83
84
 * asks to step down (using the small stepper arrows) or page down (using
 * for example the PageDown key).
 *
85
86
 * If a #GtkScrolledWindow doesn’t behave quite as you would like, or
 * doesn’t have exactly the right layout, it’s very possible to set up
87
 * your own scrolling with #GtkScrollbar and for example a #GtkGrid.
88
89
90
 */


91
92
93
94
95
96
97
/* scrolled window policy and size requisition handling:
 *
 * gtk size requisition works as follows:
 *   a widget upon size-request reports the width and height that it finds
 *   to be best suited to display its contents, including children.
 *   the width and/or height reported from a widget upon size requisition
 *   may be overidden by the user by specifying a width and/or height
98
 *   other than 0 through gtk_widget_set_size_request().
99
 *
100
 * a scrolled window needs (for implementing all three policy types) to
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
 * request its width and height based on two different rationales.
 * 1)   the user wants the scrolled window to just fit into the space
 *      that it gets allocated for a specifc dimension.
 * 1.1) this does not apply if the user specified a concrete value
 *      value for that specific dimension by either specifying usize for the
 *      scrolled window or for its child.
 * 2)   the user wants the scrolled window to take as much space up as
 *      is desired by the child for a specifc dimension (i.e. POLICY_NEVER).
 *
 * also, kinda obvious:
 * 3)   a user would certainly not have choosen a scrolled window as a container
 *      for the child, if the resulting allocation takes up more space than the
 *      child would have allocated without the scrolled window.
 *
 * conclusions:
116
 * A) from 1) follows: the scrolled window shouldn’t request more space for a
117
118
119
120
 *    specifc dimension than is required at minimum.
 * B) from 1.1) follows: the requisition may be overidden by usize of the scrolled
 *    window (done automatically) or by usize of the child (needs to be checked).
 * C) from 2) follows: for POLICY_NEVER, the scrolled window simply reports the
121
122
 *    child’s dimension.
 * D) from 3) follows: the scrolled window child’s minimum width and minimum height
123
124
125
 *    under A) at least correspond to the space taken up by its scrollbars.
 */

126
#define DEFAULT_SCROLLBAR_SPACING  3
127
128
129
130
131
132
#define TOUCH_BYPASS_CAPTURED_THRESHOLD 30

/* Kinetic scrolling */
#define MAX_OVERSHOOT_DISTANCE 50
#define FRICTION_DECELERATION 0.003
#define OVERSHOOT_INVERSE_ACCELERATION 0.003
Elliot Lee's avatar
Elliot Lee committed
133

134
135
136
137
138
struct _GtkScrolledWindowPrivate
{
  GtkWidget     *hscrollbar;
  GtkWidget     *vscrollbar;

139
  GtkCornerType  window_placement;
140
141
142
143
144
145
  guint16  shadow_type;

  guint    hscrollbar_policy      : 2;
  guint    vscrollbar_policy      : 2;
  guint    hscrollbar_visible     : 1;
  guint    vscrollbar_visible     : 1;
146
  guint    focus_out              : 1; /* Flag used by ::move-focus-out implementation */
147
148
149

  gint     min_content_width;
  gint     min_content_height;
150
151

  /* Kinetic scrolling */
152
153
154
155
156
157
  GtkGesture *drag_gesture;
  GtkGesture *swipe_gesture;
  GtkGesture *long_press_gesture;
  gdouble drag_start_x;
  gdouble drag_start_y;

158
159
160
161
  GdkWindow             *overshoot_window;
  GdkDevice             *drag_device;
  guint                  kinetic_scrolling         : 1;
  guint                  capture_button_press      : 1;
162
  guint                  in_drag                   : 1;
163
164
165
166
167
168
169
170

  guint                  deceleration_id;

  gdouble                x_velocity;
  gdouble                y_velocity;

  gdouble                unclamped_hadj_value;
  gdouble                unclamped_vadj_value;
171
};
172

173
174
175
176
177
178
179
180
181
182
typedef struct
{
  GtkScrolledWindow     *scrolled_window;
  gint64                 last_deceleration_time;

  gdouble                x_velocity;
  gdouble                y_velocity;
  gdouble                vel_cosine;
  gdouble                vel_sine;
} KineticScrollData;
183

184
enum {
Owen Taylor's avatar
Owen Taylor committed
185
186
187
188
189
190
  PROP_0,
  PROP_HADJUSTMENT,
  PROP_VADJUSTMENT,
  PROP_HSCROLLBAR_POLICY,
  PROP_VSCROLLBAR_POLICY,
  PROP_WINDOW_PLACEMENT,
191
  PROP_WINDOW_PLACEMENT_SET,
192
193
  PROP_SHADOW_TYPE,
  PROP_MIN_CONTENT_WIDTH,
194
195
  PROP_MIN_CONTENT_HEIGHT,
  PROP_KINETIC_SCROLLING
196
197
};

198
199
200
201
202
203
204
205
/* Signals */
enum
{
  SCROLL_CHILD,
  MOVE_FOCUS_OUT,
  LAST_SIGNAL
};

206
207
208
209
210
211
212
213
214
static void     gtk_scrolled_window_set_property       (GObject           *object,
                                                        guint              prop_id,
                                                        const GValue      *value,
                                                        GParamSpec        *pspec);
static void     gtk_scrolled_window_get_property       (GObject           *object,
                                                        guint              prop_id,
                                                        GValue            *value,
                                                        GParamSpec        *pspec);

215
static void     gtk_scrolled_window_destroy            (GtkWidget         *widget);
216
217
static gboolean gtk_scrolled_window_draw               (GtkWidget         *widget,
                                                        cairo_t           *cr);
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
static void     gtk_scrolled_window_size_allocate      (GtkWidget         *widget,
                                                        GtkAllocation     *allocation);
static gboolean gtk_scrolled_window_scroll_event       (GtkWidget         *widget,
                                                        GdkEventScroll    *event);
static gboolean gtk_scrolled_window_focus              (GtkWidget         *widget,
                                                        GtkDirectionType   direction);
static void     gtk_scrolled_window_add                (GtkContainer      *container,
                                                        GtkWidget         *widget);
static void     gtk_scrolled_window_remove             (GtkContainer      *container,
                                                        GtkWidget         *widget);
static void     gtk_scrolled_window_forall             (GtkContainer      *container,
                                                        gboolean           include_internals,
                                                        GtkCallback        callback,
                                                        gpointer           callback_data);
static gboolean gtk_scrolled_window_scroll_child       (GtkScrolledWindow *scrolled_window,
                                                        GtkScrollType      scroll,
                                                        gboolean           horizontal);
static void     gtk_scrolled_window_move_focus_out     (GtkScrolledWindow *scrolled_window,
                                                        GtkDirectionType   direction_type);

static void     gtk_scrolled_window_relative_allocation(GtkWidget         *widget,
                                                        GtkAllocation     *allocation);
static void     gtk_scrolled_window_adjustment_changed (GtkAdjustment     *adjustment,
                                                        gpointer           data);
242
243
static void     gtk_scrolled_window_adjustment_value_changed (GtkAdjustment     *adjustment,
                                                              gpointer           data);
244

245
static void  gtk_scrolled_window_get_preferred_width   (GtkWidget           *widget,
246
247
							gint                *minimum_size,
							gint                *natural_size);
248
static void  gtk_scrolled_window_get_preferred_height  (GtkWidget           *widget,
249
250
							gint                *minimum_size,
							gint                *natural_size);
251
static void  gtk_scrolled_window_get_preferred_height_for_width  (GtkWidget           *layout,
252
253
254
							gint                 width,
							gint                *minimum_height,
							gint                *natural_height);
255
static void  gtk_scrolled_window_get_preferred_width_for_height  (GtkWidget           *layout,
256
257
258
							gint                 width,
							gint                *minimum_height,
							gint                *natural_height);
259

260
261
262
263
static void  gtk_scrolled_window_realize               (GtkWidget           *widget);
static void  gtk_scrolled_window_unrealize             (GtkWidget           *widget);
static void  gtk_scrolled_window_map                   (GtkWidget           *widget);
static void  gtk_scrolled_window_unmap                 (GtkWidget           *widget);
264

265
266
267
268
269
270
271
272
273
static void  gtk_scrolled_window_grab_notify           (GtkWidget           *widget,
                                                        gboolean             was_grabbed);

static gboolean _gtk_scrolled_window_set_adjustment_value      (GtkScrolledWindow *scrolled_window,
                                                                GtkAdjustment     *adjustment,
                                                                gdouble            value,
                                                                gboolean           allow_overshooting,
                                                                gboolean           snap_to_border);

274
275
static void gtk_scrolled_window_cancel_deceleration (GtkScrolledWindow *scrolled_window);

276
277
278
279
280
281
282
static gboolean _gtk_scrolled_window_get_overshoot (GtkScrolledWindow *scrolled_window,
                                                    gint              *overshoot_x,
                                                    gint              *overshoot_y);
static void     _gtk_scrolled_window_allocate_overshoot_window (GtkScrolledWindow *scrolled_window);

static void     gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window);

283
static guint signals[LAST_SIGNAL] = {0};
Elliot Lee's avatar
Elliot Lee committed
284

285
G_DEFINE_TYPE_WITH_PRIVATE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN)
Elliot Lee's avatar
Elliot Lee committed
286

287
288
289
290
291
292
293
static void
add_scroll_binding (GtkBindingSet  *binding_set,
		    guint           keyval,
		    GdkModifierType mask,
		    GtkScrollType   scroll,
		    gboolean        horizontal)
{
294
  guint keypad_keyval = keyval - GDK_KEY_Left + GDK_KEY_KP_Left;
295
296
  
  gtk_binding_entry_add_signal (binding_set, keyval, mask,
297
                                "scroll-child", 2,
298
299
300
                                GTK_TYPE_SCROLL_TYPE, scroll,
				G_TYPE_BOOLEAN, horizontal);
  gtk_binding_entry_add_signal (binding_set, keypad_keyval, mask,
301
                                "scroll-child", 2,
302
303
304
305
306
307
308
309
310
                                GTK_TYPE_SCROLL_TYPE, scroll,
				G_TYPE_BOOLEAN, horizontal);
}

static void
add_tab_bindings (GtkBindingSet    *binding_set,
		  GdkModifierType   modifiers,
		  GtkDirectionType  direction)
{
311
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
312
                                "move-focus-out", 1,
313
                                GTK_TYPE_DIRECTION_TYPE, direction);
314
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
315
                                "move-focus-out", 1,
316
317
318
                                GTK_TYPE_DIRECTION_TYPE, direction);
}

Elliot Lee's avatar
Elliot Lee committed
319
320
321
static void
gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
{
322
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
Elliot Lee's avatar
Elliot Lee committed
323
324
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;
325
  GtkBindingSet *binding_set;
Elliot Lee's avatar
Elliot Lee committed
326
327
328

  widget_class = (GtkWidgetClass*) class;
  container_class = (GtkContainerClass*) class;
Manish Singh's avatar
Manish Singh committed
329

Owen Taylor's avatar
Owen Taylor committed
330
331
  gobject_class->set_property = gtk_scrolled_window_set_property;
  gobject_class->get_property = gtk_scrolled_window_get_property;
332

333
  widget_class->destroy = gtk_scrolled_window_destroy;
334
  widget_class->draw = gtk_scrolled_window_draw;
335
336
  widget_class->size_allocate = gtk_scrolled_window_size_allocate;
  widget_class->scroll_event = gtk_scrolled_window_scroll_event;
337
  widget_class->focus = gtk_scrolled_window_focus;
338
339
340
341
  widget_class->get_preferred_width = gtk_scrolled_window_get_preferred_width;
  widget_class->get_preferred_height = gtk_scrolled_window_get_preferred_height;
  widget_class->get_preferred_height_for_width = gtk_scrolled_window_get_preferred_height_for_width;
  widget_class->get_preferred_width_for_height = gtk_scrolled_window_get_preferred_width_for_height;
342
343
344
345
346
  widget_class->realize = gtk_scrolled_window_realize;
  widget_class->unrealize = gtk_scrolled_window_unrealize;
  widget_class->map = gtk_scrolled_window_map;
  widget_class->unmap = gtk_scrolled_window_unmap;
  widget_class->grab_notify = gtk_scrolled_window_grab_notify;
347
348
349
350

  container_class->add = gtk_scrolled_window_add;
  container_class->remove = gtk_scrolled_window_remove;
  container_class->forall = gtk_scrolled_window_forall;
351
  gtk_container_class_handle_border_width (container_class);
352

353
  class->scrollbar_spacing = -1;
354

355
356
357
  class->scroll_child = gtk_scrolled_window_scroll_child;
  class->move_focus_out = gtk_scrolled_window_move_focus_out;
  
Owen Taylor's avatar
Owen Taylor committed
358
359
360
  g_object_class_install_property (gobject_class,
				   PROP_HADJUSTMENT,
				   g_param_spec_object ("hadjustment",
361
362
							P_("Horizontal Adjustment"),
							P_("The GtkAdjustment for the horizontal position"),
Owen Taylor's avatar
Owen Taylor committed
363
							GTK_TYPE_ADJUSTMENT,
364
							GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
Owen Taylor's avatar
Owen Taylor committed
365
366
367
  g_object_class_install_property (gobject_class,
				   PROP_VADJUSTMENT,
				   g_param_spec_object ("vadjustment",
368
369
							P_("Vertical Adjustment"),
							P_("The GtkAdjustment for the vertical position"),
Owen Taylor's avatar
Owen Taylor committed
370
							GTK_TYPE_ADJUSTMENT,
371
							GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
Owen Taylor's avatar
Owen Taylor committed
372
373
  g_object_class_install_property (gobject_class,
                                   PROP_HSCROLLBAR_POLICY,
Matthias Clasen's avatar
x    
Matthias Clasen committed
374
                                   g_param_spec_enum ("hscrollbar-policy",
375
376
                                                      P_("Horizontal Scrollbar Policy"),
                                                      P_("When the horizontal scrollbar is displayed"),
Owen Taylor's avatar
Owen Taylor committed
377
						      GTK_TYPE_POLICY_TYPE,
378
						      GTK_POLICY_AUTOMATIC,
379
                                                      GTK_PARAM_READABLE | GTK_PARAM_WRITABLE));
Owen Taylor's avatar
Owen Taylor committed
380
381
  g_object_class_install_property (gobject_class,
                                   PROP_VSCROLLBAR_POLICY,
Matthias Clasen's avatar
x    
Matthias Clasen committed
382
                                   g_param_spec_enum ("vscrollbar-policy",
383
384
                                                      P_("Vertical Scrollbar Policy"),
                                                      P_("When the vertical scrollbar is displayed"),
Owen Taylor's avatar
Owen Taylor committed
385
						      GTK_TYPE_POLICY_TYPE,
386
						      GTK_POLICY_AUTOMATIC,
387
                                                      GTK_PARAM_READABLE | GTK_PARAM_WRITABLE));
Owen Taylor's avatar
Owen Taylor committed
388
389
390

  g_object_class_install_property (gobject_class,
                                   PROP_WINDOW_PLACEMENT,
Matthias Clasen's avatar
x    
Matthias Clasen committed
391
                                   g_param_spec_enum ("window-placement",
392
                                                      P_("Window Placement"),
393
                                                      P_("Where the contents are located with respect to the scrollbars."),
Owen Taylor's avatar
Owen Taylor committed
394
395
						      GTK_TYPE_CORNER_TYPE,
						      GTK_CORNER_TOP_LEFT,
396
                                                      GTK_PARAM_READABLE | GTK_PARAM_WRITABLE));
397
398
  
  /**
399
   * GtkScrolledWindow:window-placement-set:
400
401
   *
   * Whether "window-placement" should be used to determine the location 
402
   * of the contents with respect to the scrollbars.
403
404
   *
   * Since: 2.10
405
406
407
   *
   * Deprecated: 3.10: This value is ignored and
   * #GtkScrolledWindow:window-placement value is always honored.
408
409
410
411
412
413
   */
  g_object_class_install_property (gobject_class,
                                   PROP_WINDOW_PLACEMENT_SET,
                                   g_param_spec_boolean ("window-placement-set",
					   		 P_("Window Placement Set"),
							 P_("Whether \"window-placement\" should be used to determine the location of the contents with respect to the scrollbars."),
414
							 TRUE,
415
							 GTK_PARAM_READABLE | GTK_PARAM_WRITABLE));
Owen Taylor's avatar
Owen Taylor committed
416
417
  g_object_class_install_property (gobject_class,
                                   PROP_SHADOW_TYPE,
Matthias Clasen's avatar
x    
Matthias Clasen committed
418
                                   g_param_spec_enum ("shadow-type",
419
420
                                                      P_("Shadow Type"),
                                                      P_("Style of bevel around the contents"),
Owen Taylor's avatar
Owen Taylor committed
421
422
						      GTK_TYPE_SHADOW_TYPE,
						      GTK_SHADOW_NONE,
423
                                                      GTK_PARAM_READABLE | GTK_PARAM_WRITABLE));
424

425
426
427
428
429
430
431
  /**
   * GtkScrolledWindow:scrollbars-within-bevel:
   *
   * Whether to place scrollbars within the scrolled window's bevel.
   *
   * Since: 2.12
   */
432
433
434
435
436
437
438
  gtk_widget_class_install_style_property (widget_class,
					   g_param_spec_boolean ("scrollbars-within-bevel",
							         P_("Scrollbars within bevel"),
							         P_("Place scrollbars within the scrolled window's bevel"),
							         FALSE,
							         GTK_PARAM_READABLE));

439
  gtk_widget_class_install_style_property (widget_class,
Matthias Clasen's avatar
x    
Matthias Clasen committed
440
					   g_param_spec_int ("scrollbar-spacing",
441
442
							     P_("Scrollbar spacing"),
							     P_("Number of pixels between the scrollbars and the scrolled window"),
443
444
445
							     0,
							     G_MAXINT,
							     DEFAULT_SCROLLBAR_SPACING,
446
							     GTK_PARAM_READABLE));
447

448
449
450
451
452
453
454
  /**
   * GtkScrolledWindow:min-content-width:
   *
   * The minimum content width of @scrolled_window, or -1 if not set.
   *
   * Since: 3.0
   */
455
456
457
458
459
460
461
  g_object_class_install_property (gobject_class,
                                   PROP_MIN_CONTENT_WIDTH,
                                   g_param_spec_int ("min-content-width",
                                                     P_("Minimum Content Width"),
                                                     P_("The minimum width that the scrolled window will allocate to its content"),
                                                     -1, G_MAXINT, -1,
                                                     GTK_PARAM_READWRITE));
462
463
464
465
466
467
468
469

  /**
   * GtkScrolledWindow:min-content-height:
   *
   * The minimum content height of @scrolled_window, or -1 if not set.
   *
   * Since: 3.0
   */
470
471
472
473
474
475
476
  g_object_class_install_property (gobject_class,
                                   PROP_MIN_CONTENT_HEIGHT,
                                   g_param_spec_int ("min-content-height",
                                                     P_("Minimum Content Height"),
                                                     P_("The minimum height that the scrolled window will allocate to its content"),
                                                     -1, G_MAXINT, -1,
                                                     GTK_PARAM_READWRITE));
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493

  /**
   * GtkScrolledWindow:kinetic-scrolling:
   *
   * The kinetic scrolling behavior flags. Kinetic scrolling
   * only applies to devices with source %GDK_SOURCE_TOUCHSCREEN
   *
   * Since: 3.4
   */
  g_object_class_install_property (gobject_class,
                                   PROP_KINETIC_SCROLLING,
                                   g_param_spec_boolean ("kinetic-scrolling",
                                                         P_("Kinetic Scrolling"),
                                                         P_("Kinetic scrolling mode."),
                                                         TRUE,
                                                         GTK_PARAM_READABLE |
                                                         GTK_PARAM_WRITABLE));
494
495
496
497
498
499
500
501
  /**
   * GtkScrolledWindow::scroll-child:
   * @scrolled_window: a #GtkScrolledWindow
   * @scroll: a #GtkScrollType describing how much to scroll
   * @horizontal: whether the keybinding scrolls the child
   *   horizontally or not
   *
   * The ::scroll-child signal is a
William Jon McCann's avatar
William Jon McCann committed
502
   * [keybinding signal][GtkBindingSignal]
503
504
505
506
   * which gets emitted when a keybinding that scrolls is pressed.
   * The horizontal or vertical adjustment is updated which triggers a
   * signal that the scrolled windows child may listen to and scroll itself.
   */
507
  signals[SCROLL_CHILD] =
508
    g_signal_new (I_("scroll-child"),
509
                  G_TYPE_FROM_CLASS (gobject_class),
510
511
512
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkScrolledWindowClass, scroll_child),
                  NULL, NULL,
513
514
                  _gtk_marshal_BOOLEAN__ENUM_BOOLEAN,
                  G_TYPE_BOOLEAN, 2,
515
516
                  GTK_TYPE_SCROLL_TYPE,
		  G_TYPE_BOOLEAN);
517
518
519
520
521
522
523

  /**
   * GtkScrolledWindow::move-focus-out:
   * @scrolled_window: a #GtkScrolledWindow
   * @direction_type: either %GTK_DIR_TAB_FORWARD or
   *   %GTK_DIR_TAB_BACKWARD
   *
524
   * The ::move-focus-out signal is a
William Jon McCann's avatar
William Jon McCann committed
525
   * [keybinding signal][GtkBindingSignal] which gets
526
527
528
529
530
   * emitted when focus is moved away from the scrolled window by a
   * keybinding.  The #GtkWidget::move-focus signal is emitted with
   * @direction_type on this scrolled windows toplevel parent in the
   * container hierarchy.  The default bindings for this signal are
   * `Tab + Ctrl` and `Tab + Ctrl + Shift`.
531
   */
532
  signals[MOVE_FOCUS_OUT] =
533
    g_signal_new (I_("move-focus-out"),
534
                  G_TYPE_FROM_CLASS (gobject_class),
535
536
537
538
539
540
541
542
543
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkScrolledWindowClass, move_focus_out),
                  NULL, NULL,
                  _gtk_marshal_VOID__ENUM,
                  G_TYPE_NONE, 1,
                  GTK_TYPE_DIRECTION_TYPE);
  
  binding_set = gtk_binding_set_by_class (class);

544
545
546
547
  add_scroll_binding (binding_set, GDK_KEY_Left,  GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, TRUE);
  add_scroll_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD,  TRUE);
  add_scroll_binding (binding_set, GDK_KEY_Up,    GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, FALSE);
  add_scroll_binding (binding_set, GDK_KEY_Down,  GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD,  FALSE);
548

549
550
551
552
  add_scroll_binding (binding_set, GDK_KEY_Page_Up,   GDK_CONTROL_MASK, GTK_SCROLL_PAGE_BACKWARD, TRUE);
  add_scroll_binding (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_FORWARD,  TRUE);
  add_scroll_binding (binding_set, GDK_KEY_Page_Up,   0,                GTK_SCROLL_PAGE_BACKWARD, FALSE);
  add_scroll_binding (binding_set, GDK_KEY_Page_Down, 0,                GTK_SCROLL_PAGE_FORWARD,  FALSE);
553

554
555
556
557
  add_scroll_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK, GTK_SCROLL_START, TRUE);
  add_scroll_binding (binding_set, GDK_KEY_End,  GDK_CONTROL_MASK, GTK_SCROLL_END,   TRUE);
  add_scroll_binding (binding_set, GDK_KEY_Home, 0,                GTK_SCROLL_START, FALSE);
  add_scroll_binding (binding_set, GDK_KEY_End,  0,                GTK_SCROLL_END,   FALSE);
558
559
560

  add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
  add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
561

562
  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SCROLLED_WINDOW_ACCESSIBLE);
563
564
}

565
566
567
568
569
570
571
static void
scrolled_window_drag_begin_cb (GtkScrolledWindow *scrolled_window,
                               gdouble            start_x,
                               gdouble            start_y,
                               GtkGesture        *gesture)
{
  GtkScrolledWindowPrivate *priv = scrolled_window->priv;
572
  GtkEventSequenceState state;
573
574
  GdkEventSequence *sequence;

575
  priv->in_drag = FALSE;
576
577
578
579
580
  priv->drag_start_x = priv->unclamped_hadj_value;
  priv->drag_start_y = priv->unclamped_vadj_value;
  gtk_scrolled_window_cancel_deceleration (scrolled_window);

  if (!priv->hscrollbar_visible && !priv->vscrollbar_visible)
581
582
583
584
585
586
587
588
589
    state = GTK_EVENT_SEQUENCE_DENIED;
  else if (priv->capture_button_press)
    state = GTK_EVENT_SEQUENCE_CLAIMED;
  else
    return;

  sequence = gtk_gesture_get_last_updated_sequence (gesture);
  gtk_widget_set_sequence_state (GTK_WIDGET (scrolled_window),
                                 sequence, state);
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
}

static void
scrolled_window_drag_update_cb (GtkScrolledWindow *scrolled_window,
                                gdouble            offset_x,
                                gdouble            offset_y,
                                GtkGesture        *gesture)
{
  GtkScrolledWindowPrivate *priv = scrolled_window->priv;
  gint old_overshoot_x, old_overshoot_y;
  gint new_overshoot_x, new_overshoot_y;
  GtkAdjustment *hadjustment;
  GtkAdjustment *vadjustment;
  gdouble dx, dy;

605
606
607
608
609
610
611
612
  if (!priv->capture_button_press)
    {
      GdkEventSequence *sequence;

      sequence = gtk_gesture_get_last_updated_sequence (gesture);
      gtk_widget_set_sequence_state (GTK_WIDGET (scrolled_window),
                                     sequence, GTK_EVENT_SEQUENCE_CLAIMED);
    }
613
614
615
616
617
618
619

  _gtk_scrolled_window_get_overshoot (scrolled_window,
                                      &old_overshoot_x, &old_overshoot_y);

  hadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar));
  if (hadjustment && priv->hscrollbar_visible)
    {
620
      dx = priv->drag_start_x - offset_x;
621
622
623
624
625
626
627
      _gtk_scrolled_window_set_adjustment_value (scrolled_window, hadjustment,
                                                 dx, TRUE, FALSE);
    }

  vadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
  if (vadjustment && priv->vscrollbar_visible)
    {
628
      dy = priv->drag_start_y - offset_y;
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
      _gtk_scrolled_window_set_adjustment_value (scrolled_window, vadjustment,
                                                 dy, TRUE, FALSE);
    }

  _gtk_scrolled_window_get_overshoot (scrolled_window,
                                      &new_overshoot_x, &new_overshoot_y);

  if (old_overshoot_x != new_overshoot_x ||
      old_overshoot_y != new_overshoot_y)
    {
      if (new_overshoot_x >= 0 || new_overshoot_y >= 0)
        {
          /* We need to reallocate the widget to have it at
           * negative offset, so there's a "gravity" on the
           * bottom/right corner
           */
          gtk_widget_queue_resize (GTK_WIDGET (scrolled_window));
        }
      else if (new_overshoot_x < 0 || new_overshoot_y < 0)
        _gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
    }
}

652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
static void
scrolled_window_drag_end_cb (GtkScrolledWindow *scrolled_window,
                             gdouble            offset_x,
                             gdouble            offset_y,
                             GtkGesture        *gesture)
{
  GtkScrolledWindowPrivate *priv = scrolled_window->priv;

  if (!priv->in_drag)
    {
      GdkEventSequence *sequence;

      sequence = gtk_gesture_get_last_updated_sequence (gesture);
      gtk_widget_set_sequence_state (GTK_WIDGET (scrolled_window),
                                     sequence, GTK_EVENT_SEQUENCE_DENIED);
    }
}

670
671
672
673
674
675
676
677
678
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
static void
scrolled_window_swipe_cb (GtkScrolledWindow *scrolled_window,
                          gdouble            x_velocity,
                          gdouble            y_velocity)
{
  GtkScrolledWindowPrivate *priv = scrolled_window->priv;
  gboolean overshoot;

  overshoot = _gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL);
  priv->x_velocity = -x_velocity / 1000;
  priv->y_velocity = -y_velocity / 1000;

  /* Zero out vector components without a visible scrollbar */
  if (!priv->hscrollbar_visible)
    priv->x_velocity = 0;
  if (!priv->vscrollbar_visible)
    priv->y_velocity = 0;

  if (priv->x_velocity != 0 || priv->y_velocity != 0 || overshoot)
    {
      gtk_scrolled_window_start_deceleration (scrolled_window);
      priv->x_velocity = priv->y_velocity = 0;
    }
}

static void
scrolled_window_long_press_cb (GtkScrolledWindow *scrolled_window,
                               gdouble            x,
                               gdouble            y,
                               GtkGesture        *gesture)
{
  GdkEventSequence *sequence;

  sequence = gtk_gesture_get_last_updated_sequence (gesture);
  gtk_widget_set_sequence_state (GTK_WIDGET (scrolled_window),
                                 sequence, GTK_EVENT_SEQUENCE_DENIED);
}

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
static void
scrolled_window_long_press_cancelled_cb (GtkScrolledWindow *scrolled_window,
                                         GtkGesture        *gesture)
{
  GtkScrolledWindowPrivate *priv = scrolled_window->priv;
  GdkEventSequence *sequence;
  const GdkEvent *event;

  sequence = gtk_gesture_get_last_updated_sequence (gesture);
  event = gtk_gesture_get_last_event (gesture, sequence);

  if (event->type != GDK_TOUCH_END &&
      event->type != GDK_BUTTON_RELEASE)
    priv->in_drag = TRUE;
}

Elliot Lee's avatar
Elliot Lee committed
724
725
726
static void
gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
{
727
  GtkWidget *widget = GTK_WIDGET (scrolled_window);
728
729
  GtkScrolledWindowPrivate *priv;

730
731
  scrolled_window->priv = priv =
    gtk_scrolled_window_get_instance_private (scrolled_window);
732

733
734
  gtk_widget_set_has_window (widget, FALSE);
  gtk_widget_set_can_focus (widget, TRUE);
Elliot Lee's avatar
Elliot Lee committed
735

736
737
738
  /* Instantiated by gtk_scrolled_window_set_[hv]adjustment
   * which are both construct properties
   */
739
740
  priv->hscrollbar = NULL;
  priv->vscrollbar = NULL;
741
742
  priv->hscrollbar_policy = GTK_POLICY_AUTOMATIC;
  priv->vscrollbar_policy = GTK_POLICY_AUTOMATIC;
743
744
745
746
  priv->hscrollbar_visible = FALSE;
  priv->vscrollbar_visible = FALSE;
  priv->focus_out = FALSE;
  priv->window_placement = GTK_CORNER_TOP_LEFT;
747
748
  priv->min_content_width = -1;
  priv->min_content_height = -1;
749

750
751
752
753
754
755
756
  priv->drag_gesture = gtk_gesture_drag_new (widget);
  g_signal_connect_swapped (priv->drag_gesture, "drag-begin",
                            G_CALLBACK (scrolled_window_drag_begin_cb),
                            scrolled_window);
  g_signal_connect_swapped (priv->drag_gesture, "drag-update",
                            G_CALLBACK (scrolled_window_drag_update_cb),
                            scrolled_window);
757
758
759
  g_signal_connect_swapped (priv->drag_gesture, "drag-end",
                            G_CALLBACK (scrolled_window_drag_end_cb),
                            scrolled_window);
760
761
762
763
764
765

  priv->swipe_gesture = gtk_gesture_swipe_new (widget);
  g_signal_connect_swapped (priv->swipe_gesture, "swipe",
                            G_CALLBACK (scrolled_window_swipe_cb),
                            scrolled_window);
  priv->long_press_gesture = gtk_gesture_long_press_new (widget);
766
  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->long_press_gesture), 1);
767
768
769
  g_signal_connect_swapped (priv->long_press_gesture, "pressed",
                            G_CALLBACK (scrolled_window_long_press_cb),
                            scrolled_window);
770
771
772
  g_signal_connect_swapped (priv->long_press_gesture, "cancelled",
                            G_CALLBACK (scrolled_window_long_press_cancelled_cb),
                            scrolled_window);
773

774
775
  gtk_scrolled_window_set_kinetic_scrolling (scrolled_window, TRUE);
  gtk_scrolled_window_set_capture_button_press (scrolled_window, TRUE);
Elliot Lee's avatar
Elliot Lee committed
776
777
}

Matthias Clasen's avatar
Matthias Clasen committed
778
779
/**
 * gtk_scrolled_window_new:
780
781
 * @hadjustment: (allow-none): horizontal adjustment
 * @vadjustment: (allow-none): vertical adjustment
Matthias Clasen's avatar
Matthias Clasen committed
782
 *
783
784
 * Creates a new scrolled window.
 *
785
 * The two arguments are the scrolled window’s adjustments; these will be
Matthias Clasen's avatar
Matthias Clasen committed
786
787
788
789
790
791
 * shared with the scrollbars and the child widget to keep the bars in sync 
 * with the child. Usually you want to pass %NULL for the adjustments, which 
 * will cause the scrolled window to create them for you.
 *
 * Returns: a new scrolled window
 */
Elliot Lee's avatar
Elliot Lee committed
792
793
794
795
GtkWidget*
gtk_scrolled_window_new (GtkAdjustment *hadjustment,
			 GtkAdjustment *vadjustment)
{
796
  GtkWidget *scrolled_window;
Elliot Lee's avatar
Elliot Lee committed
797

798
799
800
801
802
  if (hadjustment)
    g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadjustment), NULL);

  if (vadjustment)
    g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadjustment), NULL);
Elliot Lee's avatar
Elliot Lee committed
803

804
  scrolled_window = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
805
806
807
				    "hadjustment", hadjustment,
				    "vadjustment", vadjustment,
				    NULL);
808

809
  return scrolled_window;
810
811
}

Matthias Clasen's avatar
Matthias Clasen committed
812
813
814
815
816
817
818
/**
 * gtk_scrolled_window_set_hadjustment:
 * @scrolled_window: a #GtkScrolledWindow
 * @hadjustment: horizontal scroll adjustment
 *
 * Sets the #GtkAdjustment for the horizontal scrollbar.
 */
819
820
821
void
gtk_scrolled_window_set_hadjustment (GtkScrolledWindow *scrolled_window,
				     GtkAdjustment     *hadjustment)
822
{
823
  GtkScrolledWindowPrivate *priv;
824
  GtkBin *bin;
Javier Jardón's avatar
Javier Jardón committed
825
  GtkWidget *child;
826

827
  g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
828
829
830
  if (hadjustment)
    g_return_if_fail (GTK_IS_ADJUSTMENT (hadjustment));
  else
831
    hadjustment = (GtkAdjustment*) g_object_new (GTK_TYPE_ADJUSTMENT, NULL);
832

833
  bin = GTK_BIN (scrolled_window);
834
  priv = scrolled_window->priv;
835

836
  if (!priv->hscrollbar)
837
    {
838
      priv->hscrollbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, hadjustment);
839

840
841
842
      gtk_widget_set_parent (priv->hscrollbar, GTK_WIDGET (scrolled_window));
      g_object_ref (priv->hscrollbar);
      gtk_widget_show (priv->hscrollbar);
843
844
845
846
    }
  else
    {
      GtkAdjustment *old_adjustment;
Tadej Borovšak's avatar
Tadej Borovšak committed
847

848
      old_adjustment = gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar));
849
850
851
      if (old_adjustment == hadjustment)
	return;

Manish Singh's avatar
Manish Singh committed
852
853
854
      g_signal_handlers_disconnect_by_func (old_adjustment,
					    gtk_scrolled_window_adjustment_changed,
					    scrolled_window);
855
      gtk_range_set_adjustment (GTK_RANGE (priv->hscrollbar),
856
857
				hadjustment);
    }
858
  hadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar));
Manish Singh's avatar
Manish Singh committed
859
860
861
862
  g_signal_connect (hadjustment,
		    "changed",
		    G_CALLBACK (gtk_scrolled_window_adjustment_changed),
		    scrolled_window);
863
864
865
866
  g_signal_connect (hadjustment,
		    "value-changed",
		    G_CALLBACK (gtk_scrolled_window_adjustment_value_changed),
		    scrolled_window);
867
  gtk_scrolled_window_adjustment_changed (hadjustment, scrolled_window);
868
  gtk_scrolled_window_adjustment_value_changed (hadjustment, scrolled_window);
Javier Jardón's avatar
Javier Jardón committed
869
870

  child = gtk_bin_get_child (bin);
Tadej Borovšak's avatar
Tadej Borovšak committed
871
  if (GTK_IS_SCROLLABLE (child))
872
    gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (child), hadjustment);
Owen Taylor's avatar
Owen Taylor committed
873
874

  g_object_notify (G_OBJECT (scrolled_window), "hadjustment");
875
}
Elliot Lee's avatar
Elliot Lee committed
876

Matthias Clasen's avatar
Matthias Clasen committed
877
878
879
880
881
882
883
/**
 * gtk_scrolled_window_set_vadjustment:
 * @scrolled_window: a #GtkScrolledWindow
 * @vadjustment: vertical scroll adjustment
 *
 * Sets the #GtkAdjustment for the vertical scrollbar.
 */
884
885
void
gtk_scrolled_window_set_vadjustment (GtkScrolledWindow *scrolled_window,
Tadej Borovšak's avatar
Tadej Borovšak committed
886
                                     GtkAdjustment     *vadjustment)
887
{
888
  GtkScrolledWindowPrivate *priv;
889
  GtkBin *bin;
Javier Jardón's avatar
Javier Jardón committed
890
  GtkWidget *child;
891

892
893
894
895
  g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
  if (vadjustment)
    g_return_if_fail (GTK_IS_ADJUSTMENT (vadjustment));
  else
896
    vadjustment = (GtkAdjustment*) g_object_new (GTK_TYPE_ADJUSTMENT, NULL);
Elliot Lee's avatar
Elliot Lee committed
897

898
  bin = GTK_BIN (scrolled_window);
899
  priv = scrolled_window->priv;
900

901
  if (!priv->vscrollbar)
902
    {
903
      priv->vscrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, vadjustment);
Elliot Lee's avatar
Elliot Lee committed
904

905
906
907
      gtk_widget_set_parent (priv->vscrollbar, GTK_WIDGET (scrolled_window));
      g_object_ref (priv->vscrollbar);
      gtk_widget_show (priv->vscrollbar);
908
909
910
911
912
    }
  else
    {
      GtkAdjustment *old_adjustment;
      
913
      old_adjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
914
915
916
      if (old_adjustment == vadjustment)
	return;

Manish Singh's avatar
Manish Singh committed
917
918
919
      g_signal_handlers_disconnect_by_func (old_adjustment,
					    gtk_scrolled_window_adjustment_changed,
					    scrolled_window);
920
      gtk_range_set_adjustment (GTK_RANGE (priv->vscrollbar),
921
922
				vadjustment);
    }
923
  vadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
Manish Singh's avatar
Manish Singh committed
924
925
926
927
  g_signal_connect (vadjustment,
		    "changed",
		    G_CALLBACK (gtk_scrolled_window_adjustment_changed),
		    scrolled_window);
928
929
930
931
  g_signal_connect (vadjustment,
		    "value-changed",
		    G_CALLBACK (gtk_scrolled_window_adjustment_value_changed),
		    scrolled_window);
932
  gtk_scrolled_window_adjustment_changed (vadjustment, scrolled_window);
933
  gtk_scrolled_window_adjustment_value_changed (vadjustment, scrolled_window);
934

Javier Jardón's avatar
Javier Jardón committed
935
  child = gtk_bin_get_child (bin);
Tadej Borovšak's avatar
Tadej Borovšak committed
936
937
  if (GTK_IS_SCROLLABLE (child))
    gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (child), vadjustment);
Owen Taylor's avatar
Owen Taylor committed
938
939

  g_object_notify (G_OBJECT (scrolled_window), "vadjustment");
Elliot Lee's avatar
Elliot Lee committed
940
941
}

Matthias Clasen's avatar
Matthias Clasen committed
942
943
944
945
/**
 * gtk_scrolled_window_get_hadjustment:
 * @scrolled_window: a #GtkScrolledWindow
 *
946
947
 * Returns the horizontal scrollbar’s adjustment, used to connect the
 * horizontal scrollbar to the child widget’s horizontal scroll
Matthias Clasen's avatar
Matthias Clasen committed
948
949
 * functionality.
 *
Matthias Clasen's avatar
Matthias Clasen committed
950
 * Returns: (transfer none): the horizontal #GtkAdjustment
Matthias Clasen's avatar
Matthias Clasen committed
951
 */
Elliot Lee's avatar
Elliot Lee committed
952
953
954
GtkAdjustment*
gtk_scrolled_window_get_hadjustment (GtkScrolledWindow *scrolled_window)
{
955
956
  GtkScrolledWindowPrivate *priv;

Elliot Lee's avatar
Elliot Lee committed
957
958
  g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL);

959
960
  priv = scrolled_window->priv;

961
  return gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar));
Elliot Lee's avatar
Elliot Lee committed
962
963
}

Matthias Clasen's avatar
Matthias Clasen committed
964
965
966
967
/**
 * gtk_scrolled_window_get_vadjustment:
 * @scrolled_window: a #GtkScrolledWindow
 * 
968
969
 * Returns the vertical scrollbar’s adjustment, used to connect the
 * vertical scrollbar to the child widget’s vertical scroll functionality.
Matthias Clasen's avatar
Matthias Clasen committed
970
 * 
Matthias Clasen's avatar
Matthias Clasen committed
971
 * Returns: (transfer none): the vertical #GtkAdjustment
Matthias Clasen's avatar
Matthias Clasen committed
972
 */
Elliot Lee's avatar
Elliot Lee committed
973
974
975
GtkAdjustment*
gtk_scrolled_window_get_vadjustment (GtkScrolledWindow *scrolled_window)
{
976
977
  GtkScrolledWindowPrivate *priv;

Elliot Lee's avatar
Elliot Lee committed
978
979
  g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL);

980
981
  priv = scrolled_window->priv;

982
  return gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
Elliot Lee's avatar
Elliot Lee committed
983
984
}

985
986
987
/**
 * gtk_scrolled_window_get_hscrollbar:
 * @scrolled_window: a #GtkScrolledWindow
Matthias Clasen's avatar
Matthias Clasen committed
988
 *
989
990
 * Returns the horizontal scrollbar of @scrolled_window.
 *
991
 * Returns: (transfer none): the horizontal scrollbar of the scrolled window.
992
993
994
 *
 * Since: 2.8
 */
995
GtkWidget*
996
997
998
gtk_scrolled_window_get_hscrollbar (GtkScrolledWindow *scrolled_window)
{
  g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL);
999
1000

  return scrolled_window->priv->hscrollbar;
For faster browsing, not all history is shown. View entire blame