1 /*
2  * windows-view: A view showing visible windows
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/windows-view.h>
29 
30 #include <glib/gi18n-lib.h>
31 #include <gtk/gtk.h>
32 
33 #include <libxfdashboard/live-window.h>
34 #include <libxfdashboard/scaled-table-layout.h>
35 #include <libxfdashboard/stage.h>
36 #include <libxfdashboard/application.h>
37 #include <libxfdashboard/view.h>
38 #include <libxfdashboard/drop-action.h>
39 #include <libxfdashboard/quicklaunch.h>
40 #include <libxfdashboard/application-button.h>
41 #include <libxfdashboard/window-tracker.h>
42 #include <libxfdashboard/image-content.h>
43 #include <libxfdashboard/utils.h>
44 #include <libxfdashboard/marshal.h>
45 #include <libxfdashboard/enums.h>
46 #include <libxfdashboard/stage-interface.h>
47 #include <libxfdashboard/live-workspace.h>
48 #include <libxfdashboard/compat.h>
49 #include <libxfdashboard/debug.h>
50 
51 
52 /* Define this class in GObject system */
53 static void _xfdashboard_windows_view_focusable_iface_init(XfdashboardFocusableInterface *iface);
54 
55 struct _XfdashboardWindowsViewPrivate
56 {
57 	/* Properties related */
58 	XfdashboardWindowTrackerWorkspace	*workspace;
59 	gfloat								spacing;
60 	gboolean							preventUpscaling;
61 	gboolean							isScrollEventChangingWorkspace;
62 
63 	/* Instance related */
64 	XfdashboardWindowTracker			*windowTracker;
65 	ClutterLayoutManager				*layout;
66 	gpointer							selectedItem;
67 
68 	XfconfChannel						*xfconfChannel;
69 	guint								xfconfScrollEventChangingWorkspaceBindingID;
70 	XfdashboardStageInterface			*scrollEventChangingWorkspaceStage;
71 	guint								scrollEventChangingWorkspaceStageSignalID;
72 
73 	gboolean							isWindowsNumberShown;
74 
75 	gboolean							filterMonitorWindows;
76 	gboolean							filterWorkspaceWindows;
77 	XfdashboardStageInterface			*currentStage;
78 	XfdashboardWindowTrackerMonitor		*currentMonitor;
79 	guint								currentStageMonitorBindingID;
80 };
81 
82 G_DEFINE_TYPE_WITH_CODE(XfdashboardWindowsView,
83 						xfdashboard_windows_view,
84 						XFDASHBOARD_TYPE_VIEW,
85 						G_ADD_PRIVATE(XfdashboardWindowsView)
86 						G_IMPLEMENT_INTERFACE(XFDASHBOARD_TYPE_FOCUSABLE, _xfdashboard_windows_view_focusable_iface_init))
87 
88 /* Properties */
89 enum
90 {
91 	PROP_0,
92 
93 	PROP_WORKSPACE,
94 	PROP_SPACING,
95 	PROP_PREVENT_UPSCALING,
96 	PROP_SCROLL_EVENT_CHANGES_WORKSPACE,
97 	PROP_FILTER_MONITOR_WINDOWS,
98 	PROP_FILTER_WORKSPACE_WINDOWS,
99 
100 	PROP_LAST
101 };
102 
103 static GParamSpec* XfdashboardWindowsViewProperties[PROP_LAST]={ 0, };
104 
105 /* Signals */
106 enum
107 {
108 	ACTION_WINDOW_CLOSE,
109 	ACTION_WINDOWS_SHOW_NUMBERS,
110 	ACTION_WINDOWS_HIDE_NUMBERS,
111 	ACTION_WINDOWS_ACTIVATE_WINDOW_ONE,
112 	ACTION_WINDOWS_ACTIVATE_WINDOW_TWO,
113 	ACTION_WINDOWS_ACTIVATE_WINDOW_THREE,
114 	ACTION_WINDOWS_ACTIVATE_WINDOW_FOUR,
115 	ACTION_WINDOWS_ACTIVATE_WINDOW_FIVE,
116 	ACTION_WINDOWS_ACTIVATE_WINDOW_SIX,
117 	ACTION_WINDOWS_ACTIVATE_WINDOW_SEVEN,
118 	ACTION_WINDOWS_ACTIVATE_WINDOW_EIGHT,
119 	ACTION_WINDOWS_ACTIVATE_WINDOW_NINE,
120 	ACTION_WINDOWS_ACTIVATE_WINDOW_TEN,
121 
122 	SIGNAL_LAST
123 };
124 
125 static guint XfdashboardWindowsViewSignals[SIGNAL_LAST]={ 0, };
126 
127 /* Forward declaration */
128 static void _xfdashboard_windows_view_recreate_window_actors(XfdashboardWindowsView *self);
129 static XfdashboardLiveWindow* _xfdashboard_windows_view_create_actor(XfdashboardWindowsView *self, XfdashboardWindowTrackerWindow *inWindow);
130 static void _xfdashboard_windows_view_set_active_workspace(XfdashboardWindowsView *self, XfdashboardWindowTrackerWorkspace *inWorkspace);
131 
132 /* IMPLEMENTATION: Private variables and methods */
133 #define SCROLL_EVENT_CHANGES_WORKSPACE_XFCONF_PROP		"/components/windows-view/scroll-event-changes-workspace"
134 
135 #define DEFAULT_VIEW_ICON								"view-fullscreen"
136 #define DEFAULT_DRAG_HANDLE_SIZE						32.0f
137 
138 /* Stage interface has changed monitor */
_xfdashboard_windows_view_update_on_stage_monitor_changed(XfdashboardWindowsView * self,GParamSpec * inSpec,gpointer inUserData)139 static void _xfdashboard_windows_view_update_on_stage_monitor_changed(XfdashboardWindowsView *self,
140 																		GParamSpec *inSpec,
141 																		gpointer inUserData)
142 {
143 	XfdashboardWindowsViewPrivate		*priv;
144 
145 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
146 
147 	priv=self->priv;
148 
149 	/* Get new reference to new monitor of stage */
150 	priv->currentMonitor=xfdashboard_stage_interface_get_monitor(priv->currentStage);
151 
152 	/* Recreate all window actors */
153 	_xfdashboard_windows_view_recreate_window_actors(self);
154 }
155 
156 /* Update reference to stage interface and monitor where this view is on */
_xfdashboard_windows_view_update_stage_and_monitor(XfdashboardWindowsView * self)157 static gboolean _xfdashboard_windows_view_update_stage_and_monitor(XfdashboardWindowsView *self)
158 {
159 	XfdashboardWindowsViewPrivate		*priv;
160 	XfdashboardStageInterface			*newStage;
161 
162 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), FALSE);
163 
164 	priv=self->priv;
165 
166 	/* Iterate through parent actors until stage interface is reached */
167 	newStage=xfdashboard_get_stage_of_actor(CLUTTER_ACTOR(self));
168 
169 	/* If stage did not change return immediately */
170 	if(newStage==priv->currentStage) return(FALSE);
171 
172 	/* Release old references to stage and monitor */
173 	priv->currentMonitor=NULL;
174 
175 	if(priv->currentStage)
176 	{
177 		if(priv->currentStageMonitorBindingID)
178 		{
179 			g_signal_handler_disconnect(priv->currentStage, priv->currentStageMonitorBindingID);
180 			priv->currentStageMonitorBindingID=0;
181 		}
182 
183 		priv->currentStage=NULL;
184 	}
185 
186 	/* Get new references to new stage and monitor and connect signal to get notified
187 	 * if stage changes monitor.
188 	 */
189 	if(newStage)
190 	{
191 		priv->currentStage=newStage;
192 		priv->currentStageMonitorBindingID=g_signal_connect_swapped(priv->currentStage,
193 																	"notify::monitor",
194 																	G_CALLBACK(_xfdashboard_windows_view_update_on_stage_monitor_changed),
195 																	self);
196 
197 		/* Get new reference to current monitor of new stage */
198 		priv->currentMonitor=xfdashboard_stage_interface_get_monitor(priv->currentStage);
199 	}
200 
201 	/* Stage and monitor changed and references were renewed and setup */
202 	return(TRUE);
203 }
204 
205 /* Check if window should be shown */
_xfdashboard_windows_view_is_visible_window(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow)206 static gboolean _xfdashboard_windows_view_is_visible_window(XfdashboardWindowsView *self,
207 																XfdashboardWindowTrackerWindow *inWindow)
208 {
209 	XfdashboardWindowsViewPrivate			*priv;
210 	XfdashboardWindowTrackerWindowState		state;
211 
212 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), FALSE);
213 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), FALSE);
214 
215 	priv=self->priv;
216 
217 	/* Get state of window */
218 	state=xfdashboard_window_tracker_window_get_state(inWindow);
219 
220 	/* Determine if windows should be shown depending on its state, size and position */
221 	if(state & XFDASHBOARD_WINDOW_TRACKER_WINDOW_STATE_SKIP_PAGER)
222 	{
223 		return(FALSE);
224 	}
225 
226 	if(state & XFDASHBOARD_WINDOW_TRACKER_WINDOW_STATE_SKIP_TASKLIST)
227 	{
228 		return(FALSE);
229 	}
230 
231 	if(xfdashboard_window_tracker_window_is_stage(inWindow))
232 	{
233 		return(FALSE);
234 	}
235 
236 	if(!priv->workspace)
237 	{
238 		return(FALSE);
239 	}
240 
241 	if(!xfdashboard_window_tracker_window_is_visible(inWindow) ||
242 		(priv->filterWorkspaceWindows && !xfdashboard_window_tracker_window_is_on_workspace(inWindow, priv->workspace)))
243 	{
244 		return(FALSE);
245 	}
246 
247 	if(priv->filterMonitorWindows &&
248 		xfdashboard_window_tracker_supports_multiple_monitors(priv->windowTracker) &&
249 		(!priv->currentMonitor || !xfdashboard_window_tracker_window_is_on_monitor(inWindow, priv->currentMonitor)))
250 	{
251 		return(FALSE);
252 	}
253 
254 	/* If we get here the window should be shown */
255 	return(TRUE);
256 }
257 
258 /* Find live window actor by window */
_xfdashboard_windows_view_find_by_window(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow)259 static XfdashboardLiveWindow* _xfdashboard_windows_view_find_by_window(XfdashboardWindowsView *self,
260 																		XfdashboardWindowTrackerWindow *inWindow)
261 {
262 	XfdashboardLiveWindow		*liveWindow;
263 	ClutterActor				*child;
264 	ClutterActorIter			iter;
265 
266 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), NULL);
267 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL);
268 
269 	/* Iterate through list of current actors and find the one for requested window */
270 	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
271 	while(clutter_actor_iter_next(&iter, &child))
272 	{
273 		if(!XFDASHBOARD_IS_LIVE_WINDOW(child)) continue;
274 
275 		liveWindow=XFDASHBOARD_LIVE_WINDOW(child);
276 		if(xfdashboard_live_window_simple_get_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(liveWindow))==inWindow)
277 		{
278 			return(liveWindow);
279 		}
280 	}
281 
282 	/* If we get here we did not find the window and we return NULL */
283 	return(NULL);
284 }
285 
286 /* Update window number in close button of each window actor */
_xfdashboard_windows_view_update_window_number_in_actors(XfdashboardWindowsView * self)287 static void _xfdashboard_windows_view_update_window_number_in_actors(XfdashboardWindowsView *self)
288 {
289 	XfdashboardWindowsViewPrivate		*priv;
290 	ClutterActor						*child;
291 	ClutterActorIter					iter;
292 	gint								index;
293 
294 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
295 
296 	priv=self->priv;
297 
298 	/* Iterate through list of current actors and for the first ten actors
299 	 * change the close button to window number and the rest will still be
300 	 * close buttons.
301 	 */
302 	index=1;
303 	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
304 	while(clutter_actor_iter_next(&iter, &child))
305 	{
306 		/* Only live window actors can be handled */
307 		if(!XFDASHBOARD_IS_LIVE_WINDOW(child)) continue;
308 
309 		/* If this is one of the first ten window actors change close button
310 		 * to window number and set number.
311 		 */
312 		if(priv->isWindowsNumberShown && index<=10)
313 		{
314 			g_object_set(child, "window-number", index, NULL);
315 			index++;
316 		}
317 			else
318 			{
319 				g_object_set(child, "window-number", 0, NULL);
320 			}
321 	}
322 }
323 
324 /* Recreate all window actors in this view */
_xfdashboard_windows_view_recreate_window_actors(XfdashboardWindowsView * self)325 static void _xfdashboard_windows_view_recreate_window_actors(XfdashboardWindowsView *self)
326 {
327 	XfdashboardWindowsViewPrivate			*priv;
328 	GList									*windowsList;
329 
330 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
331 
332 	priv=self->priv;
333 
334 	/* Remove weak reference at current selection and unset selection */
335 	if(priv->selectedItem)
336 	{
337 		g_object_remove_weak_pointer(G_OBJECT(priv->selectedItem), &priv->selectedItem);
338 		priv->selectedItem=NULL;
339 	}
340 
341 	/* Destroy all actors */
342 	xfdashboard_actor_destroy_all_children(CLUTTER_ACTOR(self));
343 
344 	/* Create live window actors for new workspace */
345 	if(priv->workspace!=NULL)
346 	{
347 		/* Get list of all windows open */
348 		windowsList=xfdashboard_window_tracker_get_windows(priv->windowTracker);
349 
350 		/* Iterate through list of window (from last to first), check if window
351 		 * is visible and create actor for it if it is.
352 		 */
353 		windowsList=g_list_last(windowsList);
354 		while(windowsList)
355 		{
356 			XfdashboardWindowTrackerWindow	*window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(windowsList->data);
357 			XfdashboardLiveWindow			*liveWindow;
358 
359 			/* Check if window is visible on this workspace */
360 			if(_xfdashboard_windows_view_is_visible_window(self, window))
361 			{
362 				/* Create actor */
363 				liveWindow=_xfdashboard_windows_view_create_actor(XFDASHBOARD_WINDOWS_VIEW(self), window);
364 				if(liveWindow)
365 				{
366 					clutter_actor_add_child(CLUTTER_ACTOR(self), CLUTTER_ACTOR(liveWindow));
367 					_xfdashboard_windows_view_update_window_number_in_actors(self);
368 				}
369 			}
370 
371 			/* Next window */
372 			windowsList=g_list_previous(windowsList);
373 		}
374 	}
375 }
376 
377 /* Move window to monitor of this window view */
_xfdashboard_windows_view_move_live_to_view(XfdashboardWindowsView * self,XfdashboardLiveWindow * inWindowActor)378 static void _xfdashboard_windows_view_move_live_to_view(XfdashboardWindowsView *self,
379 														XfdashboardLiveWindow *inWindowActor)
380 {
381 	XfdashboardWindowsViewPrivate			*priv;
382 	XfdashboardWindowTrackerWindow			*window;
383 	XfdashboardWindowTrackerWorkspace		*sourceWorkspace;
384 	XfdashboardWindowTrackerWorkspace		*targetWorkspace;
385 	XfdashboardWindowTrackerMonitor			*sourceMonitor;
386 	XfdashboardWindowTrackerMonitor			*targetMonitor;
387 	gint									oldWindowX, oldWindowY, oldWindowWidth, oldWindowHeight;
388 	gint									newWindowX, newWindowY;
389 	gint									oldMonitorX, oldMonitorY, oldMonitorWidth, oldMonitorHeight;
390 	gint									newMonitorX, newMonitorY, newMonitorWidth, newMonitorHeight;
391 	gfloat									relativeX, relativeY;
392 
393 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
394 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(inWindowActor));
395 
396 	priv=self->priv;
397 
398 	/* Get window from window actor */
399 	window=xfdashboard_live_window_simple_get_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(inWindowActor));
400 
401 	/* Get source and target workspace */
402 	sourceWorkspace=xfdashboard_window_tracker_window_get_workspace(window);
403 	targetWorkspace=priv->workspace;
404 
405 	/* Get source and target monitor */
406 	sourceMonitor=xfdashboard_window_tracker_window_get_monitor(window);
407 	targetMonitor=priv->currentMonitor;
408 
409 	XFDASHBOARD_DEBUG(self, ACTOR,
410 						"Moving window '%s' from %s-monitor %d to %s-monitor %d and from workspace '%s' (%d) to '%s' (%d)",
411 						xfdashboard_window_tracker_window_get_name(window),
412 						xfdashboard_window_tracker_monitor_is_primary(sourceMonitor) ? "primary" : "secondary",
413 						xfdashboard_window_tracker_monitor_get_number(sourceMonitor),
414 						xfdashboard_window_tracker_monitor_is_primary(targetMonitor) ? "primary" : "secondary",
415 						xfdashboard_window_tracker_monitor_get_number(targetMonitor),
416 						xfdashboard_window_tracker_workspace_get_name(sourceWorkspace),
417 						xfdashboard_window_tracker_workspace_get_number(sourceWorkspace),
418 						xfdashboard_window_tracker_workspace_get_name(targetWorkspace),
419 						xfdashboard_window_tracker_workspace_get_number(targetWorkspace));
420 
421 	/* Get position and size of window to move */
422 	xfdashboard_window_tracker_window_get_geometry(window,
423 													&oldWindowX,
424 													&oldWindowY,
425 													&oldWindowWidth,
426 													&oldWindowHeight);
427 
428 	/* Calculate source x and y coordinate relative to monitor size in percent */
429 	xfdashboard_window_tracker_monitor_get_geometry(sourceMonitor,
430 													&oldMonitorX,
431 													&oldMonitorY,
432 													&oldMonitorWidth,
433 													&oldMonitorHeight);
434 	relativeX=((gfloat)(oldWindowX-oldMonitorX)) / ((gfloat)oldMonitorWidth);
435 	relativeY=((gfloat)(oldWindowY-oldMonitorY)) / ((gfloat)oldMonitorHeight);
436 
437 	/* Calculate target x and y coordinate from relative size in percent to monitor size */
438 	xfdashboard_window_tracker_monitor_get_geometry(targetMonitor,
439 													&newMonitorX,
440 													&newMonitorY,
441 													&newMonitorWidth,
442 													&newMonitorHeight);
443 	newWindowX=newMonitorX+((gint)(relativeX*newMonitorWidth));
444 	newWindowY=newMonitorY+((gint)(relativeY*newMonitorHeight));
445 
446 	/* Move window to workspace if they are not the same */
447 	if(!xfdashboard_window_tracker_workspace_is_equal(sourceWorkspace, targetWorkspace))
448 	{
449 		xfdashboard_window_tracker_window_move_to_workspace(window, targetWorkspace);
450 		XFDASHBOARD_DEBUG(self, ACTOR,
451 							"Moved window '%s' from workspace '%s' (%d) to '%s' (%d)",
452 							xfdashboard_window_tracker_window_get_name(window),
453 							xfdashboard_window_tracker_workspace_get_name(sourceWorkspace),
454 							xfdashboard_window_tracker_workspace_get_number(sourceWorkspace),
455 							xfdashboard_window_tracker_workspace_get_name(targetWorkspace),
456 							xfdashboard_window_tracker_workspace_get_number(targetWorkspace));
457 	}
458 
459 	/* Move window to new position */
460 	xfdashboard_window_tracker_window_move(window, newWindowX, newWindowY);
461 	XFDASHBOARD_DEBUG(self, ACTOR,
462 						"Moved window '%s' from [%d,%d] at monitor [%d,%d x %d,%d] to [%d,%d] at monitor [%d,%d x %d,%d] (relative x=%.2f, y=%.2f)",
463 						xfdashboard_window_tracker_window_get_name(window),
464 						oldWindowX, oldWindowY,
465 						oldMonitorX, oldMonitorY, oldMonitorWidth, oldMonitorHeight,
466 						newWindowX, newWindowY,
467 						newMonitorX, newMonitorY, newMonitorWidth, newMonitorHeight,
468 						relativeX, relativeY);
469 }
470 
471 /* Drag of an actor to this view as drop target begins */
_xfdashboard_windows_view_on_drop_begin(XfdashboardWindowsView * self,XfdashboardDragAction * inDragAction,gpointer inUserData)472 static gboolean _xfdashboard_windows_view_on_drop_begin(XfdashboardWindowsView *self,
473 														XfdashboardDragAction *inDragAction,
474 														gpointer inUserData)
475 {
476 	ClutterActor					*dragSource;
477 	ClutterActor					*draggedActor;
478 	gboolean						canHandle;
479 
480 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), FALSE);
481 	g_return_val_if_fail(XFDASHBOARD_IS_DRAG_ACTION(inDragAction), FALSE);
482 	g_return_val_if_fail(XFDASHBOARD_IS_DROP_ACTION(inUserData), FALSE);
483 
484 	canHandle=FALSE;
485 
486 	/* Get source where dragging started and actor being dragged */
487 	dragSource=xfdashboard_drag_action_get_source(inDragAction);
488 	draggedActor=xfdashboard_drag_action_get_actor(inDragAction);
489 
490 	/* We can handle dragged actor if it is an application button and its source
491 	 * is quicklaunch.
492 	 */
493 	if(XFDASHBOARD_IS_QUICKLAUNCH(dragSource) &&
494 		XFDASHBOARD_IS_APPLICATION_BUTTON(draggedActor))
495 	{
496 		canHandle=TRUE;
497 	}
498 
499 	/* We can handle dragged actor if it is a live window and its source
500 	 * is windows view.
501 	 */
502 	if(XFDASHBOARD_IS_WINDOWS_VIEW(dragSource) &&
503 		XFDASHBOARD_IS_LIVE_WINDOW(draggedActor))
504 	{
505 		canHandle=TRUE;
506 	}
507 
508 	/* We can handle dragged actor if it is a live window and its source
509 	 * is a live workspace
510 	 */
511 	if(XFDASHBOARD_IS_LIVE_WORKSPACE(dragSource) &&
512 		XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(draggedActor))
513 	{
514 		canHandle=TRUE;
515 	}
516 
517 	/* Return TRUE if we can handle dragged actor in this drop target
518 	 * otherwise FALSE
519 	 */
520 	return(canHandle);
521 }
522 
523 /* Dragged actor was dropped on this drop target */
_xfdashboard_windows_view_on_drop_drop(XfdashboardWindowsView * self,XfdashboardDragAction * inDragAction,gfloat inX,gfloat inY,gpointer inUserData)524 static void _xfdashboard_windows_view_on_drop_drop(XfdashboardWindowsView *self,
525 													XfdashboardDragAction *inDragAction,
526 													gfloat inX,
527 													gfloat inY,
528 													gpointer inUserData)
529 {
530 	XfdashboardWindowsViewPrivate		*priv;
531 	ClutterActor						*dragSource;
532 	ClutterActor						*draggedActor;
533 	GAppLaunchContext					*context;
534 
535 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
536 	g_return_if_fail(XFDASHBOARD_IS_DRAG_ACTION(inDragAction));
537 	g_return_if_fail(XFDASHBOARD_IS_DROP_ACTION(inUserData));
538 
539 	priv=self->priv;
540 
541 	/* Get source where dragging started and actor being dragged */
542 	dragSource=xfdashboard_drag_action_get_source(inDragAction);
543 	draggedActor=xfdashboard_drag_action_get_actor(inDragAction);
544 
545 	/* Handle drop of an application button from quicklaunch */
546 	if(XFDASHBOARD_IS_QUICKLAUNCH(dragSource) &&
547 		XFDASHBOARD_IS_APPLICATION_BUTTON(draggedActor))
548 	{
549 		/* Launch application being dragged here */
550 		context=xfdashboard_create_app_context(priv->workspace);
551 		xfdashboard_application_button_execute(XFDASHBOARD_APPLICATION_BUTTON(draggedActor), context);
552 		g_object_unref(context);
553 
554 		/* Drop action handled so return here */
555 		return;
556 	}
557 
558 	/* Handle drop of an window from another windows view */
559 	if(XFDASHBOARD_IS_WINDOWS_VIEW(dragSource) &&
560 		XFDASHBOARD_IS_LIVE_WINDOW(draggedActor))
561 	{
562 		XfdashboardWindowsView			*sourceWindowsView;
563 		XfdashboardLiveWindow			*liveWindowActor;
564 
565 		/* Get source windows view */
566 		sourceWindowsView=XFDASHBOARD_WINDOWS_VIEW(dragSource);
567 
568 		/* Do nothing if source windows view is the same as target windows view
569 		 * that means this one.
570 		 */
571 		if(sourceWindowsView==self)
572 		{
573 			XFDASHBOARD_DEBUG(self, ACTOR,
574 						"Will not handle drop of %s at %s because source and target are the same.",
575 						G_OBJECT_TYPE_NAME(draggedActor),
576 						G_OBJECT_TYPE_NAME(dragSource));
577 			return;
578 		}
579 
580 		/* Get dragged window */
581 		liveWindowActor=XFDASHBOARD_LIVE_WINDOW(draggedActor);
582 
583 		/* Move dragged window to monitor of this window view */
584 		_xfdashboard_windows_view_move_live_to_view(self, liveWindowActor);
585 
586 		/* Drop action handled so return here */
587 		return;
588 	}
589 
590 	/* Handle drop of an window from a live workspace */
591 	if(XFDASHBOARD_IS_LIVE_WORKSPACE(dragSource) &&
592 		XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(draggedActor))
593 	{
594 		XfdashboardLiveWorkspace			*sourceLiveWorkspace;
595 		XfdashboardWindowTrackerWorkspace*	sourceWorkspace;
596 		XfdashboardLiveWindowSimple			*liveWindowActor;
597 		XfdashboardWindowTrackerWindow		*window;
598 
599 		/* Get source live workspace and its workspace */
600 		sourceLiveWorkspace=XFDASHBOARD_LIVE_WORKSPACE(dragSource);
601 		sourceWorkspace=xfdashboard_live_workspace_get_workspace(sourceLiveWorkspace);
602 
603 		/* Do nothing if source and destination workspaces are the same as nothing
604 		 * is to do in this case.
605 		 */
606 		if(xfdashboard_window_tracker_workspace_is_equal(sourceWorkspace, priv->workspace))
607 		{
608 			XFDASHBOARD_DEBUG(self, ACTOR,
609 						"Will not handle drop of %s at %s because source and target workspaces are the same.",
610 						G_OBJECT_TYPE_NAME(draggedActor),
611 						G_OBJECT_TYPE_NAME(dragSource));
612 			return;
613 		}
614 
615 		/* Get dragged window */
616 		liveWindowActor=XFDASHBOARD_LIVE_WINDOW_SIMPLE(draggedActor);
617 		window=xfdashboard_live_window_simple_get_window(liveWindowActor);
618 
619 		/* Move dragged window to workspace of this window view */
620 		xfdashboard_window_tracker_window_move_to_workspace(window, priv->workspace);
621 
622 		/* Drop action handled so return here */
623 		return;
624 	}
625 
626 	/* If we get here we did not handle drop action properly
627 	 * and this should never happen.
628 	 */
629 	g_critical("Did not handle drop action for dragged actor %s of source %s at target %s",
630 				G_OBJECT_TYPE_NAME(draggedActor),
631 				G_OBJECT_TYPE_NAME(dragSource),
632 				G_OBJECT_TYPE_NAME(self));
633 }
634 
635 /* A child actor was added to view */
_xfdashboard_windows_view_on_child_added(ClutterContainer * inContainer,ClutterActor * inChild,gpointer inUserData)636 static void _xfdashboard_windows_view_on_child_added(ClutterContainer *inContainer,
637 														ClutterActor *inChild,
638 														gpointer inUserData)
639 {
640 	ClutterActorIter			iter;
641 	ClutterActor				*child;
642 
643 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inContainer));
644 
645 	/* Iterate through list of current actors and enable allocation animation */
646 	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
647 	while(clutter_actor_iter_next(&iter, &child))
648 	{
649 		if(XFDASHBOARD_IS_ACTOR(child))
650 		{
651 			xfdashboard_actor_enable_allocation_animation_once(XFDASHBOARD_ACTOR(child));
652 		}
653 	}
654 }
655 
656 /* A child actor was removed from view */
_xfdashboard_windows_view_on_child_removed(ClutterContainer * inContainer,ClutterActor * inChild,gpointer inUserData)657 static void _xfdashboard_windows_view_on_child_removed(ClutterContainer *inContainer,
658 														ClutterActor *inChild,
659 														gpointer inUserData)
660 {
661 	ClutterActorIter			iter;
662 	ClutterActor				*child;
663 
664 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inContainer));
665 
666 	/* Iterate through list of current actors and enable allocation animation */
667 	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
668 	while(clutter_actor_iter_next(&iter, &child))
669 	{
670 		if(XFDASHBOARD_IS_ACTOR(child))
671 		{
672 			xfdashboard_actor_enable_allocation_animation_once(XFDASHBOARD_ACTOR(child));
673 		}
674 	}
675 }
676 
677 /* Active workspace was changed */
_xfdashboard_windows_view_on_active_workspace_changed(XfdashboardWindowsView * self,XfdashboardWindowTrackerWorkspace * inPrevWorkspace,XfdashboardWindowTrackerWorkspace * inNewWorkspace,gpointer inUserData)678 static void _xfdashboard_windows_view_on_active_workspace_changed(XfdashboardWindowsView *self,
679 																	XfdashboardWindowTrackerWorkspace *inPrevWorkspace,
680 																	XfdashboardWindowTrackerWorkspace *inNewWorkspace,
681 																	gpointer inUserData)
682 {
683 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
684 
685 	/* Update window list */
686 	_xfdashboard_windows_view_set_active_workspace(self, inNewWorkspace);
687 }
688 
689 /* A window was opened */
_xfdashboard_windows_view_on_window_opened(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow,gpointer inUserData)690 static void _xfdashboard_windows_view_on_window_opened(XfdashboardWindowsView *self,
691 														XfdashboardWindowTrackerWindow *inWindow,
692 														gpointer inUserData)
693 {
694 	XfdashboardLiveWindow				*liveWindow;
695 
696 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
697 	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow));
698 
699 	/* Check if parent stage interface changed. If not just add window actor.
700 	 * Otherwise recreate all window actors for changed stage interface and
701 	 * monitor.
702 	 */
703 	if(!_xfdashboard_windows_view_update_stage_and_monitor(self))
704 	{
705 		/* Check if window is visible on this workspace */
706 		if(!_xfdashboard_windows_view_is_visible_window(self, inWindow)) return;
707 
708 		/* Create actor if it does not exist already */
709 		liveWindow=_xfdashboard_windows_view_find_by_window(self, inWindow);
710 		if(G_LIKELY(!liveWindow))
711 		{
712 			liveWindow=_xfdashboard_windows_view_create_actor(self, inWindow);
713 			if(liveWindow)
714 			{
715 				clutter_actor_insert_child_below(CLUTTER_ACTOR(self), CLUTTER_ACTOR(liveWindow), NULL);
716 				_xfdashboard_windows_view_update_window_number_in_actors(self);
717 			}
718 		}
719 	}
720 		else
721 		{
722 			/* Recreate all window actors because parent stage interface changed */
723 			_xfdashboard_windows_view_recreate_window_actors(self);
724 		}
725 }
726 
727 /* A window has changed monitor */
_xfdashboard_windows_view_on_window_monitor_changed(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow,XfdashboardWindowTrackerMonitor * inOldMonitor,XfdashboardWindowTrackerMonitor * inNewMonitor,gpointer inUserData)728 static void _xfdashboard_windows_view_on_window_monitor_changed(XfdashboardWindowsView *self,
729 																XfdashboardWindowTrackerWindow *inWindow,
730 																XfdashboardWindowTrackerMonitor *inOldMonitor,
731 																XfdashboardWindowTrackerMonitor *inNewMonitor,
732 																gpointer inUserData)
733 {
734 	XfdashboardWindowsViewPrivate		*priv;
735 	XfdashboardLiveWindow				*liveWindow;
736 
737 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
738 	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow));
739 	g_return_if_fail(inOldMonitor==NULL || XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(inOldMonitor));
740 	g_return_if_fail(inNewMonitor==NULL || XFDASHBOARD_IS_WINDOW_TRACKER_MONITOR(inNewMonitor));
741 
742 	priv=self->priv;
743 
744 	/* Check if parent stage interface changed. If not check if window has
745 	 * moved away from this view and destroy it or it has moved to this view
746 	 * and create it. Otherwise recreate all window actors for changed stage
747 	 * interface and monitor.
748 	 */
749 	if(!_xfdashboard_windows_view_update_stage_and_monitor(self) &&
750 		G_LIKELY(!inOldMonitor) &&
751 		G_LIKELY(!inNewMonitor))
752 	{
753 		/* Check if window moved away from this view */
754 		if(priv->currentMonitor==inOldMonitor &&
755 			!_xfdashboard_windows_view_is_visible_window(self, inWindow))
756 		{
757 			/* Find live window for window to destroy it */
758 			liveWindow=_xfdashboard_windows_view_find_by_window(self, inWindow);
759 			if(G_LIKELY(liveWindow))
760 			{
761 				/* Destroy actor */
762 				xfdashboard_actor_destroy(CLUTTER_ACTOR(liveWindow));
763 			}
764 		}
765 
766 		/* Check if window moved to this view */
767 		if(priv->currentMonitor==inNewMonitor &&
768 			_xfdashboard_windows_view_is_visible_window(self, inWindow))
769 		{
770 			/* Create actor if it does not exist already */
771 			liveWindow=_xfdashboard_windows_view_find_by_window(self, inWindow);
772 			if(G_LIKELY(!liveWindow))
773 			{
774 				liveWindow=_xfdashboard_windows_view_create_actor(self, inWindow);
775 				if(liveWindow)
776 				{
777 					clutter_actor_insert_child_below(CLUTTER_ACTOR(self), CLUTTER_ACTOR(liveWindow), NULL);
778 					_xfdashboard_windows_view_update_window_number_in_actors(self);
779 				}
780 			}
781 		}
782 	}
783 		else
784 		{
785 			/* Recreate all window actors because parent stage interface changed */
786 			_xfdashboard_windows_view_recreate_window_actors(self);
787 		}
788 }
789 
790 /* A live window was clicked */
_xfdashboard_windows_view_on_window_clicked(XfdashboardWindowsView * self,gpointer inUserData)791 static void _xfdashboard_windows_view_on_window_clicked(XfdashboardWindowsView *self,
792 														gpointer inUserData)
793 {
794 	XfdashboardWindowsViewPrivate		*priv;
795 	XfdashboardLiveWindowSimple			*liveWindow;
796 	XfdashboardWindowTrackerWindow		*window;
797 	XfdashboardWindowTrackerWorkspace	*activeWorkspace;
798 	XfdashboardWindowTrackerWorkspace	*windowWorkspace;
799 
800 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
801 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(inUserData));
802 
803 	priv=self->priv;
804 	liveWindow=XFDASHBOARD_LIVE_WINDOW_SIMPLE(inUserData);
805 
806 	/* Get window to activate */
807 	window=xfdashboard_live_window_simple_get_window(liveWindow);
808 
809 	/* Move to workspace if window to active is on a different one than the active one */
810 	activeWorkspace=xfdashboard_window_tracker_get_active_workspace(priv->windowTracker);
811 	if(!xfdashboard_window_tracker_window_is_on_workspace(window, activeWorkspace))
812 	{
813 		windowWorkspace=xfdashboard_window_tracker_window_get_workspace(window);
814 		xfdashboard_window_tracker_workspace_activate(windowWorkspace);
815 	}
816 
817 	/* Activate window */
818 	xfdashboard_window_tracker_window_activate(window);
819 
820 	/* Quit application */
821 	xfdashboard_application_suspend_or_quit(NULL);
822 }
823 
824 /* The close button of a live window was clicked */
_xfdashboard_windows_view_on_window_close_clicked(XfdashboardWindowsView * self,gpointer inUserData)825 static void _xfdashboard_windows_view_on_window_close_clicked(XfdashboardWindowsView *self,
826 																gpointer inUserData)
827 {
828 	XfdashboardLiveWindowSimple			*liveWindow;
829 	XfdashboardWindowTrackerWindow		*window;
830 
831 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
832 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(inUserData));
833 
834 	liveWindow=XFDASHBOARD_LIVE_WINDOW_SIMPLE(inUserData);
835 
836 	/* Close clicked window */
837 	window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(xfdashboard_live_window_simple_get_window(liveWindow));
838 	xfdashboard_window_tracker_window_close(window);
839 }
840 
841 /* A window was moved or resized */
_xfdashboard_windows_view_on_window_geometry_changed(XfdashboardWindowsView * self,gpointer inUserData)842 static void _xfdashboard_windows_view_on_window_geometry_changed(XfdashboardWindowsView *self,
843 																	gpointer inUserData)
844 {
845 	XfdashboardLiveWindow				*liveWindow;
846 
847 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
848 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(inUserData));
849 
850 	liveWindow=XFDASHBOARD_LIVE_WINDOW(inUserData);
851 
852 	/* Force a relayout to reflect new size of window */
853 	clutter_actor_queue_relayout(CLUTTER_ACTOR(liveWindow));
854 }
855 
856 /* A window was hidden or shown */
_xfdashboard_windows_view_on_window_visibility_changed(XfdashboardWindowsView * self,gboolean inIsVisible,gpointer inUserData)857 static void _xfdashboard_windows_view_on_window_visibility_changed(XfdashboardWindowsView *self,
858 																	gboolean inIsVisible,
859 																	gpointer inUserData)
860 {
861 	XfdashboardLiveWindow				*liveWindow;
862 
863 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
864 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(inUserData));
865 
866 	liveWindow=XFDASHBOARD_LIVE_WINDOW(inUserData);
867 
868 	/* If window is shown, show it in window list - otherwise hide it.
869 	 * We should not destroy the live window actor as the window might
870 	 * get visible again.
871 	 */
872 	if(inIsVisible) clutter_actor_show(CLUTTER_ACTOR(liveWindow));
873 		else
874 		{
875 			/* Hide actor */
876 			clutter_actor_hide(CLUTTER_ACTOR(liveWindow));
877 		}
878 }
879 
880 /* A window changed workspace or was pinned to all workspaces */
_xfdashboard_windows_view_on_window_workspace_changed(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow,XfdashboardWindowTrackerWorkspace * inWorkspace,gpointer inUserData)881 static void _xfdashboard_windows_view_on_window_workspace_changed(XfdashboardWindowsView *self,
882 																	XfdashboardWindowTrackerWindow *inWindow,
883 																	XfdashboardWindowTrackerWorkspace *inWorkspace,
884 																	gpointer inUserData)
885 {
886 	XfdashboardWindowsViewPrivate		*priv;
887 	XfdashboardLiveWindow				*liveWindow;
888 
889 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
890 	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow));
891 	g_return_if_fail(!inWorkspace || XFDASHBOARD_IS_WINDOW_TRACKER_WORKSPACE(inWorkspace));
892 
893 	priv=self->priv;
894 
895 	/* Check if parent stage interface changed. If not check if window has
896 	 * moved away from this view and destroy it or it has moved to this view
897 	 * and create it. Otherwise recreate all window actors for changed stage
898 	 * interface and monitor.
899 	 */
900 	if(!_xfdashboard_windows_view_update_stage_and_monitor(self))
901 	{
902 		/* Check if window moved away from this view*/
903 		if(priv->workspace!=inWorkspace &&
904 			!_xfdashboard_windows_view_is_visible_window(self, inWindow))
905 		{
906 			/* Find live window for window to destroy it */
907 			liveWindow=_xfdashboard_windows_view_find_by_window(self, inWindow);
908 			if(G_LIKELY(liveWindow))
909 			{
910 				/* Destroy actor */
911 				xfdashboard_actor_destroy(CLUTTER_ACTOR(liveWindow));
912 			}
913 		}
914 
915 		/* Check if window moved to this view */
916 		if(priv->workspace==inWorkspace &&
917 			_xfdashboard_windows_view_is_visible_window(self, inWindow))
918 		{
919 			/* Create actor if it does not exist already */
920 			liveWindow=_xfdashboard_windows_view_find_by_window(self, inWindow);
921 			if(G_LIKELY(!liveWindow))
922 			{
923 				liveWindow=_xfdashboard_windows_view_create_actor(self, inWindow);
924 				if(liveWindow)
925 				{
926 					clutter_actor_insert_child_below(CLUTTER_ACTOR(self), CLUTTER_ACTOR(liveWindow), NULL);
927 					_xfdashboard_windows_view_update_window_number_in_actors(self);
928 				}
929 			}
930 		}
931 	}
932 		else
933 		{
934 			/* Recreate all window actors because parent stage interface changed */
935 			_xfdashboard_windows_view_recreate_window_actors(self);
936 		}
937 }
938 
939 /* Drag of a live window begins */
_xfdashboard_windows_view_on_drag_begin(ClutterDragAction * inAction,ClutterActor * inActor,gfloat inStageX,gfloat inStageY,ClutterModifierType inModifiers,gpointer inUserData)940 static void _xfdashboard_windows_view_on_drag_begin(ClutterDragAction *inAction,
941 													ClutterActor *inActor,
942 													gfloat inStageX,
943 													gfloat inStageY,
944 													ClutterModifierType inModifiers,
945 													gpointer inUserData)
946 {
947 	ClutterActor					*dragHandle;
948 	ClutterStage					*stage;
949 	GdkPixbuf						*windowIcon;
950 	ClutterContent					*image;
951 	XfdashboardLiveWindowSimple		*liveWindow;
952 
953 	g_return_if_fail(CLUTTER_IS_DRAG_ACTION(inAction));
954 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(inActor));
955 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inUserData));
956 
957 	liveWindow=XFDASHBOARD_LIVE_WINDOW_SIMPLE(inActor);
958 
959 	/* Prevent signal "clicked" from being emitted on dragged icon */
960 	g_signal_handlers_block_by_func(inActor, _xfdashboard_windows_view_on_window_clicked, inUserData);
961 
962 	/* Get stage */
963 	stage=CLUTTER_STAGE(clutter_actor_get_stage(inActor));
964 
965 	/* Create a application icon for drag handle */
966 	windowIcon=xfdashboard_window_tracker_window_get_icon(xfdashboard_live_window_simple_get_window(liveWindow));
967 	image=xfdashboard_image_content_new_for_pixbuf(windowIcon);
968 
969 	dragHandle=xfdashboard_background_new();
970 	clutter_actor_set_position(dragHandle, inStageX, inStageY);
971 	clutter_actor_set_size(dragHandle, DEFAULT_DRAG_HANDLE_SIZE, DEFAULT_DRAG_HANDLE_SIZE);
972 	xfdashboard_background_set_image(XFDASHBOARD_BACKGROUND(dragHandle), CLUTTER_IMAGE(image));
973 	clutter_actor_add_child(CLUTTER_ACTOR(stage), dragHandle);
974 
975 	clutter_drag_action_set_drag_handle(inAction, dragHandle);
976 
977 	g_object_unref(image);
978 }
979 
980 /* Drag of a live window ends */
_xfdashboard_windows_view_on_drag_end(ClutterDragAction * inAction,ClutterActor * inActor,gfloat inStageX,gfloat inStageY,ClutterModifierType inModifiers,gpointer inUserData)981 static void _xfdashboard_windows_view_on_drag_end(ClutterDragAction *inAction,
982 													ClutterActor *inActor,
983 													gfloat inStageX,
984 													gfloat inStageY,
985 													ClutterModifierType inModifiers,
986 													gpointer inUserData)
987 {
988 	ClutterActor					*dragHandle;
989 
990 	g_return_if_fail(CLUTTER_IS_DRAG_ACTION(inAction));
991 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(inActor));
992 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inUserData));
993 
994 	/* Destroy clone of application icon used as drag handle */
995 	dragHandle=clutter_drag_action_get_drag_handle(inAction);
996 	if(dragHandle)
997 	{
998 #if CLUTTER_CHECK_VERSION(1, 14, 0)
999 		/* Only unset drag handle if not running Clutter in version
1000 		 * 1.12. This prevents a critical warning message in 1.12.
1001 		 * Later versions of Clutter are fixed already.
1002 		 */
1003 		clutter_drag_action_set_drag_handle(inAction, NULL);
1004 #endif
1005 		xfdashboard_actor_destroy(dragHandle);
1006 	}
1007 
1008 	/* Allow signal "clicked" from being emitted again */
1009 	g_signal_handlers_unblock_by_func(inActor, _xfdashboard_windows_view_on_window_clicked, inUserData);
1010 }
1011 
1012 /* Create actor for wnck-window and connect signals */
_xfdashboard_windows_view_create_actor(XfdashboardWindowsView * self,XfdashboardWindowTrackerWindow * inWindow)1013 static XfdashboardLiveWindow* _xfdashboard_windows_view_create_actor(XfdashboardWindowsView *self,
1014 																		XfdashboardWindowTrackerWindow *inWindow)
1015 {
1016 	ClutterActor	*actor;
1017 	ClutterAction	*dragAction;
1018 
1019 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), NULL);
1020 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL);
1021 
1022 	/* Check if window opened is a stage window */
1023 	if(xfdashboard_window_tracker_window_is_stage(inWindow))
1024 	{
1025 		XFDASHBOARD_DEBUG(self, ACTOR, "Will not create live-window actor for stage window.");
1026 		return(NULL);
1027 	}
1028 
1029 	/* Create actor and connect signals */
1030 	actor=xfdashboard_live_window_new();
1031 	g_signal_connect_swapped(actor, "clicked", G_CALLBACK(_xfdashboard_windows_view_on_window_clicked), self);
1032 	g_signal_connect_swapped(actor, "close", G_CALLBACK(_xfdashboard_windows_view_on_window_close_clicked), self);
1033 	g_signal_connect_swapped(actor, "geometry-changed", G_CALLBACK(_xfdashboard_windows_view_on_window_geometry_changed), self);
1034 	g_signal_connect_swapped(actor, "visibility-changed", G_CALLBACK(_xfdashboard_windows_view_on_window_visibility_changed), self);
1035 	xfdashboard_live_window_simple_set_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(actor), inWindow);
1036 
1037 	dragAction=xfdashboard_drag_action_new_with_source(CLUTTER_ACTOR(self));
1038 	clutter_drag_action_set_drag_threshold(CLUTTER_DRAG_ACTION(dragAction), -1, -1);
1039 	clutter_actor_add_action(actor, dragAction);
1040 	g_signal_connect(dragAction, "drag-begin", G_CALLBACK(_xfdashboard_windows_view_on_drag_begin), self);
1041 	g_signal_connect(dragAction, "drag-end", G_CALLBACK(_xfdashboard_windows_view_on_drag_end), self);
1042 
1043 	return(XFDASHBOARD_LIVE_WINDOW(actor));
1044 }
1045 
1046 /* Set active screen */
_xfdashboard_windows_view_set_active_workspace(XfdashboardWindowsView * self,XfdashboardWindowTrackerWorkspace * inWorkspace)1047 static void _xfdashboard_windows_view_set_active_workspace(XfdashboardWindowsView *self,
1048 															XfdashboardWindowTrackerWorkspace *inWorkspace)
1049 {
1050 	XfdashboardWindowsViewPrivate			*priv;
1051 
1052 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
1053 	g_return_if_fail(inWorkspace==NULL || XFDASHBOARD_IS_WINDOW_TRACKER_WORKSPACE(inWorkspace));
1054 
1055 	priv=XFDASHBOARD_WINDOWS_VIEW(self)->priv;
1056 
1057 	/* Check if parent stage interface or workspace changed. If both have not
1058 	 * changed do nothing and return immediately.
1059 	 */
1060 	if(!_xfdashboard_windows_view_update_stage_and_monitor(self) &&
1061 		inWorkspace==priv->workspace)
1062 	{
1063 		return;
1064 	}
1065 
1066 	/* Freeze notification */
1067 	g_object_freeze_notify(G_OBJECT(self));
1068 
1069 	/* Set new workspace if changed */
1070 	if(priv->workspace!=inWorkspace)
1071 	{
1072 		/* Set new workspace */
1073 		priv->workspace=inWorkspace;
1074 
1075 		/* Notify about property change */
1076 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_WORKSPACE]);
1077 	}
1078 
1079 	/* Recreate all window actors */
1080 	_xfdashboard_windows_view_recreate_window_actors(self);
1081 
1082 	/* Thaw notification */
1083 	g_object_thaw_notify(G_OBJECT(self));
1084 }
1085 
1086 /* A scroll event occured in workspace selector (e.g. by mouse-wheel) */
_xfdashboard_windows_view_on_scroll_event(ClutterActor * inActor,ClutterEvent * inEvent,gpointer inUserData)1087 static gboolean _xfdashboard_windows_view_on_scroll_event(ClutterActor *inActor,
1088 															ClutterEvent *inEvent,
1089 															gpointer inUserData)
1090 {
1091 	XfdashboardWindowsView					*self;
1092 	XfdashboardWindowsViewPrivate			*priv;
1093 	gint									direction;
1094 	gint									workspace;
1095 	gint									maxWorkspace;
1096 	XfdashboardWindowTrackerWorkspace		*activeWorkspace;
1097 	XfdashboardWindowTrackerWorkspace		*newWorkspace;
1098 
1099 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inActor), CLUTTER_EVENT_PROPAGATE);
1100 	g_return_val_if_fail(inEvent, CLUTTER_EVENT_PROPAGATE);
1101 
1102 	self=XFDASHBOARD_WINDOWS_VIEW(inActor);
1103 	priv=self->priv;
1104 
1105 	/* Do not handle event if scroll event of mouse-wheel should not
1106 	 * change workspace. In this case propagate event to get it handled
1107 	 * by next actor in chain.
1108 	 */
1109 	if(!priv->isScrollEventChangingWorkspace) return(CLUTTER_EVENT_PROPAGATE);
1110 
1111 	/* Get direction of scroll event */
1112 	switch(clutter_event_get_scroll_direction(inEvent))
1113 	{
1114 		case CLUTTER_SCROLL_UP:
1115 		case CLUTTER_SCROLL_LEFT:
1116 			direction=-1;
1117 			break;
1118 
1119 		case CLUTTER_SCROLL_DOWN:
1120 		case CLUTTER_SCROLL_RIGHT:
1121 			direction=1;
1122 			break;
1123 
1124 		/* Unhandled directions */
1125 		default:
1126 			XFDASHBOARD_DEBUG(self, ACTOR,
1127 								"Cannot handle scroll direction %d in %s",
1128 								clutter_event_get_scroll_direction(inEvent),
1129 								G_OBJECT_TYPE_NAME(self));
1130 			return(CLUTTER_EVENT_PROPAGATE);
1131 	}
1132 
1133 	/* Get next workspace in scroll direction */
1134 	activeWorkspace=xfdashboard_window_tracker_get_active_workspace(priv->windowTracker);
1135 	maxWorkspace=xfdashboard_window_tracker_get_workspaces_count(priv->windowTracker);
1136 
1137 	workspace=xfdashboard_window_tracker_workspace_get_number(activeWorkspace)+direction;
1138 	if(workspace<0 || workspace>=maxWorkspace) return(CLUTTER_EVENT_STOP);
1139 
1140 	/* Activate new workspace */
1141 	newWorkspace=xfdashboard_window_tracker_get_workspace_by_number(priv->windowTracker, workspace);
1142 	xfdashboard_window_tracker_workspace_activate(newWorkspace);
1143 
1144 	return(CLUTTER_EVENT_STOP);
1145 }
1146 
1147 /* Set flag if scroll events (e.g. mouse-wheel up or down) should change active workspace
1148  * and set up scroll event listener or remove an existing one.
1149  */
_xfdashboard_windows_view_set_scroll_event_changes_workspace(XfdashboardWindowsView * self,gboolean inMouseWheelChangingWorkspace)1150 static void _xfdashboard_windows_view_set_scroll_event_changes_workspace(XfdashboardWindowsView *self, gboolean inMouseWheelChangingWorkspace)
1151 {
1152 	XfdashboardWindowsViewPrivate		*priv;
1153 
1154 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
1155 
1156 	priv=self->priv;
1157 
1158 	/* Set value if changed */
1159 	if(priv->isScrollEventChangingWorkspace!=inMouseWheelChangingWorkspace)
1160 	{
1161 		/* Set value */
1162 		priv->isScrollEventChangingWorkspace=inMouseWheelChangingWorkspace;
1163 
1164 		/* Notify about property change */
1165 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_SCROLL_EVENT_CHANGES_WORKSPACE]);
1166 	}
1167 }
1168 
1169 /* Set flag if this view should show all windows of all monitors or only the windows
1170  * which are at the monitor where this view is placed at.
1171  */
_xfdashboard_windows_view_set_filter_monitor_windows(XfdashboardWindowsView * self,gboolean inFilterMonitorWindows)1172 static void _xfdashboard_windows_view_set_filter_monitor_windows(XfdashboardWindowsView *self, gboolean inFilterMonitorWindows)
1173 {
1174 	XfdashboardWindowsViewPrivate		*priv;
1175 
1176 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
1177 
1178 	priv=self->priv;
1179 
1180 	/* Set value if changed */
1181 	if(priv->filterMonitorWindows!=inFilterMonitorWindows)
1182 	{
1183 		/* Set value */
1184 		priv->filterMonitorWindows=inFilterMonitorWindows;
1185 
1186 		/* Recreate all window actors */
1187 		_xfdashboard_windows_view_recreate_window_actors(self);
1188 
1189 		/* Notify about property change */
1190 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_FILTER_MONITOR_WINDOWS]);
1191 	}
1192 }
1193 
1194 /* Set flag if this view should show all windows of all workspaces or only the windows
1195  * which are at current workspace.
1196  */
_xfdashboard_windows_view_set_filter_workspace_windows(XfdashboardWindowsView * self,gboolean inFilterWorkspaceWindows)1197 static void _xfdashboard_windows_view_set_filter_workspace_windows(XfdashboardWindowsView *self, gboolean inFilterWorkspaceWindows)
1198 {
1199 	XfdashboardWindowsViewPrivate		*priv;
1200 
1201 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
1202 
1203 	priv=self->priv;
1204 
1205 	/* Set value if changed */
1206 	if(priv->filterWorkspaceWindows!=inFilterWorkspaceWindows)
1207 	{
1208 		/* Set value */
1209 		priv->filterWorkspaceWindows=inFilterWorkspaceWindows;
1210 
1211 		/* Recreate all window actors */
1212 		_xfdashboard_windows_view_recreate_window_actors(self);
1213 
1214 		/* Notify about property change */
1215 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_FILTER_WORKSPACE_WINDOWS]);
1216 	}
1217 }
1218 
1219 /* Action signal to close currently selected window was emitted */
_xfdashboard_windows_view_window_close(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1220 static gboolean _xfdashboard_windows_view_window_close(XfdashboardWindowsView *self,
1221 														XfdashboardFocusable *inSource,
1222 														const gchar *inAction,
1223 														ClutterEvent *inEvent)
1224 {
1225 	XfdashboardWindowsViewPrivate			*priv;
1226 
1227 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), CLUTTER_EVENT_PROPAGATE);
1228 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inSource), CLUTTER_EVENT_PROPAGATE);
1229 
1230 	priv=self->priv;
1231 
1232 	/* Check if a window is currenly selected */
1233 	if(!priv->selectedItem)
1234 	{
1235 		XFDASHBOARD_DEBUG(self, ACTOR, "No window to close is selected.");
1236 		return(CLUTTER_EVENT_STOP);
1237 	}
1238 
1239 	/* Close selected window */
1240 	_xfdashboard_windows_view_on_window_close_clicked(self, XFDASHBOARD_LIVE_WINDOW(priv->selectedItem));
1241 
1242 	/* We handled this event */
1243 	return(CLUTTER_EVENT_STOP);
1244 }
1245 
1246 /* Action signal to show window numbers was emitted */
_xfdashboard_windows_view_windows_show_numbers(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1247 static gboolean _xfdashboard_windows_view_windows_show_numbers(XfdashboardWindowsView *self,
1248 																XfdashboardFocusable *inSource,
1249 																const gchar *inAction,
1250 																ClutterEvent *inEvent)
1251 {
1252 	XfdashboardWindowsViewPrivate			*priv;
1253 
1254 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), CLUTTER_EVENT_PROPAGATE);
1255 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inSource), CLUTTER_EVENT_PROPAGATE);
1256 
1257 	priv=self->priv;
1258 
1259 	/* If window numbers are already shown do nothing */
1260 	if(priv->isWindowsNumberShown) return(CLUTTER_EVENT_PROPAGATE);
1261 
1262 	/* Set flag that window numbers are shown already
1263 	 * to prevent do it twice concurrently.
1264 	 */
1265 	priv->isWindowsNumberShown=TRUE;
1266 
1267 	/* Show window numbers */
1268 	_xfdashboard_windows_view_update_window_number_in_actors(self);
1269 
1270 	/* Action handled but do not prevent further processing */
1271 	return(CLUTTER_EVENT_PROPAGATE);
1272 }
1273 
1274 /* Action signal to hide window numbers was emitted */
_xfdashboard_windows_view_windows_hide_numbers(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1275 static gboolean _xfdashboard_windows_view_windows_hide_numbers(XfdashboardWindowsView *self,
1276 																XfdashboardFocusable *inSource,
1277 																const gchar *inAction,
1278 																ClutterEvent *inEvent)
1279 {
1280 	XfdashboardWindowsViewPrivate			*priv;
1281 
1282 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), CLUTTER_EVENT_PROPAGATE);
1283 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inSource), CLUTTER_EVENT_PROPAGATE);
1284 
1285 	priv=self->priv;
1286 
1287 	/* If no window numbers are shown do nothing */
1288 	if(!priv->isWindowsNumberShown) return(CLUTTER_EVENT_PROPAGATE);
1289 
1290 	/* Set flag that window numbers are hidden already
1291 	 * to prevent do it twice concurrently.
1292 	 */
1293 	priv->isWindowsNumberShown=FALSE;
1294 
1295 	/* Hide window numbers */
1296 	_xfdashboard_windows_view_update_window_number_in_actors(self);
1297 
1298 	/* Action handled but do not prevent further processing */
1299 	return(CLUTTER_EVENT_PROPAGATE);
1300 }
1301 
1302 /* Action signal to hide window numbers was emitted */
_xfdashboard_windows_view_windows_activate_window_by_number(XfdashboardWindowsView * self,guint inWindowNumber)1303 static gboolean _xfdashboard_windows_view_windows_activate_window_by_number(XfdashboardWindowsView *self,
1304 																				guint inWindowNumber)
1305 {
1306 	ClutterActor						*child;
1307 	ClutterActorIter					iter;
1308 
1309 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), CLUTTER_EVENT_PROPAGATE);
1310 
1311 	/* Iterate through list of current actors and at each live window actor
1312 	 * check if its window number matches the requested one. If it does
1313 	 * activate this window.
1314 	 */
1315 	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
1316 	while(clutter_actor_iter_next(&iter, &child))
1317 	{
1318 		guint							windowNumber;
1319 
1320 		/* Only live window actors can be handled */
1321 		if(!XFDASHBOARD_IS_LIVE_WINDOW(child)) continue;
1322 
1323 		/* Get window number set at live window actor */
1324 		windowNumber=0;
1325 		g_object_get(child, "window-number", &windowNumber, NULL);
1326 
1327 		/* If window number at live window actor matches requested one
1328 		 * activate this window.
1329 		 */
1330 		if(windowNumber==inWindowNumber)
1331 		{
1332 			/* Activate window */
1333 			_xfdashboard_windows_view_on_window_clicked(self, XFDASHBOARD_LIVE_WINDOW(child));
1334 
1335 			/* Action was handled */
1336 			return(CLUTTER_EVENT_STOP);
1337 		}
1338 	}
1339 
1340 	/* If we get here the requested window was not found
1341 	 * so this action could not be handled by this actor.
1342 	 */
1343 	return(CLUTTER_EVENT_PROPAGATE);
1344 }
1345 
_xfdashboard_windows_view_windows_activate_window_one(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1346 static gboolean _xfdashboard_windows_view_windows_activate_window_one(XfdashboardWindowsView *self,
1347 																		XfdashboardFocusable *inSource,
1348 																		const gchar *inAction,
1349 																		ClutterEvent *inEvent)
1350 {
1351 	return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 1));
1352 }
1353 
_xfdashboard_windows_view_windows_activate_window_two(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1354 static gboolean _xfdashboard_windows_view_windows_activate_window_two(XfdashboardWindowsView *self,
1355 																		XfdashboardFocusable *inSource,
1356 																		const gchar *inAction,
1357 																		ClutterEvent *inEvent)
1358 {
1359 	return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 2));
1360 }
1361 
_xfdashboard_windows_view_windows_activate_window_three(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1362 static gboolean _xfdashboard_windows_view_windows_activate_window_three(XfdashboardWindowsView *self,
1363 																		XfdashboardFocusable *inSource,
1364 																		const gchar *inAction,
1365 																		ClutterEvent *inEvent)
1366 {
1367 	return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 3));
1368 }
1369 
_xfdashboard_windows_view_windows_activate_window_four(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1370 static gboolean _xfdashboard_windows_view_windows_activate_window_four(XfdashboardWindowsView *self,
1371 																		XfdashboardFocusable *inSource,
1372 																		const gchar *inAction,
1373 																		ClutterEvent *inEvent)
1374 {
1375 	return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 4));
1376 }
1377 
_xfdashboard_windows_view_windows_activate_window_five(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1378 static gboolean _xfdashboard_windows_view_windows_activate_window_five(XfdashboardWindowsView *self,
1379 																		XfdashboardFocusable *inSource,
1380 																		const gchar *inAction,
1381 																		ClutterEvent *inEvent)
1382 {
1383 	return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 5));
1384 }
1385 
_xfdashboard_windows_view_windows_activate_window_six(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1386 static gboolean _xfdashboard_windows_view_windows_activate_window_six(XfdashboardWindowsView *self,
1387 																		XfdashboardFocusable *inSource,
1388 																		const gchar *inAction,
1389 																		ClutterEvent *inEvent)
1390 {
1391 	return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 6));
1392 }
1393 
_xfdashboard_windows_view_windows_activate_window_seven(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1394 static gboolean _xfdashboard_windows_view_windows_activate_window_seven(XfdashboardWindowsView *self,
1395 																		XfdashboardFocusable *inSource,
1396 																		const gchar *inAction,
1397 																		ClutterEvent *inEvent)
1398 {
1399 	return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 7));
1400 }
1401 
_xfdashboard_windows_view_windows_activate_window_eight(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1402 static gboolean _xfdashboard_windows_view_windows_activate_window_eight(XfdashboardWindowsView *self,
1403 																		XfdashboardFocusable *inSource,
1404 																		const gchar *inAction,
1405 																		ClutterEvent *inEvent)
1406 {
1407 	return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 8));
1408 }
1409 
_xfdashboard_windows_view_windows_activate_window_nine(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1410 static gboolean _xfdashboard_windows_view_windows_activate_window_nine(XfdashboardWindowsView *self,
1411 																		XfdashboardFocusable *inSource,
1412 																		const gchar *inAction,
1413 																		ClutterEvent *inEvent)
1414 {
1415 	return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 9));
1416 }
1417 
_xfdashboard_windows_view_windows_activate_window_ten(XfdashboardWindowsView * self,XfdashboardFocusable * inSource,const gchar * inAction,ClutterEvent * inEvent)1418 static gboolean _xfdashboard_windows_view_windows_activate_window_ten(XfdashboardWindowsView *self,
1419 																		XfdashboardFocusable *inSource,
1420 																		const gchar *inAction,
1421 																		ClutterEvent *inEvent)
1422 {
1423 	return(_xfdashboard_windows_view_windows_activate_window_by_number(self, 10));
1424 }
1425 
1426 /* IMPLEMENTATION: Interface XfdashboardFocusable */
1427 
1428 /* Determine if actor can get the focus */
_xfdashboard_windows_view_focusable_can_focus(XfdashboardFocusable * inFocusable)1429 static gboolean _xfdashboard_windows_view_focusable_can_focus(XfdashboardFocusable *inFocusable)
1430 {
1431 	XfdashboardWindowsView			*self;
1432 	XfdashboardFocusableInterface	*selfIface;
1433 	XfdashboardFocusableInterface	*parentIface;
1434 
1435 	g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE);
1436 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), FALSE);
1437 
1438 	self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1439 
1440 	/* Call parent class interface function */
1441 	selfIface=XFDASHBOARD_FOCUSABLE_GET_IFACE(inFocusable);
1442 	parentIface=g_type_interface_peek_parent(selfIface);
1443 
1444 	if(parentIface && parentIface->can_focus)
1445 	{
1446 		if(!parentIface->can_focus(inFocusable)) return(FALSE);
1447 	}
1448 
1449 	/* If this view is not enabled it is not focusable */
1450 	if(!xfdashboard_view_get_enabled(XFDASHBOARD_VIEW(self))) return(FALSE);
1451 
1452 	/* If we get here this actor can be focused */
1453 	return(TRUE);
1454 }
1455 
1456 /* Actor lost focus */
_xfdashboard_windows_view_focusable_unset_focus(XfdashboardFocusable * inFocusable)1457 static void _xfdashboard_windows_view_focusable_unset_focus(XfdashboardFocusable *inFocusable)
1458 {
1459 	XfdashboardWindowsView			*self;
1460 	XfdashboardFocusableInterface	*selfIface;
1461 	XfdashboardFocusableInterface	*parentIface;
1462 
1463 	g_return_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable));
1464 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable));
1465 
1466 	self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1467 
1468 	/* Call parent class interface function */
1469 	selfIface=XFDASHBOARD_FOCUSABLE_GET_IFACE(inFocusable);
1470 	parentIface=g_type_interface_peek_parent(selfIface);
1471 
1472 	if(parentIface && parentIface->unset_focus)
1473 	{
1474 		parentIface->unset_focus(inFocusable);
1475 	}
1476 
1477 	/* Actor lost focus so ensure window numbers are hiding again */
1478 	_xfdashboard_windows_view_windows_hide_numbers(self, XFDASHBOARD_FOCUSABLE(self), NULL, NULL);
1479 }
1480 
1481 /* Determine if this actor supports selection */
_xfdashboard_windows_view_focusable_supports_selection(XfdashboardFocusable * inFocusable)1482 static gboolean _xfdashboard_windows_view_focusable_supports_selection(XfdashboardFocusable *inFocusable)
1483 {
1484 	g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE);
1485 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), FALSE);
1486 
1487 	/* This actor supports selection */
1488 	return(TRUE);
1489 }
1490 
1491 /* Get current selection */
_xfdashboard_windows_view_focusable_get_selection(XfdashboardFocusable * inFocusable)1492 static ClutterActor* _xfdashboard_windows_view_focusable_get_selection(XfdashboardFocusable *inFocusable)
1493 {
1494 	XfdashboardWindowsView					*self;
1495 	XfdashboardWindowsViewPrivate			*priv;
1496 
1497 	g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), NULL);
1498 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), NULL);
1499 
1500 	self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1501 	priv=self->priv;
1502 
1503 	/* Return current selection */
1504 	return(priv->selectedItem);
1505 }
1506 
1507 /* Set new selection */
_xfdashboard_windows_view_focusable_set_selection(XfdashboardFocusable * inFocusable,ClutterActor * inSelection)1508 static gboolean _xfdashboard_windows_view_focusable_set_selection(XfdashboardFocusable *inFocusable,
1509 																	ClutterActor *inSelection)
1510 {
1511 	XfdashboardWindowsView					*self;
1512 	XfdashboardWindowsViewPrivate			*priv;
1513 
1514 	g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE);
1515 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), FALSE);
1516 	g_return_val_if_fail(!inSelection || CLUTTER_IS_ACTOR(inSelection), FALSE);
1517 
1518 	self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1519 	priv=self->priv;
1520 
1521 	/* Check that selection is a child of this actor */
1522 	if(inSelection &&
1523 		!clutter_actor_contains(CLUTTER_ACTOR(self), inSelection))
1524 	{
1525 		g_warning("%s is not a child of %s and cannot be selected",
1526 					G_OBJECT_TYPE_NAME(inSelection),
1527 					G_OBJECT_TYPE_NAME(self));
1528 
1529 		return(FALSE);
1530 	}
1531 
1532 	/* Remove weak reference at current selection */
1533 	if(priv->selectedItem)
1534 	{
1535 		g_object_remove_weak_pointer(G_OBJECT(priv->selectedItem), &priv->selectedItem);
1536 	}
1537 
1538 	/* Set new selection */
1539 	priv->selectedItem=inSelection;
1540 
1541 	/* Add weak reference at new selection */
1542 	if(priv->selectedItem) g_object_add_weak_pointer(G_OBJECT(priv->selectedItem), &priv->selectedItem);
1543 
1544 	/* New selection was set successfully */
1545 	return(TRUE);
1546 }
1547 
1548 /* Find requested selection target depending of current selection */
_xfdashboard_windows_view_focusable_find_selection(XfdashboardFocusable * inFocusable,ClutterActor * inSelection,XfdashboardSelectionTarget inDirection)1549 static ClutterActor* _xfdashboard_windows_view_focusable_find_selection(XfdashboardFocusable *inFocusable,
1550 																			ClutterActor *inSelection,
1551 																			XfdashboardSelectionTarget inDirection)
1552 {
1553 	XfdashboardWindowsView					*self;
1554 	XfdashboardWindowsViewPrivate			*priv;
1555 	ClutterActor							*selection;
1556 	ClutterActor							*newSelection;
1557 	gint									numberChildren;
1558 	gint									rows;
1559 	gint									columns;
1560 	gint									currentSelectionIndex;
1561 	gint									currentSelectionRow;
1562 	gint									currentSelectionColumn;
1563 	gint									newSelectionIndex;
1564 	ClutterActorIter						iter;
1565 	ClutterActor							*child;
1566 	gchar									*valueName;
1567 
1568 	g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), NULL);
1569 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), NULL);
1570 	g_return_val_if_fail(!inSelection || CLUTTER_IS_ACTOR(inSelection), NULL);
1571 	g_return_val_if_fail(inDirection>=0 && inDirection<=XFDASHBOARD_SELECTION_TARGET_NEXT, NULL);
1572 
1573 	self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1574 	priv=self->priv;
1575 	selection=inSelection;
1576 	newSelection=NULL;
1577 
1578 	/* If there is nothing selected, select first actor and return */
1579 	if(!inSelection)
1580 	{
1581 		newSelection=clutter_actor_get_first_child(CLUTTER_ACTOR(self));
1582 
1583 		valueName=xfdashboard_get_enum_value_name(XFDASHBOARD_TYPE_SELECTION_TARGET, inDirection);
1584 		XFDASHBOARD_DEBUG(self, ACTOR,
1585 							"No selection at %s, so select first child %s for direction %s",
1586 							G_OBJECT_TYPE_NAME(self),
1587 							newSelection ? G_OBJECT_TYPE_NAME(newSelection) : "<nil>",
1588 							valueName);
1589 		g_free(valueName);
1590 
1591 		return(newSelection);
1592 	}
1593 
1594 	/* Check that selection is a child of this actor otherwise return NULL */
1595 	if(!clutter_actor_contains(CLUTTER_ACTOR(self), inSelection))
1596 	{
1597 		ClutterActor						*parent;
1598 
1599 		parent=clutter_actor_get_parent(inSelection);
1600 		g_warning("Cannot lookup selection target at %s because %s is a child of %s",
1601 					G_OBJECT_TYPE_NAME(self),
1602 					G_OBJECT_TYPE_NAME(inSelection),
1603 					parent ? G_OBJECT_TYPE_NAME(parent) : "<nil>");
1604 
1605 		return(NULL);
1606 	}
1607 
1608 	/* Get number of rows and columns and also get number of children
1609 	 * of layout manager.
1610 	 */
1611 	numberChildren=xfdashboard_scaled_table_layout_get_number_children(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout));
1612 	rows=xfdashboard_scaled_table_layout_get_rows(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout));
1613 	columns=xfdashboard_scaled_table_layout_get_columns(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout));
1614 
1615 	/* Get index of current selection */
1616 	currentSelectionIndex=0;
1617 	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self));
1618 	while(clutter_actor_iter_next(&iter, &child) &&
1619 			child!=inSelection)
1620 	{
1621 		currentSelectionIndex++;
1622 	}
1623 
1624 	currentSelectionRow=(currentSelectionIndex / columns);
1625 	currentSelectionColumn=(currentSelectionIndex % columns);
1626 
1627 	/* Find target selection */
1628 	switch(inDirection)
1629 	{
1630 		case XFDASHBOARD_SELECTION_TARGET_LEFT:
1631 			currentSelectionColumn--;
1632 			if(currentSelectionColumn<0)
1633 			{
1634 				currentSelectionRow++;
1635 				newSelectionIndex=(currentSelectionRow*columns)-1;
1636 			}
1637 				else newSelectionIndex=currentSelectionIndex-1;
1638 
1639 			newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1640 			newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1641 			break;
1642 
1643 		case XFDASHBOARD_SELECTION_TARGET_RIGHT:
1644 			currentSelectionColumn++;
1645 			if(currentSelectionColumn==columns ||
1646 				currentSelectionIndex==numberChildren)
1647 			{
1648 				newSelectionIndex=(currentSelectionRow*columns);
1649 			}
1650 				else newSelectionIndex=currentSelectionIndex+1;
1651 
1652 			newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1653 			newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1654 			break;
1655 
1656 		case XFDASHBOARD_SELECTION_TARGET_UP:
1657 			currentSelectionRow--;
1658 			if(currentSelectionRow<0) currentSelectionRow=rows-1;
1659 			newSelectionIndex=(currentSelectionRow*columns)+currentSelectionColumn;
1660 
1661 			newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1662 			newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1663 			break;
1664 
1665 		case XFDASHBOARD_SELECTION_TARGET_DOWN:
1666 			currentSelectionRow++;
1667 			if(currentSelectionRow>=rows) currentSelectionRow=0;
1668 			newSelectionIndex=(currentSelectionRow*columns)+currentSelectionColumn;
1669 
1670 			newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1671 			newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1672 			break;
1673 
1674 		case XFDASHBOARD_SELECTION_TARGET_FIRST:
1675 			newSelection=clutter_actor_get_first_child(CLUTTER_ACTOR(self));
1676 			break;
1677 
1678 		case XFDASHBOARD_SELECTION_TARGET_LAST:
1679 			newSelection=clutter_actor_get_last_child(CLUTTER_ACTOR(self));
1680 			break;
1681 
1682 		case XFDASHBOARD_SELECTION_TARGET_NEXT:
1683 			newSelection=clutter_actor_get_next_sibling(inSelection);
1684 			if(!newSelection) newSelection=clutter_actor_get_previous_sibling(inSelection);
1685 			break;
1686 
1687 		case XFDASHBOARD_SELECTION_TARGET_PAGE_LEFT:
1688 			newSelectionIndex=(currentSelectionRow*columns);
1689 			newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1690 			newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1691 			break;
1692 
1693 		case XFDASHBOARD_SELECTION_TARGET_PAGE_RIGHT:
1694 			newSelectionIndex=((currentSelectionRow+1)*columns)-1;
1695 			newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1696 			newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1697 			break;
1698 
1699 		case XFDASHBOARD_SELECTION_TARGET_PAGE_UP:
1700 			newSelectionIndex=currentSelectionColumn;
1701 			newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1702 			newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1703 			break;
1704 
1705 		case XFDASHBOARD_SELECTION_TARGET_PAGE_DOWN:
1706 			newSelectionIndex=((rows-1)*columns)+currentSelectionColumn;
1707 			newSelectionIndex=MIN(newSelectionIndex, numberChildren-1);
1708 			newSelection=clutter_actor_get_child_at_index(CLUTTER_ACTOR(self), newSelectionIndex);
1709 			break;
1710 
1711 		default:
1712 			{
1713 				valueName=xfdashboard_get_enum_value_name(XFDASHBOARD_TYPE_SELECTION_TARGET, inDirection);
1714 				g_critical("Focusable object %s does not handle selection direction of type %s.",
1715 							G_OBJECT_TYPE_NAME(self),
1716 							valueName);
1717 				g_free(valueName);
1718 			}
1719 			break;
1720 	}
1721 
1722 	/* If new selection could be found override current selection with it */
1723 	if(newSelection) selection=newSelection;
1724 
1725 	/* Return new selection found */
1726 	XFDASHBOARD_DEBUG(self, ACTOR,
1727 						"Selecting %s at %s for current selection %s in direction %u",
1728 						selection ? G_OBJECT_TYPE_NAME(selection) : "<nil>",
1729 						G_OBJECT_TYPE_NAME(self),
1730 						inSelection ? G_OBJECT_TYPE_NAME(inSelection) : "<nil>",
1731 						inDirection);
1732 
1733 	return(selection);
1734 }
1735 
1736 /* Activate selection */
_xfdashboard_windows_view_focusable_activate_selection(XfdashboardFocusable * inFocusable,ClutterActor * inSelection)1737 static gboolean _xfdashboard_windows_view_focusable_activate_selection(XfdashboardFocusable *inFocusable,
1738 																		ClutterActor *inSelection)
1739 {
1740 	XfdashboardWindowsView					*self;
1741 
1742 	g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE);
1743 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inFocusable), FALSE);
1744 	g_return_val_if_fail(CLUTTER_IS_ACTOR(inSelection), FALSE);
1745 
1746 	self=XFDASHBOARD_WINDOWS_VIEW(inFocusable);
1747 
1748 	/* Check that selection is a child of this actor */
1749 	if(!clutter_actor_contains(CLUTTER_ACTOR(self), inSelection))
1750 	{
1751 		ClutterActor						*parent;
1752 
1753 		parent=clutter_actor_get_parent(inSelection);
1754 		g_warning("%s is a child of %s and cannot be activated at %s",
1755 					G_OBJECT_TYPE_NAME(inSelection),
1756 					parent ? G_OBJECT_TYPE_NAME(parent) : "<nil>",
1757 					G_OBJECT_TYPE_NAME(self));
1758 
1759 		return(FALSE);
1760 	}
1761 
1762 	/* Check that child is a live window */
1763 	if(!XFDASHBOARD_IS_LIVE_WINDOW(inSelection))
1764 	{
1765 		g_warning("Cannot activate selection of type %s at %s because expecting type %s",
1766 					G_OBJECT_TYPE_NAME(inSelection),
1767 					G_OBJECT_TYPE_NAME(self),
1768 					g_type_name(XFDASHBOARD_TYPE_LIVE_WINDOW));
1769 
1770 		return(FALSE);
1771 	}
1772 
1773 	/* Activate selection means clicking on window */
1774 	_xfdashboard_windows_view_on_window_clicked(self, XFDASHBOARD_LIVE_WINDOW(inSelection));
1775 
1776 	return(TRUE);
1777 }
1778 
1779 /* Interface initialization
1780  * Set up default functions
1781  */
_xfdashboard_windows_view_focusable_iface_init(XfdashboardFocusableInterface * iface)1782 void _xfdashboard_windows_view_focusable_iface_init(XfdashboardFocusableInterface *iface)
1783 {
1784 	iface->can_focus=_xfdashboard_windows_view_focusable_can_focus;
1785 	iface->unset_focus=_xfdashboard_windows_view_focusable_unset_focus;
1786 
1787 	iface->supports_selection=_xfdashboard_windows_view_focusable_supports_selection;
1788 	iface->get_selection=_xfdashboard_windows_view_focusable_get_selection;
1789 	iface->set_selection=_xfdashboard_windows_view_focusable_set_selection;
1790 	iface->find_selection=_xfdashboard_windows_view_focusable_find_selection;
1791 	iface->activate_selection=_xfdashboard_windows_view_focusable_activate_selection;
1792 }
1793 
1794 /* IMPLEMENTATION: ClutterActor */
1795 
1796 /* Actor will be mapped */
_xfdashboard_windows_view_map(ClutterActor * inActor)1797 static void _xfdashboard_windows_view_map(ClutterActor *inActor)
1798 {
1799 	XfdashboardWindowsView			*self;
1800 	XfdashboardWindowsViewPrivate	*priv;
1801 	ClutterActorClass				*clutterActorClass;
1802 
1803 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inActor));
1804 
1805 	self=XFDASHBOARD_WINDOWS_VIEW(inActor);
1806 	priv=self->priv;
1807 
1808 	/* Call parent's virtual function */
1809 	clutterActorClass=CLUTTER_ACTOR_CLASS(xfdashboard_windows_view_parent_class);
1810 	if(clutterActorClass->map) clutterActorClass->map(inActor);
1811 
1812 	/* Disconnect signal handler if available */
1813 	if(priv->scrollEventChangingWorkspaceStage)
1814 	{
1815 		if(priv->scrollEventChangingWorkspaceStageSignalID)
1816 		{
1817 			g_signal_handler_disconnect(priv->scrollEventChangingWorkspaceStage, priv->scrollEventChangingWorkspaceStageSignalID);
1818 			priv->scrollEventChangingWorkspaceStageSignalID=0;
1819 		}
1820 
1821 		priv->scrollEventChangingWorkspaceStage=NULL;
1822 	}
1823 
1824 	/* Get stage interface where this actor belongs to and connect
1825 	 * signal handler if found.
1826 	 */
1827 	priv->scrollEventChangingWorkspaceStage=xfdashboard_get_stage_of_actor(CLUTTER_ACTOR(self));
1828 	if(priv->scrollEventChangingWorkspaceStage)
1829 	{
1830 		priv->scrollEventChangingWorkspaceStageSignalID=g_signal_connect_swapped(priv->scrollEventChangingWorkspaceStage,
1831 																					"scroll-event",
1832 																					G_CALLBACK(_xfdashboard_windows_view_on_scroll_event),
1833 																					self);
1834 	}
1835 }
1836 
1837 /* Actor will be unmapped */
_xfdashboard_windows_view_unmap(ClutterActor * inActor)1838 static void _xfdashboard_windows_view_unmap(ClutterActor *inActor)
1839 {
1840 	XfdashboardWindowsView			*self;
1841 	XfdashboardWindowsViewPrivate	*priv;
1842 	ClutterActorClass				*clutterActorClass;
1843 
1844 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(inActor));
1845 
1846 	self=XFDASHBOARD_WINDOWS_VIEW(inActor);
1847 	priv=self->priv;
1848 
1849 	/* Call parent's virtual function */
1850 	clutterActorClass=CLUTTER_ACTOR_CLASS(xfdashboard_windows_view_parent_class);
1851 	if(clutterActorClass->unmap) clutterActorClass->unmap(inActor);
1852 
1853 	/* Disconnect signal handler if available */
1854 	if(priv->scrollEventChangingWorkspaceStage)
1855 	{
1856 		if(priv->scrollEventChangingWorkspaceStageSignalID)
1857 		{
1858 			g_signal_handler_disconnect(priv->scrollEventChangingWorkspaceStage, priv->scrollEventChangingWorkspaceStageSignalID);
1859 			priv->scrollEventChangingWorkspaceStageSignalID=0;
1860 		}
1861 
1862 		priv->scrollEventChangingWorkspaceStage=NULL;
1863 	}
1864 }
1865 
1866 /* IMPLEMENTATION: GObject */
1867 
1868 /* Dispose this object */
_xfdashboard_windows_view_dispose(GObject * inObject)1869 static void _xfdashboard_windows_view_dispose(GObject *inObject)
1870 {
1871 	XfdashboardWindowsView			*self=XFDASHBOARD_WINDOWS_VIEW(inObject);
1872 	XfdashboardWindowsViewPrivate	*priv=XFDASHBOARD_WINDOWS_VIEW(self)->priv;
1873 
1874 	/* Release allocated resources */
1875 	if(priv->selectedItem)
1876 	{
1877 		g_object_remove_weak_pointer(G_OBJECT(priv->selectedItem), &priv->selectedItem);
1878 		priv->selectedItem=NULL;
1879 	}
1880 
1881 	if(priv->scrollEventChangingWorkspaceStage)
1882 	{
1883 		if(priv->scrollEventChangingWorkspaceStageSignalID)
1884 		{
1885 			g_signal_handler_disconnect(priv->scrollEventChangingWorkspaceStage, priv->scrollEventChangingWorkspaceStageSignalID);
1886 			priv->scrollEventChangingWorkspaceStageSignalID=0;
1887 		}
1888 
1889 		priv->scrollEventChangingWorkspaceStage=NULL;
1890 	}
1891 
1892 	if(priv->xfconfChannel)
1893 	{
1894 		priv->xfconfChannel=NULL;
1895 	}
1896 
1897 	if(priv->xfconfScrollEventChangingWorkspaceBindingID)
1898 	{
1899 		xfconf_g_property_unbind(priv->xfconfScrollEventChangingWorkspaceBindingID);
1900 		priv->xfconfScrollEventChangingWorkspaceBindingID=0;
1901 	}
1902 
1903 	if(priv->workspace)
1904 	{
1905 		_xfdashboard_windows_view_set_active_workspace(self, NULL);
1906 	}
1907 
1908 	if(priv->layout)
1909 	{
1910 		priv->layout=NULL;
1911 	}
1912 
1913 	if(priv->currentMonitor)
1914 	{
1915 		priv->currentMonitor=NULL;
1916 	}
1917 
1918 	if(priv->currentStage)
1919 	{
1920 		if(priv->currentStageMonitorBindingID)
1921 		{
1922 			g_signal_handler_disconnect(priv->currentStage, priv->currentStageMonitorBindingID);
1923 			priv->currentStageMonitorBindingID=0;
1924 		}
1925 
1926 		priv->currentStage=NULL;
1927 	}
1928 
1929 	if(priv->windowTracker)
1930 	{
1931 		g_signal_handlers_disconnect_by_data(priv->windowTracker, self);
1932 		g_object_unref(priv->windowTracker);
1933 		priv->windowTracker=NULL;
1934 	}
1935 
1936 	/* Call parent's class dispose method */
1937 	G_OBJECT_CLASS(xfdashboard_windows_view_parent_class)->dispose(inObject);
1938 }
1939 
1940 /* Set/get properties */
_xfdashboard_windows_view_set_property(GObject * inObject,guint inPropID,const GValue * inValue,GParamSpec * inSpec)1941 static void _xfdashboard_windows_view_set_property(GObject *inObject,
1942 													guint inPropID,
1943 													const GValue *inValue,
1944 													GParamSpec *inSpec)
1945 {
1946 	XfdashboardWindowsView		*self=XFDASHBOARD_WINDOWS_VIEW(inObject);
1947 
1948 	switch(inPropID)
1949 	{
1950 		case PROP_WORKSPACE:
1951 			_xfdashboard_windows_view_set_active_workspace(self, g_value_get_object(inValue));
1952 			break;
1953 
1954 		case PROP_SPACING:
1955 			xfdashboard_windows_view_set_spacing(self, g_value_get_float(inValue));
1956 			break;
1957 
1958 		case PROP_PREVENT_UPSCALING:
1959 			xfdashboard_windows_view_set_prevent_upscaling(self, g_value_get_boolean(inValue));
1960 			break;
1961 
1962 		case PROP_SCROLL_EVENT_CHANGES_WORKSPACE:
1963 			_xfdashboard_windows_view_set_scroll_event_changes_workspace(self, g_value_get_boolean(inValue));
1964 			break;
1965 
1966 		case PROP_FILTER_MONITOR_WINDOWS:
1967 			_xfdashboard_windows_view_set_filter_monitor_windows(self, g_value_get_boolean(inValue));
1968 			break;
1969 
1970 		case PROP_FILTER_WORKSPACE_WINDOWS:
1971 			_xfdashboard_windows_view_set_filter_workspace_windows(self, g_value_get_boolean(inValue));
1972 			break;
1973 
1974 		default:
1975 			G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
1976 			break;
1977 	}
1978 }
1979 
_xfdashboard_windows_view_get_property(GObject * inObject,guint inPropID,GValue * outValue,GParamSpec * inSpec)1980 static void _xfdashboard_windows_view_get_property(GObject *inObject,
1981 													guint inPropID,
1982 													GValue *outValue,
1983 													GParamSpec *inSpec)
1984 {
1985 	XfdashboardWindowsView			*self=XFDASHBOARD_WINDOWS_VIEW(inObject);
1986 	XfdashboardWindowsViewPrivate	*priv=self->priv;
1987 
1988 	switch(inPropID)
1989 	{
1990 		case PROP_WORKSPACE:
1991 			g_value_set_object(outValue, priv->workspace);
1992 			break;
1993 
1994 		case PROP_SPACING:
1995 			g_value_set_float(outValue, priv->spacing);
1996 			break;
1997 
1998 		case PROP_PREVENT_UPSCALING:
1999 			g_value_set_boolean(outValue, self->priv->preventUpscaling);
2000 			break;
2001 
2002 		case PROP_SCROLL_EVENT_CHANGES_WORKSPACE:
2003 			g_value_set_boolean(outValue, self->priv->isScrollEventChangingWorkspace);
2004 			break;
2005 
2006 		case PROP_FILTER_MONITOR_WINDOWS:
2007 			g_value_set_boolean(outValue, self->priv->filterMonitorWindows);
2008 			break;
2009 
2010 		case PROP_FILTER_WORKSPACE_WINDOWS:
2011 			g_value_set_boolean(outValue, self->priv->filterWorkspaceWindows);
2012 			break;
2013 
2014 		default:
2015 			G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
2016 			break;
2017 	}
2018 }
2019 
2020 /* Class initialization
2021  * Override functions in parent classes and define properties
2022  * and signals
2023  */
xfdashboard_windows_view_class_init(XfdashboardWindowsViewClass * klass)2024 static void xfdashboard_windows_view_class_init(XfdashboardWindowsViewClass *klass)
2025 {
2026 	XfdashboardActorClass	*actorClass=XFDASHBOARD_ACTOR_CLASS(klass);
2027 	ClutterActorClass		*clutterActorClass=CLUTTER_ACTOR_CLASS(klass);
2028 	GObjectClass			*gobjectClass=G_OBJECT_CLASS(klass);
2029 
2030 	/* Override functions */
2031 	gobjectClass->dispose=_xfdashboard_windows_view_dispose;
2032 	gobjectClass->set_property=_xfdashboard_windows_view_set_property;
2033 	gobjectClass->get_property=_xfdashboard_windows_view_get_property;
2034 
2035 	clutterActorClass->map=_xfdashboard_windows_view_map;
2036 	clutterActorClass->unmap=_xfdashboard_windows_view_unmap;
2037 
2038 	klass->window_close=_xfdashboard_windows_view_window_close;
2039 	klass->windows_show_numbers=_xfdashboard_windows_view_windows_show_numbers;
2040 	klass->windows_hide_numbers=_xfdashboard_windows_view_windows_hide_numbers;
2041 	klass->windows_activate_window_one=_xfdashboard_windows_view_windows_activate_window_one;
2042 	klass->windows_activate_window_two=_xfdashboard_windows_view_windows_activate_window_two;
2043 	klass->windows_activate_window_three=_xfdashboard_windows_view_windows_activate_window_three;
2044 	klass->windows_activate_window_four=_xfdashboard_windows_view_windows_activate_window_four;
2045 	klass->windows_activate_window_five=_xfdashboard_windows_view_windows_activate_window_five;
2046 	klass->windows_activate_window_six=_xfdashboard_windows_view_windows_activate_window_six;
2047 	klass->windows_activate_window_seven=_xfdashboard_windows_view_windows_activate_window_seven;
2048 	klass->windows_activate_window_eight=_xfdashboard_windows_view_windows_activate_window_eight;
2049 	klass->windows_activate_window_nine=_xfdashboard_windows_view_windows_activate_window_nine;
2050 	klass->windows_activate_window_ten=_xfdashboard_windows_view_windows_activate_window_ten;
2051 
2052 	/* Define properties */
2053 	XfdashboardWindowsViewProperties[PROP_WORKSPACE]=
2054 		g_param_spec_object("workspace",
2055 							"Current workspace",
2056 							"The current workspace whose windows are shown",
2057 							XFDASHBOARD_TYPE_WINDOW_TRACKER_WORKSPACE,
2058 							G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
2059 
2060 	XfdashboardWindowsViewProperties[PROP_SPACING]=
2061 		g_param_spec_float("spacing",
2062 							"Spacing",
2063 							"Spacing between each element in view",
2064 							0.0f, G_MAXFLOAT,
2065 							0.0f,
2066 							G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2067 
2068 	XfdashboardWindowsViewProperties[PROP_PREVENT_UPSCALING]=
2069 		g_param_spec_boolean("prevent-upscaling",
2070 								"Prevent upscaling",
2071 								"Whether this view should prevent upsclaing any window beyond its real size",
2072 								FALSE,
2073 								G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2074 
2075 	XfdashboardWindowsViewProperties[PROP_SCROLL_EVENT_CHANGES_WORKSPACE]=
2076 		g_param_spec_boolean("scroll-event-changes-workspace",
2077 								"Scroll event changes workspace",
2078 								"Whether this view should change active workspace on scroll events",
2079 								FALSE,
2080 								G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2081 
2082 	XfdashboardWindowsViewProperties[PROP_FILTER_MONITOR_WINDOWS]=
2083 		g_param_spec_boolean("filter-monitor-windows",
2084 								"Filter monitor windows",
2085 								"Whether this view should only show windows of monitor where it placed at",
2086 								FALSE,
2087 								G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2088 
2089 	XfdashboardWindowsViewProperties[PROP_FILTER_WORKSPACE_WINDOWS]=
2090 		g_param_spec_boolean("filter-workspace-windows",
2091 								"Filter workspace windows",
2092 								"Whether this view should only show windows of active workspace",
2093 								TRUE,
2094 								G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2095 
2096 	g_object_class_install_properties(gobjectClass, PROP_LAST, XfdashboardWindowsViewProperties);
2097 
2098 	/* Define stylable properties */
2099 	xfdashboard_actor_install_stylable_property(actorClass, XfdashboardWindowsViewProperties[PROP_SPACING]);
2100 	xfdashboard_actor_install_stylable_property(actorClass, XfdashboardWindowsViewProperties[PROP_PREVENT_UPSCALING]);
2101 	xfdashboard_actor_install_stylable_property(actorClass, XfdashboardWindowsViewProperties[PROP_FILTER_MONITOR_WINDOWS]);
2102 	xfdashboard_actor_install_stylable_property(actorClass, XfdashboardWindowsViewProperties[PROP_FILTER_WORKSPACE_WINDOWS]);
2103 
2104 	/* Define actions */
2105 	XfdashboardWindowsViewSignals[ACTION_WINDOW_CLOSE]=
2106 		g_signal_new("window-close",
2107 						G_TYPE_FROM_CLASS(klass),
2108 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2109 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, window_close),
2110 						g_signal_accumulator_true_handled,
2111 						NULL,
2112 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2113 						G_TYPE_BOOLEAN,
2114 						3,
2115 						XFDASHBOARD_TYPE_FOCUSABLE,
2116 						G_TYPE_STRING,
2117 						CLUTTER_TYPE_EVENT);
2118 
2119 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_SHOW_NUMBERS]=
2120 		g_signal_new("windows-show-numbers",
2121 						G_TYPE_FROM_CLASS(klass),
2122 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2123 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_show_numbers),
2124 						g_signal_accumulator_true_handled,
2125 						NULL,
2126 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2127 						G_TYPE_BOOLEAN,
2128 						3,
2129 						XFDASHBOARD_TYPE_FOCUSABLE,
2130 						G_TYPE_STRING,
2131 						CLUTTER_TYPE_EVENT);
2132 
2133 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_HIDE_NUMBERS]=
2134 		g_signal_new("windows-hide-numbers",
2135 						G_TYPE_FROM_CLASS(klass),
2136 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2137 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_hide_numbers),
2138 						g_signal_accumulator_true_handled,
2139 						NULL,
2140 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2141 						G_TYPE_BOOLEAN,
2142 						3,
2143 						XFDASHBOARD_TYPE_FOCUSABLE,
2144 						G_TYPE_STRING,
2145 						CLUTTER_TYPE_EVENT);
2146 
2147 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_ONE]=
2148 		g_signal_new("windows-activate-window-one",
2149 						G_TYPE_FROM_CLASS(klass),
2150 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2151 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_one),
2152 						g_signal_accumulator_true_handled,
2153 						NULL,
2154 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2155 						G_TYPE_BOOLEAN,
2156 						3,
2157 						XFDASHBOARD_TYPE_FOCUSABLE,
2158 						G_TYPE_STRING,
2159 						CLUTTER_TYPE_EVENT);
2160 
2161 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_TWO]=
2162 		g_signal_new("windows-activate-window-two",
2163 						G_TYPE_FROM_CLASS(klass),
2164 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2165 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_two),
2166 						g_signal_accumulator_true_handled,
2167 						NULL,
2168 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2169 						G_TYPE_BOOLEAN,
2170 						3,
2171 						XFDASHBOARD_TYPE_FOCUSABLE,
2172 						G_TYPE_STRING,
2173 						CLUTTER_TYPE_EVENT);
2174 
2175 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_THREE]=
2176 		g_signal_new("windows-activate-window-three",
2177 						G_TYPE_FROM_CLASS(klass),
2178 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2179 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_three),
2180 						g_signal_accumulator_true_handled,
2181 						NULL,
2182 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2183 						G_TYPE_BOOLEAN,
2184 						3,
2185 						XFDASHBOARD_TYPE_FOCUSABLE,
2186 						G_TYPE_STRING,
2187 						CLUTTER_TYPE_EVENT);
2188 
2189 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_FOUR]=
2190 		g_signal_new("windows-activate-window-four",
2191 						G_TYPE_FROM_CLASS(klass),
2192 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2193 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_four),
2194 						g_signal_accumulator_true_handled,
2195 						NULL,
2196 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2197 						G_TYPE_BOOLEAN,
2198 						3,
2199 						XFDASHBOARD_TYPE_FOCUSABLE,
2200 						G_TYPE_STRING,
2201 						CLUTTER_TYPE_EVENT);
2202 
2203 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_FIVE]=
2204 		g_signal_new("windows-activate-window-five",
2205 						G_TYPE_FROM_CLASS(klass),
2206 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2207 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_five),
2208 						g_signal_accumulator_true_handled,
2209 						NULL,
2210 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2211 						G_TYPE_BOOLEAN,
2212 						3,
2213 						XFDASHBOARD_TYPE_FOCUSABLE,
2214 						G_TYPE_STRING,
2215 						CLUTTER_TYPE_EVENT);
2216 
2217 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_SIX]=
2218 		g_signal_new("windows-activate-window-six",
2219 						G_TYPE_FROM_CLASS(klass),
2220 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2221 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_six),
2222 						g_signal_accumulator_true_handled,
2223 						NULL,
2224 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2225 						G_TYPE_BOOLEAN,
2226 						3,
2227 						XFDASHBOARD_TYPE_FOCUSABLE,
2228 						G_TYPE_STRING,
2229 						CLUTTER_TYPE_EVENT);
2230 
2231 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_SEVEN]=
2232 		g_signal_new("windows-activate-window-seven",
2233 						G_TYPE_FROM_CLASS(klass),
2234 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2235 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_seven),
2236 						g_signal_accumulator_true_handled,
2237 						NULL,
2238 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2239 						G_TYPE_BOOLEAN,
2240 						3,
2241 						XFDASHBOARD_TYPE_FOCUSABLE,
2242 						G_TYPE_STRING,
2243 						CLUTTER_TYPE_EVENT);
2244 
2245 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_EIGHT]=
2246 		g_signal_new("windows-activate-window-eight",
2247 						G_TYPE_FROM_CLASS(klass),
2248 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2249 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_eight),
2250 						g_signal_accumulator_true_handled,
2251 						NULL,
2252 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2253 						G_TYPE_BOOLEAN,
2254 						3,
2255 						XFDASHBOARD_TYPE_FOCUSABLE,
2256 						G_TYPE_STRING,
2257 						CLUTTER_TYPE_EVENT);
2258 
2259 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_NINE]=
2260 		g_signal_new("windows-activate-window-nine",
2261 						G_TYPE_FROM_CLASS(klass),
2262 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2263 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_nine),
2264 						g_signal_accumulator_true_handled,
2265 						NULL,
2266 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2267 						G_TYPE_BOOLEAN,
2268 						3,
2269 						XFDASHBOARD_TYPE_FOCUSABLE,
2270 						G_TYPE_STRING,
2271 						CLUTTER_TYPE_EVENT);
2272 
2273 	XfdashboardWindowsViewSignals[ACTION_WINDOWS_ACTIVATE_WINDOW_TEN]=
2274 		g_signal_new("windows-activate-window-ten",
2275 						G_TYPE_FROM_CLASS(klass),
2276 						G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2277 						G_STRUCT_OFFSET(XfdashboardWindowsViewClass, windows_activate_window_ten),
2278 						g_signal_accumulator_true_handled,
2279 						NULL,
2280 						_xfdashboard_marshal_BOOLEAN__OBJECT_STRING_BOXED,
2281 						G_TYPE_BOOLEAN,
2282 						3,
2283 						XFDASHBOARD_TYPE_FOCUSABLE,
2284 						G_TYPE_STRING,
2285 						CLUTTER_TYPE_EVENT);
2286 }
2287 
2288 /* Object initialization
2289  * Create private structure and set up default values
2290  */
xfdashboard_windows_view_init(XfdashboardWindowsView * self)2291 static void xfdashboard_windows_view_init(XfdashboardWindowsView *self)
2292 {
2293 	XfdashboardWindowsViewPrivate		*priv;
2294 	ClutterAction						*action;
2295 	XfdashboardWindowTrackerWorkspace	*activeWorkspace;
2296 
2297 	self->priv=priv=xfdashboard_windows_view_get_instance_private(self);
2298 
2299 	/* Set up default values */
2300 	priv->windowTracker=xfdashboard_window_tracker_get_default();
2301 	priv->workspace=NULL;
2302 	priv->spacing=0.0f;
2303 	priv->preventUpscaling=FALSE;
2304 	priv->selectedItem=NULL;
2305 	priv->isWindowsNumberShown=FALSE;
2306 	priv->xfconfChannel=xfdashboard_application_get_xfconf_channel(NULL);
2307 	priv->isScrollEventChangingWorkspace=FALSE;
2308 	priv->scrollEventChangingWorkspaceStage=NULL;
2309 	priv->scrollEventChangingWorkspaceStageSignalID=0;
2310 	priv->filterMonitorWindows=FALSE;
2311 	priv->filterWorkspaceWindows=TRUE;
2312 	priv->currentStage=NULL;
2313 	priv->currentMonitor=NULL;
2314 	priv->currentStageMonitorBindingID=0;
2315 
2316 	/* Set up view */
2317 	xfdashboard_view_set_name(XFDASHBOARD_VIEW(self), _("Windows"));
2318 	xfdashboard_view_set_icon(XFDASHBOARD_VIEW(self), DEFAULT_VIEW_ICON);
2319 	xfdashboard_view_set_view_fit_mode(XFDASHBOARD_VIEW(self), XFDASHBOARD_VIEW_FIT_MODE_BOTH);
2320 
2321 	/* Setup actor */
2322 	xfdashboard_actor_set_can_focus(XFDASHBOARD_ACTOR(self), TRUE);
2323 
2324 	priv->layout=xfdashboard_scaled_table_layout_new();
2325 	xfdashboard_scaled_table_layout_set_relative_scale(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout), TRUE);
2326 	xfdashboard_scaled_table_layout_set_prevent_upscaling(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout), priv->preventUpscaling);
2327 	clutter_actor_set_layout_manager(CLUTTER_ACTOR(self), priv->layout);
2328 
2329 	action=xfdashboard_drop_action_new();
2330 	clutter_actor_add_action(CLUTTER_ACTOR(self), action);
2331 	g_signal_connect_swapped(action, "begin", G_CALLBACK(_xfdashboard_windows_view_on_drop_begin), self);
2332 	g_signal_connect_swapped(action, "drop", G_CALLBACK(_xfdashboard_windows_view_on_drop_drop), self);
2333 
2334 	/* Bind to xfconf to react on changes */
2335 	priv->xfconfScrollEventChangingWorkspaceBindingID=xfconf_g_property_bind(priv->xfconfChannel,
2336 																				SCROLL_EVENT_CHANGES_WORKSPACE_XFCONF_PROP,
2337 																				G_TYPE_BOOLEAN,
2338 																				self,
2339 																				"scroll-event-changes-workspace");
2340 
2341 	/* Connect signals */
2342 	g_signal_connect(self,
2343 						"actor-added",
2344 						G_CALLBACK(_xfdashboard_windows_view_on_child_added),
2345 						NULL);
2346 
2347 	g_signal_connect(self,
2348 						"actor-removed",
2349 						G_CALLBACK(_xfdashboard_windows_view_on_child_removed),
2350 						NULL);
2351 
2352 	g_signal_connect_swapped(priv->windowTracker,
2353 								"active-workspace-changed",
2354 								G_CALLBACK(_xfdashboard_windows_view_on_active_workspace_changed),
2355 								self);
2356 
2357 	g_signal_connect_swapped(priv->windowTracker,
2358 								"window-workspace-changed",
2359 								G_CALLBACK(_xfdashboard_windows_view_on_window_workspace_changed),
2360 								self);
2361 
2362 	g_signal_connect_swapped(priv->windowTracker,
2363 								"window-opened",
2364 								G_CALLBACK(_xfdashboard_windows_view_on_window_opened),
2365 								self);
2366 
2367 	g_signal_connect_swapped(priv->windowTracker,
2368 								"window-monitor-changed",
2369 								G_CALLBACK(_xfdashboard_windows_view_on_window_monitor_changed),
2370 								self);
2371 
2372 	/* If active workspace is already available then set up this view */
2373 	activeWorkspace=xfdashboard_window_tracker_get_active_workspace(priv->windowTracker);
2374 	if(activeWorkspace)
2375 	{
2376 		_xfdashboard_windows_view_set_active_workspace(self, activeWorkspace);
2377 	}
2378 }
2379 
2380 /* IMPLEMENTATION: Public API */
2381 
2382 /* Get/set spacing between elements */
xfdashboard_windows_view_get_spacing(XfdashboardWindowsView * self)2383 gfloat xfdashboard_windows_view_get_spacing(XfdashboardWindowsView *self)
2384 {
2385 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), 0.0f);
2386 
2387 	return(self->priv->spacing);
2388 }
2389 
xfdashboard_windows_view_set_spacing(XfdashboardWindowsView * self,const gfloat inSpacing)2390 void xfdashboard_windows_view_set_spacing(XfdashboardWindowsView *self, const gfloat inSpacing)
2391 {
2392 	XfdashboardWindowsViewPrivate		*priv;
2393 
2394 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
2395 	g_return_if_fail(inSpacing>=0.0f);
2396 
2397 	priv=self->priv;
2398 
2399 	/* Set value if changed */
2400 	if(priv->spacing!=inSpacing)
2401 	{
2402 		/* Set value */
2403 		priv->spacing=inSpacing;
2404 
2405 		/* Update layout manager */
2406 		if(priv->layout)
2407 		{
2408 			xfdashboard_scaled_table_layout_set_spacing(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout), priv->spacing);
2409 		}
2410 
2411 		/* Notify about property change */
2412 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_SPACING]);
2413 	}
2414 }
2415 
2416 /* Get/set if layout manager should prevent to size any child larger than its real size */
xfdashboard_windows_view_get_prevent_upscaling(XfdashboardWindowsView * self)2417 gboolean xfdashboard_windows_view_get_prevent_upscaling(XfdashboardWindowsView *self)
2418 {
2419 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self), FALSE);
2420 
2421 	return(self->priv->preventUpscaling);
2422 }
2423 
xfdashboard_windows_view_set_prevent_upscaling(XfdashboardWindowsView * self,gboolean inPreventUpscaling)2424 void xfdashboard_windows_view_set_prevent_upscaling(XfdashboardWindowsView *self, gboolean inPreventUpscaling)
2425 {
2426 	XfdashboardWindowsViewPrivate		*priv;
2427 
2428 	g_return_if_fail(XFDASHBOARD_IS_WINDOWS_VIEW(self));
2429 
2430 	priv=self->priv;
2431 
2432 	/* Set value if changed */
2433 	if(priv->preventUpscaling!=inPreventUpscaling)
2434 	{
2435 		/* Set value */
2436 		priv->preventUpscaling=inPreventUpscaling;
2437 
2438 		/* Update layout manager */
2439 		if(priv->layout)
2440 		{
2441 			xfdashboard_scaled_table_layout_set_prevent_upscaling(XFDASHBOARD_SCALED_TABLE_LAYOUT(priv->layout), priv->preventUpscaling);
2442 		}
2443 
2444 		/* Notify about property change */
2445 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardWindowsViewProperties[PROP_PREVENT_UPSCALING]);
2446 	}
2447 }
2448