[gnome-shell] Add shell_app_system_create_from_window



commit d94606587bf8fab284f1bfb2f26a07f30c09a525
Author: Colin Walters <walters verbum org>
Date:   Fri Aug 14 04:34:28 2009 -0400

    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*.

 src/shell-app-system.c |  148 +++++++++++++++++++++++++++++++++++++++---------
 src/shell-app-system.h |    6 ++-
 2 files changed, 125 insertions(+), 29 deletions(-)
---
diff --git a/src/shell-app-system.c b/src/shell-app-system.c
index d4ee4cb..05060c2 100644
--- a/src/shell-app-system.c
+++ b/src/shell-app-system.c
@@ -57,7 +57,8 @@ G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
 
 typedef enum {
   SHELL_APP_INFO_TYPE_ENTRY,
-  SHELL_APP_INFO_TYPE_DESKTOP_FILE
+  SHELL_APP_INFO_TYPE_DESKTOP_FILE,
+  SHELL_APP_INFO_TYPE_WINDOW
 } ShellAppInfoType;
 
 struct _ShellAppInfo {
@@ -75,6 +76,9 @@ struct _ShellAppInfo {
 
   GKeyFile *keyfile;
   char *keyfile_path;
+
+  MetaWindow *window;
+  char *window_id;
 };
 
 ShellAppInfo*
@@ -97,6 +101,9 @@ shell_app_info_unref (ShellAppInfo *info)
   case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
     g_key_file_free (info->keyfile);
     g_free (info->keyfile_path);
+  case SHELL_APP_INFO_TYPE_WINDOW:
+    g_object_unref (info->window);
+    g_free (info->window_id);
     break;
   }
   g_slice_free (ShellAppInfo, info);
@@ -118,6 +125,23 @@ shell_app_info_new_from_tree_item (GMenuTreeItem *item)
 }
 
 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 *
 shell_app_info_new_from_keyfile_take_ownership (GKeyFile   *keyfile,
                                                 const char *path)
 {
@@ -574,8 +598,6 @@ set_gconf_value_string_list (GConfValue *val, GList *items)
   g_slist_free (tmp);
 }
 
-
-
 void
 shell_app_system_add_favorite (ShellAppSystem *system, const char *id)
 {
@@ -671,6 +693,21 @@ shell_app_system_load_from_desktop_file (ShellAppSystem   *system,
 }
 
 /**
+ * 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:
  * @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);
     case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
       return info->keyfile_path;
+    case SHELL_APP_INFO_TYPE_WINDOW:
+      return info->window_id;
   }
   g_assert_not_reached ();
   return NULL;
@@ -735,6 +774,12 @@ shell_app_info_get_name (ShellAppInfo *info)
       return g_strdup (gmenu_tree_entry_get_name ((GMenuTreeEntry*)info->entry));
     case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
       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 ();
   return NULL;
@@ -749,6 +794,8 @@ shell_app_info_get_description (ShellAppInfo *info)
       return g_strdup (gmenu_tree_entry_get_comment ((GMenuTreeEntry*)info->entry));
     case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
       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 ();
   return NULL;
@@ -763,6 +810,8 @@ shell_app_info_get_executable (ShellAppInfo *info)
       return g_strdup (gmenu_tree_entry_get_exec ((GMenuTreeEntry*)info->entry));
     case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
       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 ();
   return NULL;
@@ -776,45 +825,29 @@ shell_app_info_get_desktop_file_path (ShellAppInfo *info)
     case SHELL_APP_INFO_TYPE_ENTRY:
       return g_strdup (gmenu_tree_entry_get_desktop_file_path ((GMenuTreeEntry*)info->entry));
     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 ();
   return NULL;
 }
 
-GIcon *
-shell_app_info_get_icon (ShellAppInfo *info)
+static GIcon *
+themed_icon_from_name (const char *iconname)
 {
-  char *iconname = NULL;
   GIcon *icon;
 
-  /* This code adapted from gdesktopappinfo.c
-   * Copyright (C) 2006-2007 Red Hat, Inc.
-   * Copyright © 2007 Ryan Lortie
-   * LGPL
-   */
-
-  switch (info->type)
-  {
-    case SHELL_APP_INFO_TYPE_ENTRY:
-      iconname = g_strdup (gmenu_tree_entry_get_icon ((GMenuTreeEntry*)info->entry));
-      break;
-    case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
-      iconname = g_key_file_get_locale_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Icon", NULL, NULL);
-      break;
-  }
-
   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;
@@ -827,15 +860,42 @@ shell_app_info_get_icon (ShellAppInfo *info)
         {
           *p = 0;
         }
-
       icon = g_themed_icon_new (tmp_name);
       g_free (tmp_name);
     }
-  g_free (iconname);
 
   return icon;
 }
 
+static GIcon *
+shell_app_info_get_icon (ShellAppInfo *info)
+{
+  char *iconname = NULL;
+  GIcon *icon;
+
+  /* This code adapted from gdesktopappinfo.c
+   * Copyright (C) 2006-2007 Red Hat, Inc.
+   * Copyright © 2007 Ryan Lortie
+   * LGPL
+   */
+
+  switch (info->type)
+  {
+    case SHELL_APP_INFO_TYPE_ENTRY:
+      return themed_icon_from_name (gmenu_tree_entry_get_icon ((GMenuTreeEntry*)info->entry));
+    case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
+      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;
+    case SHELL_APP_INFO_TYPE_WINDOW:
+      return NULL;
+  }
+  g_assert_not_reached ();
+  return NULL;
+}
+
 GSList *
 shell_app_info_get_categories (ShellAppInfo *info)
 {
@@ -850,6 +910,7 @@ shell_app_info_get_is_nodisplay (ShellAppInfo *info)
     case SHELL_APP_INFO_TYPE_ENTRY:
       return gmenu_tree_entry_get_is_nodisplay ((GMenuTreeEntry*)info->entry);
     case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
+    case SHELL_APP_INFO_TYPE_WINDOW:
       return FALSE;
   }
   g_assert_not_reached ();
@@ -857,6 +918,19 @@ shell_app_info_get_is_nodisplay (ShellAppInfo *info)
 }
 
 /**
+ * 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:
  *
  * Look up the icon for this application, and create a #ClutterTexture
@@ -870,6 +944,13 @@ shell_app_info_create_icon_texture (ShellAppInfo *info, float size)
   GIcon *icon;
   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);
   if (!icon)
     {
@@ -908,6 +989,17 @@ shell_app_info_launch_full (ShellAppInfo *info,
   if (startup_id)
     *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);
   gapp = g_desktop_app_info_new_from_filename (filename);
   g_free (filename);
diff --git a/src/shell-app-system.h b/src/shell-app-system.h
index 7691eaf..b8d20f9 100644
--- a/src/shell-app-system.h
+++ b/src/shell-app-system.h
@@ -4,6 +4,8 @@
 #include <gio/gio.h>
 #include <clutter/clutter.h>
 
+#include "window.h"
+
 #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_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_executable (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);
 GSList *shell_app_info_get_categories (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,
                             guint         timestamp,
                             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_create_from_window (ShellAppSystem *system, MetaWindow *window);
+
 GSList *shell_app_system_get_menus (ShellAppSystem *system);
 
 GSList *shell_app_system_get_all_settings (ShellAppSystem *system);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]