Example #1
0
/* Get desktop ID from window names.
 * Callee is responsible to free result with g_object_unref().
 */
static GAppInfo* _xfdashboard_application_tracker_get_desktop_id_from_window_names(XfdashboardApplicationTracker *self,
																					XfdashboardWindowTrackerWindow *inWindow)
{
	XfdashboardApplicationTrackerPrivate	*priv;
	GAppInfo								*foundAppInfo;
	gchar									**names;
	gchar									**iter;

	g_return_val_if_fail(XFDASHBOARD_IS_APPLICATION_TRACKER(self), NULL);
	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL);

	priv=self->priv;
	foundAppInfo=NULL;

	/* Get window's names */
	names=xfdashboard_window_tracker_window_get_instance_names(inWindow);

	/* Iterate through window's names to try to find matching desktop file */
	iter=names;
	while(iter && *iter)
	{
		GAppInfo							*appInfo;

		/* Lookup application from unmodified name */
		if(g_str_has_suffix(*iter, ".desktop"))
		{
			appInfo=xfdashboard_application_database_lookup_desktop_id(priv->appDatabase, *iter);
		}
			else
			{
				gchar						*desktopID;

				desktopID=g_strconcat(*iter, ".desktop", NULL);
				appInfo=xfdashboard_application_database_lookup_desktop_id(priv->appDatabase, desktopID);
				g_free(desktopID);
			}

		/* Lookup application from to-lower-case converted name if previous
		 * lookup with unmodified name failed.
		 */
		if(!appInfo)
		{
			gchar							*lowerDesktopID;

			/* Convert name to lower case */
			lowerDesktopID=g_utf8_strdown(*iter, -1);

			/* Lookup application from lower-case name. No need to add '.desktop'
			 * as suffix as it was done before.
			 */
			if(g_str_has_suffix(lowerDesktopID, ".desktop"))
			{
				appInfo=xfdashboard_application_database_lookup_desktop_id(priv->appDatabase, lowerDesktopID);
			}
				else
				{
					gchar					*desktopID;

					desktopID=g_strconcat(lowerDesktopID, ".desktop", NULL);
					appInfo=xfdashboard_application_database_lookup_desktop_id(priv->appDatabase, desktopID);
					g_free(desktopID);
				}

			/* Free lower case of name */
			g_free(lowerDesktopID);

			/* If we still did not find an application continue with next
			 * name in list.
			 */
			if(!appInfo)
			{
				/* Continue with next name in list */
				iter++;
				continue;
			}
		}

		/* Check if found application info matches previous one. If it does not match
		 * the desktop IDs found previously are ambigous, so return NULL result.
		 */
		if(foundAppInfo &&
			!g_app_info_equal(foundAppInfo, appInfo))
		{
			g_debug("Resolved window names of '%s' are ambiguous - discarding desktop IDs '%s' and '%s'",
						xfdashboard_window_tracker_window_get_title(inWindow),
						g_app_info_get_id(foundAppInfo),
						g_app_info_get_id(appInfo));

			/* Release allocated resources */
			if(foundAppInfo) g_object_unref(foundAppInfo);
			if(appInfo) g_object_unref(appInfo);
			if(names) g_strfreev(names);

			return(NULL);
		}

		/* If it is the first application info found, remember it */
		if(!foundAppInfo) foundAppInfo=g_object_ref(appInfo);

		/* Release allocated resources */
		if(appInfo) g_object_unref(appInfo);

		/* Continue with next name in list */
		iter++;
	}

	/* Release allocated resources */
	if(names) g_strfreev(names);

	/* Return found application info */
	g_debug("Resolved window names of '%s' to desktop ID '%s'",
				xfdashboard_window_tracker_window_get_title(inWindow),
				foundAppInfo ? g_app_info_get_id(foundAppInfo) : "<nil>");

	return(foundAppInfo);
}
/* Get desktop ID from window names.
 * Callee is responsible to free result with g_object_unref().
 */
static GAppInfo* _xfdashboard_application_tracker_get_desktop_id_from_window_names(XfdashboardApplicationTracker *self,
																					XfdashboardWindowTrackerWindow *inWindow)
{
	XfdashboardApplicationTrackerPrivate	*priv;
	GAppInfo								*foundAppInfo;
	gchar									**names;
	gchar									**iter;
	GList									*apps;

	g_return_val_if_fail(XFDASHBOARD_IS_APPLICATION_TRACKER(self), NULL);
	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL);

	priv=self->priv;
	foundAppInfo=NULL;

	/* Get list of applications */
	apps=xfdashboard_application_database_get_all_applications(priv->appDatabase);

	/* Get window's names */
	names=xfdashboard_window_tracker_window_get_instance_names(inWindow);

	/* Iterate through window's names to try to find matching desktop file */
	iter=names;
	while(iter && *iter)
	{
		GAppInfo							*appInfo;
		gchar								*iterName;
		gchar								*iterNameLowerCase;

		/* Build desktop ID from iterated name */
		if(!g_str_has_suffix(*iter, ".desktop")) iterName=g_strconcat(*iter, ".desktop", NULL);
			else iterName=g_strdup(*iter);

		iterNameLowerCase=g_utf8_strdown(iterName, -1);

		/* Lookup application from unmodified name */
		appInfo=xfdashboard_application_database_lookup_desktop_id(priv->appDatabase, iterName);

		/* Lookup application from to-lower-case converted name if previous
		 * lookup with unmodified name failed.
		 */
		if(!appInfo)
		{
			/* Lookup application from lower-case name */
			appInfo=xfdashboard_application_database_lookup_desktop_id(priv->appDatabase, iterNameLowerCase);
		}

		/* If no application was found for the name it may be an application
		 * located in a subdirectory. Then the desktop ID is prefixed with
		 * the subdirectory's name followed by a dash. So iterate through all
		 * applications and lookup with glob pattern '*-' followed by name
		 * and suffix '.desktop'.
		 */
		if(!appInfo)
		{
			GList							*iterApps;
			GList							*foundSubdirApps;
			gchar							*globName;
			GPatternSpec					*globPattern;
			GAppInfo						*globAppInfo;

			/* Build glob pattern */
			globAppInfo=NULL;
			globName=g_strconcat("*-", iterNameLowerCase, NULL);
			globPattern=g_pattern_spec_new(globName);

			/* Iterate through application and collect applications matching
			 * glob pattern.
			 */
			foundSubdirApps=NULL;
			for(iterApps=apps; iterApps; iterApps=g_list_next(iterApps))
			{
				if(!G_IS_APP_INFO(iterApps->data)) continue;
				globAppInfo=G_APP_INFO(iterApps->data);

				if(g_pattern_match_string(globPattern, g_app_info_get_id(globAppInfo)))
				{
					foundSubdirApps=g_list_prepend(foundSubdirApps, globAppInfo);
					g_debug("Found possible application '%s' for window '%s' using pattern '%s'",
							g_app_info_get_id(globAppInfo),
							xfdashboard_window_tracker_window_get_title(inWindow),
							globName);
				}
			}

			/* If exactly one application was collected because it matched
			 * the glob pattern then we found the application.
			 */
			if(g_list_length(foundSubdirApps)==1)
			{
				appInfo=G_APP_INFO(g_object_ref(G_OBJECT(foundSubdirApps->data)));

				g_debug("Found exactly one application named '%s' for window '%s' using pattern '%s'",
						g_app_info_get_id(appInfo),
						xfdashboard_window_tracker_window_get_title(inWindow),
						globName);
			}

			/* Release allocated resources */
			if(foundSubdirApps) g_list_free(foundSubdirApps);
			if(globPattern) g_pattern_spec_free(globPattern);
			if(globName) g_free(globName);
		}

		/* If we still did not find an application continue with next
		 * name in list.
		 */
		if(!appInfo)
		{
			/* Release allocated resources */
			if(iterName) g_free(iterName);
			if(iterNameLowerCase) g_free(iterNameLowerCase);

			/* Continue with next name in list */
			iter++;
			continue;
		}

		/* Check if found application info matches previous one. If it does not match
		 * the desktop IDs found previously are ambigous, so return NULL result.
		 */
		if(foundAppInfo &&
			!g_app_info_equal(foundAppInfo, appInfo))
		{
			g_debug("Resolved window names of '%s' are ambiguous - discarding desktop IDs '%s' and '%s'",
						xfdashboard_window_tracker_window_get_title(inWindow),
						g_app_info_get_id(foundAppInfo),
						g_app_info_get_id(appInfo));

			/* Release allocated resources */
			if(iterName) g_free(iterName);
			if(iterNameLowerCase) g_free(iterNameLowerCase);
			if(foundAppInfo) g_object_unref(foundAppInfo);
			if(appInfo) g_object_unref(appInfo);
			if(names) g_strfreev(names);
			if(apps) g_list_free_full(apps, g_object_unref);

			return(NULL);
		}

		/* If it is the first application info found, remember it */
		if(!foundAppInfo) foundAppInfo=g_object_ref(appInfo);

		/* Release allocated resources */
		if(iterName) g_free(iterName);
		if(iterNameLowerCase) g_free(iterNameLowerCase);
		if(appInfo) g_object_unref(appInfo);

		/* Continue with next name in list */
		iter++;
	}

	/* Release allocated resources */
	if(names) g_strfreev(names);
	if(apps) g_list_free_full(apps, g_object_unref);

	/* Return found application info */
	g_debug("Resolved window names of '%s' to desktop ID '%s'",
				xfdashboard_window_tracker_window_get_title(inWindow),
				foundAppInfo ? g_app_info_get_id(foundAppInfo) : "<nil>");

	return(foundAppInfo);
}
Example #3
0
/* Get desktop ID from process' environment which owns window.
 * Callee is responsible to free result with g_object_unref().
 */
static GAppInfo* _xfdashboard_application_tracker_get_desktop_id_from_environment(XfdashboardApplicationTracker *self,
																					XfdashboardWindowTrackerWindow *inWindow)
{
	XfdashboardApplicationTrackerPrivate	*priv;
	GAppInfo								*foundAppInfo;
	gint									windowPID;
	gchar									*procEnvFile;
	gchar									*envContent;
	gsize									envLength;
	GError									*error;
	gchar									*iter;
	const gchar								*gioLaunchedPID;
	const gchar								*gioLaunchedDesktopFile;

	g_return_val_if_fail(XFDASHBOARD_IS_APPLICATION_TRACKER(self), NULL);
	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL);

	priv=self->priv;
	foundAppInfo=NULL;
	error=NULL;

	/* Get process ID running this window */
	windowPID=xfdashboard_window_tracker_window_get_pid(inWindow);
	if(windowPID<=0)
	{
		g_debug("Could not get PID for window '%s' of a running application to parse environment variables",
				xfdashboard_window_tracker_window_get_title(inWindow));

		return(NULL);
	}

	/* Open enviroment variables of process.
	 * This is the initial set of environment variables set when process was spawned.
	 * But that is ok because the environment variables we lookup are set
	 * at launch time and do not change.
	 */
	envContent=NULL;
	envLength=0;

	procEnvFile=g_strdup_printf("/proc/%d/environ", windowPID);
	if(!g_file_get_contents(procEnvFile, &envContent, &envLength, &error))
	{
		g_debug("Could read in enviroment varibles for PID %d of window '%s' at %s: %s",
					windowPID,
					xfdashboard_window_tracker_window_get_title(inWindow),
					procEnvFile,
					error ? error->message : _("Unknown error"));

		/* Release allocated resources */
		if(error) g_error_free(error);
		if(procEnvFile) g_free(procEnvFile);
		if(envContent) g_free(envContent);

		/* Return NULL result */
		return(NULL);
	}

	g_debug("Enviroment set at %s is %lu bytes long for window '%s'",
				procEnvFile,
				envLength,
				xfdashboard_window_tracker_window_get_title(inWindow));

	/* Iterate through enviroment variables and lookup GIO_LAUNCHED_DESKTOP_FILE
	 * and GIO_LAUNCHED_DESKTOP_FILE_PID.
	 */
	gioLaunchedPID=NULL;
	gioLaunchedDesktopFile=NULL;

	iter=envContent;
	while(envLength>0)
	{
		gsize								len;

		/* Skip NULL-termination */
		if(!*iter)
		{
			envLength--;
			iter++;
			continue;
		}

		/* Check current iterated enviroment variable matches a requested one */
		if(g_str_has_prefix(iter, "GIO_LAUNCHED_DESKTOP_FILE="))
		{
			/* Each enviroment variable should be listed only once
			 * otherwise is an error.
			 */
			if(gioLaunchedDesktopFile)
			{
				g_debug("Could parse in enviroment varibles for PID %d of window '%s' at %s because GIO_LAUNCHED_DESKTOP_FILE exists more than once",
							windowPID,
							xfdashboard_window_tracker_window_get_title(inWindow),
							procEnvFile);

				/* Release allocated resources */
				if(foundAppInfo) g_object_unref(foundAppInfo);
				if(procEnvFile) g_free(procEnvFile);
				if(envContent) g_free(envContent);

				/* Return NULL result */
				return(NULL);
			}

			/* Remember value of environment variable */
			gioLaunchedDesktopFile=iter;
		}
			else if(g_str_has_prefix(iter, "GIO_LAUNCHED_DESKTOP_FILE_PID="))
			{
				/* Each enviroment variable should be listed only once
				 * otherwise is an error.
				 */
				if(gioLaunchedPID)
				{
					g_debug("Could parse in enviroment varibles for PID %d of window '%s' at %s because GIO_LAUNCHED_DESKTOP_FILE_PID exists more than once",
								windowPID,
								xfdashboard_window_tracker_window_get_title(inWindow),
								procEnvFile);

					/* Release allocated resources */
					if(foundAppInfo) g_object_unref(foundAppInfo);
					if(procEnvFile) g_free(procEnvFile);
					if(envContent) g_free(envContent);

					/* Return NULL result */
					return(NULL);
				}

				/* Remember value of environment variable */
				gioLaunchedPID=iter;
			}

		/* If all requested environment variable has been found stop iterating */
		if(gioLaunchedPID && gioLaunchedDesktopFile) break;

		/* Continue with next environment variable */
		len=strlen(iter);
		iter+=len;
		envLength-=len;
	}

	/* If all requested environment variable has been found then check if
	 * GIO_LAUNCHED_DESKTOP_FILE_PID matches window owner's process ID.
	 */
	if(gioLaunchedPID && gioLaunchedDesktopFile)
	{
		/* Move pointer of environment variables to value */
		while(*gioLaunchedPID && *gioLaunchedPID!='=') gioLaunchedPID++;
		while(*gioLaunchedDesktopFile && *gioLaunchedDesktopFile!='=') gioLaunchedDesktopFile++;

		/* Check if pointers points to value assignment character */
		if(*gioLaunchedPID=='=' &&
			*gioLaunchedDesktopFile=='=')
		{
			gint							checkPID;

			/* Move pointer one byte further where value begins really */
			gioLaunchedPID++;
			gioLaunchedDesktopFile++;

			/* Check if PID of enviroment variable matches window owner's
			 * process ID.
			 */
			checkPID=atoi(gioLaunchedPID);
			if(checkPID==windowPID)
			{
				/* Lookup application from full path */
				foundAppInfo=xfdashboard_application_database_lookup_desktop_id(priv->appDatabase, gioLaunchedDesktopFile);
				if(!foundAppInfo)
				{
					/* Lookup application from basename of path */
					gioLaunchedDesktopFile=g_strrstr(gioLaunchedDesktopFile, G_DIR_SEPARATOR_S);
					if(gioLaunchedDesktopFile)
					{
						gioLaunchedDesktopFile++;
						foundAppInfo=xfdashboard_application_database_lookup_desktop_id(priv->appDatabase, gioLaunchedDesktopFile);
					}
				}
			}
				else
				{
					g_debug("PID %d of environment variable does not match window PID %d for '%s'",
								checkPID,
								windowPID,
								xfdashboard_window_tracker_window_get_title(inWindow));
				}
		}
	}

	/* Release allocated resources */
	if(procEnvFile) g_free(procEnvFile);
	if(envContent) g_free(envContent);

	/* Return found application info */
	g_debug("Resolved enviroment variables of window '%s' to desktop ID '%s'",
				xfdashboard_window_tracker_window_get_title(inWindow),
				foundAppInfo ? g_app_info_get_id(foundAppInfo) : "<nil>");

	return(foundAppInfo);
}
/* Get desktop ID from process' environment which owns window.
 * Callee is responsible to free result with g_object_unref().
 */
static GAppInfo* _xfdashboard_application_tracker_get_desktop_id_from_environment(XfdashboardApplicationTracker *self,
																					XfdashboardWindowTrackerWindow *inWindow)
{
	XfdashboardApplicationTrackerPrivate	*priv;
	GAppInfo								*foundAppInfo;
	gint									windowPID;
	GHashTable								*environments;
	gchar									*value;
	gint									checkPID;

	g_return_val_if_fail(XFDASHBOARD_IS_APPLICATION_TRACKER(self), NULL);
	g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL);

	priv=self->priv;
	foundAppInfo=NULL;

	/* Get process ID running this window */
	windowPID=xfdashboard_window_tracker_window_get_pid(inWindow);
	if(windowPID<=0)
	{
		g_debug("Could not get PID for window '%s' of a running application to parse environment variables",
				xfdashboard_window_tracker_window_get_title(inWindow));

		/* Return NULL result */
		return(NULL);
	}

	/* Get hash-table with environment variables found for window's PID */
	environments=_xfdashboard_application_tracker_get_environment_from_pid(windowPID);
	if(!environments)
	{
		g_debug("Could not get environments for PID %d of windows '%s'",
				windowPID,
				xfdashboard_window_tracker_window_get_title(inWindow));

		/* Return NULL result */
		return(NULL);
	}

	/* Check that environment variable GIO_LAUNCHED_DESKTOP_FILE_PID exists.
	 * Also check that the PID in value matches the requested window's PID
	 * as the process may inherit the environments of its parent process
	 * but then this one is not the initial process for this application.
	 */
	if(!g_hash_table_lookup_extended(environments, "GIO_LAUNCHED_DESKTOP_FILE_PID", NULL, (gpointer)&value))
	{
		g_debug("Missing 'GIO_LAUNCHED_DESKTOP_FILE_PID' in environment variables for PID %d of windows '%s'",
					windowPID,
					xfdashboard_window_tracker_window_get_title(inWindow));

		/* Release allocated resources */
		if(environments) g_hash_table_destroy(environments);

		/* Return NULL result */
		return(NULL);
	}

	checkPID=atoi(value);
	if(checkPID!=windowPID)
	{
		g_debug("PID %d of environment variables does not match requested window PID %d for '%s'",
					checkPID,
					windowPID,
					xfdashboard_window_tracker_window_get_title(inWindow));

		/* Release allocated resources */
		if(environments) g_hash_table_destroy(environments);

		/* Return NULL result */
		return(NULL);
	}

	/* Check that environment variable GIO_LAUNCHED_DESKTOP_FILE exists and
	 * lookup application from full path as set in environment's value.
	 */
	if(!g_hash_table_lookup_extended(environments, "GIO_LAUNCHED_DESKTOP_FILE", NULL, (gpointer)&value))
	{
		g_debug("Missing 'GIO_LAUNCHED_DESKTOP_FILE' in environment variables for PID %d of windows '%s'",
					windowPID,
					xfdashboard_window_tracker_window_get_title(inWindow));

		/* Release allocated resources */
		if(environments) g_hash_table_destroy(environments);

		/* Return NULL result */
		return(NULL);
	}

	foundAppInfo=xfdashboard_application_database_lookup_desktop_id(priv->appDatabase, value);
	if(!foundAppInfo)
	{
		/* Lookup application from basename of path */
		value=g_strrstr(value, G_DIR_SEPARATOR_S);
		if(value)
		{
			value++;
			foundAppInfo=xfdashboard_application_database_lookup_desktop_id(priv->appDatabase, value);
		}
	}

	/* Release allocated resources */
	if(environments) g_hash_table_destroy(environments);

	/* Return found application info which may be NULL if not found in
	 * application database.
	 */
	g_debug("Resolved enviroment variables of window '%s' to desktop ID '%s'",
				xfdashboard_window_tracker_window_get_title(inWindow),
				foundAppInfo ? g_app_info_get_id(foundAppInfo) : "<nil>");

	return(foundAppInfo);
}