[Xfce4-commits] [apps/xfdashboard] 01/01: Implemented enhancements to layout xml file to specify which actor of the focusable ones should be selected on theme load. The following changes were applied:

noreply at xfce.org noreply at xfce.org
Fri Apr 21 09:45:27 CEST 2017


This is an automated email from the git hooks/post-receive script.

nomad pushed a commit to branch master
in repository apps/xfdashboard.

commit 20920e77061d71ea82dd2ccea03c71b8e4a9f784
Author: Stephan Haller <nomad at froevel.de>
Date:   Fri Apr 21 09:42:14 2017 +0200

    Implemented enhancements to layout xml file to specify which actor of the focusable ones should	be selected on theme load. The following changes were applied:
    
    - Added a new optional attribute to <focus>, a sub-node of <focusables>, in layout xml files called "selected". This attribute "selected" is a boolean attribute and expects to be set to either "true" or "false". If set to "true" this actor will be selected instead of the search box. If set to "false" it has no impact and handled as this attribute does not exist.
    - The new optional attribute "selected" of <focus> is optional. If not used at all the old behaviour, selecting the search box by default, applies.
    - The new optional attribute "selected" of <focus> should only be used once over all layout xml	files. A warning will be printed if it used more than once but the theme will load successfully.
    - Removed unfocuable actor "view-selector" from	primary	stage interface	layout
    - Improved code at XfdashboardStage to use weak references instead of connecting signal which get called when actor is destroyed to set reference pointers to NULL
    - Modified packaged theme to use new theme possibilities
    - Fixed	typos
    
    This commit addresses issue GH #144
---
 .../xfdashboard-auber/xfdashboard-secondary.xml    |   6 +-
 data/themes/xfdashboard-auber/xfdashboard.xml      |   1 -
 .../xfdashboard-blue/xfdashboard-secondary.xml     |   6 +-
 data/themes/xfdashboard-blue/xfdashboard.xml       |   1 -
 .../xfdashboard-dark/xfdashboard-secondary.xml     |   6 +-
 data/themes/xfdashboard-dark/xfdashboard.xml       |   1 -
 .../xfdashboard-mint/xfdashboard-secondary.xml     |   6 +-
 data/themes/xfdashboard-mint/xfdashboard.xml       |   1 -
 .../xfdashboard-moranga/xfdashboard-secondary.xml  |   6 +-
 data/themes/xfdashboard-moranga/xfdashboard.xml    |   1 -
 .../xfdashboard-wine/xfdashboard-secondary.xml     |   6 +-
 data/themes/xfdashboard-wine/xfdashboard.xml       |   1 -
 data/themes/xfdashboard/xfdashboard-secondary.xml  |   6 +-
 data/themes/xfdashboard/xfdashboard.xml            |   1 -
 libxfdashboard/actor.c                             |   2 +-
 libxfdashboard/stage.c                             | 282 ++++++++++++++-------
 libxfdashboard/theme-layout.c                      | 260 ++++++++++++++-----
 libxfdashboard/theme-layout.h                      |  33 ++-
 18 files changed, 448 insertions(+), 178 deletions(-)

diff --git a/data/themes/xfdashboard-auber/xfdashboard-secondary.xml b/data/themes/xfdashboard-auber/xfdashboard-secondary.xml
index 8bb264a..95343f0 100644
--- a/data/themes/xfdashboard-auber/xfdashboard-secondary.xml
+++ b/data/themes/xfdashboard-auber/xfdashboard-secondary.xml
@@ -42,7 +42,7 @@
 				</child>
 
 				<child>
-					<object class="XfdashboardWindowsView">
+					<object class="XfdashboardWindowsView" id="windows-view">
 						<property name="view-id">windows</property>
 						<property name="x-expand">true</property>
 						<property name="y-expand">true</property>
@@ -51,4 +51,8 @@
 			</object>
 		</child>
 	</object>
+
+	<focusables>
+		<focus ref="windows-view" />
+	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-auber/xfdashboard.xml b/data/themes/xfdashboard-auber/xfdashboard.xml
index 2574715..0b268a3 100644
--- a/data/themes/xfdashboard-auber/xfdashboard.xml
+++ b/data/themes/xfdashboard-auber/xfdashboard.xml
@@ -137,6 +137,5 @@
 		<focus ref="viewpad" />
 		<focus ref="workspace-selector" />
 		<focus ref="quicklaunch" />
-		<focus ref="view-selector" />
 	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-blue/xfdashboard-secondary.xml b/data/themes/xfdashboard-blue/xfdashboard-secondary.xml
index 8bb264a..95343f0 100644
--- a/data/themes/xfdashboard-blue/xfdashboard-secondary.xml
+++ b/data/themes/xfdashboard-blue/xfdashboard-secondary.xml
@@ -42,7 +42,7 @@
 				</child>
 
 				<child>
-					<object class="XfdashboardWindowsView">
+					<object class="XfdashboardWindowsView" id="windows-view">
 						<property name="view-id">windows</property>
 						<property name="x-expand">true</property>
 						<property name="y-expand">true</property>
@@ -51,4 +51,8 @@
 			</object>
 		</child>
 	</object>
+
+	<focusables>
+		<focus ref="windows-view" />
+	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-blue/xfdashboard.xml b/data/themes/xfdashboard-blue/xfdashboard.xml
index 2574715..0b268a3 100644
--- a/data/themes/xfdashboard-blue/xfdashboard.xml
+++ b/data/themes/xfdashboard-blue/xfdashboard.xml
@@ -137,6 +137,5 @@
 		<focus ref="viewpad" />
 		<focus ref="workspace-selector" />
 		<focus ref="quicklaunch" />
-		<focus ref="view-selector" />
 	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-dark/xfdashboard-secondary.xml b/data/themes/xfdashboard-dark/xfdashboard-secondary.xml
index 8bb264a..95343f0 100644
--- a/data/themes/xfdashboard-dark/xfdashboard-secondary.xml
+++ b/data/themes/xfdashboard-dark/xfdashboard-secondary.xml
@@ -42,7 +42,7 @@
 				</child>
 
 				<child>
-					<object class="XfdashboardWindowsView">
+					<object class="XfdashboardWindowsView" id="windows-view">
 						<property name="view-id">windows</property>
 						<property name="x-expand">true</property>
 						<property name="y-expand">true</property>
@@ -51,4 +51,8 @@
 			</object>
 		</child>
 	</object>
+
+	<focusables>
+		<focus ref="windows-view" />
+	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-dark/xfdashboard.xml b/data/themes/xfdashboard-dark/xfdashboard.xml
index 2574715..0b268a3 100644
--- a/data/themes/xfdashboard-dark/xfdashboard.xml
+++ b/data/themes/xfdashboard-dark/xfdashboard.xml
@@ -137,6 +137,5 @@
 		<focus ref="viewpad" />
 		<focus ref="workspace-selector" />
 		<focus ref="quicklaunch" />
-		<focus ref="view-selector" />
 	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-mint/xfdashboard-secondary.xml b/data/themes/xfdashboard-mint/xfdashboard-secondary.xml
index 8bb264a..95343f0 100644
--- a/data/themes/xfdashboard-mint/xfdashboard-secondary.xml
+++ b/data/themes/xfdashboard-mint/xfdashboard-secondary.xml
@@ -42,7 +42,7 @@
 				</child>
 
 				<child>
-					<object class="XfdashboardWindowsView">
+					<object class="XfdashboardWindowsView" id="windows-view">
 						<property name="view-id">windows</property>
 						<property name="x-expand">true</property>
 						<property name="y-expand">true</property>
@@ -51,4 +51,8 @@
 			</object>
 		</child>
 	</object>
+
+	<focusables>
+		<focus ref="windows-view" />
+	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-mint/xfdashboard.xml b/data/themes/xfdashboard-mint/xfdashboard.xml
index 2574715..0b268a3 100644
--- a/data/themes/xfdashboard-mint/xfdashboard.xml
+++ b/data/themes/xfdashboard-mint/xfdashboard.xml
@@ -137,6 +137,5 @@
 		<focus ref="viewpad" />
 		<focus ref="workspace-selector" />
 		<focus ref="quicklaunch" />
-		<focus ref="view-selector" />
 	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-moranga/xfdashboard-secondary.xml b/data/themes/xfdashboard-moranga/xfdashboard-secondary.xml
index 8bb264a..95343f0 100644
--- a/data/themes/xfdashboard-moranga/xfdashboard-secondary.xml
+++ b/data/themes/xfdashboard-moranga/xfdashboard-secondary.xml
@@ -42,7 +42,7 @@
 				</child>
 
 				<child>
-					<object class="XfdashboardWindowsView">
+					<object class="XfdashboardWindowsView" id="windows-view">
 						<property name="view-id">windows</property>
 						<property name="x-expand">true</property>
 						<property name="y-expand">true</property>
@@ -51,4 +51,8 @@
 			</object>
 		</child>
 	</object>
+
+	<focusables>
+		<focus ref="windows-view" />
+	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-moranga/xfdashboard.xml b/data/themes/xfdashboard-moranga/xfdashboard.xml
index 2574715..0b268a3 100644
--- a/data/themes/xfdashboard-moranga/xfdashboard.xml
+++ b/data/themes/xfdashboard-moranga/xfdashboard.xml
@@ -137,6 +137,5 @@
 		<focus ref="viewpad" />
 		<focus ref="workspace-selector" />
 		<focus ref="quicklaunch" />
-		<focus ref="view-selector" />
 	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-wine/xfdashboard-secondary.xml b/data/themes/xfdashboard-wine/xfdashboard-secondary.xml
index 8bb264a..95343f0 100644
--- a/data/themes/xfdashboard-wine/xfdashboard-secondary.xml
+++ b/data/themes/xfdashboard-wine/xfdashboard-secondary.xml
@@ -42,7 +42,7 @@
 				</child>
 
 				<child>
-					<object class="XfdashboardWindowsView">
+					<object class="XfdashboardWindowsView" id="windows-view">
 						<property name="view-id">windows</property>
 						<property name="x-expand">true</property>
 						<property name="y-expand">true</property>
@@ -51,4 +51,8 @@
 			</object>
 		</child>
 	</object>
+
+	<focusables>
+		<focus ref="windows-view" />
+	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard-wine/xfdashboard.xml b/data/themes/xfdashboard-wine/xfdashboard.xml
index 2574715..0b268a3 100644
--- a/data/themes/xfdashboard-wine/xfdashboard.xml
+++ b/data/themes/xfdashboard-wine/xfdashboard.xml
@@ -137,6 +137,5 @@
 		<focus ref="viewpad" />
 		<focus ref="workspace-selector" />
 		<focus ref="quicklaunch" />
-		<focus ref="view-selector" />
 	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard/xfdashboard-secondary.xml b/data/themes/xfdashboard/xfdashboard-secondary.xml
index 8ff3e50..0c86858 100644
--- a/data/themes/xfdashboard/xfdashboard-secondary.xml
+++ b/data/themes/xfdashboard/xfdashboard-secondary.xml
@@ -50,7 +50,7 @@
 				</child>
 
 				<child>
-					<object class="XfdashboardWindowsView">
+					<object class="XfdashboardWindowsView" id="windows-view">
 						<property name="view-id">windows</property>
 						<property name="x-expand">true</property>
 						<property name="y-expand">true</property>
@@ -59,4 +59,8 @@
 			</object>
 		</child>
 	</object>
+
+	<focusables>
+		<focus ref="windows-view" />
+	</focusables>
 </interface>
diff --git a/data/themes/xfdashboard/xfdashboard.xml b/data/themes/xfdashboard/xfdashboard.xml
index 8bec014..35d99db 100644
--- a/data/themes/xfdashboard/xfdashboard.xml
+++ b/data/themes/xfdashboard/xfdashboard.xml
@@ -143,6 +143,5 @@
 		<focus ref="viewpad" />
 		<focus ref="workspace-selector" />
 		<focus ref="quicklaunch" />
-		<focus ref="view-selector" />
 	</focusables>
 </interface>
diff --git a/libxfdashboard/actor.c b/libxfdashboard/actor.c
index 61205a2..15b91b8 100644
--- a/libxfdashboard/actor.c
+++ b/libxfdashboard/actor.c
@@ -308,7 +308,7 @@ static gboolean _xfdashboard_actor_focusable_can_focus(XfdashboardFocusable *inF
 	self=XFDASHBOARD_ACTOR(inFocusable);
 	priv=self->priv;
 
-	/* This actor can only be focused if it is mapped, visibl	e and reactive */
+	/* This actor can only be focused if it is mapped, visible and reactive */
 	if(priv->canFocus &&
 		clutter_actor_is_mapped(CLUTTER_ACTOR(self)) &&
 		clutter_actor_is_visible(CLUTTER_ACTOR(self)) &&
diff --git a/libxfdashboard/stage.c b/libxfdashboard/stage.c
index 42a4024..64255ed 100644
--- a/libxfdashboard/stage.c
+++ b/libxfdashboard/stage.c
@@ -76,15 +76,14 @@ struct _XfdashboardStagePrivate
 	ClutterActor							*backgroundImageLayer;
 	ClutterActor							*backgroundColorLayer;
 
-	ClutterActor							*primaryInterface;
-
-	ClutterActor							*quicklaunch;
-	ClutterActor							*searchbox;
-	ClutterActor							*workspaces;
-	ClutterActor							*viewpad;
-	ClutterActor							*viewSelector;
-	ClutterActor							*notification;
-	ClutterActor							*tooltip;
+	gpointer								primaryInterface;
+	gpointer								quicklaunch;
+	gpointer								searchbox;
+	gpointer								workspaces;
+	gpointer								viewpad;
+	gpointer								viewSelector;
+	gpointer								notification;
+	gpointer								tooltip;
 
 	/* Instance related */
 	XfdashboardWindowTracker				*windowTracker;
@@ -94,6 +93,7 @@ struct _XfdashboardStagePrivate
 	gint									lastSearchTextLength;
 	XfdashboardView							*viewBeforeSearch;
 	gchar									*switchToView;
+	gpointer								focusActorOnShow;
 
 	guint									notificationTimeoutID;
 
@@ -143,6 +143,14 @@ static guint XfdashboardStageSignals[SIGNAL_LAST]={ 0, };
 #define XFDASHBOARD_THEME_LAYOUT_PRIMARY				"primary"
 #define XFDASHBOARD_THEME_LAYOUT_SECONDARY				"secondary"
 
+typedef struct _XfdashboardStageThemeInterfaceData		XfdashboardStageThemeInterfaceData;
+struct _XfdashboardStageThemeInterfaceData
+{
+	ClutterActor		*actor;
+	GPtrArray			*focusables;
+	ClutterActor		*focus;
+};
+
 /* Handle an event */
 static gboolean _xfdashboard_stage_event(ClutterActor *inActor, ClutterEvent *inEvent)
 {
@@ -226,16 +234,15 @@ static gboolean _xfdashboard_stage_event(ClutterActor *inActor, ClutterEvent *in
 static void _xfdashboard_stage_set_focus(XfdashboardStage *self)
 {
 	XfdashboardStagePrivate		*priv;
-	ClutterActor				*actor;
+	XfdashboardFocusable		*actor;
 
 	g_return_if_fail(XFDASHBOARD_IS_STAGE(self));
 
 	priv=self->priv;
 
 	/* Set focus if no focus is set */
-	actor=clutter_stage_get_key_focus(CLUTTER_STAGE(self));
-	if(!XFDASHBOARD_IS_FOCUSABLE(actor) ||
-		!xfdashboard_focus_manager_is_registered(priv->focusManager, XFDASHBOARD_FOCUSABLE(actor)))
+	actor=xfdashboard_focus_manager_get_focus(priv->focusManager);
+	if(!actor)
 	{
 		XfdashboardFocusable	*focusable;
 
@@ -762,38 +769,34 @@ static void _xfdashboard_stage_on_application_resume(XfdashboardStage *self, gpo
 	clutter_actor_queue_redraw(CLUTTER_ACTOR(self));
 }
 
-/* Callback function to to set reference to NULL in stage object
- * when an actor of special interest like searchbox, notification etc.
- * is going to be destroyed.
- */
-static void _xfdashboard_stage_reset_reference_on_destroy(ClutterActor *inActor,
-															gpointer inUserData)
+/* Theme in application has changed */
+static void _xfdashboard_stage_theme_interface_data_free(XfdashboardStageThemeInterfaceData *inData)
 {
-	ClutterActor			**actorReference;
+	g_return_if_fail(inData);
 
-	g_return_if_fail(CLUTTER_IS_ACTOR(inActor));
-	g_return_if_fail(inUserData);
+	/* Release each data in data structure but do not unref the interface actor
+	 * as it might be used at stage. The stage is responsible to destroy the
+	 * interface actor in *any* case.
+	 */
+	if(inData->focusables) g_ptr_array_unref(inData->focusables);
+	if(inData->focus) g_object_unref(inData->focus);
 
-	actorReference=(ClutterActor**)inUserData;
+	/* Release allocated memory */
+	g_free(inData);
+}
 
-	/* User data points to address in stage object which holds a pointer to address
-	 * of the actor which is going to be destroyed. So we should check that the value
-	 * at the address in user data contains the address of the actor which is going
-	 * to be destroyed. If it is reset value at address in user data to NULL otherwise
-	 * leave value untouched but show critical warning because this function should
-	 * never be called in this case.
-	 */
-	if(*actorReference!=inActor)
-	{
-		g_critical("Will not reset reference to actor of type %s at address %p because address in stage object points to %p and does not match actor's address.",
-					G_OBJECT_TYPE_NAME(inActor),
-					inActor,
-					*actorReference);
-	}
-		else *actorReference=NULL;
+static XfdashboardStageThemeInterfaceData* _xfdashboard_stage_theme_interface_data_new(void)
+{
+	XfdashboardStageThemeInterfaceData   *data;
+
+	/* Allocate memory for data structure */
+	data=g_new0(XfdashboardStageThemeInterfaceData, 1);
+	if(!data) return(NULL);
+
+	/* Return newly create and initialized data structure */
+	return(data);
 }
 
-/* Theme in application has changed */
 static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *self,
 															XfdashboardTheme *inTheme,
 															gpointer inUserData)
@@ -801,14 +804,13 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 	XfdashboardStagePrivate				*priv;
 	XfdashboardThemeLayout				*themeLayout;
 	GList								*interfaces;
-	ClutterActor						*interface;
+	XfdashboardStageThemeInterfaceData	*interface;
 	GList								*iter;
 	GList								*monitors;
 	XfdashboardWindowTrackerMonitor		*monitor;
 	ClutterActorIter					childIter;
 	ClutterActor						*child;
 	GObject								*focusObject;
-	GPtrArray							*interfaceFocusTable;
 	guint								i;
 
 	g_return_if_fail(XFDASHBOARD_IS_STAGE(self));
@@ -834,21 +836,27 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 			if(xfdashboard_window_tracker_monitor_is_primary(monitor))
 			{
 				/* Get interface for primary monitor */
-				interface=xfdashboard_theme_layout_build_interface(themeLayout, XFDASHBOARD_THEME_LAYOUT_PRIMARY);
-				if(!interface)
+				interface=_xfdashboard_stage_theme_interface_data_new();
+				interface->actor=xfdashboard_theme_layout_build_interface(themeLayout,
+																			XFDASHBOARD_THEME_LAYOUT_PRIMARY,
+																			XFDASHBOARD_THEME_LAYOUT_BUILD_GET_FOCUSABLES, &interface->focusables,
+																			XFDASHBOARD_THEME_LAYOUT_BUILD_GET_SELECTED_FOCUS, &interface->focus,
+																			-1);
+				if(!interface->actor)
 				{
 					g_critical(_("Could not build interface '%s' from theme '%s'"),
 								XFDASHBOARD_THEME_LAYOUT_PRIMARY,
 								xfdashboard_theme_get_theme_name(inTheme));
 
 					/* Release allocated resources */
-					g_list_foreach(interfaces, (GFunc)g_object_unref, NULL);
+					_xfdashboard_stage_theme_interface_data_free(interface);
+					g_list_foreach(interfaces, (GFunc)_xfdashboard_stage_theme_interface_data_free, NULL);
 					g_list_free(interfaces);
 
 					return;
 				}
 
-				if(!XFDASHBOARD_IS_STAGE_INTERFACE(interface))
+				if(!XFDASHBOARD_IS_STAGE_INTERFACE(interface->actor))
 				{
 					g_critical(_("Interface '%s' from theme '%s' must be an actor of type %s"),
 								XFDASHBOARD_THEME_LAYOUT_PRIMARY,
@@ -856,7 +864,8 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 								g_type_name(XFDASHBOARD_TYPE_STAGE_INTERFACE));
 
 					/* Release allocated resources */
-					g_list_foreach(interfaces, (GFunc)g_object_unref, NULL);
+					_xfdashboard_stage_theme_interface_data_free(interface);
+					g_list_foreach(interfaces, (GFunc)_xfdashboard_stage_theme_interface_data_free, NULL);
 					g_list_free(interfaces);
 
 					return;
@@ -867,13 +876,18 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 					/* Get interface for non-primary monitors. If no interface
 					 * is defined in theme then create an empty interface.
 					 */
-					interface=xfdashboard_theme_layout_build_interface(themeLayout, XFDASHBOARD_THEME_LAYOUT_SECONDARY);
-					if(!interface)
+					interface=_xfdashboard_stage_theme_interface_data_new();
+					interface->actor=xfdashboard_theme_layout_build_interface(themeLayout,
+																				XFDASHBOARD_THEME_LAYOUT_SECONDARY,
+																				XFDASHBOARD_THEME_LAYOUT_BUILD_GET_FOCUSABLES, &interface->focusables,
+																				XFDASHBOARD_THEME_LAYOUT_BUILD_GET_SELECTED_FOCUS, &interface->focus,
+																				-1);
+					if(!interface->actor)
 					{
-						interface=xfdashboard_stage_interface_new();
+						interface->actor=xfdashboard_stage_interface_new();
 					}
 
-					if(!XFDASHBOARD_IS_STAGE_INTERFACE(interface))
+					if(!XFDASHBOARD_IS_STAGE_INTERFACE(interface->actor))
 					{
 						g_critical(_("Interface '%s' from theme '%s' must be an actor of type %s"),
 									XFDASHBOARD_THEME_LAYOUT_SECONDARY,
@@ -881,7 +895,8 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 									g_type_name(XFDASHBOARD_TYPE_STAGE_INTERFACE));
 
 						/* Release allocated resources */
-						g_list_foreach(interfaces, (GFunc)g_object_unref, NULL);
+						_xfdashboard_stage_theme_interface_data_free(interface);
+						g_list_foreach(interfaces, (GFunc)_xfdashboard_stage_theme_interface_data_free, NULL);
 						g_list_free(interfaces);
 
 						return;
@@ -889,7 +904,7 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 				}
 
 			/* Set monitor at interface */
-			xfdashboard_stage_interface_set_monitor(XFDASHBOARD_STAGE_INTERFACE(interface), monitor);
+			xfdashboard_stage_interface_set_monitor(XFDASHBOARD_STAGE_INTERFACE(interface->actor), monitor);
 
 			/* Add interface to list of interfaces */
 			interfaces=g_list_prepend(interfaces, interface);
@@ -901,21 +916,38 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 		else
 		{
 			/* Get interface for primary monitor */
-			interface=xfdashboard_theme_layout_build_interface(themeLayout, XFDASHBOARD_THEME_LAYOUT_PRIMARY);
-			if(!interface)
+			interface=_xfdashboard_stage_theme_interface_data_new();
+			interface->actor=xfdashboard_theme_layout_build_interface(themeLayout,
+																		XFDASHBOARD_THEME_LAYOUT_PRIMARY,
+																		XFDASHBOARD_THEME_LAYOUT_BUILD_GET_FOCUSABLES, &interface->focusables,
+																		XFDASHBOARD_THEME_LAYOUT_BUILD_GET_SELECTED_FOCUS, &interface->focus,
+																		-1);
+			if(!interface->actor)
 			{
 				g_critical(_("Could not build interface '%s' from theme '%s'"),
 							XFDASHBOARD_THEME_LAYOUT_PRIMARY,
 							xfdashboard_theme_get_theme_name(inTheme));
+
+				/* Release allocated resources */
+				_xfdashboard_stage_theme_interface_data_free(interface);
+				g_list_foreach(interfaces, (GFunc)_xfdashboard_stage_theme_interface_data_free, NULL);
+				g_list_free(interfaces);
+
 				return;
 			}
 
-			if(!XFDASHBOARD_IS_STAGE_INTERFACE(interface))
+			if(!XFDASHBOARD_IS_STAGE_INTERFACE(interface->actor))
 			{
 				g_critical(_("Interface '%s' from theme '%s' must be an actor of type %s"),
 							XFDASHBOARD_THEME_LAYOUT_PRIMARY,
 							xfdashboard_theme_get_theme_name(inTheme),
 							g_type_name(XFDASHBOARD_TYPE_STAGE_INTERFACE));
+
+				/* Release allocated resources */
+				_xfdashboard_stage_theme_interface_data_free(interface);
+				g_list_foreach(interfaces, (GFunc)_xfdashboard_stage_theme_interface_data_free, NULL);
+				g_list_free(interfaces);
+
 				return;
 			}
 
@@ -943,26 +975,26 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 	for(iter=interfaces; iter; iter=g_list_next(iter))
 	{
 		/* Get interface to add to stage */
-		interface=CLUTTER_ACTOR(iter->data);
+		interface=(XfdashboardStageThemeInterfaceData*)(iter->data);
 		if(!interface) continue;
 
-		/* Get focus table of interface */
-		interfaceFocusTable=g_object_get_qdata(G_OBJECT(interface), XFDASHBOARD_THEME_LAYOUT_FOCUS_TABLE_DATA);
+		/* Check for interface actor to add to stage */
+		if(!interface->actor) continue;
 
 		/* Add interface to stage */
-		clutter_actor_add_child(CLUTTER_ACTOR(self), interface);
+		clutter_actor_add_child(CLUTTER_ACTOR(self), interface->actor);
 
 		/* Only check children, set up pointer variables to quicklaunch, searchbox etc.
 		 * and connect signals for primary monitor.
 		 */
-		monitor=xfdashboard_stage_interface_get_monitor(XFDASHBOARD_STAGE_INTERFACE(interface));
+		monitor=xfdashboard_stage_interface_get_monitor(XFDASHBOARD_STAGE_INTERFACE(interface->actor));
 		if(!monitor || xfdashboard_window_tracker_monitor_is_primary(monitor))
 		{
 			/* Remember primary interface */
 			if(!priv->primaryInterface)
 			{
-				priv->primaryInterface=interface;
-				g_signal_connect(priv->primaryInterface, "destroy", G_CALLBACK(_xfdashboard_stage_reset_reference_on_destroy), &priv->primaryInterface);
+				priv->primaryInterface=interface->actor;
+				g_object_add_weak_pointer(G_OBJECT(priv->primaryInterface), &priv->primaryInterface);
 			}
 				else g_critical(_("Invalid multiple stages for primary monitor"));
 
@@ -972,10 +1004,10 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 			if(child && XFDASHBOARD_IS_VIEW_SELECTOR(child))
 			{
 				priv->viewSelector=child;
-				g_signal_connect(child, "destroy", G_CALLBACK(_xfdashboard_stage_reset_reference_on_destroy), &priv->viewSelector);
+				g_object_add_weak_pointer(G_OBJECT(priv->viewSelector), &priv->viewSelector);
 
 				/* Register this focusable actor if it is focusable */
-				if(!interfaceFocusTable && XFDASHBOARD_IS_FOCUSABLE(priv->viewSelector))
+				if(!interface->focusables && XFDASHBOARD_IS_FOCUSABLE(priv->viewSelector))
 				{
 					xfdashboard_focus_manager_register(priv->focusManager,
 														XFDASHBOARD_FOCUSABLE(priv->viewSelector));
@@ -987,7 +1019,7 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 			if(child && XFDASHBOARD_IS_TEXT_BOX(child))
 			{
 				priv->searchbox=child;
-				g_signal_connect(child, "destroy", G_CALLBACK(_xfdashboard_stage_reset_reference_on_destroy), &priv->searchbox);
+				g_object_add_weak_pointer(G_OBJECT(priv->searchbox), &priv->searchbox);
 
 				/* If no hint-text was defined, set default one */
 				if(!xfdashboard_text_box_is_hint_text_set(XFDASHBOARD_TEXT_BOX(priv->searchbox)))
@@ -1007,7 +1039,7 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 											self);
 
 				/* Register this focusable actor if it is focusable */
-				if(!interfaceFocusTable && XFDASHBOARD_IS_FOCUSABLE(priv->searchbox))
+				if(!interface->focusables && XFDASHBOARD_IS_FOCUSABLE(priv->searchbox))
 				{
 					xfdashboard_focus_manager_register(priv->focusManager,
 														XFDASHBOARD_FOCUSABLE(priv->searchbox));
@@ -1019,13 +1051,13 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 			if(child && XFDASHBOARD_IS_VIEWPAD(child))
 			{
 				priv->viewpad=child;
-				g_signal_connect(child, "destroy", G_CALLBACK(_xfdashboard_stage_reset_reference_on_destroy), &priv->viewpad);
+				g_object_add_weak_pointer(G_OBJECT(priv->viewpad), &priv->viewpad);
 
 				/* Connect signals */
 				g_signal_connect_swapped(priv->viewpad, "view-activated", G_CALLBACK(_xfdashboard_stage_on_view_activated), self);
 
 				/* Register this focusable actor if it is focusable */
-				if(!interfaceFocusTable && XFDASHBOARD_IS_FOCUSABLE(priv->viewpad))
+				if(!interface->focusables && XFDASHBOARD_IS_FOCUSABLE(priv->viewpad))
 				{
 					xfdashboard_focus_manager_register(priv->focusManager,
 														XFDASHBOARD_FOCUSABLE(priv->viewpad));
@@ -1045,7 +1077,7 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 				XfdashboardToggleButton		*appsButton;
 
 				priv->quicklaunch=child;
-				g_signal_connect(child, "destroy", G_CALLBACK(_xfdashboard_stage_reset_reference_on_destroy), &priv->quicklaunch);
+				g_object_add_weak_pointer(G_OBJECT(priv->quicklaunch), &priv->quicklaunch);
 
 				/* Connect signals */
 				appsButton=xfdashboard_quicklaunch_get_apps_button(XFDASHBOARD_QUICKLAUNCH(priv->quicklaunch));
@@ -1058,7 +1090,7 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 				}
 
 				/* Register this focusable actor if it is focusable */
-				if(!interfaceFocusTable && XFDASHBOARD_IS_FOCUSABLE(priv->quicklaunch))
+				if(!interface->focusables && XFDASHBOARD_IS_FOCUSABLE(priv->quicklaunch))
 				{
 					xfdashboard_focus_manager_register(priv->focusManager,
 														XFDASHBOARD_FOCUSABLE(priv->quicklaunch));
@@ -1070,10 +1102,10 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 			if(child && XFDASHBOARD_IS_WORKSPACE_SELECTOR(child))
 			{
 				priv->workspaces=child;
-				g_signal_connect(child, "destroy", G_CALLBACK(_xfdashboard_stage_reset_reference_on_destroy), &priv->workspaces);
+				g_object_add_weak_pointer(G_OBJECT(priv->workspaces), &priv->workspaces);
 
 				/* Register this focusable actor if it is focusable */
-				if(!interfaceFocusTable && XFDASHBOARD_IS_FOCUSABLE(priv->workspaces))
+				if(!interface->focusables && XFDASHBOARD_IS_FOCUSABLE(priv->workspaces))
 				{
 					xfdashboard_focus_manager_register(priv->focusManager,
 														XFDASHBOARD_FOCUSABLE(priv->workspaces));
@@ -1085,10 +1117,10 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 			if(child && XFDASHBOARD_IS_TEXT_BOX(child))
 			{
 				priv->notification=child;
-				g_signal_connect(child, "destroy", G_CALLBACK(_xfdashboard_stage_reset_reference_on_destroy), &priv->notification);
+				g_object_add_weak_pointer(G_OBJECT(priv->notification), &priv->notification);
 
 				/* Register this focusable actor if it is focusable */
-				if(!interfaceFocusTable && XFDASHBOARD_IS_FOCUSABLE(priv->notification))
+				if(!interface->focusables && XFDASHBOARD_IS_FOCUSABLE(priv->notification))
 				{
 					xfdashboard_focus_manager_register(priv->focusManager,
 														XFDASHBOARD_FOCUSABLE(priv->notification));
@@ -1104,10 +1136,10 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 			if(child && XFDASHBOARD_IS_TEXT_BOX(child))
 			{
 				priv->tooltip=child;
-				g_signal_connect(child, "destroy", G_CALLBACK(_xfdashboard_stage_reset_reference_on_destroy), &priv->tooltip);
+				g_object_add_weak_pointer(G_OBJECT(priv->tooltip), &priv->tooltip);
 
 				/* Register this focusable actor if it is focusable */
-				if(!interfaceFocusTable && XFDASHBOARD_IS_FOCUSABLE(priv->tooltip))
+				if(!interface->focusables && XFDASHBOARD_IS_FOCUSABLE(priv->tooltip))
 				{
 					xfdashboard_focus_manager_register(priv->focusManager,
 														XFDASHBOARD_FOCUSABLE(priv->tooltip));
@@ -1117,37 +1149,83 @@ static void _xfdashboard_stage_on_application_theme_changed(XfdashboardStage *se
 				clutter_actor_hide(priv->tooltip);
 				clutter_actor_set_reactive(priv->tooltip, FALSE);
 			}
-		}
 
-		/* Register focusable actors at focus manager */
-		if(interfaceFocusTable)
-		{
-			for(i=0; i<interfaceFocusTable->len; i++)
+			/* Register focusable actors at focus manager */
+			if(interface->focusables)
 			{
-				/* Get actor to register at focus manager */
-				focusObject=G_OBJECT(g_ptr_array_index(interfaceFocusTable, i));
-				if(!focusObject) continue;
+				for(i=0; i<interface->focusables->len; i++)
+				{
+					/* Get actor to register at focus manager */
+					focusObject=G_OBJECT(g_ptr_array_index(interface->focusables, i));
+					if(!focusObject) continue;
 
-				/* Check that actor is focusable */
-				if(!XFDASHBOARD_IS_FOCUSABLE(focusObject))
+					/* Check that actor is focusable */
+					if(!XFDASHBOARD_IS_FOCUSABLE(focusObject))
+					{
+						g_warning("Object %s is not focusable and cannot be registered.",
+									G_OBJECT_TYPE_NAME(focusObject));
+						continue;
+					}
+
+					/* Register actor at focus manager */
+					xfdashboard_focus_manager_register(priv->focusManager,
+														XFDASHBOARD_FOCUSABLE(focusObject));
+					XFDASHBOARD_DEBUG(self, ACTOR,
+										"Registering actor %s of interface with ID '%s' at focus manager",
+										G_OBJECT_TYPE_NAME(focusObject),
+										clutter_actor_get_name(interface->actor));
+				}
+			}
+
+			/* Move focus to selected actor or remember actor focus to set it later
+			 * but only if selected actor is a focusable actor and is registered
+			 * to focus manager.
+			 */
+			if(interface->focus &&
+				XFDASHBOARD_IS_FOCUSABLE(interface->focus) &&
+				xfdashboard_focus_manager_is_registered(priv->focusManager, XFDASHBOARD_FOCUSABLE(interface->focus)))
+			{
+				/* If actor can be focused then move focus to actor ... */
+				if(xfdashboard_focusable_can_focus(XFDASHBOARD_FOCUSABLE(interface->focus)))
 				{
-					g_warning("Object %s is not focusable and cannot be registered.",
-								G_OBJECT_TYPE_NAME(focusObject));
-					continue;
+					xfdashboard_focus_manager_set_focus(priv->focusManager, XFDASHBOARD_FOCUSABLE(interface->focus));
+					XFDASHBOARD_DEBUG(self, ACTOR,
+										"Moved focus to actor %s of interface with ID '%s'",
+										G_OBJECT_TYPE_NAME(interface->focus),
+										clutter_actor_get_name(interface->actor));
 				}
+					/* ... otherwise if stage is not visible, remember the actor
+					 * to focus to move the focus to it as soon as stage is
+					 * visible ...
+					 */
+					else if(!clutter_actor_is_visible(CLUTTER_ACTOR(self)))
+					{
+						priv->focusActorOnShow=XFDASHBOARD_FOCUSABLE(interface->focus);
+						g_object_add_weak_pointer(G_OBJECT(priv->focusActorOnShow), &priv->focusActorOnShow);
 
-				/* Register actor at focus manager */
-				xfdashboard_focus_manager_register(priv->focusManager,
-													XFDASHBOARD_FOCUSABLE(focusObject));
-				XFDASHBOARD_DEBUG(self, ACTOR,
-									"Registering actor %s of interface with ID '%s' at focus manager",
-									G_OBJECT_TYPE_NAME(focusObject),
-									clutter_actor_get_name(interface));
+						XFDASHBOARD_DEBUG(self, ACTOR,
+											"Cannot move focus to actor %s of interface with ID '%s' but will try again when stage is visible",
+											G_OBJECT_TYPE_NAME(interface->focus),
+											clutter_actor_get_name(interface->actor));
+					}
+					/* ... otherwise just show a debug message */
+					else
+					{
+						XFDASHBOARD_DEBUG(self, ACTOR,
+											"Cannot move focus to actor %s of interface with ID '%s' because actor cannot be focused",
+											G_OBJECT_TYPE_NAME(interface->focus),
+											clutter_actor_get_name(interface->actor));
+					}
 			}
+				else
+				{
+					XFDASHBOARD_DEBUG(self, ACTOR, "Cannot move focus to any actor because no one was selected in theme");
+				}
 		}
 	}
 
 	/* Release allocated resources */
+	g_list_foreach(interfaces, (GFunc)_xfdashboard_stage_theme_interface_data_free, NULL);
 	g_list_free(interfaces);
 
 	/* Set focus */
@@ -1399,6 +1477,17 @@ static void _xfdashboard_stage_show(ClutterActor *inActor)
 	{
 		CLUTTER_ACTOR_CLASS(xfdashboard_stage_parent_class)->show(inActor);
 	}
+
+	/* Now move focus to actor is one was remembered when theme was loaded */
+	if(priv->focusActorOnShow)
+	{
+		/* Move focus to actor */
+		xfdashboard_focus_manager_set_focus(priv->focusManager, XFDASHBOARD_FOCUSABLE(priv->focusActorOnShow));
+
+		/* Forget actor to focus now ;) */
+		g_object_remove_weak_pointer(G_OBJECT(priv->focusActorOnShow), &priv->focusActorOnShow);
+		priv->focusActorOnShow=NULL;
+	}
 }
 
 /* IMPLEMENTATION: GObject */
@@ -1727,6 +1816,7 @@ static void xfdashboard_stage_init(XfdashboardStage *self)
 	priv->backgroundColorLayer=NULL;
 	priv->backgroundImageLayer=NULL;
 	priv->switchToView=NULL;
+	priv->focusActorOnShow=NULL;
 
 	/* Create background actors but order of adding background children is important */
 	widthConstraint=clutter_bind_constraint_new(CLUTTER_ACTOR(self), CLUTTER_BIND_WIDTH, 0.0f);
diff --git a/libxfdashboard/theme-layout.c b/libxfdashboard/theme-layout.c
index 7d0799b..7337f9c 100644
--- a/libxfdashboard/theme-layout.c
+++ b/libxfdashboard/theme-layout.c
@@ -31,6 +31,7 @@
 #include <glib.h>
 #include <gio/gio.h>
 
+#include <libxfdashboard/enums.h>
 #include <libxfdashboard/utils.h>
 #include <libxfdashboard/compat.h>
 #include <libxfdashboard/debug.h>
@@ -41,6 +42,13 @@ G_DEFINE_TYPE(XfdashboardThemeLayout,
 				xfdashboard_theme_layout,
 				G_TYPE_OBJECT)
 
+/* Forward declaration */
+typedef struct _XfdashboardThemeLayoutTagData				XfdashboardThemeLayoutTagData;
+typedef struct _XfdashboardThemeLayoutParsedObject			XfdashboardThemeLayoutParsedObject;
+typedef struct _XfdashboardThemeLayoutParserData			XfdashboardThemeLayoutParserData;
+typedef struct _XfdashboardThemeLayoutUnresolvedBuildID		XfdashboardThemeLayoutUnresolvedBuildID;
+typedef struct _XfdashboardThemeLayoutCheckRefID			XfdashboardThemeLayoutCheckRefID;
+
 /* Private structure - access only by public API if needed */
 #define XFDASHBOARD_THEME_LAYOUT_GET_PRIVATE(obj) \
 	(G_TYPE_INSTANCE_GET_PRIVATE((obj), XFDASHBOARD_TYPE_THEME_LAYOUT, XfdashboardThemeLayoutPrivate))
@@ -48,7 +56,9 @@ G_DEFINE_TYPE(XfdashboardThemeLayout,
 struct _XfdashboardThemeLayoutPrivate
 {
 	/* Instance related */
-	GSList			*interfaces;
+	GSList								*interfaces;
+
+	XfdashboardThemeLayoutTagData		*focusSelected;
 };
 
 /* IMPLEMENTATION: Private variables and methods */
@@ -65,7 +75,6 @@ enum
 	TAG_FOCUS
 };
 
-typedef struct _XfdashboardThemeLayoutTagData			XfdashboardThemeLayoutTagData;
 struct _XfdashboardThemeLayoutTagData
 {
 	gint								refCount;
@@ -91,11 +100,11 @@ struct _XfdashboardThemeLayoutTagData
 		struct
 		{
 			gchar						*refID;
+			gboolean					selected;
 		} focus;
 	} tag;
 };
 
-typedef struct _XfdashboardThemeLayoutParsedObject		XfdashboardThemeLayoutParsedObject;
 struct _XfdashboardThemeLayoutParsedObject
 {
 	gint								refCount;
@@ -109,7 +118,6 @@ struct _XfdashboardThemeLayoutParsedObject
 	GPtrArray							*focusables;	/* 0, 1 or more entries of XfdashboardThemeLayoutTagData (only used at <interface>) */
 };
 
-typedef struct _XfdashboardThemeLayoutParserData		XfdashboardThemeLayoutParserData;
 struct _XfdashboardThemeLayoutParserData
 {
 	XfdashboardThemeLayout				*self;
@@ -122,16 +130,22 @@ struct _XfdashboardThemeLayoutParserData
 	gint								lastLine;
 	gint								lastPosition;
 	gint								currentLine;
-	gint								currentPostition;;
+	gint								currentPostition;
+	const gchar							*currentPath;
 };
 
-typedef struct _XfdashboardThemeLayoutUnresolvedBuildID		XfdashboardThemeLayoutUnresolvedBuildID;
 struct _XfdashboardThemeLayoutUnresolvedBuildID
 {
 	GObject								*targetObject;
 	XfdashboardThemeLayoutTagData		*property;
 };
 
+struct _XfdashboardThemeLayoutCheckRefID
+{
+	XfdashboardThemeLayout				*self;
+	GHashTable							*ids;
+};
+
 /* Forward declarations */
 static void _xfdashboard_theme_layout_parse_set_error(XfdashboardThemeLayoutParserData *inParserData,
 														GMarkupParseContext *inContext,
@@ -250,7 +264,8 @@ static void _xfdashboard_theme_layout_parse_set_error(XfdashboardThemeLayoutPars
 	if(inParserData)
 	{
 		g_prefix_error(&tempError,
-						_("Error on line %d char %d: "),
+						_("File %s - Error on line %d char %d: "),
+						inParserData->currentPath,
 						inParserData->lastLine,
 						inParserData->lastPosition);
 	}
@@ -554,16 +569,23 @@ static void _xfdashboard_theme_layout_create_object_free_unresolved(gpointer inD
  */
 static void _xfdashboard_theme_layout_create_object_resolve_unresolved(XfdashboardThemeLayout *self,
 																		GHashTable *inIDs,
-																		GSList *inUnresolvedIDs)
+																		GSList *inUnresolvedIDs,
+																		va_list inArgs)
 {
 	GSList										*iter;
 	XfdashboardThemeLayoutUnresolvedBuildID		*unresolvedID;
 	GObject										*refObject;
 	GPtrArray									*focusTable;
+	ClutterActor								*focusSelected;
+	gint										extraDataID;
+	gpointer									*extraDataStorage;
 
 	g_return_if_fail(XFDASHBOARD_IS_THEME_LAYOUT(self));
 	g_return_if_fail(inIDs);
 
+	focusTable=NULL;
+	focusSelected=NULL;
+
 	/* Return if no list of unresolved IDs is provided */
 	if(!inUnresolvedIDs) return;
 
@@ -600,16 +622,8 @@ static void _xfdashboard_theme_layout_create_object_resolve_unresolved(Xfdashboa
 				/* Get referenced object */
 				refObject=g_hash_table_lookup(inIDs, unresolvedID->property->tag.focus.refID);
 
-				/* Get current focus table from object */
-				focusTable=g_object_get_qdata(unresolvedID->targetObject, XFDASHBOARD_THEME_LAYOUT_FOCUS_TABLE_DATA);
-				if(!focusTable)
-				{
-					focusTable=g_ptr_array_new();
-					g_object_set_qdata_full(unresolvedID->targetObject,
-											XFDASHBOARD_THEME_LAYOUT_FOCUS_TABLE_DATA,
-											focusTable,
-											(GDestroyNotify)g_ptr_array_unref);
-				}
+				/* Store reference object in list of focusable actors */
+				if(!focusTable) focusTable=g_ptr_array_new();
 				g_ptr_array_add(focusTable, refObject);
 
 				XFDASHBOARD_DEBUG(self, THEME,
@@ -617,14 +631,75 @@ static void _xfdashboard_theme_layout_create_object_resolve_unresolved(Xfdashboa
 									refObject ? G_OBJECT_TYPE_NAME(refObject) : "<unknown object>",
 									unresolvedID->property->tag.focus.refID,
 									unresolvedID->targetObject ? G_OBJECT_TYPE_NAME(unresolvedID->targetObject) : "<unknown object>");
+
+				/* If focusable actor is pre-selected and no other pre-selected
+				 * one was seen so far, remember it now.
+				 */
+				if(!focusSelected && unresolvedID->property->tag.focus.selected)
+				{
+					focusSelected=g_object_ref(refObject);
+
+					XFDASHBOARD_DEBUG(self, THEME,
+										"Remember resolved focusable actor %s with reference ID '%s' as pre-selected actor at target object %s ",
+										refObject ? G_OBJECT_TYPE_NAME(refObject) : "<unknown object>",
+										unresolvedID->property->tag.focus.refID,
+										unresolvedID->targetObject ? G_OBJECT_TYPE_NAME(unresolvedID->targetObject) : "<unknown object>");
+				}
 				break;
 
 			default:
 				g_critical(_("Unsupported tag type '%s' to resolve ID"),
 							_xfdashboard_theme_layout_get_tag_by_id(unresolvedID->property->tagType));
-				break;;
+				break;
 		}
 	}
+
+	/* Iterate through extra data ID and pointer where to store the value (the
+	 * resolved object(s)) until end of list (marked with -1) is reached.
+	 */
+	extraDataID=va_arg(inArgs, gint);
+	while(extraDataID!=-1)
+	{
+		/* Get generic pointer to storage as it will be casted as necessary
+		 * when determining which extra data is requested.
+		 */
+		extraDataStorage=va_arg(inArgs, gpointer*);
+		if(!extraDataStorage)
+		{
+			gchar *valueName;
+
+			valueName=xfdashboard_get_enum_value_name(XFDASHBOARD_TYPE_THEME_LAYOUT_BUILD_GET, extraDataID);
+			g_warning(_("No storage pointer provided to store value of %s"),
+						valueName);
+			g_free(valueName);
+			break;
+		}
+
+		/* Check which extra data is requested and store value at pointer */
+		switch(extraDataID)
+		{
+			case XFDASHBOARD_THEME_LAYOUT_BUILD_GET_FOCUSABLES:
+				if(focusTable) *((GPtrArray**)extraDataStorage)=g_ptr_array_ref(focusTable);
+					else *extraDataStorage=NULL;
+				break;
+
+			case XFDASHBOARD_THEME_LAYOUT_BUILD_GET_SELECTED_FOCUS:
+				if(focusSelected) *extraDataStorage=g_object_ref(focusSelected);
+					else *extraDataStorage=NULL;
+				break;
+
+			default:
+				g_assert_not_reached();
+				break;
+		}
+
+		/* Continue with next extra data ID and storage pointer */
+		extraDataID=va_arg(inArgs, gint);
+	}
+
+	/* Release allocated resources */
+	if(focusTable) g_ptr_array_unref(focusTable);
+	if(focusSelected) g_object_unref(focusSelected);
 }
 
 /* Create object with all its constraints, layout and children recursively.
@@ -1401,6 +1476,9 @@ static void _xfdashboard_theme_layout_parse_general_start(GMarkupParseContext *i
 											G_MARKUP_COLLECT_STRDUP,
 											"ref",
 											&tagData->tag.focus.refID,
+											G_MARKUP_COLLECT_BOOLEAN | G_MARKUP_COLLECT_OPTIONAL,
+											"selected",
+											&tagData->tag.focus.selected,
 											G_MARKUP_COLLECT_INVALID))
 		{
 			g_propagate_error(outError, error);
@@ -1543,8 +1621,42 @@ static void _xfdashboard_theme_layout_parse_general_end(GMarkupParseContext *inC
 	/* Handle end of element <focus> */
 	if(subTagData->tagType==TAG_FOCUS)
 	{
+
 		g_assert(data->focusables);
 
+		/* Check if an actor was already marked as selected and print a warning
+		 * if now multiple actors are marked as selected.
+		 */
+		if(subTagData->tag.focus.selected)
+		{
+			XfdashboardThemeLayoutPrivate		*priv;
+
+			priv=data->self->priv;
+
+			/* Check if any focus was already set and print a warning */
+			if(priv->focusSelected)
+			{
+				g_warning(_("File %s - Warning on line %d char %d: At interface '%s' the ID '%s' should get focus but the ID '%s' was selected already"),
+							data->currentPath,
+							data->lastLine,
+							data->lastPosition,
+							data->interface->id,
+							subTagData->tag.focus.refID,
+							priv->focusSelected->tag.focus.refID);
+				XFDASHBOARD_DEBUG(data->self, THEME,
+									"In file '%s' at interface '%s' the ID '%s' should get focus but the ID '%s' was selected already",
+									data->currentPath,
+									data->interface->id,
+									subTagData->tag.focus.refID,
+									priv->focusSelected->tag.focus.refID);
+			}
+				/* Remember actor as pre-selected focus */
+				else
+				{
+					priv->focusSelected=_xfdashboard_theme_layout_tag_data_ref(subTagData);
+				}
+		}
+
 		/* Add focusable actor to parser data */
 		g_ptr_array_add(data->focusables, _xfdashboard_theme_layout_tag_data_ref(subTagData));
 		XFDASHBOARD_DEBUG(data->self, THEME,
@@ -1577,7 +1689,7 @@ static void _xfdashboard_theme_layout_parse_general_end(GMarkupParseContext *inC
 static void _xfdashboard_theme_layout_check_refids(gpointer inData, gpointer inUserData)
 {
 	XfdashboardThemeLayoutParsedObject	*object;
-	GHashTable							*ids;
+	XfdashboardThemeLayoutCheckRefID	*checkRefID;
 	gpointer							value;
 	GSList								*entry;
 	XfdashboardThemeLayoutTagData		*property;
@@ -1586,7 +1698,7 @@ static void _xfdashboard_theme_layout_check_refids(gpointer inData, gpointer inU
 	g_return_if_fail(inUserData);
 
 	object=(XfdashboardThemeLayoutParsedObject*)inData;
-	ids=(GHashTable*)inUserData;
+	checkRefID=(XfdashboardThemeLayoutCheckRefID*)inUserData;
 
 	/* Iterate through properties and check referenced IDs */
 	for(entry=object->properties; entry; entry=g_slist_next(entry))
@@ -1598,16 +1710,16 @@ static void _xfdashboard_theme_layout_check_refids(gpointer inData, gpointer inU
 		 * If found do nothing (keep value at zero).
 		 */
 		if(property->tag.property.refID &&
-			!g_hash_table_lookup_extended(ids, property->tag.property.refID, NULL, &value))
+			!g_hash_table_lookup_extended(checkRefID->ids, property->tag.property.refID, NULL, &value))
 		{
-			g_hash_table_insert(ids, property->tag.property.refID, GINT_TO_POINTER(1));
-			XFDASHBOARD_DEBUG(NULL, THEME,
+			g_hash_table_insert(checkRefID->ids, property->tag.property.refID, GINT_TO_POINTER(1));
+			XFDASHBOARD_DEBUG(checkRefID->self, THEME,
 								"Could not resolve referenced ID '%s', set counter to 1",
 								property->tag.property.refID);
 		}
 			else if(property->tag.property.refID)
 			{
-				XFDASHBOARD_DEBUG(NULL, THEME,
+				XFDASHBOARD_DEBUG(checkRefID->self, THEME,
 									"Referenced ID '%s' resolved successfully",
 									property->tag.property.refID);
 			}
@@ -1626,14 +1738,14 @@ static void _xfdashboard_theme_layout_check_refids(gpointer inData, gpointer inU
 static void _xfdashboard_theme_layout_check_ids(gpointer inData, gpointer inUserData)
 {
 	XfdashboardThemeLayoutParsedObject	*object;
-	GHashTable							*ids;
+	XfdashboardThemeLayoutCheckRefID	*checkRefID;
 	gpointer							value;
 
 	g_return_if_fail(inData);
 	g_return_if_fail(inUserData);
 
 	object=(XfdashboardThemeLayoutParsedObject*)inData;
-	ids=(GHashTable*)inUserData;
+	checkRefID=(XfdashboardThemeLayoutCheckRefID*)inUserData;
 
 	/* If ID at object is set then lookup key in hashtable.
 	 * If not found create key with ID and value of 1.
@@ -1642,10 +1754,10 @@ static void _xfdashboard_theme_layout_check_ids(gpointer inData, gpointer inUser
 	if(object->id)
 	{
 		/* If key does not exist create it with value of 1 ... */
-		if(!g_hash_table_lookup_extended(ids, object->id, NULL, &value))
+		if(!g_hash_table_lookup_extended(checkRefID->ids, object->id, NULL, &value))
 		{
-			g_hash_table_insert(ids, object->id, GINT_TO_POINTER(1));
-			XFDASHBOARD_DEBUG(NULL, THEME,
+			g_hash_table_insert(checkRefID->ids, object->id, GINT_TO_POINTER(1));
+			XFDASHBOARD_DEBUG(checkRefID->self, THEME,
 								"First occurence of ID '%s', set counter to 1",
 								object->id);
 		}
@@ -1656,8 +1768,8 @@ static void _xfdashboard_theme_layout_check_ids(gpointer inData, gpointer inUser
 
 				count=GPOINTER_TO_INT(value);
 				count++;
-				g_hash_table_replace(ids, object->id, GINT_TO_POINTER(count));
-				XFDASHBOARD_DEBUG(NULL, THEME,
+				g_hash_table_replace(checkRefID->ids, object->id, GINT_TO_POINTER(count));
+				XFDASHBOARD_DEBUG(checkRefID->self, THEME,
 									"Found ID '%s' and increased counter to %d",
 									object->id,
 									count);
@@ -1678,10 +1790,10 @@ static gboolean _xfdashboard_theme_layout_check_ids_and_refids(XfdashboardThemeL
 																XfdashboardThemeLayoutParsedObject *inInterfaceObject,
 																GError **outError)
 {
-	gboolean			success;
-	GHashTable			*ids;
-	GHashTableIter		iter;
-	gpointer			key, value;
+	gboolean							success;
+	GHashTableIter						iter;
+	gpointer							key, value;
+	XfdashboardThemeLayoutCheckRefID	checkRefID;
 
 	g_return_val_if_fail(XFDASHBOARD_IS_THEME_LAYOUT(self), FALSE);
 	g_return_val_if_fail(inInterfaceObject, FALSE);
@@ -1694,8 +1806,8 @@ static gboolean _xfdashboard_theme_layout_check_ids_and_refids(XfdashboardThemeL
 	 * of a hashtable which uses the ID as key and the value indicates
 	 * check results.
 	 */
-	g_object_ref(self);
-	ids=g_hash_table_new(g_str_hash, g_str_equal);
+	checkRefID.self=g_object_ref(self);
+	checkRefID.ids=g_hash_table_new(g_str_hash, g_str_equal);
 
 	/* Step one: Iterate through all objects and their contraints, layouts
 	 * and children recursively beginning at interface object. For each ID
@@ -1703,13 +1815,13 @@ static gboolean _xfdashboard_theme_layout_check_ids_and_refids(XfdashboardThemeL
 	 * increase counter (which is an error because ID is used more than once)
 	 * or create key with integer value 1.
 	 */
-	_xfdashboard_theme_layout_check_ids(inInterfaceObject, ids);
+	_xfdashboard_theme_layout_check_ids(inInterfaceObject, &checkRefID);
 
 	/* Check if any key in hashtable has a value greater than one which means
 	 * that this ID is used more than once and is an error. Reset each key
 	 * check successfully to zero.
 	 */
-	g_hash_table_iter_init(&iter, ids);
+	g_hash_table_iter_init(&iter, checkRefID.ids);
 	while(success && g_hash_table_iter_next(&iter, &key, &value)) 
 	{
 		if(GPOINTER_TO_INT(value)>1)
@@ -1733,14 +1845,14 @@ static gboolean _xfdashboard_theme_layout_check_ids_and_refids(XfdashboardThemeL
 	 * key (containing ID) in hashtable. If found do nothing and if was
 	 * not found create key with integer value 1.
 	 */
-	if(success) _xfdashboard_theme_layout_check_refids(inInterfaceObject, ids);
+	if(success) _xfdashboard_theme_layout_check_refids(inInterfaceObject, &checkRefID);
 
 	/* Check if any key in hashtable has a value greater than zero which
 	 * means that this referenced ID could not be resolved and is an error.
 	 */
 	if(success)
 	{
-		g_hash_table_iter_init(&iter, ids);
+		g_hash_table_iter_init(&iter, checkRefID.ids);
 		while(success && g_hash_table_iter_next(&iter, &key, &value)) 
 		{
 			if(GPOINTER_TO_INT(value)>0)
@@ -1756,8 +1868,8 @@ static gboolean _xfdashboard_theme_layout_check_ids_and_refids(XfdashboardThemeL
 	}
 
 	/* Release allocated resources */
-	g_hash_table_destroy(ids);
-	g_object_unref(self);
+	g_hash_table_destroy(checkRefID.ids);
+	g_object_unref(checkRefID.self);
 
 	/* Return result of checks */
 	return(success);
@@ -1830,6 +1942,7 @@ static gboolean _xfdashboard_theme_layout_parse_xml(XfdashboardThemeLayout *self
 	data->lastPosition=1;
 	data->currentLine=1;
 	data->currentPostition=1;
+	data->currentPath=inPath;
 
 	/* Parse XML string */
 	if(success && !g_markup_parse_context_parse(context, inContents, -1, &error))
@@ -1840,6 +1953,9 @@ static gboolean _xfdashboard_theme_layout_parse_xml(XfdashboardThemeLayout *self
 
 	if(success && !g_markup_parse_context_end_parse(context, &error))
 	{
+		g_prefix_error(&error,
+						_("File %s - "),
+						inPath);
 		g_propagate_error(outError, error);
 		success=FALSE;
 	}
@@ -1924,6 +2040,12 @@ static void _xfdashboard_theme_layout_dispose(GObject *inObject)
 	XfdashboardThemeLayoutPrivate		*priv=self->priv;
 
 	/* Release allocated resources */
+	if(priv->focusSelected)
+	{
+		_xfdashboard_theme_layout_tag_data_unref(priv->focusSelected);
+		priv->focusSelected=NULL;
+	}
+
 	if(priv->interfaces)
 	{
 		g_slist_foreach(priv->interfaces, _xfdashboard_theme_layout_object_data_free_foreach_callback, NULL);
@@ -1961,6 +2083,7 @@ void xfdashboard_theme_layout_init(XfdashboardThemeLayout *self)
 
 	/* Set default values */
 	priv->interfaces=NULL;
+	priv->focusSelected=NULL;
 }
 
 /* IMPLEMENTATION: Errors */
@@ -2018,12 +2141,13 @@ gboolean xfdashboard_theme_layout_add_file(XfdashboardThemeLayout *self,
 
 /* Build requested interface */
 ClutterActor* xfdashboard_theme_layout_build_interface(XfdashboardThemeLayout *self,
-														const gchar *inID)
+														const gchar *inID,
+														...)
 {
 	XfdashboardThemeLayoutPrivate				*priv;
 	GSList										*iter;
 	XfdashboardThemeLayoutParsedObject			*interfaceData;
-	ClutterActor								*actor;
+	GObject										*actor;
 	GHashTable									*ids;
 	GSList										*unresolved;
 
@@ -2072,16 +2196,36 @@ ClutterActor* xfdashboard_theme_layout_build_interface(XfdashboardThemeLayout *s
 	unresolved=NULL;
 
 	/* Create actor */
-	actor=CLUTTER_ACTOR(_xfdashboard_theme_layout_create_object(self, interfaceData, ids, &unresolved));
+	actor=_xfdashboard_theme_layout_create_object(self, interfaceData, ids, &unresolved);
 	if(actor)
 	{
-		XFDASHBOARD_DEBUG(self, THEME,
-							"Created actor %s for interface '%s'",
-							G_OBJECT_TYPE_NAME(actor),
-							inID);
+		/* Check if really an actor was created */
+		if(CLUTTER_IS_ACTOR(actor))
+		{
+			va_list								args;
+
+			XFDASHBOARD_DEBUG(self, THEME,
+								"Created actor %s for interface '%s'",
+								G_OBJECT_TYPE_NAME(actor),
+								inID);
 
-		/* Resolved unresolved properties of newly created object */
-		_xfdashboard_theme_layout_create_object_resolve_unresolved(self, ids, unresolved);
+			/* Resolved unresolved properties of newly created object */
+			va_start(args, inID);
+			_xfdashboard_theme_layout_create_object_resolve_unresolved(self, ids, unresolved, args);
+			va_end(args);
+		}
+			else
+			{
+				XFDASHBOARD_DEBUG(self, THEME,
+									"Failed to create actor for interface '%s' because object of type %s is not derived from %s",
+									inID,
+									G_OBJECT_TYPE_NAME(actor),
+									g_type_name(CLUTTER_TYPE_ACTOR));
+
+				/* Release object which is not an actor */
+				g_object_unref(actor);
+				actor=NULL;
+			}
 	}
 		else
 		{
@@ -2098,13 +2242,5 @@ ClutterActor* xfdashboard_theme_layout_build_interface(XfdashboardThemeLayout *s
 	_xfdashboard_theme_layout_object_data_unref(interfaceData);
 
 	/* Return created actor */
-	return(actor);
-}
-
-/* Quark for accessing focus table data (a GPtrArray) at an actor
- * with g_object_get_qdata() created by xfdashboard_theme_layout_build_interface().
- */
-GQuark xfdashboard_theme_layout_focus_table_quark(void)
-{
-	return(g_quark_from_static_string("xfdashboard-theme-layout-focus-table-quark"));
+	return(actor ? CLUTTER_ACTOR(actor) : NULL);
 }
diff --git a/libxfdashboard/theme-layout.h b/libxfdashboard/theme-layout.h
index b9556d2..017edf6 100644
--- a/libxfdashboard/theme-layout.h
+++ b/libxfdashboard/theme-layout.h
@@ -32,6 +32,21 @@
 
 G_BEGIN_DECLS
 
+/* Public definitions */
+/**
+ * XfdashboardThemeLayoutBuildGet:
+ * @XFDASHBOARD_THEME_LAYOUT_BUILD_GET_FOCUSABLES: Get #GPtrArray of pointer to defined focusable actors. Caller must free returned #GPtrArray with g_ptr_array_unref().
+ * @XFDASHBOARD_THEME_LAYOUT_BUILD_GET_SELECTED_FOCUS: Get #ClutterActor which should gain the focus. Caller must unref returned #ClutterActor with g_object_unref().
+ *
+ * The extra data to fetch when building an object from theme layout.
+ */
+typedef enum /*< prefix=XFDASHBOARD_THEME_LAYOUT_BUILD_GET >*/
+{
+	XFDASHBOARD_THEME_LAYOUT_BUILD_GET_FOCUSABLES=0,
+	XFDASHBOARD_THEME_LAYOUT_BUILD_GET_SELECTED_FOCUS
+} XfdashboardThemeLayoutBuildGet;
+
+/* Object declaration */
 #define XFDASHBOARD_TYPE_THEME_LAYOUT				(xfdashboard_theme_layout_get_type())
 #define XFDASHBOARD_THEME_LAYOUT(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), XFDASHBOARD_TYPE_THEME_LAYOUT, XfdashboardThemeLayout))
 #define XFDASHBOARD_IS_THEME_LAYOUT(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), XFDASHBOARD_TYPE_THEME_LAYOUT))
@@ -43,6 +58,12 @@ typedef struct _XfdashboardThemeLayout				XfdashboardThemeLayout;
 typedef struct _XfdashboardThemeLayoutClass			XfdashboardThemeLayoutClass;
 typedef struct _XfdashboardThemeLayoutPrivate		XfdashboardThemeLayoutPrivate;
 
+/**
+ * XfdashboardThemeLayout:
+ *
+ * The #XfdashboardThemeLayout structure contains only private data and
+ * should be accessed using the provided API
+ */
 struct _XfdashboardThemeLayout
 {
 	/*< private >*/
@@ -53,6 +74,11 @@ struct _XfdashboardThemeLayout
 	XfdashboardThemeLayoutPrivate		*priv;
 };
 
+/**
+ * XfdashboardThemeLayoutClass:
+ *
+ * The #XfdashboardThemeLayoutClass structure contains only private data
+ */
 struct _XfdashboardThemeLayoutClass
 {
 	/*< private >*/
@@ -84,11 +110,8 @@ gboolean xfdashboard_theme_layout_add_file(XfdashboardThemeLayout *self,
 											GError **outError);
 
 ClutterActor* xfdashboard_theme_layout_build_interface(XfdashboardThemeLayout *self,
-														const gchar *inID);
-
-
-#define XFDASHBOARD_THEME_LAYOUT_FOCUS_TABLE_DATA	(xfdashboard_theme_layout_focus_table_quark())
-GQuark xfdashboard_theme_layout_focus_table_quark(void);
+														const gchar *inID,
+														...);
 
 G_END_DECLS
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list