/** * cinnamon_window_tracker_get_app_from_pid: * @self; A #CinnamonAppSystem * @pid: A Unix process identifier * * Look up the application corresponding to a process. * * Returns: (transfer none): A #CinnamonApp, or %NULL if none */ CinnamonApp * cinnamon_window_tracker_get_app_from_pid (CinnamonWindowTracker *self, int pid) { GSList *running = cinnamon_app_system_get_running (cinnamon_app_system_get_default()); GSList *iter; CinnamonApp *result = NULL; for (iter = running; iter; iter = iter->next) { CinnamonApp *app = iter->data; GSList *pids = cinnamon_app_get_pids (app); GSList *pids_iter; for (pids_iter = pids; pids_iter; pids_iter = pids_iter->next) { int app_pid = GPOINTER_TO_INT (pids_iter->data); if (app_pid == pid) { result = app; break; } } g_slist_free (pids); if (result != NULL) break; } g_slist_free (running); return result; }
/** * cinnamon_startup_sequence_get_app: * @sequence: A #CinnamonStartupSequence * * Returns: (transfer none): The application being launched, or %NULL if unknown. */ CinnamonApp * cinnamon_startup_sequence_get_app (CinnamonStartupSequence *sequence) { const char *appid; CinnamonAppSystem *appsys; CinnamonApp *app; appid = sn_startup_sequence_get_application_id ((SnStartupSequence*)sequence); if (!appid) return NULL; appsys = cinnamon_app_system_get_default (); app = cinnamon_app_system_lookup_app_for_path (appsys, appid); return app; }
static void cinnamon_app_state_transition (CinnamonApp *app, CinnamonAppState state) { if (app->state == state) return; g_return_if_fail (!(app->state == CINNAMON_APP_STATE_RUNNING && state == CINNAMON_APP_STATE_STARTING)); app->state = state; if (app->state == CINNAMON_APP_STATE_STOPPED && app->running_state) { unref_running_state (app->running_state); app->running_state = NULL; } _cinnamon_app_system_notify_app_state_changed (cinnamon_app_system_get_default (), app); g_object_notify (G_OBJECT (app), "state"); }
/** * get_app_from_gapplication_id: * @monitor: a #CinnamonWindowTracker * @window: a #MetaWindow * * Looks only at the given window, and attempts to determine * an application based on _GTK_APPLICATION_ID. If one can't be determined, * return %NULL. * * Return value: (transfer full): A newly-referenced #CinnamonApp, or %NULL */ static CinnamonApp * get_app_from_gapplication_id (MetaWindow *window) { CinnamonApp *app; CinnamonAppSystem *appsys; const char *id; char *desktop_file; appsys = cinnamon_app_system_get_default (); id = meta_window_get_gtk_application_id (window); if (!id) return NULL; desktop_file = g_strconcat (id, ".desktop", NULL); app = cinnamon_app_system_lookup_app (appsys, desktop_file); if (app) g_object_ref (app); g_free (desktop_file); return app; }
/** * get_app_from_window_wmclass: * * Looks only at the given window, and attempts to determine * an application based on WM_CLASS. If one can't be determined, * return %NULL. * * Return value: (transfer full): A newly-referenced #CinnamonApp, or %NULL */ static CinnamonApp * get_app_from_window_wmclass (MetaWindow *window) { CinnamonApp *app; CinnamonAppSystem *appsys; char *wmclass; char *with_desktop; appsys = cinnamon_app_system_get_default (); wmclass = strip_extension(get_appid_from_window (window)); if (!wmclass) return NULL; with_desktop = g_strjoin (NULL, wmclass, ".desktop", NULL); g_free (wmclass); app = cinnamon_app_system_lookup_heuristic_basename (appsys, with_desktop); if (app != NULL) g_object_ref (app); g_free (with_desktop); return app; }
/** * get_app_from_window_wmclass: * * Looks only at the given window, and attempts to determine * an application based on WM_CLASS. If one can't be determined, * return %NULL. * * Return value: (transfer full): A newly-referenced #CinnamonApp, or %NULL */ static CinnamonApp * get_app_from_window_wmclass (MetaWindow *window) { CinnamonApp *app; CinnamonAppSystem *appsys; const char *wm_class; const char *wm_instance; appsys = cinnamon_app_system_get_default (); /* Notes on the heuristics used here: much of the complexity here comes from the desire to support Chrome apps. From https://bugzilla.gnome.org/show_bug.cgi?id=673657#c13 Currently chrome sets WM_CLASS as follows (the first string is the 'instance', the second one is the 'class': For the normal browser: WM_CLASS(STRING) = "chromium", "Chromium" For a bookmarked page (through 'Tools -> Create application shortcuts') WM_CLASS(STRING) = "wiki.gnome.org__GnomeShell_ApplicationBased", "Chromium" For an application from the chrome store (with a .desktop file created through right click, "Create shortcuts" from Chrome's apps overview) WM_CLASS(STRING) = "crx_blpcfgokakmgnkcojhhkbfbldkacnbeo", "Chromium" The .desktop file has a matching StartupWMClass, but the name differs, e.g. for the store app (youtube) there is .local/share/applications/chrome-blpcfgokakmgnkcojhhkbfbldkacnbeo-Default.desktop with StartupWMClass=crx_blpcfgokakmgnkcojhhkbfbldkacnbeo Note that chromium (but not google-chrome!) includes a StartupWMClass=chromium in their .desktop file, so we must match the instance first. Also note that in the good case (regular gtk+ app without hacks), instance and class are the same except for case and there is no StartupWMClass at all. */ /* first try a match from WM_CLASS (instance part) to StartupWMClass */ wm_instance = meta_window_get_wm_class_instance (window); app = cinnamon_app_system_lookup_startup_wmclass (appsys, wm_instance); if (app != NULL) return g_object_ref (app); /* then try a match from WM_CLASS to StartupWMClass */ wm_class = meta_window_get_wm_class (window); app = cinnamon_app_system_lookup_startup_wmclass (appsys, wm_class); if (app != NULL) return g_object_ref (app); /* then try a match from WM_CLASS (instance part) to .desktop */ app = cinnamon_app_system_lookup_desktop_wmclass (appsys, wm_instance); if (app != NULL) return g_object_ref (app); /* finally, try a match from WM_CLASS to .desktop */ app = cinnamon_app_system_lookup_desktop_wmclass (appsys, wm_class); if (app != NULL) return g_object_ref (app); return NULL; }