gnome-shell-3.6.3.1/src/st/st-scroll-bar.c

Location Tool Test ID Function Issue
st/st-scroll-bar.c:757:7 gcc deprecated-declarations trough_paging_cb 'clutter_animation_completed' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-animation.h:155)
st/st-scroll-bar.c:762:3 gcc deprecated-declarations trough_paging_cb 'clutter_animation_get_type' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-animation.h:94)
st/st-scroll-bar.c:769:3 gcc deprecated-declarations trough_paging_cb 'clutter_animation_bind' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-animation.h:130)
st/st-scroll-bar.c:770:3 gcc deprecated-declarations trough_paging_cb 'clutter_animation_get_timeline' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-animation.h:123)
  1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2 /*
  3  * st-scroll-bar.c: Scroll bar actor
  4  *
  5  * Copyright 2008 OpenedHand
  6  * Copyright 2008, 2009 Intel Corporation.
  7  * Copyright 2009, 2010 Red Hat, Inc.
  8  * Copyright 2010 Maxim Ermilov
  9  *
 10  * This program is free software; you can redistribute it and/or modify it
 11  * under the terms and conditions of the GNU Lesser General Public License,
 12  * version 2.1, as published by the Free Software Foundation.
 13  *
 14  * This program is distributed in the hope it will be useful, but WITHOUT ANY
 15  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 16  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 17  * more details.
 18  *
 19  * You should have received a copy of the GNU Lesser General Public License
 20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
 21  */
 22 
 23 /**
 24  * SECTION:st-scroll-bar
 25  * @short_description: a user interface element to control scrollable areas.
 26  *
 27  * The #StScrollBar allows users to scroll scrollable actors, either by
 28  * the step or page amount, or by manually dragging the handle.
 29  */
 30 
 31 #ifdef HAVE_CONFIG_H
 32 #include "config.h"
 33 #endif
 34 
 35 #include <math.h>
 36 #include <clutter/clutter.h>
 37 
 38 #include "st-scroll-bar.h"
 39 #include "st-bin.h"
 40 #include "st-enum-types.h"
 41 #include "st-private.h"
 42 #include "st-button.h"
 43 
 44 G_DEFINE_TYPE (StScrollBar, st_scroll_bar, ST_TYPE_WIDGET)
 45 
 46 #define ST_SCROLL_BAR_GET_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_SCROLL_BAR, StScrollBarPrivate))
 47 
 48 #define PAGING_INITIAL_REPEAT_TIMEOUT 500
 49 #define PAGING_SUBSEQUENT_REPEAT_TIMEOUT 200
 50 
 51 struct _StScrollBarPrivate
 52 {
 53   StAdjustment *adjustment;
 54 
 55   gboolean      grabbed;
 56   gfloat        x_origin;
 57   gfloat        y_origin;
 58 
 59   ClutterActor *trough;
 60   ClutterActor *handle;
 61 
 62   gfloat        move_x;
 63   gfloat        move_y;
 64 
 65   /* Trough-click handling. */
 66   enum { NONE, UP, DOWN }  paging_direction;
 67   guint             paging_source_id;
 68   guint             paging_event_no;
 69 
 70   ClutterAnimation *paging_animation;
 71 
 72   guint             vertical : 1;
 73 };
 74 
 75 enum
 76 {
 77   PROP_0,
 78 
 79   PROP_ADJUSTMENT,
 80   PROP_VERTICAL
 81 };
 82 
 83 enum
 84 {
 85   SCROLL_START,
 86   SCROLL_STOP,
 87 
 88   LAST_SIGNAL
 89 };
 90 
 91 static guint signals[LAST_SIGNAL] = { 0, };
 92 
 93 extern gfloat st_slow_down_factor;
 94 
 95 static gboolean
 96 handle_button_press_event_cb (ClutterActor       *actor,
 97                               ClutterButtonEvent *event,
 98                               StScrollBar        *bar);
 99 
100 static void stop_scrolling (StScrollBar *bar);
101 
102 static void
103 st_scroll_bar_get_property (GObject    *gobject,
104                             guint       prop_id,
105                             GValue     *value,
106                             GParamSpec *pspec)
107 {
108   StScrollBarPrivate *priv = ST_SCROLL_BAR (gobject)->priv;
109 
110   switch (prop_id)
111     {
112     case PROP_ADJUSTMENT:
113       g_value_set_object (value, priv->adjustment);
114       break;
115 
116     case PROP_VERTICAL:
117       g_value_set_boolean (value, priv->vertical);
118       break;
119 
120     default:
121       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
122       break;
123     }
124 }
125 
126 static void
127 st_scroll_bar_set_property (GObject      *gobject,
128                             guint         prop_id,
129                             const GValue *value,
130                             GParamSpec   *pspec)
131 {
132   StScrollBar *bar = ST_SCROLL_BAR (gobject);
133 
134   switch (prop_id)
135     {
136     case PROP_ADJUSTMENT:
137       st_scroll_bar_set_adjustment (bar, g_value_get_object (value));
138       break;
139 
140     case PROP_VERTICAL:
141       bar->priv->vertical = g_value_get_boolean (value);
142       if (bar->priv->vertical)
143         clutter_actor_set_name (CLUTTER_ACTOR (bar->priv->handle),
144                                 "vhandle");
145       else
146         clutter_actor_set_name (CLUTTER_ACTOR (bar->priv->handle),
147                                 "hhandle");
148       clutter_actor_queue_relayout ((ClutterActor*) gobject);
149       break;
150 
151     default:
152       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
153       break;
154     }
155 }
156 
157 static void
158 st_scroll_bar_dispose (GObject *gobject)
159 {
160   StScrollBar *bar = ST_SCROLL_BAR (gobject);
161   StScrollBarPrivate *priv = bar->priv;
162 
163   if (priv->adjustment)
164     st_scroll_bar_set_adjustment (bar, NULL);
165 
166   if (priv->handle)
167     {
168       clutter_actor_destroy (priv->handle);
169       priv->handle = NULL;
170     }
171 
172   if (priv->trough)
173     {
174       clutter_actor_destroy (priv->trough);
175       priv->trough = NULL;
176     }
177 
178   G_OBJECT_CLASS (st_scroll_bar_parent_class)->dispose (gobject);
179 }
180 
181 static void
182 st_scroll_bar_unmap (ClutterActor *actor)
183 {
184   CLUTTER_ACTOR_CLASS (st_scroll_bar_parent_class)->unmap (actor);
185 
186   stop_scrolling (ST_SCROLL_BAR (actor));
187 }
188 
189 static void
190 scroll_bar_allocate_children (StScrollBar           *bar,
191                               const ClutterActorBox *box,
192                               ClutterAllocationFlags flags)
193 {
194   StScrollBarPrivate *priv = bar->priv;
195   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (bar));
196   ClutterActorBox content_box, trough_box;
197 
198   st_theme_node_get_content_box (theme_node, box, &content_box);
199 
200   if (priv->vertical)
201     {
202       trough_box.x1 = content_box.x1;
203       trough_box.y1 = content_box.y1;
204       trough_box.x2 = content_box.x2;
205       trough_box.y2 = content_box.y2;
206       clutter_actor_allocate (priv->trough, &trough_box, flags);
207     }
208   else
209     {
210       trough_box.x1 = content_box.x1;
211       trough_box.y1 = content_box.y1;
212       trough_box.x2 = content_box.x2;
213       trough_box.y2 = content_box.y2;
214       clutter_actor_allocate (priv->trough, &trough_box, flags);
215     }
216 
217 
218   if (priv->adjustment)
219     {
220       float handle_size, position, avail_size;
221       gdouble value, lower, upper, page_size, increment, min_size, max_size;
222       ClutterActorBox handle_box = { 0, };
223 
224       st_adjustment_get_values (priv->adjustment,
225                                 &value,
226                                 &lower,
227                                 &upper,
228                                 NULL,
229                                 NULL,
230                                 &page_size);
231 
232       if ((upper == lower)
233           || (page_size >= (upper - lower)))
234         increment = 1.0;
235       else
236         increment = page_size / (upper - lower);
237 
238       min_size = 32.;
239       st_theme_node_lookup_length (theme_node, "min-size", FALSE, &min_size);
240       max_size = G_MAXINT16;
241       st_theme_node_lookup_length (theme_node, "max-size", FALSE, &max_size);
242 
243       if (upper - lower - page_size <= 0)
244         position = 0;
245       else
246         position = (value - lower) / (upper - lower - page_size);
247 
248       if (priv->vertical)
249         {
250           avail_size = content_box.y2 - content_box.y1;
251           handle_size = increment * avail_size;
252           handle_size = CLAMP (handle_size, min_size, max_size);
253 
254           handle_box.x1 = content_box.x1;
255           handle_box.y1 = content_box.y1 + position * (avail_size - handle_size);
256 
257           handle_box.x2 = content_box.x2;
258           handle_box.y2 = handle_box.y1 + handle_size;
259         }
260       else
261         {
262           avail_size = content_box.x2 - content_box.x1;
263           handle_size = increment * avail_size;
264           handle_size = CLAMP (handle_size, min_size, max_size);
265 
266           handle_box.x1 = content_box.x1 + position * (avail_size - handle_size);
267           handle_box.y1 = content_box.y1;
268 
269           handle_box.x2 = handle_box.x1 + handle_size;
270           handle_box.y2 = content_box.y2;
271         }
272 
273       /* snap to pixel */
274       handle_box.x1 = (int) handle_box.x1;
275       handle_box.y1 = (int) handle_box.y1;
276       handle_box.x2 = (int) handle_box.x2;
277       handle_box.y2 = (int) handle_box.y2;
278 
279       clutter_actor_allocate (priv->handle,
280                               &handle_box,
281                               flags);
282     }
283 }
284 
285 static void
286 st_scroll_bar_get_preferred_width (ClutterActor *self,
287                                    gfloat        for_height,
288                                    gfloat       *min_width_p,
289                                    gfloat       *natural_width_p)
290 {
291   StScrollBar *bar = ST_SCROLL_BAR (self);
292   StScrollBarPrivate *priv = bar->priv;
293   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
294   gfloat trough_min_width, trough_natural_width;
295   gfloat handle_min_width, handle_natural_width;
296 
297   st_theme_node_adjust_for_height (theme_node, &for_height);
298 
299   _st_actor_get_preferred_width (priv->trough, for_height, TRUE,
300                                  &trough_min_width, &trough_natural_width);
301 
302   _st_actor_get_preferred_width (priv->handle, for_height, TRUE,
303                                  &handle_min_width, &handle_natural_width);
304 
305   if (priv->vertical)
306     {
307       if (min_width_p)
308         *min_width_p = MAX (trough_min_width, handle_min_width);
309 
310       if (natural_width_p)
311         *natural_width_p = MAX (trough_natural_width, handle_natural_width);
312     }
313   else
314     {
315       if (min_width_p)
316         *min_width_p = trough_min_width + handle_min_width;
317 
318       if (natural_width_p)
319         *natural_width_p = trough_natural_width + handle_natural_width;
320     }
321 
322   st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
323 }
324 
325 static void
326 st_scroll_bar_get_preferred_height (ClutterActor *self,
327                                     gfloat        for_width,
328                                     gfloat       *min_height_p,
329                                     gfloat       *natural_height_p)
330 {
331   StScrollBar *bar = ST_SCROLL_BAR (self);
332   StScrollBarPrivate *priv = bar->priv;
333   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
334   gfloat trough_min_height, trough_natural_height;
335   gfloat handle_min_height, handle_natural_height;
336 
337   st_theme_node_adjust_for_width (theme_node, &for_width);
338 
339   _st_actor_get_preferred_height (priv->trough, for_width, TRUE,
340                                   &trough_min_height, &trough_natural_height);
341 
342   _st_actor_get_preferred_height (priv->handle, for_width, TRUE,
343                                   &handle_min_height, &handle_natural_height);
344 
345   if (priv->vertical)
346     {
347       if (min_height_p)
348         *min_height_p = trough_min_height + handle_min_height;
349 
350       if (natural_height_p)
351         *natural_height_p = trough_natural_height + handle_natural_height;
352     }
353   else
354     {
355       if (min_height_p)
356         *min_height_p = MAX (trough_min_height, handle_min_height);
357 
358       if (natural_height_p)
359         *natural_height_p = MAX (trough_natural_height, handle_natural_height);
360     }
361 
362   st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
363 }
364 
365 static void
366 st_scroll_bar_allocate (ClutterActor          *actor,
367                         const ClutterActorBox *box,
368                         ClutterAllocationFlags flags)
369 {
370   StScrollBar *bar = ST_SCROLL_BAR (actor);
371 
372   clutter_actor_set_allocation (actor, box, flags);
373 
374   scroll_bar_allocate_children (bar, box, flags);
375 }
376 
377 static void
378 scroll_bar_update_positions (StScrollBar *bar)
379 {
380   ClutterActorBox box;
381 
382   /* Due to a change in the adjustments, we need to reposition our
383    * children; since adjustments changes can come from allocation
384    * changes in the scrolled area, we can't just queue a new relayout -
385    * we may already be in a relayout cycle. On the other hand, if
386    * a relayout is already queued, we can't just go ahead and allocate
387    * our children, since we don't have a valid allocation, and calling
388    * clutter_actor_get_allocation_box() will trigger an immediate
389    * stage relayout. So what we do is go ahead and immediately
390    * allocate our children if we already have a valid allocation, and
391    * otherwise just wait for the queued relayout.
392    */
393   if (!clutter_actor_has_allocation (CLUTTER_ACTOR (bar)))
394     return;
395 
396   clutter_actor_get_allocation_box (CLUTTER_ACTOR (bar), &box);
397   scroll_bar_allocate_children (bar, &box, CLUTTER_ALLOCATION_NONE);
398 }
399 
400 static void
401 st_scroll_bar_style_changed (StWidget *widget)
402 {
403   StScrollBarPrivate *priv = ST_SCROLL_BAR (widget)->priv;
404 
405   st_widget_style_changed (ST_WIDGET (priv->trough));
406   st_widget_style_changed (ST_WIDGET (priv->handle));
407 
408   ST_WIDGET_CLASS (st_scroll_bar_parent_class)->style_changed (widget);
409 }
410 
411 static void
412 bar_reactive_notify_cb (GObject    *gobject,
413                         GParamSpec *arg1,
414                         gpointer    user_data)
415 {
416   StScrollBar *bar = ST_SCROLL_BAR (gobject);
417 
418   clutter_actor_set_reactive (bar->priv->handle,
419                               clutter_actor_get_reactive (CLUTTER_ACTOR (bar)));
420 }
421 
422 static GObject*
423 st_scroll_bar_constructor (GType                  type,
424                            guint                  n_properties,
425                            GObjectConstructParam *properties)
426 {
427   GObjectClass *gobject_class;
428   GObject *obj;
429   StScrollBar *bar;
430 
431   gobject_class = G_OBJECT_CLASS (st_scroll_bar_parent_class);
432   obj = gobject_class->constructor (type, n_properties, properties);
433 
434   bar  = ST_SCROLL_BAR (obj);
435 
436   g_signal_connect (bar, "notify::reactive",
437                     G_CALLBACK (bar_reactive_notify_cb), NULL);
438 
439   return obj;
440 }
441 
442 static gboolean
443 st_scroll_bar_scroll_event (ClutterActor       *actor,
444                             ClutterScrollEvent *event)
445 {
446   StScrollBarPrivate *priv = ST_SCROLL_BAR (actor)->priv;
447   gdouble step, value, delta_x, delta_y;
448 
449   if (priv->adjustment)
450     {
451       g_object_get (priv->adjustment,
452                     "step-increment", &step,
453                     "value", &value,
454                     NULL);
455     }
456   else
457     {
458       return FALSE;
459     }
460 
461   switch (event->direction)
462     {
463     case CLUTTER_SCROLL_SMOOTH:
464       clutter_event_get_scroll_delta ((ClutterEvent *)event,
465                                       &delta_x, &delta_y);
466       if (fabs (delta_x) > fabs (delta_y))
467         st_adjustment_set_value (priv->adjustment, value + delta_x);
468       else
469         st_adjustment_set_value (priv->adjustment, value + delta_y);
470       break;
471     case CLUTTER_SCROLL_UP:
472     case CLUTTER_SCROLL_LEFT:
473       st_adjustment_set_value (priv->adjustment, value - step);
474       break;
475     case CLUTTER_SCROLL_DOWN:
476     case CLUTTER_SCROLL_RIGHT:
477       st_adjustment_set_value (priv->adjustment, value + step);
478       break;
479     }
480 
481   return TRUE;
482 }
483 
484 static void
485 st_scroll_bar_class_init (StScrollBarClass *klass)
486 {
487   GObjectClass *object_class = G_OBJECT_CLASS (klass);
488   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
489   StWidgetClass *widget_class = ST_WIDGET_CLASS (klass);
490   GParamSpec *pspec;
491 
492   g_type_class_add_private (klass, sizeof (StScrollBarPrivate));
493 
494   object_class->get_property = st_scroll_bar_get_property;
495   object_class->set_property = st_scroll_bar_set_property;
496   object_class->dispose      = st_scroll_bar_dispose;
497   object_class->constructor  = st_scroll_bar_constructor;
498 
499   actor_class->get_preferred_width  = st_scroll_bar_get_preferred_width;
500   actor_class->get_preferred_height = st_scroll_bar_get_preferred_height;
501   actor_class->allocate       = st_scroll_bar_allocate;
502   actor_class->scroll_event   = st_scroll_bar_scroll_event;
503   actor_class->unmap          = st_scroll_bar_unmap;
504 
505   widget_class->style_changed = st_scroll_bar_style_changed;
506 
507   g_object_class_install_property
508                  (object_class,
509                  PROP_ADJUSTMENT,
510                  g_param_spec_object ("adjustment",
511                                       "Adjustment",
512                                       "The adjustment",
513                                       ST_TYPE_ADJUSTMENT,
514                                       ST_PARAM_READWRITE));
515 
516   pspec = g_param_spec_boolean ("vertical",
517                                 "Vertical Orientation",
518                                 "Vertical Orientation",
519                                 FALSE,
520                                 ST_PARAM_READWRITE);
521   g_object_class_install_property (object_class, PROP_VERTICAL, pspec);
522 
523   signals[SCROLL_START] =
524     g_signal_new ("scroll-start",
525                   G_TYPE_FROM_CLASS (klass),
526                   G_SIGNAL_RUN_LAST,
527                   G_STRUCT_OFFSET (StScrollBarClass, scroll_start),
528                   NULL, NULL, NULL,
529                   G_TYPE_NONE, 0);
530 
531   signals[SCROLL_STOP] =
532     g_signal_new ("scroll-stop",
533                   G_TYPE_FROM_CLASS (klass),
534                   G_SIGNAL_RUN_LAST,
535                   G_STRUCT_OFFSET (StScrollBarClass, scroll_stop),
536                   NULL, NULL, NULL,
537                   G_TYPE_NONE, 0);
538 }
539 
540 static void
541 move_slider (StScrollBar *bar,
542              gfloat       x,
543              gfloat       y)
544 {
545   StScrollBarPrivate *priv = bar->priv;
546   gdouble position, lower, upper, page_size;
547   gfloat ux, uy, pos, size;
548 
549   if (!priv->adjustment)
550     return;
551 
552   if (!clutter_actor_transform_stage_point (priv->trough, x, y, &ux, &uy))
553     return;
554 
555   if (priv->vertical)
556     size = clutter_actor_get_height (priv->trough)
557            - clutter_actor_get_height (priv->handle);
558   else
559     size = clutter_actor_get_width (priv->trough)
560            - clutter_actor_get_width (priv->handle);
561 
562   if (size == 0)
563     return;
564 
565   if (priv->vertical)
566     pos = uy - priv->y_origin;
567   else
568     pos = ux - priv->x_origin;
569   pos = CLAMP (pos, 0, size);
570 
571   st_adjustment_get_values (priv->adjustment,
572                             NULL,
573                             &lower,
574                             &upper,
575                             NULL,
576                             NULL,
577                             &page_size);
578 
579   position = ((pos / size)
580               * (upper - lower - page_size))
581              + lower;
582 
583   st_adjustment_set_value (priv->adjustment, position);
584 }
585 
586 static void
587 stop_scrolling (StScrollBar *bar)
588 {
589   if (!bar->priv->grabbed)
590     return;
591 
592   st_widget_remove_style_pseudo_class (ST_WIDGET (bar->priv->handle), "active");
593 
594   clutter_ungrab_pointer ();
595   bar->priv->grabbed = FALSE;
596   g_signal_emit (bar, signals[SCROLL_STOP], 0);
597 }
598 
599 static gboolean
600 handle_motion_event_cb (ClutterActor       *trough,
601                         ClutterMotionEvent *event,
602                         StScrollBar        *bar)
603 {
604   if (!bar->priv->grabbed)
605     return FALSE;
606 
607   move_slider (bar, event->x, event->y);
608   return TRUE;
609 }
610 
611 static gboolean
612 handle_button_release_event_cb (ClutterActor       *trough,
613                                 ClutterButtonEvent *event,
614                                 StScrollBar        *bar)
615 {
616   if (event->button != 1)
617     return FALSE;
618 
619   stop_scrolling (bar);
620   return TRUE;
621 }
622 
623 static gboolean
624 handle_button_press_event_cb (ClutterActor       *actor,
625                               ClutterButtonEvent *event,
626                               StScrollBar        *bar)
627 {
628   StScrollBarPrivate *priv = bar->priv;
629 
630   if (event->button != 1)
631     return FALSE;
632 
633   if (!clutter_actor_transform_stage_point (priv->handle,
634                                             event->x,
635                                             event->y,
636                                             &priv->x_origin,
637                                             &priv->y_origin))
638     return FALSE;
639 
640   st_widget_add_style_pseudo_class (ST_WIDGET (priv->handle), "active");
641 
642   /* Account for the scrollbar-trough-handle nesting. */
643   priv->x_origin += clutter_actor_get_x (priv->trough);
644   priv->y_origin += clutter_actor_get_y (priv->trough);
645 
646   g_assert (!priv->grabbed);
647 
648   clutter_grab_pointer (priv->handle);
649   priv->grabbed = TRUE;
650   g_signal_emit (bar, signals[SCROLL_START], 0);
651 
652   return TRUE;
653 }
654 
655 static void
656 animation_completed_cb (ClutterAnimation   *animation,
657                         StScrollBarPrivate *priv)
658 {
659   g_object_unref (priv->paging_animation);
660   priv->paging_animation = NULL;
661 }
662 
663 static gboolean
664 trough_paging_cb (StScrollBar *self)
665 {
666   gfloat handle_pos, event_pos, tx, ty;
667   gdouble value;
668   gdouble page_increment;
669   gboolean ret;
670 
671   gulong mode;
672   ClutterAnimation *a;
673   GValue v = { 0, };
674   ClutterTimeline *t;
675 
676   if (self->priv->paging_event_no == 0)
677     {
678       /* Scroll on after initial timeout. */
679       mode = CLUTTER_EASE_OUT_CUBIC;
680       ret = FALSE;
681       self->priv->paging_event_no = 1;
682       self->priv->paging_source_id = g_timeout_add (
683         PAGING_INITIAL_REPEAT_TIMEOUT,
684         (GSourceFunc) trough_paging_cb,
685         self);
686     }
687   else if (self->priv->paging_event_no == 1)
688     {
689       /* Scroll on after subsequent timeout. */
690       ret = FALSE;
691       mode = CLUTTER_EASE_IN_CUBIC;
692       self->priv->paging_event_no = 2;
693       self->priv->paging_source_id = g_timeout_add (
694         PAGING_SUBSEQUENT_REPEAT_TIMEOUT,
695         (GSourceFunc) trough_paging_cb,
696         self);
697     }
698   else
699     {
700       /* Keep scrolling. */
701       ret = TRUE;
702       mode = CLUTTER_LINEAR;
703       self->priv->paging_event_no++;
704     }
705 
706   /* Do the scrolling */
707   st_adjustment_get_values (self->priv->adjustment,
708                             &value, NULL, NULL,
709                             NULL, &page_increment, NULL);
710 
711   if (self->priv->vertical)
712     handle_pos = clutter_actor_get_y (self->priv->handle);
713   else
714     handle_pos = clutter_actor_get_x (self->priv->handle);
715 
716   clutter_actor_transform_stage_point (CLUTTER_ACTOR (self->priv->trough),
717                                        self->priv->move_x,
718                                        self->priv->move_y,
719                                        &tx, &ty);
720 
721   if (self->priv->vertical)
722     event_pos = ty;
723   else
724     event_pos = tx;
725 
726   if (event_pos > handle_pos)
727     {
728       if (self->priv->paging_direction == NONE)
729         {
730           /* Remember direction. */
731           self->priv->paging_direction = DOWN;
732         }
733       if (self->priv->paging_direction == UP)
734         {
735           /* Scrolled far enough. */
736           return FALSE;
737         }
738       value += page_increment;
739     }
740   else
741     {
742       if (self->priv->paging_direction == NONE)
743         {
744           /* Remember direction. */
745           self->priv->paging_direction = UP;
746         }
747       if (self->priv->paging_direction == DOWN)
748         {
749           /* Scrolled far enough. */
750           return FALSE;
751         }
752       value -= page_increment;
753     }
754 
755   if (self->priv->paging_animation)
756     {
757       clutter_animation_completed (self->priv->paging_animation);
'clutter_animation_completed' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-animation.h:155)
(emitted by gcc)
758 } 759 760 /* FIXME: Creating a new animation for each scroll is probably not the best 761 * idea, but it's a lot less involved than extenind the current animation */ 762 a = self->priv->paging_animation = g_object_new (CLUTTER_TYPE_ANIMATION,
'clutter_animation_get_type' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-animation.h:94)
(emitted by gcc)
763 "object", self->priv->adjustment, 764 "duration", (guint)(PAGING_SUBSEQUENT_REPEAT_TIMEOUT * st_slow_down_factor), 765 "mode", mode, 766 NULL); 767 g_value_init (&v, G_TYPE_DOUBLE); 768 g_value_set_double (&v, value); 769 clutter_animation_bind (self->priv->paging_animation, "value", &v);
'clutter_animation_bind' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-animation.h:130)
(emitted by gcc)
770 t = clutter_animation_get_timeline (self->priv->paging_animation);
'clutter_animation_get_timeline' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-animation.h:123)
(emitted by gcc)
771 g_signal_connect (a, "completed", G_CALLBACK (animation_completed_cb), 772 self->priv); 773 clutter_timeline_start (t); 774 775 return ret; 776 } 777 778 static gboolean 779 trough_button_press_event_cb (ClutterActor *actor, 780 ClutterButtonEvent *event, 781 StScrollBar *self) 782 { 783 g_return_val_if_fail (self, FALSE); 784 785 if (event->button != 1) 786 return FALSE; 787 788 if (self->priv->adjustment == NULL) 789 return FALSE; 790 791 self->priv->move_x = event->x; 792 self->priv->move_y = event->y; 793 self->priv->paging_direction = NONE; 794 self->priv->paging_event_no = 0; 795 trough_paging_cb (self); 796 797 return TRUE; 798 } 799 800 static gboolean 801 trough_button_release_event_cb (ClutterActor *actor, 802 ClutterButtonEvent *event, 803 StScrollBar *self) 804 { 805 if (event->button != 1) 806 return FALSE; 807 808 if (self->priv->paging_source_id) 809 { 810 g_source_remove (self->priv->paging_source_id); 811 self->priv->paging_source_id = 0; 812 } 813 814 return TRUE; 815 } 816 817 static gboolean 818 trough_leave_event_cb (ClutterActor *actor, 819 ClutterEvent *event, 820 StScrollBar *self) 821 { 822 if (self->priv->paging_source_id) 823 { 824 g_source_remove (self->priv->paging_source_id); 825 self->priv->paging_source_id = 0; 826 return TRUE; 827 } 828 829 return FALSE; 830 } 831 832 static void 833 st_scroll_bar_notify_reactive (StScrollBar *self) 834 { 835 StScrollBarPrivate *priv = self->priv; 836 837 gboolean reactive = CLUTTER_ACTOR_IS_REACTIVE (self); 838 839 clutter_actor_set_reactive (CLUTTER_ACTOR (priv->trough), reactive); 840 clutter_actor_set_reactive (CLUTTER_ACTOR (priv->handle), reactive); 841 } 842 843 static void 844 st_scroll_bar_init (StScrollBar *self) 845 { 846 self->priv = ST_SCROLL_BAR_GET_PRIVATE (self); 847 848 self->priv->trough = (ClutterActor *) st_bin_new (); 849 clutter_actor_set_reactive ((ClutterActor *) self->priv->trough, TRUE); 850 clutter_actor_set_name (CLUTTER_ACTOR (self->priv->trough), "trough"); 851 clutter_actor_add_child (CLUTTER_ACTOR (self), 852 CLUTTER_ACTOR (self->priv->trough)); 853 g_signal_connect (self->priv->trough, "button-press-event", 854 G_CALLBACK (trough_button_press_event_cb), self); 855 g_signal_connect (self->priv->trough, "button-release-event", 856 G_CALLBACK (trough_button_release_event_cb), self); 857 g_signal_connect (self->priv->trough, "leave-event", 858 G_CALLBACK (trough_leave_event_cb), self); 859 860 self->priv->handle = (ClutterActor *) st_button_new (); 861 clutter_actor_set_name (CLUTTER_ACTOR (self->priv->handle), "hhandle"); 862 clutter_actor_add_child (CLUTTER_ACTOR (self), 863 CLUTTER_ACTOR (self->priv->handle)); 864 g_signal_connect (self->priv->handle, "button-press-event", 865 G_CALLBACK (handle_button_press_event_cb), self); 866 g_signal_connect (self->priv->handle, "button-release-event", 867 G_CALLBACK (handle_button_release_event_cb), self); 868 g_signal_connect (self->priv->handle, "motion-event", 869 G_CALLBACK (handle_motion_event_cb), self); 870 871 clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE); 872 873 g_signal_connect (self, "notify::reactive", 874 G_CALLBACK (st_scroll_bar_notify_reactive), NULL); 875 } 876 877 StWidget * 878 st_scroll_bar_new (StAdjustment *adjustment) 879 { 880 return g_object_new (ST_TYPE_SCROLL_BAR, 881 "adjustment", adjustment, 882 NULL); 883 } 884 885 static void 886 on_notify_value (GObject *object, 887 GParamSpec *pspec, 888 StScrollBar *bar) 889 { 890 scroll_bar_update_positions (bar); 891 } 892 893 static void 894 on_changed (StAdjustment *adjustment, 895 StScrollBar *bar) 896 { 897 scroll_bar_update_positions (bar); 898 } 899 900 void 901 st_scroll_bar_set_adjustment (StScrollBar *bar, 902 StAdjustment *adjustment) 903 { 904 StScrollBarPrivate *priv; 905 906 g_return_if_fail (ST_IS_SCROLL_BAR (bar)); 907 908 priv = bar->priv; 909 910 if (adjustment == priv->adjustment) 911 return; 912 913 if (priv->adjustment) 914 { 915 g_signal_handlers_disconnect_by_func (priv->adjustment, 916 on_notify_value, 917 bar); 918 g_signal_handlers_disconnect_by_func (priv->adjustment, 919 on_changed, 920 bar); 921 g_object_unref (priv->adjustment); 922 priv->adjustment = NULL; 923 } 924 925 if (adjustment) 926 { 927 priv->adjustment = g_object_ref (adjustment); 928 929 g_signal_connect (priv->adjustment, "notify::value", 930 G_CALLBACK (on_notify_value), 931 bar); 932 g_signal_connect (priv->adjustment, "changed", 933 G_CALLBACK (on_changed), 934 bar); 935 936 clutter_actor_queue_relayout (CLUTTER_ACTOR (bar)); 937 } 938 939 g_object_notify (G_OBJECT (bar), "adjustment"); 940 } 941 942 /** 943 * st_scroll_bar_get_adjustment: 944 * @bar: a #StScrollbar 945 * 946 * Gets the adjustment object that stores the current position 947 * of the scrollbar. 948 * 949 * Return value: (transfer none): the adjustment 950 */ 951 StAdjustment * 952 st_scroll_bar_get_adjustment (StScrollBar *bar) 953 { 954 g_return_val_if_fail (ST_IS_SCROLL_BAR (bar), NULL); 955 956 return bar->priv->adjustment; 957 }