/* Create new application tracker item */ static XfdashboardApplicationTrackerItem* _xfdashboard_application_tracker_item_new(GAppInfo *inAppInfo, XfdashboardWindowTrackerWindow *inWindow) { XfdashboardApplicationTrackerItem *item; g_return_val_if_fail(G_IS_APP_INFO(inAppInfo), NULL); g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL); /* Create new application item and set up */ item=g_new0(XfdashboardApplicationTrackerItem, 1); item->pid=xfdashboard_window_tracker_window_get_pid(inWindow); item->appInfo=g_object_ref(inAppInfo); item->desktopID=g_strdup(g_app_info_get_id(inAppInfo)); item->windows=g_list_prepend(item->windows, inWindow); /* Return newly created application tracker item */ return(item); }
/* 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); }