1 /*
2  * live-window-simple: An actor showing the content of a window which will
3  *                     be updated if changed and visible on active workspace.
4  *
5  * Copyright 2012-2020 Stephan Haller <nomad@froevel.de>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20  * MA 02110-1301, USA.
21  *
22  *
23  */
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include <libxfdashboard/live-window-simple.h>
30 
31 #include <glib/gi18n-lib.h>
32 
33 #include <libxfdashboard/click-action.h>
34 #include <libxfdashboard/window-content.h>
35 #include <libxfdashboard/image-content.h>
36 #include <libxfdashboard/stylable.h>
37 #include <libxfdashboard/enums.h>
38 #include <libxfdashboard/compat.h>
39 #include <libxfdashboard/debug.h>
40 
41 
42 /* Define this class in GObject system */
43 struct _XfdashboardLiveWindowSimplePrivate
44 {
45 	/* Properties related */
46 	XfdashboardWindowTrackerWindow			*window;
47 	XfdashboardLiveWindowSimpleDisplayType	displayType;
48 
49 	/* Instance related */
50 	gboolean								isVisible;
51 	ClutterActor							*actorWindow;
52 	gboolean								destroyOnClose;
53 };
54 
55 G_DEFINE_TYPE_WITH_PRIVATE(XfdashboardLiveWindowSimple,
56 							xfdashboard_live_window_simple,
57 							XFDASHBOARD_TYPE_BACKGROUND)
58 
59 /* Properties */
60 enum
61 {
62 	PROP_0,
63 
64 	PROP_WINDOW,
65 	PROP_DISPLAY_TYPE,
66 	PROP_DESTROY_ON_CLOSE,
67 
68 	PROP_LAST
69 };
70 
71 static GParamSpec* XfdashboardLiveWindowSimpleProperties[PROP_LAST]={ 0, };
72 
73 /* Signals */
74 enum
75 {
76 	SIGNAL_GEOMETRY_CHANGED,
77 	SIGNAL_VISIBILITY_CHANGED,
78 	SIGNAL_WORKSPACE_CHANGED,
79 
80 	SIGNAL_LAST
81 };
82 
83 static guint XfdashboardLiveWindowSimpleSignals[SIGNAL_LAST]={ 0, };
84 
85 /* IMPLEMENTATION: Private variables and methods */
86 
87 /* Check if window should be shown */
_xfdashboard_live_window_simple_is_visible_window(XfdashboardLiveWindowSimple * self,XfdashboardWindowTrackerWindow * inWindow)88 static gboolean _xfdashboard_live_window_simple_is_visible_window(XfdashboardLiveWindowSimple *self, XfdashboardWindowTrackerWindow *inWindow)
89 {
90 	XfdashboardWindowTrackerWindowState		state;
91 
92 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), FALSE);
93 
94 	/* Determine if windows should be shown depending on its state */
95 	state=xfdashboard_window_tracker_window_get_state(inWindow);
96 	if((state & XFDASHBOARD_WINDOW_TRACKER_WINDOW_STATE_SKIP_PAGER) ||
97 		(state & XFDASHBOARD_WINDOW_TRACKER_WINDOW_STATE_SKIP_TASKLIST))
98 	{
99 		return(FALSE);
100 	}
101 
102 	/* If we get here the window should be shown */
103 	return(TRUE);
104 }
105 
106 /* Position and/or size of window has changed */
_xfdashboard_live_window_simple_on_geometry_changed(XfdashboardLiveWindowSimple * self,gpointer inUserData)107 static void _xfdashboard_live_window_simple_on_geometry_changed(XfdashboardLiveWindowSimple *self,
108 																gpointer inUserData)
109 {
110 	XfdashboardLiveWindowSimplePrivate	*priv;
111 	XfdashboardWindowTrackerWindow		*window;
112 
113 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self));
114 	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inUserData));
115 
116 	priv=self->priv;
117 	window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(inUserData);
118 
119 	/* Check if signal is for this window */
120 	if(window!=priv->window) return;
121 
122 	/* Actor's allocation may change because of new geometry so relayout */
123 	clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
124 
125 	/* Emit "geometry-changed" signal */
126 	g_signal_emit(self, XfdashboardLiveWindowSimpleSignals[SIGNAL_GEOMETRY_CHANGED], 0);
127 }
128 
129 /* Window's state has changed */
_xfdashboard_live_window_simple_on_state_changed(XfdashboardLiveWindowSimple * self,XfdashboardWindowTrackerWindowState inOldState,gpointer inUserData)130 static void _xfdashboard_live_window_simple_on_state_changed(XfdashboardLiveWindowSimple *self,
131 																XfdashboardWindowTrackerWindowState inOldState,
132 																gpointer inUserData)
133 {
134 	XfdashboardLiveWindowSimplePrivate		*priv;
135 	XfdashboardWindowTrackerWindow			*window;
136 	gboolean								isVisible;
137 	XfdashboardWindowTrackerWindowState		state;
138 
139 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self));
140 	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inUserData));
141 
142 	priv=self->priv;
143 	window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(inUserData);
144 
145 	/* Check if signal is for this window */
146 	if(window!=priv->window) return;
147 
148 	/* Check if window's visibility has changed */
149 	isVisible=_xfdashboard_live_window_simple_is_visible_window(self, window);
150 	if(priv->isVisible!=isVisible)
151 	{
152 		priv->isVisible=isVisible;
153 		g_signal_emit(self, XfdashboardLiveWindowSimpleSignals[SIGNAL_VISIBILITY_CHANGED], 0);
154 	}
155 
156 	/* Add or remove class depending on 'pinned' window state */
157 	state=xfdashboard_window_tracker_window_get_state(window);
158 	if(state & XFDASHBOARD_WINDOW_TRACKER_WINDOW_STATE_PINNED)
159 	{
160 		xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(self), "window-state-pinned");
161 	}
162 		else
163 		{
164 			xfdashboard_stylable_remove_class(XFDASHBOARD_STYLABLE(self), "window-state-pinned");
165 		}
166 
167 	/* Add or remove class depending on 'minimized' window state */
168 	if(state & XFDASHBOARD_WINDOW_TRACKER_WINDOW_STATE_MINIMIZED)
169 	{
170 		xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(self), "window-state-minimized");
171 	}
172 		else
173 		{
174 			xfdashboard_stylable_remove_class(XFDASHBOARD_STYLABLE(self), "window-state-minimized");
175 		}
176 
177 	/* Add or remove class depending on 'maximized' window state */
178 	if(state & XFDASHBOARD_WINDOW_TRACKER_WINDOW_STATE_MAXIMIZED)
179 	{
180 		xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(self), "window-state-maximized");
181 	}
182 		else
183 		{
184 			xfdashboard_stylable_remove_class(XFDASHBOARD_STYLABLE(self), "window-state-maximized");
185 		}
186 
187 	/* Add or remove class depending on 'urgent' window state */
188 	if(state & XFDASHBOARD_WINDOW_TRACKER_WINDOW_STATE_URGENT)
189 	{
190 		xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(self), "window-state-urgent");
191 	}
192 		else
193 		{
194 			xfdashboard_stylable_remove_class(XFDASHBOARD_STYLABLE(self), "window-state-urgent");
195 		}
196 }
197 
198 /* Window's workspace has changed */
_xfdashboard_live_window_simple_on_workspace_changed(XfdashboardLiveWindowSimple * self,XfdashboardWindowTrackerWorkspace * inWorkspace,gpointer inUserData)199 static void _xfdashboard_live_window_simple_on_workspace_changed(XfdashboardLiveWindowSimple *self,
200 																	XfdashboardWindowTrackerWorkspace *inWorkspace,
201 																	gpointer inUserData)
202 {
203 	XfdashboardLiveWindowSimplePrivate	*priv;
204 	XfdashboardWindowTrackerWindow		*window;
205 
206 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self));
207 	g_return_if_fail(!inWorkspace || XFDASHBOARD_IS_WINDOW_TRACKER_WORKSPACE(inWorkspace));
208 	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inUserData));
209 
210 	priv=self->priv;
211 	window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(inUserData);
212 
213 	/* Check if signal is for this window */
214 	if(window!=priv->window) return;
215 
216 	/* Emit "workspace-changed" signal */
217 	g_signal_emit(self, XfdashboardLiveWindowSimpleSignals[SIGNAL_WORKSPACE_CHANGED], 0);
218 }
219 
220 /* Window's was closed */
_xfdashboard_live_window_simple_on_closed(XfdashboardLiveWindowSimple * self,gpointer inUserData)221 static void _xfdashboard_live_window_simple_on_closed(XfdashboardLiveWindowSimple *self,
222 														gpointer inUserData)
223 {
224 	XfdashboardLiveWindowSimplePrivate	*priv;
225 	XfdashboardWindowTrackerWindow		*window;
226 
227 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self));
228 	g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inUserData));
229 
230 	priv=self->priv;
231 	window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(inUserData);
232 
233 	/* Check if signal is for this window */
234 	if(window!=priv->window) return;
235 
236 	/* Check if actor should be destroy when window was closed */
237 	if(priv->destroyOnClose)
238 	{
239 		XFDASHBOARD_DEBUG(self, WINDOWS,
240 							"Window '%s' was closed and auto-destruction of actor was requested",
241 							xfdashboard_window_tracker_window_get_name(priv->window));
242 
243 		if(xfdashboard_actor_destroy(CLUTTER_ACTOR(self)))
244 		{
245 			/* Release allocated resources early, before the dispose function
246 			 * is called, if an animation was started as the window is now gone!
247 			 */
248 			if(priv->window)
249 			{
250 				g_signal_handlers_disconnect_by_data(priv->window, self);
251 				priv->window=NULL;
252 			}
253 		}
254 	}
255 }
256 
257 /* Set up actor's content depending on display. If no window is set the current
258  * content of this actor is destroyed and a new one is not set up. The actor will
259  * be displayed empty.
260  */
_xfdashboard_live_window_simple_setup_content(XfdashboardLiveWindowSimple * self)261 static void _xfdashboard_live_window_simple_setup_content(XfdashboardLiveWindowSimple *self)
262 {
263 	XfdashboardLiveWindowSimplePrivate	*priv;
264 	ClutterContent						*content;
265 
266 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self));
267 
268 	priv=self->priv;
269 
270 	/* Destroy old actor's content */
271 	clutter_actor_set_content(priv->actorWindow, NULL);
272 
273 	/* If no window is set we cannot set up actor's content but only destroy the
274 	 * old. So return here if no window is set.
275 	 */
276 	if(!priv->window) return;
277 
278 	/* Setup actor's content depending on display type */
279 	switch(priv->displayType)
280 	{
281 		case XFDASHBOARD_LIVE_WINDOW_SIMPLE_DISPLAY_TYPE_LIVE_PREVIEW:
282 			content=xfdashboard_window_tracker_window_get_content(priv->window);
283 			clutter_actor_set_content(priv->actorWindow, content);
284 			g_object_unref(content);
285 			break;
286 
287 		case XFDASHBOARD_LIVE_WINDOW_SIMPLE_DISPLAY_TYPE_ICON:
288 			content=xfdashboard_image_content_new_for_pixbuf(xfdashboard_window_tracker_window_get_icon(priv->window));
289 			clutter_actor_set_content(priv->actorWindow, content);
290 			g_object_unref(content);
291 			break;
292 
293 		default:
294 			g_assert_not_reached();
295 			break;
296 	}
297 }
298 
299 /* IMPLEMENTATION: ClutterActor */
300 
301 /* Get preferred width/height */
_xfdashboard_live_window_simple_get_preferred_height(ClutterActor * self,gfloat inForWidth,gfloat * outMinHeight,gfloat * outNaturalHeight)302 static void _xfdashboard_live_window_simple_get_preferred_height(ClutterActor *self,
303 																	gfloat inForWidth,
304 																	gfloat *outMinHeight,
305 																	gfloat *outNaturalHeight)
306 {
307 	XfdashboardLiveWindowSimplePrivate	*priv=XFDASHBOARD_LIVE_WINDOW_SIMPLE(self)->priv;
308 	gfloat								minHeight, naturalHeight;
309 
310 	minHeight=naturalHeight=0.0f;
311 
312 	/* Determine size of window if available and visible (should usually be the largest actor) */
313 	if(priv->actorWindow &&
314 		clutter_actor_is_visible(priv->actorWindow) &&
315 		priv->window)
316 	{
317 		gint							windowHeight;
318 
319 		xfdashboard_window_tracker_window_get_geometry(priv->window, NULL, NULL, NULL, &windowHeight);
320 		if(windowHeight<=0.0)
321 		{
322 			ClutterContent				*content;
323 			gfloat						childNaturalHeight;
324 
325 			/* If we get here getting window size failed so fallback to old
326 			 * behaviour by getting size of window content associated to actor.
327 			 */
328 			content=clutter_actor_get_content(priv->actorWindow);
329 			if(content &&
330 				XFDASHBOARD_IS_WINDOW_CONTENT(content))
331 			{
332 				if(clutter_content_get_preferred_size(content, NULL, &childNaturalHeight)) windowHeight=childNaturalHeight;
333 				XFDASHBOARD_DEBUG(self, WINDOWS,
334 									"Using fallback method to determine preferred height for window '%s'",
335 									xfdashboard_window_tracker_window_get_name(priv->window));
336 			}
337 		}
338 
339 		if(windowHeight>minHeight) minHeight=windowHeight;
340 		if(windowHeight>naturalHeight) naturalHeight=windowHeight;
341 	}
342 
343 	/* Store sizes computed */
344 	if(outMinHeight) *outMinHeight=minHeight;
345 	if(outNaturalHeight) *outNaturalHeight=naturalHeight;
346 }
347 
_xfdashboard_live_window_simple_get_preferred_width(ClutterActor * self,gfloat inForHeight,gfloat * outMinWidth,gfloat * outNaturalWidth)348 static void _xfdashboard_live_window_simple_get_preferred_width(ClutterActor *self,
349 																gfloat inForHeight,
350 																gfloat *outMinWidth,
351 																gfloat *outNaturalWidth)
352 {
353 	XfdashboardLiveWindowSimplePrivate	*priv=XFDASHBOARD_LIVE_WINDOW_SIMPLE(self)->priv;
354 	gfloat								minWidth, naturalWidth;
355 
356 	minWidth=naturalWidth=0.0f;
357 
358 	/* Determine size of window if available and visible (should usually be the largest actor) */
359 	if(priv->actorWindow &&
360 		clutter_actor_is_visible(priv->actorWindow) &&
361 		priv->window)
362 	{
363 		gint							windowWidth;
364 
365 		xfdashboard_window_tracker_window_get_geometry(priv->window, NULL, NULL, &windowWidth, NULL);
366 		if(windowWidth<=0.0)
367 		{
368 			ClutterContent				*content;
369 			gfloat						childNaturalWidth;
370 
371 			/* If we get here getting window size failed so fallback to old
372 			 * behaviour by getting size of window content associated to actor.
373 			 */
374 			content=clutter_actor_get_content(priv->actorWindow);
375 			if(content &&
376 				XFDASHBOARD_IS_WINDOW_CONTENT(content))
377 			{
378 				if(clutter_content_get_preferred_size(content, &childNaturalWidth, NULL)) windowWidth=childNaturalWidth;
379 				XFDASHBOARD_DEBUG(self, WINDOWS,
380 									"Using fallback method to determine preferred width for window '%s'",
381 									xfdashboard_window_tracker_window_get_name(priv->window));
382 			}
383 		}
384 
385 		if(windowWidth>minWidth) minWidth=windowWidth;
386 		if(windowWidth>naturalWidth) naturalWidth=windowWidth;
387 	}
388 
389 	/* Store sizes computed */
390 	if(outMinWidth) *outMinWidth=minWidth;
391 	if(outNaturalWidth) *outNaturalWidth=naturalWidth;
392 }
393 
394 /* Allocate position and size of actor and its children */
_xfdashboard_live_window_simple_allocate(ClutterActor * self,const ClutterActorBox * inBox,ClutterAllocationFlags inFlags)395 static void _xfdashboard_live_window_simple_allocate(ClutterActor *self,
396 														const ClutterActorBox *inBox,
397 														ClutterAllocationFlags inFlags)
398 {
399 	XfdashboardLiveWindowSimplePrivate	*priv=XFDASHBOARD_LIVE_WINDOW_SIMPLE(self)->priv;
400 	ClutterActorBox						*boxActorWindow=NULL;
401 
402 	/* Chain up to store the allocation of the actor */
403 	CLUTTER_ACTOR_CLASS(xfdashboard_live_window_simple_parent_class)->allocate(self, inBox, inFlags);
404 
405 	/* Set allocation on window texture */
406 	boxActorWindow=clutter_actor_box_copy(inBox);
407 	clutter_actor_box_set_origin(boxActorWindow, 0.0f, 0.0f);
408 	clutter_actor_allocate(priv->actorWindow, boxActorWindow, inFlags);
409 
410 	/* Release allocated resources */
411 	if(boxActorWindow) clutter_actor_box_free(boxActorWindow);
412 }
413 
414 /* IMPLEMENTATION: GObject */
415 
416 /* Dispose this object */
_xfdashboard_live_window_simple_dispose(GObject * inObject)417 static void _xfdashboard_live_window_simple_dispose(GObject *inObject)
418 {
419 	XfdashboardLiveWindowSimple			*self=XFDASHBOARD_LIVE_WINDOW_SIMPLE(inObject);
420 	XfdashboardLiveWindowSimplePrivate	*priv=self->priv;
421 
422 	/* Dispose allocated resources */
423 	if(priv->window)
424 	{
425 		g_signal_handlers_disconnect_by_data(priv->window, self);
426 		priv->window=NULL;
427 	}
428 
429 	if(priv->actorWindow)
430 	{
431 		clutter_actor_destroy(priv->actorWindow);
432 		priv->actorWindow=NULL;
433 	}
434 
435 	/* Call parent's class dispose method */
436 	G_OBJECT_CLASS(xfdashboard_live_window_simple_parent_class)->dispose(inObject);
437 }
438 
439 /* Set/get properties */
_xfdashboard_live_window_simple_set_property(GObject * inObject,guint inPropID,const GValue * inValue,GParamSpec * inSpec)440 static void _xfdashboard_live_window_simple_set_property(GObject *inObject,
441 													guint inPropID,
442 													const GValue *inValue,
443 													GParamSpec *inSpec)
444 {
445 	XfdashboardLiveWindowSimple			*self=XFDASHBOARD_LIVE_WINDOW_SIMPLE(inObject);
446 
447 	switch(inPropID)
448 	{
449 		case PROP_WINDOW:
450 			xfdashboard_live_window_simple_set_window(self, g_value_get_object(inValue));
451 			break;
452 
453 		case PROP_DISPLAY_TYPE:
454 			xfdashboard_live_window_simple_set_display_type(self, g_value_get_enum(inValue));
455 			break;
456 
457 		case PROP_DESTROY_ON_CLOSE:
458 			xfdashboard_live_window_simple_set_destroy_on_close(self, g_value_get_boolean(inValue));
459 			break;
460 
461 		default:
462 			G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
463 			break;
464 	}
465 }
466 
_xfdashboard_live_window_simple_get_property(GObject * inObject,guint inPropID,GValue * outValue,GParamSpec * inSpec)467 static void _xfdashboard_live_window_simple_get_property(GObject *inObject,
468 													guint inPropID,
469 													GValue *outValue,
470 													GParamSpec *inSpec)
471 {
472 	XfdashboardLiveWindowSimple	*self=XFDASHBOARD_LIVE_WINDOW_SIMPLE(inObject);
473 
474 	switch(inPropID)
475 	{
476 		case PROP_WINDOW:
477 			g_value_set_object(outValue, self->priv->window);
478 			break;
479 
480 		case PROP_DISPLAY_TYPE:
481 			g_value_set_enum(outValue, self->priv->displayType);
482 			break;
483 
484 		case PROP_DESTROY_ON_CLOSE:
485 			g_value_set_boolean(outValue, self->priv->destroyOnClose);
486 			break;
487 
488 		default:
489 			G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
490 			break;
491 	}
492 }
493 
494 /* Class initialization
495  * Override functions in parent classes and define properties
496  * and signals
497  */
xfdashboard_live_window_simple_class_init(XfdashboardLiveWindowSimpleClass * klass)498 static void xfdashboard_live_window_simple_class_init(XfdashboardLiveWindowSimpleClass *klass)
499 {
500 	XfdashboardActorClass	*actorClass=XFDASHBOARD_ACTOR_CLASS(klass);
501 	ClutterActorClass		*clutterActorClass=CLUTTER_ACTOR_CLASS(klass);
502 	GObjectClass			*gobjectClass=G_OBJECT_CLASS(klass);
503 
504 	/* Override functions */
505 	clutterActorClass->get_preferred_width=_xfdashboard_live_window_simple_get_preferred_width;
506 	clutterActorClass->get_preferred_height=_xfdashboard_live_window_simple_get_preferred_height;
507 	clutterActorClass->allocate=_xfdashboard_live_window_simple_allocate;
508 
509 	gobjectClass->dispose=_xfdashboard_live_window_simple_dispose;
510 	gobjectClass->set_property=_xfdashboard_live_window_simple_set_property;
511 	gobjectClass->get_property=_xfdashboard_live_window_simple_get_property;
512 
513 	/* Define properties */
514 	XfdashboardLiveWindowSimpleProperties[PROP_WINDOW]=
515 		g_param_spec_object("window",
516 								"Window",
517 								"The window to show",
518 								XFDASHBOARD_TYPE_WINDOW_TRACKER_WINDOW,
519 								G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
520 
521 	XfdashboardLiveWindowSimpleProperties[PROP_DISPLAY_TYPE]=
522 		g_param_spec_enum("display-type",
523 							"Display type",
524 							"How to display the window",
525 							XFDASHBOARD_TYPE_LIVE_WINDOW_SIMPLE_DISPLAY_TYPE,
526 							XFDASHBOARD_LIVE_WINDOW_SIMPLE_DISPLAY_TYPE_LIVE_PREVIEW,
527 							G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
528 
529 	XfdashboardLiveWindowSimpleProperties[PROP_DESTROY_ON_CLOSE]=
530 		g_param_spec_boolean("destroy-on-close",
531 								"Destroy on close",
532 								"If this actor should be destroy when window was closed",
533 								TRUE,
534 								G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
535 
536 	g_object_class_install_properties(gobjectClass, PROP_LAST, XfdashboardLiveWindowSimpleProperties);
537 
538 	/* Define stylable properties */
539 	xfdashboard_actor_install_stylable_property(actorClass, XfdashboardLiveWindowSimpleProperties[PROP_DISPLAY_TYPE]);
540 
541 	/* Define signals */
542 	XfdashboardLiveWindowSimpleSignals[SIGNAL_GEOMETRY_CHANGED]=
543 		g_signal_new("geometry-changed",
544 						G_TYPE_FROM_CLASS(klass),
545 						G_SIGNAL_RUN_LAST,
546 						G_STRUCT_OFFSET(XfdashboardLiveWindowSimpleClass, geometry_changed),
547 						NULL,
548 						NULL,
549 						g_cclosure_marshal_VOID__VOID,
550 						G_TYPE_NONE,
551 						0);
552 
553 	XfdashboardLiveWindowSimpleSignals[SIGNAL_VISIBILITY_CHANGED]=
554 		g_signal_new("visibility-changed",
555 						G_TYPE_FROM_CLASS(klass),
556 						G_SIGNAL_RUN_LAST,
557 						G_STRUCT_OFFSET(XfdashboardLiveWindowSimpleClass, visibility_changed),
558 						NULL,
559 						NULL,
560 						g_cclosure_marshal_VOID__BOOLEAN,
561 						G_TYPE_NONE,
562 						1,
563 						G_TYPE_BOOLEAN);
564 
565 	XfdashboardLiveWindowSimpleSignals[SIGNAL_WORKSPACE_CHANGED]=
566 		g_signal_new("workspace-changed",
567 						G_TYPE_FROM_CLASS(klass),
568 						G_SIGNAL_RUN_LAST,
569 						G_STRUCT_OFFSET(XfdashboardLiveWindowSimpleClass, workspace_changed),
570 						NULL,
571 						NULL,
572 						g_cclosure_marshal_VOID__VOID,
573 						G_TYPE_NONE,
574 						0);
575 }
576 
577 /* Object initialization
578  * Create private structure and set up default values
579  */
xfdashboard_live_window_simple_init(XfdashboardLiveWindowSimple * self)580 static void xfdashboard_live_window_simple_init(XfdashboardLiveWindowSimple *self)
581 {
582 	XfdashboardLiveWindowSimplePrivate	*priv;
583 
584 	priv=self->priv=xfdashboard_live_window_simple_get_instance_private(self);
585 
586 	/* This actor reacts on events */
587 	clutter_actor_set_reactive(CLUTTER_ACTOR(self), TRUE);
588 
589 	/* Set default values */
590 	priv->window=NULL;
591 	priv->displayType=XFDASHBOARD_LIVE_WINDOW_SIMPLE_DISPLAY_TYPE_LIVE_PREVIEW;
592 	priv->destroyOnClose=TRUE;
593 
594 
595 	/* Set up child actors (order is important) */
596 	priv->actorWindow=clutter_actor_new();
597 	clutter_actor_show(priv->actorWindow);
598 	clutter_actor_add_child(CLUTTER_ACTOR(self), priv->actorWindow);
599 }
600 
601 /* IMPLEMENTATION: Public API */
602 
603 /* Create new instance */
xfdashboard_live_window_simple_new(void)604 ClutterActor* xfdashboard_live_window_simple_new(void)
605 {
606 	return(CLUTTER_ACTOR(g_object_new(XFDASHBOARD_TYPE_LIVE_WINDOW_SIMPLE, NULL)));
607 }
608 
xfdashboard_live_window_simple_new_for_window(XfdashboardWindowTrackerWindow * inWindow)609 ClutterActor* xfdashboard_live_window_simple_new_for_window(XfdashboardWindowTrackerWindow *inWindow)
610 {
611 	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL);
612 
613 	return(CLUTTER_ACTOR(g_object_new(XFDASHBOARD_TYPE_LIVE_WINDOW_SIMPLE,
614 										"window", inWindow,
615 										NULL)));
616 }
617 
618 /* Get/set window to show */
xfdashboard_live_window_simple_get_window(XfdashboardLiveWindowSimple * self)619 XfdashboardWindowTrackerWindow* xfdashboard_live_window_simple_get_window(XfdashboardLiveWindowSimple *self)
620 {
621 	g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self), NULL);
622 
623 	return(self->priv->window);
624 }
625 
xfdashboard_live_window_simple_set_window(XfdashboardLiveWindowSimple * self,XfdashboardWindowTrackerWindow * inWindow)626 void xfdashboard_live_window_simple_set_window(XfdashboardLiveWindowSimple *self, XfdashboardWindowTrackerWindow *inWindow)
627 {
628 	XfdashboardLiveWindowSimplePrivate	*priv;
629 
630 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self));
631 	g_return_if_fail(!inWindow || XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow));
632 
633 	priv=self->priv;
634 
635 	/* Only set value if it changes */
636 	if(inWindow==priv->window) return;
637 
638 	/* Release old value */
639 	if(priv->window)
640 	{
641 		g_signal_handlers_disconnect_by_data(priv->window, self);
642 		priv->window=NULL;
643 	}
644 
645 	/* Set new value
646 	 * Window tracker objects should never be refed or unrefed, so just set new value
647 	 */
648 	priv->window=inWindow;
649 	if(priv->window)
650 	{
651 		/* Get visibility state of window */
652 		priv->isVisible=_xfdashboard_live_window_simple_is_visible_window(self, priv->window);
653 
654 		/* Setup window actor content */
655 		_xfdashboard_live_window_simple_setup_content(self);
656 
657 		/* Set up this actor and child actor by calling each signal handler now */
658 		_xfdashboard_live_window_simple_on_geometry_changed(self, priv->window);
659 		_xfdashboard_live_window_simple_on_state_changed(self, 0, priv->window);
660 		_xfdashboard_live_window_simple_on_workspace_changed(self, NULL, priv->window);
661 
662 		/* Connect signal handlers */
663 		g_signal_connect_swapped(priv->window, "geometry-changed", G_CALLBACK(_xfdashboard_live_window_simple_on_geometry_changed), self);
664 		g_signal_connect_swapped(priv->window, "state-changed", G_CALLBACK(_xfdashboard_live_window_simple_on_state_changed), self);
665 		g_signal_connect_swapped(priv->window, "workspace-changed", G_CALLBACK(_xfdashboard_live_window_simple_on_workspace_changed), self);
666 		g_signal_connect_swapped(priv->window, "closed", G_CALLBACK(_xfdashboard_live_window_simple_on_closed), self);
667 	}
668 		else
669 		{
670 			/* Clean window actor */
671 			clutter_actor_set_content(priv->actorWindow, NULL);
672 
673 			/* Set window to invisible as NULL window is no window */
674 			priv->isVisible=FALSE;
675 		}
676 
677 	/* Notify about property change */
678 	g_object_notify_by_pspec(G_OBJECT(self), XfdashboardLiveWindowSimpleProperties[PROP_WINDOW]);
679 }
680 
681 /* Get/set display type of window */
xfdashboard_live_window_simple_get_display_type(XfdashboardLiveWindowSimple * self)682 XfdashboardLiveWindowSimpleDisplayType xfdashboard_live_window_simple_get_display_type(XfdashboardLiveWindowSimple *self)
683 {
684 	g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self), XFDASHBOARD_LIVE_WINDOW_SIMPLE_DISPLAY_TYPE_LIVE_PREVIEW);
685 
686 	return(self->priv->displayType);
687 }
688 
xfdashboard_live_window_simple_set_display_type(XfdashboardLiveWindowSimple * self,XfdashboardLiveWindowSimpleDisplayType inType)689 void xfdashboard_live_window_simple_set_display_type(XfdashboardLiveWindowSimple *self, XfdashboardLiveWindowSimpleDisplayType inType)
690 {
691 	XfdashboardLiveWindowSimplePrivate	*priv;
692 
693 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self));
694 	g_return_if_fail(inType>=XFDASHBOARD_LIVE_WINDOW_SIMPLE_DISPLAY_TYPE_LIVE_PREVIEW && inType<=XFDASHBOARD_LIVE_WINDOW_SIMPLE_DISPLAY_TYPE_ICON);
695 
696 	priv=self->priv;
697 
698 	/* Only set value if it changes */
699 	if(priv->displayType!=inType)
700 	{
701 		/* Set value */
702 		priv->displayType=inType;
703 
704 		/* Setup window actor content */
705 		_xfdashboard_live_window_simple_setup_content(self);
706 
707 		/* Notify about property change */
708 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardLiveWindowSimpleProperties[PROP_DISPLAY_TYPE]);
709 	}
710 }
711 
712 /* Get/set flag for destruction on window close */
xfdashboard_live_window_simple_get_destroy_on_close(XfdashboardLiveWindowSimple * self)713 gboolean xfdashboard_live_window_simple_get_destroy_on_close(XfdashboardLiveWindowSimple *self)
714 {
715 	g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self), FALSE);
716 
717 	return(self->priv->destroyOnClose);
718 }
719 
xfdashboard_live_window_simple_set_destroy_on_close(XfdashboardLiveWindowSimple * self,gboolean inDestroyOnClose)720 void xfdashboard_live_window_simple_set_destroy_on_close(XfdashboardLiveWindowSimple *self, gboolean inDestroyOnClose)
721 {
722 	XfdashboardLiveWindowSimplePrivate	*priv;
723 
724 	g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(self));
725 
726 	priv=self->priv;
727 
728 	/* Only set value if it changes */
729 	if(priv->destroyOnClose!=inDestroyOnClose)
730 	{
731 		/* Set value */
732 		priv->destroyOnClose=inDestroyOnClose;
733 
734 		/* Notify about property change */
735 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardLiveWindowSimpleProperties[PROP_DESTROY_ON_CLOSE]);
736 	}
737 }
738