Add shell_app_system_create_from_window
For various cases such as when we don't know a .desktop file for a window, it's desirable to "fake" an application from the contents of a MetaWindow*.
This commit is contained in:
parent
74ea9f9305
commit
d94606587b
@ -57,7 +57,8 @@ G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SHELL_APP_INFO_TYPE_ENTRY,
|
SHELL_APP_INFO_TYPE_ENTRY,
|
||||||
SHELL_APP_INFO_TYPE_DESKTOP_FILE
|
SHELL_APP_INFO_TYPE_DESKTOP_FILE,
|
||||||
|
SHELL_APP_INFO_TYPE_WINDOW
|
||||||
} ShellAppInfoType;
|
} ShellAppInfoType;
|
||||||
|
|
||||||
struct _ShellAppInfo {
|
struct _ShellAppInfo {
|
||||||
@ -75,6 +76,9 @@ struct _ShellAppInfo {
|
|||||||
|
|
||||||
GKeyFile *keyfile;
|
GKeyFile *keyfile;
|
||||||
char *keyfile_path;
|
char *keyfile_path;
|
||||||
|
|
||||||
|
MetaWindow *window;
|
||||||
|
char *window_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
ShellAppInfo*
|
ShellAppInfo*
|
||||||
@ -97,6 +101,9 @@ shell_app_info_unref (ShellAppInfo *info)
|
|||||||
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
||||||
g_key_file_free (info->keyfile);
|
g_key_file_free (info->keyfile);
|
||||||
g_free (info->keyfile_path);
|
g_free (info->keyfile_path);
|
||||||
|
case SHELL_APP_INFO_TYPE_WINDOW:
|
||||||
|
g_object_unref (info->window);
|
||||||
|
g_free (info->window_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
g_slice_free (ShellAppInfo, info);
|
g_slice_free (ShellAppInfo, info);
|
||||||
@ -117,6 +124,23 @@ shell_app_info_new_from_tree_item (GMenuTreeItem *item)
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ShellAppInfo *
|
||||||
|
shell_app_info_new_from_window (MetaWindow *window)
|
||||||
|
{
|
||||||
|
ShellAppInfo *info;
|
||||||
|
|
||||||
|
info = g_slice_alloc (sizeof (ShellAppInfo));
|
||||||
|
info->type = SHELL_APP_INFO_TYPE_WINDOW;
|
||||||
|
info->refcount = 1;
|
||||||
|
info->window = g_object_ref (window);
|
||||||
|
/* For windows, its id is simply its pointer address as a string.
|
||||||
|
* There are various other alternatives, but the address is unique
|
||||||
|
* and unchanging, which is pretty much the best we can do.
|
||||||
|
*/
|
||||||
|
info->window_id = g_strdup_printf ("window:%p", window);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
static ShellAppInfo *
|
static ShellAppInfo *
|
||||||
shell_app_info_new_from_keyfile_take_ownership (GKeyFile *keyfile,
|
shell_app_info_new_from_keyfile_take_ownership (GKeyFile *keyfile,
|
||||||
const char *path)
|
const char *path)
|
||||||
@ -574,8 +598,6 @@ set_gconf_value_string_list (GConfValue *val, GList *items)
|
|||||||
g_slist_free (tmp);
|
g_slist_free (tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
shell_app_system_add_favorite (ShellAppSystem *system, const char *id)
|
shell_app_system_add_favorite (ShellAppSystem *system, const char *id)
|
||||||
{
|
{
|
||||||
@ -670,6 +692,21 @@ shell_app_system_load_from_desktop_file (ShellAppSystem *system,
|
|||||||
return appinfo;
|
return appinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_app_system_create_from_window:
|
||||||
|
*
|
||||||
|
* In the case where we can't otherwise determine an application
|
||||||
|
* associated with a window, this function can create a "fake"
|
||||||
|
* application just backed by information from the window itself.
|
||||||
|
*
|
||||||
|
* Return value: (transfer full): A new #ShellAppInfo
|
||||||
|
*/
|
||||||
|
ShellAppInfo *
|
||||||
|
shell_app_system_create_from_window (ShellAppSystem *system, MetaWindow *window)
|
||||||
|
{
|
||||||
|
return shell_app_info_new_from_window (window);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_app_system_lookup_heuristic_basename:
|
* shell_app_system_lookup_heuristic_basename:
|
||||||
* @name: Probable application identifier
|
* @name: Probable application identifier
|
||||||
@ -719,6 +756,8 @@ shell_app_info_get_id (ShellAppInfo *info)
|
|||||||
return gmenu_tree_entry_get_desktop_file_id ((GMenuTreeEntry*)info->entry);
|
return gmenu_tree_entry_get_desktop_file_id ((GMenuTreeEntry*)info->entry);
|
||||||
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
||||||
return info->keyfile_path;
|
return info->keyfile_path;
|
||||||
|
case SHELL_APP_INFO_TYPE_WINDOW:
|
||||||
|
return info->window_id;
|
||||||
}
|
}
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -735,6 +774,12 @@ shell_app_info_get_name (ShellAppInfo *info)
|
|||||||
return g_strdup (gmenu_tree_entry_get_name ((GMenuTreeEntry*)info->entry));
|
return g_strdup (gmenu_tree_entry_get_name ((GMenuTreeEntry*)info->entry));
|
||||||
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
||||||
return g_key_file_get_locale_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Name", NULL, NULL);
|
return g_key_file_get_locale_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Name", NULL, NULL);
|
||||||
|
case SHELL_APP_INFO_TYPE_WINDOW:
|
||||||
|
{
|
||||||
|
char *title;
|
||||||
|
g_object_get (info->window, "title", &title, NULL);
|
||||||
|
return title;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -749,6 +794,8 @@ shell_app_info_get_description (ShellAppInfo *info)
|
|||||||
return g_strdup (gmenu_tree_entry_get_comment ((GMenuTreeEntry*)info->entry));
|
return g_strdup (gmenu_tree_entry_get_comment ((GMenuTreeEntry*)info->entry));
|
||||||
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
||||||
return g_key_file_get_locale_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Comment", NULL, NULL);
|
return g_key_file_get_locale_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Comment", NULL, NULL);
|
||||||
|
case SHELL_APP_INFO_TYPE_WINDOW:
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -763,6 +810,8 @@ shell_app_info_get_executable (ShellAppInfo *info)
|
|||||||
return g_strdup (gmenu_tree_entry_get_exec ((GMenuTreeEntry*)info->entry));
|
return g_strdup (gmenu_tree_entry_get_exec ((GMenuTreeEntry*)info->entry));
|
||||||
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
||||||
return g_key_file_get_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Exec", NULL);
|
return g_key_file_get_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Exec", NULL);
|
||||||
|
case SHELL_APP_INFO_TYPE_WINDOW:
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -776,13 +825,49 @@ shell_app_info_get_desktop_file_path (ShellAppInfo *info)
|
|||||||
case SHELL_APP_INFO_TYPE_ENTRY:
|
case SHELL_APP_INFO_TYPE_ENTRY:
|
||||||
return g_strdup (gmenu_tree_entry_get_desktop_file_path ((GMenuTreeEntry*)info->entry));
|
return g_strdup (gmenu_tree_entry_get_desktop_file_path ((GMenuTreeEntry*)info->entry));
|
||||||
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
||||||
return g_strdup (info->keyfile_path);;
|
return g_strdup (info->keyfile_path);
|
||||||
|
case SHELL_APP_INFO_TYPE_WINDOW:
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GIcon *
|
static GIcon *
|
||||||
|
themed_icon_from_name (const char *iconname)
|
||||||
|
{
|
||||||
|
GIcon *icon;
|
||||||
|
|
||||||
|
if (!iconname)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (g_path_is_absolute (iconname))
|
||||||
|
{
|
||||||
|
GFile *file;
|
||||||
|
file = g_file_new_for_path (iconname);
|
||||||
|
icon = G_ICON (g_file_icon_new (file));
|
||||||
|
g_object_unref (file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *tmp_name, *p;
|
||||||
|
tmp_name = strdup (iconname);
|
||||||
|
/* Work around a common mistake in desktop files */
|
||||||
|
if ((p = strrchr (tmp_name, '.')) != NULL &&
|
||||||
|
(strcmp (p, ".png") == 0 ||
|
||||||
|
strcmp (p, ".xpm") == 0 ||
|
||||||
|
strcmp (p, ".svg") == 0))
|
||||||
|
{
|
||||||
|
*p = 0;
|
||||||
|
}
|
||||||
|
icon = g_themed_icon_new (tmp_name);
|
||||||
|
g_free (tmp_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GIcon *
|
||||||
shell_app_info_get_icon (ShellAppInfo *info)
|
shell_app_info_get_icon (ShellAppInfo *info)
|
||||||
{
|
{
|
||||||
char *iconname = NULL;
|
char *iconname = NULL;
|
||||||
@ -797,43 +882,18 @@ shell_app_info_get_icon (ShellAppInfo *info)
|
|||||||
switch (info->type)
|
switch (info->type)
|
||||||
{
|
{
|
||||||
case SHELL_APP_INFO_TYPE_ENTRY:
|
case SHELL_APP_INFO_TYPE_ENTRY:
|
||||||
iconname = g_strdup (gmenu_tree_entry_get_icon ((GMenuTreeEntry*)info->entry));
|
return themed_icon_from_name (gmenu_tree_entry_get_icon ((GMenuTreeEntry*)info->entry));
|
||||||
break;
|
|
||||||
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
||||||
iconname = g_key_file_get_locale_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Icon", NULL, NULL);
|
iconname = g_key_file_get_locale_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Icon", NULL, NULL);
|
||||||
|
icon = themed_icon_from_name (iconname);
|
||||||
|
g_free (iconname);
|
||||||
|
return icon;
|
||||||
break;
|
break;
|
||||||
|
case SHELL_APP_INFO_TYPE_WINDOW:
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
g_assert_not_reached ();
|
||||||
if (!iconname)
|
return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (g_path_is_absolute (iconname))
|
|
||||||
{
|
|
||||||
GFile *file;
|
|
||||||
|
|
||||||
file = g_file_new_for_path (iconname);
|
|
||||||
icon = G_ICON (g_file_icon_new (file));
|
|
||||||
g_object_unref (file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *tmp_name, *p;
|
|
||||||
tmp_name = strdup (iconname);
|
|
||||||
/* Work around a common mistake in desktop files */
|
|
||||||
if ((p = strrchr (tmp_name, '.')) != NULL &&
|
|
||||||
(strcmp (p, ".png") == 0 ||
|
|
||||||
strcmp (p, ".xpm") == 0 ||
|
|
||||||
strcmp (p, ".svg") == 0))
|
|
||||||
{
|
|
||||||
*p = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
icon = g_themed_icon_new (tmp_name);
|
|
||||||
g_free (tmp_name);
|
|
||||||
}
|
|
||||||
g_free (iconname);
|
|
||||||
|
|
||||||
return icon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GSList *
|
GSList *
|
||||||
@ -850,12 +910,26 @@ shell_app_info_get_is_nodisplay (ShellAppInfo *info)
|
|||||||
case SHELL_APP_INFO_TYPE_ENTRY:
|
case SHELL_APP_INFO_TYPE_ENTRY:
|
||||||
return gmenu_tree_entry_get_is_nodisplay ((GMenuTreeEntry*)info->entry);
|
return gmenu_tree_entry_get_is_nodisplay ((GMenuTreeEntry*)info->entry);
|
||||||
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
|
||||||
|
case SHELL_APP_INFO_TYPE_WINDOW:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_app_info_is_transient:
|
||||||
|
*
|
||||||
|
* A "transient" application is one which represents
|
||||||
|
* just an open window, i.e. we don't know how to launch it
|
||||||
|
* again.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
shell_app_info_is_transient (ShellAppInfo *info)
|
||||||
|
{
|
||||||
|
return info->type == SHELL_APP_INFO_TYPE_WINDOW;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_app_info_create_icon_texture:
|
* shell_app_info_create_icon_texture:
|
||||||
*
|
*
|
||||||
@ -870,6 +944,13 @@ shell_app_info_create_icon_texture (ShellAppInfo *info, float size)
|
|||||||
GIcon *icon;
|
GIcon *icon;
|
||||||
ClutterActor *ret;
|
ClutterActor *ret;
|
||||||
|
|
||||||
|
if (info->type == SHELL_APP_INFO_TYPE_WINDOW)
|
||||||
|
{
|
||||||
|
return shell_texture_cache_bind_pixbuf_property (shell_texture_cache_get_default (),
|
||||||
|
G_OBJECT (info->window),
|
||||||
|
"icon");
|
||||||
|
}
|
||||||
|
|
||||||
icon = shell_app_info_get_icon (info);
|
icon = shell_app_info_get_icon (info);
|
||||||
if (!icon)
|
if (!icon)
|
||||||
{
|
{
|
||||||
@ -908,6 +989,17 @@ shell_app_info_launch_full (ShellAppInfo *info,
|
|||||||
if (startup_id)
|
if (startup_id)
|
||||||
*startup_id = NULL;
|
*startup_id = NULL;
|
||||||
|
|
||||||
|
if (info->type == SHELL_APP_INFO_TYPE_WINDOW)
|
||||||
|
{
|
||||||
|
/* We can't pass URIs into a window; shouldn't hit this
|
||||||
|
* code path. If we do, fix the caller to disallow it.
|
||||||
|
*/
|
||||||
|
g_return_val_if_fail (uris == NULL, TRUE);
|
||||||
|
|
||||||
|
meta_window_activate (info->window, timestamp);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
filename = shell_app_info_get_desktop_file_path (info);
|
filename = shell_app_info_get_desktop_file_path (info);
|
||||||
gapp = g_desktop_app_info_new_from_filename (filename);
|
gapp = g_desktop_app_info_new_from_filename (filename);
|
||||||
g_free (filename);
|
g_free (filename);
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
#define SHELL_TYPE_APP_SYSTEM (shell_app_system_get_type ())
|
#define SHELL_TYPE_APP_SYSTEM (shell_app_system_get_type ())
|
||||||
#define SHELL_APP_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_APP_SYSTEM, ShellAppSystem))
|
#define SHELL_APP_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_APP_SYSTEM, ShellAppSystem))
|
||||||
#define SHELL_APP_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_APP_SYSTEM, ShellAppSystemClass))
|
#define SHELL_APP_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_APP_SYSTEM, ShellAppSystemClass))
|
||||||
@ -58,10 +60,10 @@ char *shell_app_info_get_name (ShellAppInfo *info);
|
|||||||
char *shell_app_info_get_description (ShellAppInfo *info);
|
char *shell_app_info_get_description (ShellAppInfo *info);
|
||||||
char *shell_app_info_get_executable (ShellAppInfo *info);
|
char *shell_app_info_get_executable (ShellAppInfo *info);
|
||||||
char *shell_app_info_get_desktop_file_path (ShellAppInfo *info);
|
char *shell_app_info_get_desktop_file_path (ShellAppInfo *info);
|
||||||
GIcon *shell_app_info_get_icon (ShellAppInfo *info);
|
|
||||||
ClutterActor *shell_app_info_create_icon_texture (ShellAppInfo *info, float size);
|
ClutterActor *shell_app_info_create_icon_texture (ShellAppInfo *info, float size);
|
||||||
GSList *shell_app_info_get_categories (ShellAppInfo *info);
|
GSList *shell_app_info_get_categories (ShellAppInfo *info);
|
||||||
gboolean shell_app_info_get_is_nodisplay (ShellAppInfo *info);
|
gboolean shell_app_info_get_is_nodisplay (ShellAppInfo *info);
|
||||||
|
gboolean shell_app_info_is_transient (ShellAppInfo *info);
|
||||||
gboolean shell_app_info_launch_full (ShellAppInfo *info,
|
gboolean shell_app_info_launch_full (ShellAppInfo *info,
|
||||||
guint timestamp,
|
guint timestamp,
|
||||||
GList *uris,
|
GList *uris,
|
||||||
@ -77,6 +79,8 @@ ShellAppInfo *shell_app_system_lookup_cached_app (ShellAppSystem *system, const
|
|||||||
|
|
||||||
ShellAppInfo *shell_app_system_lookup_heuristic_basename (ShellAppSystem *system, const char *id);
|
ShellAppInfo *shell_app_system_lookup_heuristic_basename (ShellAppSystem *system, const char *id);
|
||||||
|
|
||||||
|
ShellAppInfo *shell_app_system_create_from_window (ShellAppSystem *system, MetaWindow *window);
|
||||||
|
|
||||||
GSList *shell_app_system_get_menus (ShellAppSystem *system);
|
GSList *shell_app_system_get_menus (ShellAppSystem *system);
|
||||||
|
|
||||||
GSList *shell_app_system_get_all_settings (ShellAppSystem *system);
|
GSList *shell_app_system_get_all_settings (ShellAppSystem *system);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user