1 /*
2 * viewpad: A viewpad managing views
3 *
4 * Copyright 2012-2020 Stephan Haller <nomad@froevel.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 *
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <libxfdashboard/viewpad.h>
29
30 #include <glib/gi18n-lib.h>
31 #include <gtk/gtk.h>
32 #include <math.h>
33
34 #include <libxfdashboard/view-manager.h>
35 #include <libxfdashboard/scrollbar.h>
36 #include <libxfdashboard/enums.h>
37 #include <libxfdashboard/utils.h>
38 #include <libxfdashboard/focusable.h>
39 #include <libxfdashboard/focus-manager.h>
40 #include <libxfdashboard/compat.h>
41 #include <libxfdashboard/debug.h>
42
43
44 /* Define this class in GObject system */
45 static void _xfdashboard_viewpad_focusable_iface_init(XfdashboardFocusableInterface *iface);
46
47 struct _XfdashboardViewpadPrivate
48 {
49 /* Properties related */
50 gfloat spacing;
51 XfdashboardView *activeView;
52 XfdashboardVisibilityPolicy hScrollbarPolicy;
53 gboolean hScrollbarVisible;
54 XfdashboardVisibilityPolicy vScrollbarPolicy;
55 gboolean vScrollbarVisible;
56
57 /* Instance related */
58 XfdashboardViewManager *viewManager;
59
60 ClutterLayoutManager *layout;
61 ClutterActor *container;
62 ClutterActor *hScrollbar;
63 ClutterActor *vScrollbar;
64
65 guint scrollbarUpdateID;
66
67 gboolean doRegisterFocusableViews;
68
69 ClutterActorBox *lastAllocation;
70 };
71
72 G_DEFINE_TYPE_WITH_CODE(XfdashboardViewpad,
73 xfdashboard_viewpad,
74 XFDASHBOARD_TYPE_BACKGROUND,
75 G_ADD_PRIVATE(XfdashboardViewpad)
76 G_IMPLEMENT_INTERFACE(XFDASHBOARD_TYPE_FOCUSABLE, _xfdashboard_viewpad_focusable_iface_init))
77
78 /* Properties */
79 enum
80 {
81 PROP_0,
82
83 PROP_SPACING,
84 PROP_ACTIVE_VIEW,
85 PROP_HSCROLLBAR_POLICY,
86 PROP_HSCROLLBAR_VISIBLE,
87 PROP_VSCROLLBAR_POLICY,
88 PROP_VSCROLLBAR_VISIBLE,
89
90 PROP_LAST
91 };
92
93 static GParamSpec* XfdashboardViewpadProperties[PROP_LAST]={ 0, };
94
95 /* Signals */
96 enum
97 {
98 SIGNAL_VIEW_ADDED,
99 SIGNAL_VIEW_REMOVED,
100
101 SIGNAL_VIEW_ACTIVATING,
102 SIGNAL_VIEW_ACTIVATED,
103 SIGNAL_VIEW_DEACTIVATING,
104 SIGNAL_VIEW_DEACTIVATED,
105
106 SIGNAL_LAST
107 };
108
109 static guint XfdashboardViewpadSignals[SIGNAL_LAST]={ 0, };
110
111 /* Forward declaration */
112 static void _xfdashboard_viewpad_allocate(ClutterActor *self, const ClutterActorBox *inBox, ClutterAllocationFlags inFlags);
113
114 /* IMPLEMENTATION: Private variables and methods */
115
116 /* Update view depending on scrollbar values */
_xfdashboard_viewpad_update_view_viewport(XfdashboardViewpad * self)117 static void _xfdashboard_viewpad_update_view_viewport(XfdashboardViewpad *self)
118 {
119 XfdashboardViewpadPrivate *priv;
120 ClutterMatrix transform;
121 gfloat x, y, w, h;
122
123 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
124
125 priv=self->priv;
126
127 /* Check for active view */
128 if(priv->activeView==NULL)
129 {
130 g_warning("Cannot update viewport of view because no one is active");
131 return;
132 }
133
134 /* Get offset from scrollbars and view size from clipping */
135 if(clutter_actor_has_clip(CLUTTER_ACTOR(priv->activeView)))
136 {
137 clutter_actor_get_clip(CLUTTER_ACTOR(priv->activeView), &x, &y, &w, &h);
138 }
139 else
140 {
141 x=y=0.0f;
142 clutter_actor_get_size(CLUTTER_ACTOR(priv->activeView), &w, &h);
143 }
144
145 /* To avoid blur convert float to ints (virtually) */
146 x=ceil(x);
147 y=ceil(y);
148 w=ceil(w);
149 h=ceil(h);
150
151 /* Set transformation (offset) */
152 cogl_matrix_init_identity(&transform);
153 cogl_matrix_translate(&transform, -x, -y, 0.0f);
154 clutter_actor_set_transform(CLUTTER_ACTOR(priv->activeView), &transform);
155
156 /* Set new clipping */
157 clutter_actor_set_clip(CLUTTER_ACTOR(priv->activeView), x, y, w, h);
158 }
159
160 /* The value of a scrollbar has changed */
_xfdashboard_viewpad_on_scrollbar_value_changed(XfdashboardViewpad * self,gfloat inValue,gpointer inUserData)161 static void _xfdashboard_viewpad_on_scrollbar_value_changed(XfdashboardViewpad *self,
162 gfloat inValue,
163 gpointer inUserData)
164 {
165 XfdashboardViewpadPrivate *priv;
166 ClutterActor *scrollbar;
167 gfloat x, y, w, h;
168
169 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
170 g_return_if_fail(XFDASHBOARD_IS_SCROLLBAR(inUserData));
171
172 priv=self->priv;
173 scrollbar=CLUTTER_ACTOR(inUserData);
174
175 /* Update clipping */
176 if(clutter_actor_has_clip(CLUTTER_ACTOR(priv->activeView)))
177 {
178 clutter_actor_get_clip(CLUTTER_ACTOR(priv->activeView), &x, &y, &w, &h);
179 if(scrollbar==priv->hScrollbar) x=inValue;
180 else if(scrollbar==priv->vScrollbar) y=inValue;
181 }
182 else
183 {
184 x=y=0.0f;
185 clutter_actor_get_size(CLUTTER_ACTOR(priv->activeView), &w, &h);
186 }
187 clutter_actor_set_clip(CLUTTER_ACTOR(priv->activeView), x, y, w, h);
188
189 /* Update viewport */
190 _xfdashboard_viewpad_update_view_viewport(self);
191 }
192
193 /* Allocation of a view changed */
_xfdashboard_viewpad_update_scrollbars(XfdashboardViewpad * self)194 static void _xfdashboard_viewpad_update_scrollbars(XfdashboardViewpad *self)
195 {
196 XfdashboardViewpadPrivate *priv;
197 gfloat w, h;
198
199 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
200
201 priv=self->priv;
202
203 /* Set range of scroll bar to width and height of active view
204 * But we need to check for nan-values here - I do not get rid of it :(
205 */
206 if(priv->activeView) clutter_actor_get_size(CLUTTER_ACTOR(priv->activeView), &w, &h);
207 else w=h=1.0f;
208
209 xfdashboard_scrollbar_set_range(XFDASHBOARD_SCROLLBAR(priv->vScrollbar), isnan(h)==0 ? h : 0.0f);
210
211 /* If any scroll bar policy is automatic then reallocate the
212 * same allocation again in an unkindly way to force a recalculation
213 * if scroll bars needed to shown (or hidden what is unlikely)
214 */
215 if(clutter_actor_is_visible(CLUTTER_ACTOR(self)) &&
216 (priv->hScrollbarPolicy==XFDASHBOARD_VISIBILITY_POLICY_AUTOMATIC ||
217 priv->vScrollbarPolicy==XFDASHBOARD_VISIBILITY_POLICY_AUTOMATIC))
218 {
219 ClutterActorBox box;
220
221 clutter_actor_get_allocation_box(CLUTTER_ACTOR(self), &box);
222 _xfdashboard_viewpad_allocate(CLUTTER_ACTOR(self), &box, CLUTTER_DELEGATE_LAYOUT);
223 }
224 }
225
226 /* Set new active view and deactive current one */
_xfdashboard_viewpad_activate_view(XfdashboardViewpad * self,XfdashboardView * inView)227 static void _xfdashboard_viewpad_activate_view(XfdashboardViewpad *self, XfdashboardView *inView)
228 {
229 XfdashboardViewpadPrivate *priv;
230 gfloat x, y;
231 XfdashboardFocusManager *focusManager;
232 gboolean hasFocus;
233
234 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
235 g_return_if_fail(inView==NULL || XFDASHBOARD_IS_VIEW(inView));
236
237 priv=self->priv;
238 hasFocus=FALSE;
239
240 /* Only set value if it changes */
241 if(inView==priv->activeView) return;
242
243 /* Check if view is a child of this actor */
244 if(inView && clutter_actor_contains(CLUTTER_ACTOR(self), CLUTTER_ACTOR(inView))==FALSE)
245 {
246 g_warning("View %s is not a child of %s and cannot be activated",
247 G_OBJECT_TYPE_NAME(inView), G_OBJECT_TYPE_NAME(self));
248 return;
249 }
250
251 /* Only allow enabled views to be activated */
252 if(inView && !xfdashboard_view_get_enabled(inView))
253 {
254 g_warning("Cannot activate disabled view %s at %s",
255 G_OBJECT_TYPE_NAME(inView), G_OBJECT_TYPE_NAME(self));
256 return;
257 }
258
259 /* Determine if this viewpad has the focus because we have to move focus in this case */
260 focusManager=xfdashboard_focus_manager_get_default();
261
262 /* Deactivate current view */
263 if(priv->activeView)
264 {
265 /* Unset focus at current active view if this view has the focus */
266 hasFocus=xfdashboard_focus_manager_has_focus(focusManager, XFDASHBOARD_FOCUSABLE(priv->activeView));
267 if(hasFocus)
268 {
269 xfdashboard_focusable_unset_focus(XFDASHBOARD_FOCUSABLE(priv->activeView));
270 XFDASHBOARD_DEBUG(self, ACTOR,
271 "Unset focus from view '%s' because it is the active view at viewpad",
272 xfdashboard_view_get_name(priv->activeView));
273 }
274
275 /* Hide current view and emit signal before and after deactivation */
276 g_signal_emit(self, XfdashboardViewpadSignals[SIGNAL_VIEW_DEACTIVATING], 0, priv->activeView);
277 g_signal_emit_by_name(priv->activeView, "deactivating");
278
279 clutter_actor_hide(CLUTTER_ACTOR(priv->activeView));
280 XFDASHBOARD_DEBUG(self, ACTOR,
281 "Deactivated view %s",
282 G_OBJECT_TYPE_NAME(priv->activeView));
283
284 g_signal_emit_by_name(priv->activeView, "deactivated");
285 g_signal_emit(self, XfdashboardViewpadSignals[SIGNAL_VIEW_DEACTIVATED], 0, priv->activeView);
286
287 g_object_unref(priv->activeView);
288 priv->activeView=NULL;
289 }
290
291 /* Activate new view (if available) by showing new view, setting up
292 * scrollbars and emitting signal before and after activation.
293 * Prevent signal handling for scrollbars' "value-changed" as it will
294 * mess up with clipping and viewport. We only need to set value of
295 * scrollbars but we do not need to handle the changed value.
296 */
297 if(inView)
298 {
299 priv->activeView=g_object_ref(inView);
300
301 g_signal_emit(self, XfdashboardViewpadSignals[SIGNAL_VIEW_ACTIVATING], 0, priv->activeView);
302 g_signal_emit_by_name(priv->activeView, "activating");
303
304 g_signal_handlers_block_by_func(priv->hScrollbar, _xfdashboard_viewpad_on_scrollbar_value_changed, self);
305 g_signal_handlers_block_by_func(priv->vScrollbar, _xfdashboard_viewpad_on_scrollbar_value_changed, self);
306
307 x=y=0.0f;
308 clutter_actor_get_clip(CLUTTER_ACTOR(priv->activeView), &x, &y, NULL, NULL);
309 _xfdashboard_viewpad_update_scrollbars(self);
310 xfdashboard_scrollbar_set_value(XFDASHBOARD_SCROLLBAR(priv->hScrollbar), x);
311 xfdashboard_scrollbar_set_value(XFDASHBOARD_SCROLLBAR(priv->vScrollbar), y);
312 _xfdashboard_viewpad_update_view_viewport(self);
313 clutter_actor_show(CLUTTER_ACTOR(priv->activeView));
314 XFDASHBOARD_DEBUG(self, ACTOR,
315 "Activated view %s",
316 G_OBJECT_TYPE_NAME(priv->activeView));
317
318 g_signal_handlers_unblock_by_func(priv->hScrollbar, _xfdashboard_viewpad_on_scrollbar_value_changed, self);
319 g_signal_handlers_unblock_by_func(priv->vScrollbar, _xfdashboard_viewpad_on_scrollbar_value_changed, self);
320
321 g_signal_emit_by_name(priv->activeView, "activated");
322 g_signal_emit(self, XfdashboardViewpadSignals[SIGNAL_VIEW_ACTIVATED], 0, priv->activeView);
323
324 /* Set focus to new active view if this viewpad has the focus */
325 if(hasFocus)
326 {
327 xfdashboard_focus_manager_set_focus(focusManager, XFDASHBOARD_FOCUSABLE(priv->activeView));
328 XFDASHBOARD_DEBUG(self, ACTOR,
329 "The previous active view at viewpad had focus so set focus to new active view '%s'",
330 xfdashboard_view_get_name(priv->activeView));
331 }
332 }
333
334 /* If no view is active at this time move focus to next focusable actor
335 * if this viewpad has the focus.
336 */
337 if(hasFocus && !priv->activeView)
338 {
339 XfdashboardFocusable *newFocusable;
340
341 newFocusable=xfdashboard_focus_manager_get_next_focusable(focusManager, XFDASHBOARD_FOCUSABLE(self));
342 if(newFocusable)
343 {
344 xfdashboard_focus_manager_set_focus(focusManager, newFocusable);
345 XFDASHBOARD_DEBUG(self, ACTOR,
346 "Viewpad has focus but no view is active so move focus to next focusable actor of type '%s'",
347 G_OBJECT_TYPE_NAME(newFocusable));
348 }
349 }
350
351 /* Release allocated resources */
352 if(focusManager) g_object_unref(focusManager);
353
354 /* Notify about property change */
355 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardViewpadProperties[PROP_ACTIVE_VIEW]);
356 }
357
358 /* A view was disabled */
_xfdashboard_viewpad_on_view_disabled(XfdashboardViewpad * self,XfdashboardView * inView)359 static void _xfdashboard_viewpad_on_view_disabled(XfdashboardViewpad *self, XfdashboardView *inView)
360 {
361 XfdashboardViewpadPrivate *priv;
362 ClutterActorIter iter;
363 ClutterActor *child;
364 XfdashboardView *firstActivatableView;
365
366 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
367 g_return_if_fail(XFDASHBOARD_IS_VIEW(inView));
368
369 priv=self->priv;
370 firstActivatableView=NULL;
371
372 /* If the currently disabled view is the active one, activate a next available view */
373 if(inView==priv->activeView)
374 {
375 /* Iterate through create views and lookup view of given type */
376 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
377 while(clutter_actor_iter_next(&iter, &child))
378 {
379 /* Check if child is a view otherwise continue iterating */
380 if(XFDASHBOARD_IS_VIEW(child)!=TRUE) continue;
381
382 /* If child is not the view being disabled check if it could
383 * become the next activatable view
384 * the first activatable view after we destroyed all views found.
385 */
386 if(XFDASHBOARD_VIEW(child)!=inView &&
387 xfdashboard_view_get_enabled(XFDASHBOARD_VIEW(child)))
388 {
389 firstActivatableView=XFDASHBOARD_VIEW(child);
390 }
391 }
392
393 /* Now activate the first activatable view we found during iteration.
394 * It can also be no view (NULL pointer).
395 */
396 XFDASHBOARD_DEBUG(self, ACTOR,
397 "Disabled view %s was the active view in %s - will activate %s",
398 G_OBJECT_TYPE_NAME(inView),
399 G_OBJECT_TYPE_NAME(self),
400 firstActivatableView ? G_OBJECT_TYPE_NAME(firstActivatableView) : "no other view");
401 _xfdashboard_viewpad_activate_view(self, firstActivatableView);
402 }
403 }
404
405 /* A view was enabled */
_xfdashboard_viewpad_on_view_enabled(XfdashboardViewpad * self,XfdashboardView * inView)406 static void _xfdashboard_viewpad_on_view_enabled(XfdashboardViewpad *self, XfdashboardView *inView)
407 {
408 XfdashboardViewpadPrivate *priv;
409
410 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
411 g_return_if_fail(XFDASHBOARD_IS_VIEW(inView));
412
413 priv=self->priv;
414
415 /* If no view is active this new enabled view will be activated */
416 if(!priv->activeView) _xfdashboard_viewpad_activate_view(self, inView);
417 }
418
419 /* Allocation of a view changed */
_xfdashboard_viewpad_on_allocation_changed_repaint_callback(gpointer inUserData)420 static gboolean _xfdashboard_viewpad_on_allocation_changed_repaint_callback(gpointer inUserData)
421 {
422 XfdashboardViewpad *self;
423 XfdashboardViewpadPrivate *priv;
424
425 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(inUserData), G_SOURCE_REMOVE);
426
427 self=XFDASHBOARD_VIEWPAD(inUserData);
428 priv=self->priv;
429
430 /* Update scrollbars */
431 _xfdashboard_viewpad_update_scrollbars(self);
432
433 /* Ensure view is visible */
434 _xfdashboard_viewpad_on_scrollbar_value_changed(self,
435 xfdashboard_scrollbar_get_value(XFDASHBOARD_SCROLLBAR(priv->hScrollbar)),
436 priv->hScrollbar);
437 _xfdashboard_viewpad_on_scrollbar_value_changed(self,
438 xfdashboard_scrollbar_get_value(XFDASHBOARD_SCROLLBAR(priv->vScrollbar)),
439 priv->vScrollbar);
440
441 /* Do not call this callback again */
442 priv->scrollbarUpdateID=0;
443 return(G_SOURCE_REMOVE);
444 }
445
_xfdashboard_viewpad_on_allocation_changed(ClutterActor * inActor,ClutterActorBox * inBox,ClutterAllocationFlags inFlags,gpointer inUserData)446 static void _xfdashboard_viewpad_on_allocation_changed(ClutterActor *inActor,
447 ClutterActorBox *inBox,
448 ClutterAllocationFlags inFlags,
449 gpointer inUserData)
450 {
451 XfdashboardViewpad *self;
452 XfdashboardViewpadPrivate *priv;
453 XfdashboardView *view G_GNUC_UNUSED;
454
455 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(inActor));
456 g_return_if_fail(XFDASHBOARD_IS_VIEW(inUserData));
457
458 self=XFDASHBOARD_VIEWPAD(inActor);
459 priv=self->priv;
460 view=XFDASHBOARD_VIEW(inUserData);
461
462 /* Defer updating scrollbars but only if view whose allocation
463 * has changed is the active one
464 */
465 if(priv->scrollbarUpdateID==0)
466 {
467 priv->scrollbarUpdateID=
468 clutter_threads_add_repaint_func_full(CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD | CLUTTER_REPAINT_FLAGS_POST_PAINT,
469 _xfdashboard_viewpad_on_allocation_changed_repaint_callback,
470 self,
471 NULL);
472 }
473 }
474
475 /* Scroll to requested position in view */
_xfdashboard_viewpad_on_view_scroll_to(XfdashboardViewpad * self,gfloat inX,gfloat inY,gpointer inUserData)476 static void _xfdashboard_viewpad_on_view_scroll_to(XfdashboardViewpad *self,
477 gfloat inX,
478 gfloat inY,
479 gpointer inUserData)
480 {
481 XfdashboardViewpadPrivate *priv;
482 XfdashboardView *view;
483 gfloat x, y, w, h;
484
485 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
486 g_return_if_fail(XFDASHBOARD_IS_VIEW(inUserData));
487
488 priv=self->priv;
489 view=XFDASHBOARD_VIEW(inUserData);
490
491 /* If to-scroll view is the active view in viewpad
492 * just set scrollbar value to the new ones
493 */
494 if(view==priv->activeView)
495 {
496 if(inX>=0.0f) xfdashboard_scrollbar_set_value(XFDASHBOARD_SCROLLBAR(priv->hScrollbar), inX);
497 if(inY>=0.0f) xfdashboard_scrollbar_set_value(XFDASHBOARD_SCROLLBAR(priv->vScrollbar), inY);
498 }
499 /* If to-scroll view is not the active one update its clipping */
500 else
501 {
502 if(clutter_actor_has_clip(CLUTTER_ACTOR(view)))
503 {
504 clutter_actor_get_clip(CLUTTER_ACTOR(view), &x, &y, &w, &h);
505 if(inX>=0.0f) x=inX;
506 if(inY>=0.0f) y=inY;
507 }
508 else
509 {
510 x=y=0.0f;
511 clutter_actor_get_size(CLUTTER_ACTOR(view), &w, &h);
512 }
513 clutter_actor_set_clip(CLUTTER_ACTOR(view), x, y, w, h);
514 }
515 }
516
517 /* Determine if scrolling is needed to get requested actor visible in viewpad and
518 * return the distance in x and y direction if scrolling is needed.
519 */
_xfdashboard_viewpad_view_needs_scrolling_for_child(XfdashboardViewpad * self,XfdashboardView * inView,ClutterActor * inViewChild,gfloat * outScrollX,gfloat * outScrollY)520 static gboolean _xfdashboard_viewpad_view_needs_scrolling_for_child(XfdashboardViewpad *self,
521 XfdashboardView *inView,
522 ClutterActor *inViewChild,
523 gfloat *outScrollX,
524 gfloat *outScrollY)
525 {
526 XfdashboardViewpadPrivate *priv;
527 ClutterVertex origin;
528 ClutterVertex transformedUpperLeft;
529 ClutterVertex transformedLowerRight;
530 gfloat x, y, w, h;
531 gboolean viewFitsIntoViewpad;
532 gboolean needScrolling;
533 gfloat scrollX, scrollY;
534 gfloat viewpadWidth, viewpadHeight;
535
536 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), FALSE);
537 g_return_val_if_fail(XFDASHBOARD_IS_VIEW(inView), FALSE);
538 g_return_val_if_fail(CLUTTER_IS_ACTOR(inViewChild), FALSE);
539
540 priv=self->priv;
541 viewFitsIntoViewpad=FALSE;
542 needScrolling=FALSE;
543 scrollX=scrollY=0.0f;
544
545 /* Check if view would fit into this viewpad completely */
546 if(priv->lastAllocation)
547 {
548 viewpadWidth=clutter_actor_box_get_width(priv->lastAllocation);
549 viewpadHeight=clutter_actor_box_get_height(priv->lastAllocation);
550
551 clutter_actor_get_size(CLUTTER_ACTOR(inView), &w, &h);
552 if(w<=viewpadWidth && h<=viewpadHeight) viewFitsIntoViewpad=TRUE;
553 }
554 else
555 {
556 clutter_actor_get_size(CLUTTER_ACTOR(self), &viewpadWidth, &viewpadHeight);
557 }
558
559 /* Get position and size of view but respect scrolled position */
560 if(inView==priv->activeView)
561 {
562 x=xfdashboard_scrollbar_get_value(XFDASHBOARD_SCROLLBAR(priv->hScrollbar));
563 y=xfdashboard_scrollbar_get_value(XFDASHBOARD_SCROLLBAR(priv->vScrollbar));
564 w=viewpadWidth;
565 h=viewpadHeight;
566 }
567 else
568 {
569 if(clutter_actor_has_clip(CLUTTER_ACTOR(inView)))
570 {
571 clutter_actor_get_clip(CLUTTER_ACTOR(inView), &x, &y, &w, &h);
572 }
573 else
574 {
575 x=y=0.0f;
576 clutter_actor_get_size(CLUTTER_ACTOR(inView), &w, &h);
577 }
578 }
579
580 /* Check that upper left point of actor is visible otherwise set flag for scrolling */
581 if(!viewFitsIntoViewpad)
582 {
583 origin.x=origin.y=origin.z=0.0f;
584 clutter_actor_apply_relative_transform_to_point(inViewChild, CLUTTER_ACTOR(inView), &origin, &transformedUpperLeft);
585 }
586 else
587 {
588 origin.x=origin.y=origin.z=0.0f;
589 clutter_actor_apply_relative_transform_to_point(CLUTTER_ACTOR(inView), CLUTTER_ACTOR(self), &origin, &transformedUpperLeft);
590 }
591
592 if(transformedUpperLeft.x<x ||
593 transformedUpperLeft.x>(x+w) ||
594 transformedUpperLeft.y<y ||
595 transformedUpperLeft.y>(y+h))
596 {
597 needScrolling=TRUE;
598 }
599
600 /* Check that lower right point of actor is visible otherwise set flag for scrolling */
601 if(!viewFitsIntoViewpad)
602 {
603 origin.z=0.0f;
604 clutter_actor_get_size(inViewChild, &origin.x, &origin.y);
605 clutter_actor_apply_relative_transform_to_point(inViewChild, CLUTTER_ACTOR(inView), &origin, &transformedLowerRight);
606 }
607 else
608 {
609 origin.x=clutter_actor_box_get_width(priv->lastAllocation);
610 origin.y=clutter_actor_box_get_height(priv->lastAllocation);
611 origin.z=0.0f;
612 clutter_actor_apply_relative_transform_to_point(CLUTTER_ACTOR(inView), CLUTTER_ACTOR(self), &origin, &transformedLowerRight);
613 }
614
615 if(transformedLowerRight.x<x ||
616 transformedLowerRight.x>(x+w) ||
617 transformedLowerRight.y<y ||
618 transformedLowerRight.y>(y+h))
619 {
620 needScrolling=TRUE;
621 }
622
623 /* Check if we need to scroll */
624 if(needScrolling)
625 {
626 gfloat distanceUpperLeft;
627 gfloat distanceLowerRight;
628
629 /* Find shortest way to scroll and then scroll */
630 distanceUpperLeft=sqrtf(powf(transformedUpperLeft.x-x, 2.0f)+powf(transformedUpperLeft.y-y, 2.0f));
631 distanceLowerRight=sqrtf(powf(transformedLowerRight.x-(x+w), 2.0f)+powf(transformedLowerRight.y-(y+h), 2.0f));
632
633 if(distanceUpperLeft<=distanceLowerRight)
634 {
635 scrollX=transformedUpperLeft.x;
636 scrollY=transformedUpperLeft.y;
637 }
638 else
639 {
640 scrollX=transformedUpperLeft.x;
641 scrollY=transformedLowerRight.y-h;
642 }
643 }
644
645 /* Store values computed */
646 if(outScrollX) *outScrollX=scrollX;
647 if(outScrollY) *outScrollY=scrollY;
648
649 /* Return TRUE if scrolling is needed otherwise FALSE */
650 return(needScrolling);
651 }
652
653 /* Determine if scrolling is needed to get requested actor visible in viewpad */
_xfdashboard_viewpad_on_view_child_needs_scroll(XfdashboardViewpad * self,ClutterActor * inActor,gpointer inUserData)654 static gboolean _xfdashboard_viewpad_on_view_child_needs_scroll(XfdashboardViewpad *self,
655 ClutterActor *inActor,
656 gpointer inUserData)
657 {
658 XfdashboardView *view;
659
660 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), FALSE);
661 g_return_val_if_fail(CLUTTER_IS_ACTOR(inActor), FALSE);
662 g_return_val_if_fail(XFDASHBOARD_IS_VIEW(inUserData), FALSE);
663
664 view=XFDASHBOARD_VIEW(inUserData);
665
666 /* Determine if scrolling is needed and return result */
667 return(_xfdashboard_viewpad_view_needs_scrolling_for_child(self, view, inActor, NULL, NULL));
668 }
669
670 /* Ensure that a child of a view is visible by scrolling if needed */
_xfdashboard_viewpad_on_view_child_ensure_visible(XfdashboardViewpad * self,ClutterActor * inActor,gpointer inUserData)671 static void _xfdashboard_viewpad_on_view_child_ensure_visible(XfdashboardViewpad *self,
672 ClutterActor *inActor,
673 gpointer inUserData)
674 {
675 XfdashboardView *view;
676 gfloat scrollX, scrollY;
677
678 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
679 g_return_if_fail(CLUTTER_IS_ACTOR(inActor));
680 g_return_if_fail(XFDASHBOARD_IS_VIEW(inUserData));
681
682 view=XFDASHBOARD_VIEW(inUserData);
683
684 /* Check if scrolling is needed to scroll in direction and amount determined */
685 if(_xfdashboard_viewpad_view_needs_scrolling_for_child(self, view, inActor, &scrollX, &scrollY))
686 {
687 _xfdashboard_viewpad_on_view_scroll_to(self, scrollX, scrollY, view);
688 }
689 }
690
691 /* Create view of given type and add to this actor */
_xfdashboard_viewpad_add_view(XfdashboardViewpad * self,const gchar * inID)692 static void _xfdashboard_viewpad_add_view(XfdashboardViewpad *self, const gchar *inID)
693 {
694 XfdashboardViewpadPrivate *priv;
695 GObject *view;
696
697 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
698 g_return_if_fail(inID && *inID);
699
700 priv=self->priv;
701
702 /* Create instance and check if it is a view */
703 XFDASHBOARD_DEBUG(self, ACTOR,
704 "Creating view %s for viewpad",
705 inID);
706
707 view=xfdashboard_view_manager_create_view(priv->viewManager, inID);
708 if(view==NULL)
709 {
710 g_critical("Failed to create view %s for viewpad", inID);
711 return;
712 }
713
714 if(XFDASHBOARD_IS_VIEW(view)!=TRUE)
715 {
716 g_critical("View %s of type %s is not a %s and cannot be added to %s",
717 inID,
718 G_OBJECT_TYPE_NAME(view),
719 g_type_name(XFDASHBOARD_TYPE_VIEW),
720 G_OBJECT_TYPE_NAME(self));
721 return;
722 }
723
724 /* Add new view instance to this actor but hidden */
725 clutter_actor_hide(CLUTTER_ACTOR(view));
726 clutter_actor_add_child(CLUTTER_ACTOR(self), CLUTTER_ACTOR(view));
727 g_signal_connect_swapped(view, "allocation-changed", G_CALLBACK(_xfdashboard_viewpad_on_allocation_changed), self);
728 g_signal_connect_swapped(view, "scroll-to", G_CALLBACK(_xfdashboard_viewpad_on_view_scroll_to), self);
729 g_signal_connect_swapped(view, "child-needs-scroll", G_CALLBACK(_xfdashboard_viewpad_on_view_child_needs_scroll), self);
730 g_signal_connect_swapped(view, "child-ensure-visible", G_CALLBACK(_xfdashboard_viewpad_on_view_child_ensure_visible), self);
731 g_signal_connect_swapped(view, "disabled", G_CALLBACK(_xfdashboard_viewpad_on_view_disabled), self);
732 g_signal_connect_swapped(view, "enabled", G_CALLBACK(_xfdashboard_viewpad_on_view_enabled), self);
733 g_signal_emit(self, XfdashboardViewpadSignals[SIGNAL_VIEW_ADDED], 0, view);
734
735 /* Set active view if none active (usually it is the first view created) */
736 if(priv->activeView==NULL &&
737 xfdashboard_view_get_enabled(XFDASHBOARD_VIEW(view)))
738 {
739 _xfdashboard_viewpad_activate_view(self, XFDASHBOARD_VIEW(view));
740 }
741
742 /* If newly added view is focusable register it to focus manager */
743 if(priv->doRegisterFocusableViews &&
744 XFDASHBOARD_IS_FOCUSABLE(view))
745 {
746 XfdashboardFocusManager *focusManager;
747
748 focusManager=xfdashboard_focus_manager_get_default();
749 xfdashboard_focus_manager_register_after(focusManager,
750 XFDASHBOARD_FOCUSABLE(view),
751 XFDASHBOARD_FOCUSABLE(self));
752 g_object_unref(focusManager);
753 }
754 }
755
756 /* Called when a new view type was registered */
_xfdashboard_viewpad_on_view_registered(XfdashboardViewpad * self,const gchar * inID,gpointer inUserData)757 static void _xfdashboard_viewpad_on_view_registered(XfdashboardViewpad *self,
758 const gchar *inID,
759 gpointer inUserData)
760 {
761 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
762 g_return_if_fail(inID && *inID);
763
764 _xfdashboard_viewpad_add_view(self, inID);
765 }
766
767 /* Called when a view type was unregistered */
_xfdashboard_viewpad_on_view_unregistered(XfdashboardViewpad * self,const gchar * inID,gpointer inUserData)768 static void _xfdashboard_viewpad_on_view_unregistered(XfdashboardViewpad *self,
769 const gchar *inID,
770 gpointer inUserData)
771 {
772 XfdashboardViewpadPrivate *priv;
773 ClutterActorIter iter;
774 ClutterActor *child;
775 ClutterActor *firstActivatableView;
776
777 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
778 g_return_if_fail(inID && *inID);
779
780 priv=self->priv;
781 firstActivatableView=NULL;
782
783 /* Iterate through create views and lookup view of given type */
784 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
785 while(clutter_actor_iter_next(&iter, &child))
786 {
787 /* Check if child is a view otherwise continue iterating */
788 if(XFDASHBOARD_IS_VIEW(child)!=TRUE) continue;
789
790 /* If this child is not the one being unregistered and is not
791 * disabled then it will get the first activatable view after
792 * we destroyed all views found.
793 */
794 if(!xfdashboard_view_has_id(XFDASHBOARD_VIEW(child), inID))
795 {
796 if(xfdashboard_view_get_enabled(XFDASHBOARD_VIEW(child))) firstActivatableView=child;
797 }
798 else
799 {
800 if(G_OBJECT(child)==G_OBJECT(priv->activeView)) _xfdashboard_viewpad_activate_view(self, NULL);
801 g_signal_emit(self, XfdashboardViewpadSignals[SIGNAL_VIEW_REMOVED], 0, child);
802 clutter_actor_destroy(child);
803 }
804 }
805
806 /* Now activate the first activatable view we found during iteration */
807 if(firstActivatableView) _xfdashboard_viewpad_activate_view(self, XFDASHBOARD_VIEW(firstActivatableView));
808 }
809
810 /* Scroll event happened at this actor because it was not handled
811 * with any child actor
812 */
_xfdashboard_viewpad_on_scroll_event(ClutterActor * inActor,ClutterEvent * inEvent,gpointer inUserData)813 static gboolean _xfdashboard_viewpad_on_scroll_event(ClutterActor *inActor,
814 ClutterEvent *inEvent,
815 gpointer inUserData)
816 {
817 XfdashboardViewpad *self;
818 XfdashboardViewpadPrivate *priv;
819 gboolean result;
820
821 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(inActor), FALSE);
822 g_return_val_if_fail(inEvent, FALSE);
823
824 self=XFDASHBOARD_VIEWPAD(inActor);
825 priv=self->priv;
826 result=CLUTTER_EVENT_PROPAGATE;
827
828 /* If vertical scroll bar is visible emit scroll event there */
829 if(priv->vScrollbarVisible)
830 {
831 result=clutter_actor_event(priv->vScrollbar, inEvent, FALSE);
832 }
833 /* Otherwise try horizontal scroll bar if visible */
834 else if(priv->hScrollbarVisible)
835 {
836 result=clutter_actor_event(priv->hScrollbar, inEvent, FALSE);
837 }
838
839 return(result);
840 }
841
842 /* IMPLEMENTATION: ClutterActor */
843
844 /* Show this actor and the current active view */
_xfdashboard_viewpad_show(ClutterActor * self)845 static void _xfdashboard_viewpad_show(ClutterActor *self)
846 {
847 XfdashboardViewpadPrivate *priv=XFDASHBOARD_VIEWPAD(self)->priv;
848 ClutterActorClass *actorClass=CLUTTER_ACTOR_CLASS(xfdashboard_viewpad_parent_class);
849
850 /* Only show active view again */
851 if(priv->activeView) clutter_actor_show(CLUTTER_ACTOR(priv->activeView));
852
853 /* Call parent's class show method */
854 if(actorClass->show) actorClass->show(self);
855 }
856
857 /* Get preferred width/height */
_xfdashboard_viewpad_get_preferred_height(ClutterActor * self,gfloat inForWidth,gfloat * outMinHeight,gfloat * outNaturalHeight)858 static void _xfdashboard_viewpad_get_preferred_height(ClutterActor *self,
859 gfloat inForWidth,
860 gfloat *outMinHeight,
861 gfloat *outNaturalHeight)
862 {
863 gfloat minHeight, naturalHeight;
864
865 /* Do not set any minimum or natural sizes. The parent actor is responsible
866 * to set this actor's sizes as viewport.
867 */
868 minHeight=naturalHeight=0.0f;
869
870 /* Store sizes computed */
871 if(outMinHeight) *outMinHeight=minHeight;
872 if(outNaturalHeight) *outNaturalHeight=naturalHeight;
873 }
874
_xfdashboard_viewpad_get_preferred_width(ClutterActor * self,gfloat inForHeight,gfloat * outMinWidth,gfloat * outNaturalWidth)875 static void _xfdashboard_viewpad_get_preferred_width(ClutterActor *self,
876 gfloat inForHeight,
877 gfloat *outMinWidth,
878 gfloat *outNaturalWidth)
879 {
880 gfloat minWidth, naturalWidth;
881
882 /* Do not set any minimum or natural sizes. The parent actor is responsible
883 * to set this actor's sizes as viewport.
884 */
885 minWidth=naturalWidth=0.0f;
886
887 /* Store sizes computed */
888 if(outMinWidth) *outMinWidth=minWidth;
889 if(outNaturalWidth) *outNaturalWidth=naturalWidth;
890 }
891
892 /* Allocate position and size of actor and its children */
_xfdashboard_viewpad_allocate(ClutterActor * self,const ClutterActorBox * inBox,ClutterAllocationFlags inFlags)893 static void _xfdashboard_viewpad_allocate(ClutterActor *self,
894 const ClutterActorBox *inBox,
895 ClutterAllocationFlags inFlags)
896 {
897 XfdashboardViewpadPrivate *priv=XFDASHBOARD_VIEWPAD(self)->priv;
898 ClutterActorClass *actorClass=CLUTTER_ACTOR_CLASS(xfdashboard_viewpad_parent_class);
899 gfloat viewWidth, viewHeight;
900 gfloat vScrollbarWidth, vScrollbarHeight;
901 gfloat hScrollbarWidth, hScrollbarHeight;
902 gboolean hScrollbarVisible, vScrollbarVisible;
903 ClutterActorBox *box;
904 gfloat x, y, w, h;
905
906 /* Chain up to store the allocation of the actor */
907 if(actorClass->allocate) actorClass->allocate(self, inBox, inFlags);
908
909 /* Initialize largest possible allocation for view and determine
910 * real size of view to show. The real size is used to determine
911 * scroll bar visibility if policy is automatic */
912 viewWidth=clutter_actor_box_get_width(inBox);
913 viewHeight=clutter_actor_box_get_height(inBox);
914
915 /* Determine visibility of scroll bars */
916 hScrollbarVisible=FALSE;
917 if(priv->hScrollbarPolicy==XFDASHBOARD_VISIBILITY_POLICY_ALWAYS ||
918 (priv->hScrollbarPolicy==XFDASHBOARD_VISIBILITY_POLICY_AUTOMATIC &&
919 xfdashboard_scrollbar_get_range(XFDASHBOARD_SCROLLBAR(priv->hScrollbar))>viewWidth))
920 {
921 hScrollbarVisible=TRUE;
922 }
923 if(xfdashboard_view_get_view_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_VIEW_FIT_MODE_HORIZONTAL ||
924 xfdashboard_view_get_view_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_VIEW_FIT_MODE_BOTH)
925 {
926 hScrollbarVisible=FALSE;
927 }
928
929 vScrollbarVisible=FALSE;
930 if(priv->vScrollbarPolicy==XFDASHBOARD_VISIBILITY_POLICY_ALWAYS ||
931 (priv->vScrollbarPolicy==XFDASHBOARD_VISIBILITY_POLICY_AUTOMATIC &&
932 xfdashboard_scrollbar_get_range(XFDASHBOARD_SCROLLBAR(priv->vScrollbar))>viewHeight))
933 {
934 vScrollbarVisible=TRUE;
935 }
936 if(xfdashboard_view_get_view_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_VIEW_FIT_MODE_VERTICAL ||
937 xfdashboard_view_get_view_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_VIEW_FIT_MODE_BOTH)
938 {
939 vScrollbarVisible=FALSE;
940 }
941
942 /* Set allocation for visible scroll bars */
943 vScrollbarWidth=0.0f;
944 vScrollbarHeight=viewHeight;
945 clutter_actor_get_preferred_width(priv->vScrollbar, -1, NULL, &vScrollbarWidth);
946
947 hScrollbarWidth=viewWidth;
948 hScrollbarHeight=0.0f;
949 clutter_actor_get_preferred_height(priv->hScrollbar, -1, NULL, &hScrollbarHeight);
950
951 if(hScrollbarVisible && vScrollbarVisible)
952 {
953 vScrollbarHeight-=hScrollbarHeight;
954 hScrollbarWidth-=vScrollbarWidth;
955 }
956
957 if(vScrollbarVisible==FALSE) box=clutter_actor_box_new(0, 0, 0, 0);
958 else box=clutter_actor_box_new(viewWidth-vScrollbarWidth, 0, viewWidth, vScrollbarHeight);
959 clutter_actor_allocate(priv->vScrollbar, box, inFlags);
960 clutter_actor_box_free(box);
961
962 if(hScrollbarVisible==FALSE) box=clutter_actor_box_new(0, 0, 0, 0);
963 else box=clutter_actor_box_new(0, viewHeight-hScrollbarHeight, hScrollbarWidth, viewHeight);
964 clutter_actor_allocate(priv->hScrollbar, box, inFlags);
965 clutter_actor_box_free(box);
966
967 /* Reduce allocation for view by any visible scroll bar
968 * and set allocation and clipping of view
969 */
970 if(priv->activeView)
971 {
972 /* Set allocation */
973 if(vScrollbarVisible) viewWidth-=vScrollbarWidth;
974 if(hScrollbarVisible) viewHeight-=hScrollbarHeight;
975
976 x=y=0.0f;
977 if(clutter_actor_has_clip(CLUTTER_ACTOR(priv->activeView)))
978 {
979 clutter_actor_get_clip(CLUTTER_ACTOR(priv->activeView), &x, &y, NULL, NULL);
980 }
981
982 switch(xfdashboard_view_get_view_fit_mode(XFDASHBOARD_VIEW(priv->activeView)))
983 {
984 case XFDASHBOARD_VIEW_FIT_MODE_BOTH:
985 w=viewWidth;
986 h=viewHeight;
987 break;
988
989 case XFDASHBOARD_VIEW_FIT_MODE_HORIZONTAL:
990 w=viewWidth;
991 clutter_actor_get_preferred_height(CLUTTER_ACTOR(priv->activeView), w, NULL, &h);
992 break;
993
994 case XFDASHBOARD_VIEW_FIT_MODE_VERTICAL:
995 h=viewHeight;
996 clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->activeView), h, NULL, &w);
997 break;
998
999 default:
1000 clutter_actor_get_preferred_size(CLUTTER_ACTOR(priv->activeView), NULL, NULL, &w, &h);
1001 break;
1002 }
1003
1004 box=clutter_actor_box_new(0, 0, w, h);
1005 clutter_actor_allocate(CLUTTER_ACTOR(priv->activeView), box, inFlags);
1006 clutter_actor_box_free(box);
1007
1008 clutter_actor_set_clip(CLUTTER_ACTOR(priv->activeView), x, y, viewWidth, viewHeight);
1009 }
1010
1011 /* Only set value if it changes */
1012 if(priv->hScrollbarVisible!=hScrollbarVisible)
1013 {
1014 /* Set new value */
1015 priv->hScrollbarVisible=hScrollbarVisible;
1016
1017 /* Notify about property change */
1018 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardViewpadProperties[PROP_HSCROLLBAR_VISIBLE]);
1019 }
1020
1021 if(priv->vScrollbarVisible!=vScrollbarVisible)
1022 {
1023 /* Set new value */
1024 priv->vScrollbarVisible=vScrollbarVisible;
1025
1026 /* Notify about property change */
1027 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardViewpadProperties[PROP_VSCROLLBAR_VISIBLE]);
1028 }
1029
1030 /* Remember this allocation as last one set */
1031 if(priv->lastAllocation)
1032 {
1033 clutter_actor_box_free(priv->lastAllocation);
1034 priv->lastAllocation=NULL;
1035 }
1036
1037 priv->lastAllocation=clutter_actor_box_copy(inBox);
1038 }
1039
1040 /* IMPLEMENTATION: Interface XfdashboardFocusable */
1041
1042 /* Determine if actor can get the focus */
_xfdashboard_viewpad_focusable_can_focus(XfdashboardFocusable * inFocusable)1043 static gboolean _xfdashboard_viewpad_focusable_can_focus(XfdashboardFocusable *inFocusable)
1044 {
1045 XfdashboardViewpad *self;
1046 XfdashboardViewpadPrivate *priv;
1047
1048 g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE);
1049 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(inFocusable), FALSE);
1050
1051 self=XFDASHBOARD_VIEWPAD(inFocusable);
1052 priv=self->priv;
1053
1054 /* If it is the first time this viewpad is checked if it is focusable register
1055 * all registered and focusable views at focus manager and set flag that newly
1056 * added views should be registered to focus manager also because now the insert
1057 * position at focus manager for this viewpad is known and we can keep the focus
1058 * order for the views.
1059 * We determine if this is the first time this viewpad is check for its focusability
1060 * by checking if the "do-register-view" flag is still not set.
1061 */
1062 if(!priv->doRegisterFocusableViews)
1063 {
1064 XfdashboardFocusManager *focusManager;
1065 ClutterActorIter iter;
1066 ClutterActor *child;
1067
1068 /* Get focus manager */
1069 focusManager=xfdashboard_focus_manager_get_default();
1070
1071 /* Iterate through children of this viewpad and register each focusable view found */
1072 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
1073 while(clutter_actor_iter_next(&iter, &child))
1074 {
1075 /* Check if child is a view otherwise continue iterating */
1076 if(XFDASHBOARD_IS_VIEW(child)!=TRUE) continue;
1077
1078 /* If view is focusable register it to focus manager */
1079 if(XFDASHBOARD_IS_FOCUSABLE(child))
1080 {
1081 xfdashboard_focus_manager_register_after(focusManager,
1082 XFDASHBOARD_FOCUSABLE(child),
1083 XFDASHBOARD_FOCUSABLE(self));
1084 }
1085 }
1086
1087 /* Release allocated resources */
1088 if(focusManager) g_object_unref(focusManager);
1089
1090 /* Set flag that from now on each newly added view should be added to focus manager */
1091 priv->doRegisterFocusableViews=TRUE;
1092 }
1093
1094 /* This viewpad cannot be focused. It is only registered at focus manager as
1095 * a placeholder to register focusable views just after this viewpad to keep
1096 * order of focusable actors.
1097 */
1098 return(FALSE);
1099 }
1100
1101 /* Interface initialization
1102 * Set up default functions
1103 */
_xfdashboard_viewpad_focusable_iface_init(XfdashboardFocusableInterface * iface)1104 void _xfdashboard_viewpad_focusable_iface_init(XfdashboardFocusableInterface *iface)
1105 {
1106 iface->can_focus=_xfdashboard_viewpad_focusable_can_focus;
1107 }
1108
1109 /* IMPLEMENTATION: GObject */
1110
1111 /* Dispose this object */
_xfdashboard_viewpad_dispose(GObject * inObject)1112 static void _xfdashboard_viewpad_dispose(GObject *inObject)
1113 {
1114 XfdashboardViewpad *self=XFDASHBOARD_VIEWPAD(inObject);
1115 XfdashboardViewpadPrivate *priv=self->priv;
1116
1117 /* Prevent further registers of views */
1118 priv->doRegisterFocusableViews=FALSE;
1119
1120 /* Deactivate current view */
1121 if(priv->activeView) _xfdashboard_viewpad_activate_view(self, NULL);
1122
1123 /* Disconnect signals handlers */
1124 if(priv->viewManager)
1125 {
1126 g_signal_handlers_disconnect_by_data(priv->viewManager, self);
1127 g_object_unref(priv->viewManager);
1128 priv->viewManager=NULL;
1129 }
1130
1131 /* Release allocated resources */
1132 if(priv->lastAllocation)
1133 {
1134 clutter_actor_box_free(priv->lastAllocation);
1135 priv->lastAllocation=NULL;
1136 }
1137
1138 /* Call parent's class dispose method */
1139 G_OBJECT_CLASS(xfdashboard_viewpad_parent_class)->dispose(inObject);
1140 }
1141
1142 /* Set/get properties */
_xfdashboard_viewpad_set_property(GObject * inObject,guint inPropID,const GValue * inValue,GParamSpec * inSpec)1143 static void _xfdashboard_viewpad_set_property(GObject *inObject,
1144 guint inPropID,
1145 const GValue *inValue,
1146 GParamSpec *inSpec)
1147 {
1148 XfdashboardViewpad *self=XFDASHBOARD_VIEWPAD(inObject);
1149
1150 switch(inPropID)
1151 {
1152 case PROP_SPACING:
1153 xfdashboard_viewpad_set_spacing(self, g_value_get_float(inValue));
1154 break;
1155
1156 case PROP_HSCROLLBAR_POLICY:
1157 xfdashboard_viewpad_set_horizontal_scrollbar_policy(self, (XfdashboardVisibilityPolicy)g_value_get_enum(inValue));
1158 break;
1159
1160 case PROP_VSCROLLBAR_POLICY:
1161 xfdashboard_viewpad_set_vertical_scrollbar_policy(self, (XfdashboardVisibilityPolicy)g_value_get_enum(inValue));
1162 break;
1163
1164 default:
1165 G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
1166 break;
1167 }
1168 }
1169
_xfdashboard_viewpad_get_property(GObject * inObject,guint inPropID,GValue * outValue,GParamSpec * inSpec)1170 static void _xfdashboard_viewpad_get_property(GObject *inObject,
1171 guint inPropID,
1172 GValue *outValue,
1173 GParamSpec *inSpec)
1174 {
1175 XfdashboardViewpad *self=XFDASHBOARD_VIEWPAD(inObject);
1176
1177 switch(inPropID)
1178 {
1179 case PROP_SPACING:
1180 g_value_set_float(outValue, self->priv->spacing);
1181 break;
1182
1183 case PROP_ACTIVE_VIEW:
1184 g_value_set_object(outValue, self->priv->activeView);
1185 break;
1186
1187 case PROP_HSCROLLBAR_POLICY:
1188 g_value_set_enum(outValue, self->priv->hScrollbarPolicy);
1189 break;
1190
1191 case PROP_HSCROLLBAR_VISIBLE:
1192 g_value_set_boolean(outValue, self->priv->hScrollbarVisible);
1193 break;
1194
1195 case PROP_VSCROLLBAR_POLICY:
1196 g_value_set_enum(outValue, self->priv->vScrollbarPolicy);
1197 break;
1198
1199 case PROP_VSCROLLBAR_VISIBLE:
1200 g_value_set_boolean(outValue, self->priv->vScrollbarVisible);
1201 break;
1202
1203 default:
1204 G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
1205 break;
1206 }
1207 }
1208
1209 /* Class initialization
1210 * Override functions in parent classes and define properties
1211 * and signals
1212 */
xfdashboard_viewpad_class_init(XfdashboardViewpadClass * klass)1213 static void xfdashboard_viewpad_class_init(XfdashboardViewpadClass *klass)
1214 {
1215 XfdashboardActorClass *actorClass=XFDASHBOARD_ACTOR_CLASS(klass);
1216 ClutterActorClass *clutterActorClass=CLUTTER_ACTOR_CLASS(klass);
1217 GObjectClass *gobjectClass=G_OBJECT_CLASS(klass);
1218
1219 /* Override functions */
1220 gobjectClass->set_property=_xfdashboard_viewpad_set_property;
1221 gobjectClass->get_property=_xfdashboard_viewpad_get_property;
1222 gobjectClass->dispose=_xfdashboard_viewpad_dispose;
1223
1224 clutterActorClass->show=_xfdashboard_viewpad_show;
1225 clutterActorClass->get_preferred_width=_xfdashboard_viewpad_get_preferred_width;
1226 clutterActorClass->get_preferred_height=_xfdashboard_viewpad_get_preferred_height;
1227 clutterActorClass->allocate=_xfdashboard_viewpad_allocate;
1228
1229 /* Define properties */
1230 XfdashboardViewpadProperties[PROP_SPACING]=
1231 g_param_spec_float("spacing",
1232 "Spacing",
1233 "The spacing between views and scrollbars",
1234 0.0f, G_MAXFLOAT,
1235 0.0f,
1236 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1237
1238 XfdashboardViewpadProperties[PROP_ACTIVE_VIEW]=
1239 g_param_spec_object("active-view",
1240 "Active view",
1241 "The current active view in viewpad",
1242 XFDASHBOARD_TYPE_VIEW,
1243 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
1244
1245 XfdashboardViewpadProperties[PROP_HSCROLLBAR_VISIBLE]=
1246 g_param_spec_boolean("horizontal-scrollbar-visible",
1247 "Horizontal scrollbar visibility",
1248 "This flag indicates if horizontal scrollbar is visible",
1249 FALSE,
1250 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
1251
1252 XfdashboardViewpadProperties[PROP_HSCROLLBAR_POLICY]=
1253 g_param_spec_enum("horizontal-scrollbar-policy",
1254 "Horizontal scrollbar policy",
1255 "The policy for horizontal scrollbar controlling when it is displayed",
1256 XFDASHBOARD_TYPE_VISIBILITY_POLICY,
1257 XFDASHBOARD_VISIBILITY_POLICY_AUTOMATIC,
1258 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1259
1260 XfdashboardViewpadProperties[PROP_VSCROLLBAR_VISIBLE]=
1261 g_param_spec_boolean("vertical-scrollbar-visible",
1262 "Vertical scrollbar visibility",
1263 "This flag indicates if vertical scrollbar is visible",
1264 FALSE,
1265 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
1266
1267 XfdashboardViewpadProperties[PROP_VSCROLLBAR_POLICY]=
1268 g_param_spec_enum("vertical-scrollbar-policy",
1269 "Vertical scrollbar policy",
1270 "The policy for vertical scrollbar controlling when it is displayed",
1271 XFDASHBOARD_TYPE_VISIBILITY_POLICY,
1272 XFDASHBOARD_VISIBILITY_POLICY_AUTOMATIC,
1273 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1274
1275 g_object_class_install_properties(gobjectClass, PROP_LAST, XfdashboardViewpadProperties);
1276
1277 /* Define stylable properties */
1278 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardViewpadProperties[PROP_SPACING]);
1279 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardViewpadProperties[PROP_HSCROLLBAR_POLICY]);
1280 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardViewpadProperties[PROP_VSCROLLBAR_POLICY]);
1281
1282 /* Define signals */
1283 XfdashboardViewpadSignals[SIGNAL_VIEW_ADDED]=
1284 g_signal_new("view-added",
1285 G_TYPE_FROM_CLASS(klass),
1286 G_SIGNAL_RUN_LAST,
1287 G_STRUCT_OFFSET(XfdashboardViewpadClass, view_added),
1288 NULL,
1289 NULL,
1290 g_cclosure_marshal_VOID__OBJECT,
1291 G_TYPE_NONE,
1292 1,
1293 XFDASHBOARD_TYPE_VIEW);
1294
1295 XfdashboardViewpadSignals[SIGNAL_VIEW_REMOVED]=
1296 g_signal_new("view-removed",
1297 G_TYPE_FROM_CLASS(klass),
1298 G_SIGNAL_RUN_LAST,
1299 G_STRUCT_OFFSET(XfdashboardViewpadClass, view_removed),
1300 NULL,
1301 NULL,
1302 g_cclosure_marshal_VOID__OBJECT,
1303 G_TYPE_NONE,
1304 1,
1305 XFDASHBOARD_TYPE_VIEW);
1306
1307 XfdashboardViewpadSignals[SIGNAL_VIEW_ACTIVATING]=
1308 g_signal_new("view-activating",
1309 G_TYPE_FROM_CLASS(klass),
1310 G_SIGNAL_RUN_LAST,
1311 G_STRUCT_OFFSET(XfdashboardViewpadClass, view_activating),
1312 NULL,
1313 NULL,
1314 g_cclosure_marshal_VOID__OBJECT,
1315 G_TYPE_NONE,
1316 1,
1317 XFDASHBOARD_TYPE_VIEW);
1318
1319 XfdashboardViewpadSignals[SIGNAL_VIEW_ACTIVATED]=
1320 g_signal_new("view-activated",
1321 G_TYPE_FROM_CLASS(klass),
1322 G_SIGNAL_RUN_LAST,
1323 G_STRUCT_OFFSET(XfdashboardViewpadClass, view_activated),
1324 NULL,
1325 NULL,
1326 g_cclosure_marshal_VOID__OBJECT,
1327 G_TYPE_NONE,
1328 1,
1329 XFDASHBOARD_TYPE_VIEW);
1330
1331 XfdashboardViewpadSignals[SIGNAL_VIEW_DEACTIVATING]=
1332 g_signal_new("view-deactivating",
1333 G_TYPE_FROM_CLASS(klass),
1334 G_SIGNAL_RUN_LAST,
1335 G_STRUCT_OFFSET(XfdashboardViewpadClass, view_deactivating),
1336 NULL,
1337 NULL,
1338 g_cclosure_marshal_VOID__OBJECT,
1339 G_TYPE_NONE,
1340 1,
1341 XFDASHBOARD_TYPE_VIEW);
1342
1343 XfdashboardViewpadSignals[SIGNAL_VIEW_DEACTIVATED]=
1344 g_signal_new("view-deactivated",
1345 G_TYPE_FROM_CLASS(klass),
1346 G_SIGNAL_RUN_LAST,
1347 G_STRUCT_OFFSET(XfdashboardViewpadClass, view_deactivated),
1348 NULL,
1349 NULL,
1350 g_cclosure_marshal_VOID__OBJECT,
1351 G_TYPE_NONE,
1352 1,
1353 XFDASHBOARD_TYPE_VIEW);
1354 }
1355
1356 /* Object initialization
1357 * Create private structure and set up default values
1358 */
xfdashboard_viewpad_init(XfdashboardViewpad * self)1359 static void xfdashboard_viewpad_init(XfdashboardViewpad *self)
1360 {
1361 XfdashboardViewpadPrivate *priv;
1362 GList *views, *viewEntry;
1363
1364 priv=self->priv=xfdashboard_viewpad_get_instance_private(self);
1365
1366 /* Set up default values */
1367 priv->viewManager=xfdashboard_view_manager_get_default();
1368 priv->activeView=NULL;
1369 priv->spacing=0.0f;
1370 priv->hScrollbarVisible=FALSE;
1371 priv->hScrollbarPolicy=XFDASHBOARD_VISIBILITY_POLICY_AUTOMATIC;
1372 priv->vScrollbarVisible=FALSE;
1373 priv->vScrollbarPolicy=XFDASHBOARD_VISIBILITY_POLICY_AUTOMATIC;
1374 priv->scrollbarUpdateID=0;
1375 priv->doRegisterFocusableViews=FALSE;
1376 priv->lastAllocation=NULL;
1377
1378 /* Set up this actor */
1379 clutter_actor_set_reactive(CLUTTER_ACTOR(self), TRUE);
1380 g_signal_connect(self, "scroll-event", G_CALLBACK(_xfdashboard_viewpad_on_scroll_event), NULL);
1381
1382 /* Set up child actors */
1383 priv->hScrollbar=xfdashboard_scrollbar_new(CLUTTER_ORIENTATION_HORIZONTAL);
1384 clutter_actor_add_child(CLUTTER_ACTOR(self), priv->hScrollbar);
1385 g_signal_connect_swapped(priv->hScrollbar, "value-changed", G_CALLBACK(_xfdashboard_viewpad_on_scrollbar_value_changed), self);
1386
1387 priv->vScrollbar=xfdashboard_scrollbar_new(CLUTTER_ORIENTATION_VERTICAL);
1388 clutter_actor_add_child(CLUTTER_ACTOR(self), priv->vScrollbar);
1389 g_signal_connect_swapped(priv->vScrollbar, "value-changed", G_CALLBACK(_xfdashboard_viewpad_on_scrollbar_value_changed), self);
1390
1391 /* Create instance of each registered view type and add it to this actor
1392 * and connect signals
1393 */
1394 views=viewEntry=xfdashboard_view_manager_get_registered(priv->viewManager);
1395 for(; viewEntry; viewEntry=g_list_next(viewEntry))
1396 {
1397 const gchar *viewID;
1398
1399 viewID=(const gchar*)viewEntry->data;
1400 _xfdashboard_viewpad_add_view(self, viewID);
1401 }
1402 g_list_free_full(views, g_free);
1403
1404 g_signal_connect_swapped(priv->viewManager, "registered", G_CALLBACK(_xfdashboard_viewpad_on_view_registered), self);
1405 g_signal_connect_swapped(priv->viewManager, "unregistered", G_CALLBACK(_xfdashboard_viewpad_on_view_unregistered), self);
1406 }
1407
1408 /* IMPLEMENTATION: Public API */
1409
1410 /* Create new instance */
xfdashboard_viewpad_new(void)1411 ClutterActor* xfdashboard_viewpad_new(void)
1412 {
1413 return(CLUTTER_ACTOR(g_object_new(XFDASHBOARD_TYPE_VIEWPAD, NULL)));
1414 }
1415
1416 /* Get/set spacing */
xfdashboard_viewpad_get_spacing(XfdashboardViewpad * self)1417 gfloat xfdashboard_viewpad_get_spacing(XfdashboardViewpad *self)
1418 {
1419 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), 0.0f);
1420
1421 return(self->priv->spacing);
1422 }
1423
xfdashboard_viewpad_set_spacing(XfdashboardViewpad * self,gfloat inSpacing)1424 void xfdashboard_viewpad_set_spacing(XfdashboardViewpad *self, gfloat inSpacing)
1425 {
1426 XfdashboardViewpadPrivate *priv;
1427
1428 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
1429 g_return_if_fail(inSpacing>=0.0f);
1430
1431 priv=self->priv;
1432
1433 /* Only set value if it changes */
1434 if(inSpacing==priv->spacing) return;
1435
1436 /* Set new value */
1437 priv->spacing=inSpacing;
1438 if(priv->layout)
1439 {
1440 clutter_grid_layout_set_column_spacing(CLUTTER_GRID_LAYOUT(priv->layout), priv->spacing);
1441 clutter_grid_layout_set_row_spacing(CLUTTER_GRID_LAYOUT(priv->layout), priv->spacing);
1442 }
1443 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1444
1445 /* Notify about property change */
1446 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardViewpadProperties[PROP_SPACING]);
1447 }
1448
1449 /* Get list of views */
xfdashboard_viewpad_get_views(XfdashboardViewpad * self)1450 GList* xfdashboard_viewpad_get_views(XfdashboardViewpad *self)
1451 {
1452 ClutterActorIter iter;
1453 ClutterActor *child;
1454 GList *list;
1455
1456 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), NULL);
1457
1458 list=NULL;
1459
1460 /* Iterate through children and create list of views */
1461 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
1462 while(clutter_actor_iter_next(&iter, &child))
1463 {
1464 /* Check if child is a view and add to list */
1465 if(XFDASHBOARD_IS_VIEW(child)==TRUE) list=g_list_prepend(list, child);
1466 }
1467 list=g_list_reverse(list);
1468
1469 return(list);
1470 }
1471
1472 /* Determine if viewpad contains requested view */
xfdashboard_viewpad_has_view(XfdashboardViewpad * self,XfdashboardView * inView)1473 gboolean xfdashboard_viewpad_has_view(XfdashboardViewpad *self, XfdashboardView *inView)
1474 {
1475 ClutterActorIter iter;
1476 ClutterActor *child;
1477
1478 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), FALSE);
1479 g_return_val_if_fail(XFDASHBOARD_IS_VIEW(inView), FALSE);
1480
1481 /* Iterate through children and check if child is requested view */
1482 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
1483 while(clutter_actor_iter_next(&iter, &child))
1484 {
1485 if(XFDASHBOARD_IS_VIEW(child) &&
1486 XFDASHBOARD_VIEW(child)==inView)
1487 {
1488 return(TRUE);
1489 }
1490 }
1491
1492 /* If we get here the requested view could not be found
1493 * so return FALSE.
1494 */
1495 return(FALSE);
1496 }
1497
1498 /* Find view by type */
xfdashboard_viewpad_find_view_by_type(XfdashboardViewpad * self,GType inType)1499 XfdashboardView* xfdashboard_viewpad_find_view_by_type(XfdashboardViewpad *self, GType inType)
1500 {
1501 ClutterActorIter iter;
1502 ClutterActor *child;
1503 XfdashboardView *view;
1504
1505 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), NULL);
1506
1507 view=NULL;
1508
1509 /* Iterate through children and create list of views */
1510 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
1511 while(!view && clutter_actor_iter_next(&iter, &child))
1512 {
1513 /* Check if child is a view and of type looking for */
1514 if(XFDASHBOARD_IS_VIEW(child)==TRUE &&
1515 G_OBJECT_TYPE(child)==inType)
1516 {
1517 view=XFDASHBOARD_VIEW(child);
1518 }
1519 }
1520
1521 /* Return view found which may be NULL if no view of requested type was found */
1522 return(view);
1523 }
1524
1525 /* Find view by ID */
xfdashboard_viewpad_find_view_by_id(XfdashboardViewpad * self,const gchar * inID)1526 XfdashboardView* xfdashboard_viewpad_find_view_by_id(XfdashboardViewpad *self, const gchar *inID)
1527 {
1528 ClutterActorIter iter;
1529 ClutterActor *child;
1530 XfdashboardView *view;
1531
1532 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), NULL);
1533 g_return_val_if_fail(inID && *inID, NULL);
1534
1535 view=NULL;
1536
1537 /* Iterate through children and lookup view matching requested name */
1538 clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
1539 while(!view && clutter_actor_iter_next(&iter, &child))
1540 {
1541 /* Check if child is a view and its internal name matches requested name */
1542 if(XFDASHBOARD_IS_VIEW(child)==TRUE &&
1543 xfdashboard_view_has_id(XFDASHBOARD_VIEW(child), inID))
1544 {
1545 view=XFDASHBOARD_VIEW(child);
1546 }
1547 }
1548
1549 /* Return view found which may be NULL if no view of requested type was found */
1550 return(view);
1551 }
1552
1553 /* Get/set active view */
xfdashboard_viewpad_get_active_view(XfdashboardViewpad * self)1554 XfdashboardView* xfdashboard_viewpad_get_active_view(XfdashboardViewpad *self)
1555 {
1556 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), NULL);
1557
1558 return(self->priv->activeView);
1559 }
1560
xfdashboard_viewpad_set_active_view(XfdashboardViewpad * self,XfdashboardView * inView)1561 void xfdashboard_viewpad_set_active_view(XfdashboardViewpad *self, XfdashboardView *inView)
1562 {
1563 XfdashboardViewpadPrivate *priv;
1564
1565 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
1566 g_return_if_fail(XFDASHBOARD_IS_VIEW(inView));
1567
1568 priv=self->priv;
1569
1570 /* Only activate view if it changes */
1571 if(priv->activeView!=inView) _xfdashboard_viewpad_activate_view(self, inView);
1572 }
1573
1574 /* Get/set scroll bar visibility */
xfdashboard_viewpad_get_horizontal_scrollbar_visible(XfdashboardViewpad * self)1575 gboolean xfdashboard_viewpad_get_horizontal_scrollbar_visible(XfdashboardViewpad *self)
1576 {
1577 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), FALSE);
1578
1579 return(self->priv->hScrollbarVisible);
1580 }
1581
xfdashboard_viewpad_get_vertical_scrollbar_visible(XfdashboardViewpad * self)1582 gboolean xfdashboard_viewpad_get_vertical_scrollbar_visible(XfdashboardViewpad *self)
1583 {
1584 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), FALSE);
1585
1586 return(self->priv->vScrollbarVisible);
1587 }
1588
1589 /* Get/set scroll bar policy */
xfdashboard_viewpad_get_horizontal_scrollbar_policy(XfdashboardViewpad * self)1590 XfdashboardVisibilityPolicy xfdashboard_viewpad_get_horizontal_scrollbar_policy(XfdashboardViewpad *self)
1591 {
1592 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), XFDASHBOARD_VISIBILITY_POLICY_AUTOMATIC);
1593
1594 return(self->priv->hScrollbarPolicy);
1595 }
1596
xfdashboard_viewpad_set_horizontal_scrollbar_policy(XfdashboardViewpad * self,XfdashboardVisibilityPolicy inPolicy)1597 void xfdashboard_viewpad_set_horizontal_scrollbar_policy(XfdashboardViewpad *self, XfdashboardVisibilityPolicy inPolicy)
1598 {
1599 XfdashboardViewpadPrivate *priv;
1600
1601 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
1602
1603 priv=self->priv;
1604
1605 /* Only set new value if it differs from current value */
1606 if(priv->hScrollbarPolicy==inPolicy) return;
1607
1608 /* Set new value */
1609 priv->hScrollbarPolicy=inPolicy;
1610 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1611
1612 /* Notify about property change */
1613 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardViewpadProperties[PROP_HSCROLLBAR_POLICY]);
1614 }
1615
xfdashboard_viewpad_get_vertical_scrollbar_policy(XfdashboardViewpad * self)1616 XfdashboardVisibilityPolicy xfdashboard_viewpad_get_vertical_scrollbar_policy(XfdashboardViewpad *self)
1617 {
1618 g_return_val_if_fail(XFDASHBOARD_IS_VIEWPAD(self), XFDASHBOARD_VISIBILITY_POLICY_AUTOMATIC);
1619
1620 return(self->priv->vScrollbarPolicy);
1621 }
1622
xfdashboard_viewpad_set_vertical_scrollbar_policy(XfdashboardViewpad * self,XfdashboardVisibilityPolicy inPolicy)1623 void xfdashboard_viewpad_set_vertical_scrollbar_policy(XfdashboardViewpad *self, XfdashboardVisibilityPolicy inPolicy)
1624 {
1625 XfdashboardViewpadPrivate *priv;
1626
1627 g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));
1628
1629 priv=self->priv;
1630
1631 /* Only set new value if it differs from current value */
1632 if(priv->vScrollbarPolicy==inPolicy) return;
1633
1634 /* Set new value */
1635 priv->vScrollbarPolicy=inPolicy;
1636 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1637
1638 /* Notify about property change */
1639 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardViewpadProperties[PROP_VSCROLLBAR_POLICY]);
1640 }
1641