]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkapplaunchcontext-x11.c
Fix a segfault if the GAppInfo does not have an icon
[~andy/gtk] / gdk / x11 / gdkapplaunchcontext-x11.c
index b91b21355e17f46e1b2961c871d2f91ab955d890..825be753e4d886d217d272c5c3d56a935655ec05 100644 (file)
 
 #include "config.h"
 
-#include <string.h>
-#include <unistd.h>
+#include "gdkx11applaunchcontext.h"
+#include "gdkapplaunchcontextprivate.h"
+#include "gdkscreen.h"
+#include "gdkintl.h"
+#include "gdkprivate-x11.h"
 
 #include <glib.h>
 #include <gio/gdesktopappinfo.h>
 
-#include "gdkx.h"
-#include "gdkapplaunchcontext.h"
-#include "gdkscreen.h"
-#include "gdkinternals.h"
-#include "gdkintl.h"
-
+#include <string.h>
+#include <unistd.h>
 
 static char *
-get_display_name (GFile *file)
+get_display_name (GFile     *file,
+                  GFileInfo *info)
 {
-  GFileInfo *info;
   char *name, *tmp;
 
-  /* This does sync I/O, which isn't ideal.
-   * It should probably use the NautilusFile machinery
-   */
-
   name = NULL;
-  info = g_file_query_info (file,
-                           G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0, NULL, NULL);
   if (info)
-    {
-      name = g_strdup (g_file_info_get_display_name (info));
-      g_object_unref (info);
-    }
+    name = g_strdup (g_file_info_get_display_name (info));
 
   if (name == NULL)
     {
       name = g_file_get_basename (file);
       if (!g_utf8_validate (name, -1, NULL))
-       {
-         tmp = name;
-         name =
-           g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH,
-                                TRUE);
-         g_free (tmp);
-       }
+        {
+          tmp = name;
+          name =
+            g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
+          g_free (tmp);
+        }
     }
 
   return name;
 }
 
 static GIcon *
-get_icon (GFile *file)
+get_icon (GFile     *file,
+          GFileInfo *info)
 {
-  GFileInfo *info;
   GIcon *icon;
 
   icon = NULL;
-  info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_ICON, 0, NULL, NULL);
+
   if (info)
     {
       icon = g_file_info_get_icon (info);
       if (icon)
-       g_object_ref (icon);
-      g_object_unref (info);
+        g_object_ref (icon);
     }
 
   return icon;
@@ -99,13 +87,13 @@ gicon_to_string (GIcon *icon)
     {
       file = g_file_icon_get_file (G_FILE_ICON (icon));
       if (file)
-       return g_file_get_path (file);
+        return g_file_get_path (file);
     }
   else if (G_IS_THEMED_ICON (icon))
     {
       names = g_themed_icon_get_names (G_THEMED_ICON (icon));
       if (names)
-       return g_strdup (names[0]);
+        return g_strdup (names[0]);
     }
   else if (G_IS_EMBLEMED_ICON (icon))
     {
@@ -121,11 +109,11 @@ gicon_to_string (GIcon *icon)
 
 static void
 end_startup_notification (GdkDisplay *display,
-                         const char *startup_id)
+                          const char *startup_id)
 {
   gdk_x11_display_broadcast_startup_message (display, "remove",
-                                            "ID", startup_id,
-                                            NULL);
+                                             "ID", startup_id,
+                                             NULL);
 }
 
 
@@ -140,10 +128,10 @@ end_startup_notification (GdkDisplay *display,
  * timeouts. The reason our timeout is dumb is that we don't monitor
  * the sequence (don't use an SnMonitorContext)
  */
-#define STARTUP_TIMEOUT_LENGTH_SECONDS 30 
+#define STARTUP_TIMEOUT_LENGTH_SECONDS 30
 #define STARTUP_TIMEOUT_LENGTH (STARTUP_TIMEOUT_LENGTH_SECONDS * 1000)
 
-typedef struct 
+typedef struct
 {
   GdkDisplay *display;
   char *startup_id;
@@ -160,7 +148,7 @@ free_startup_notification_data (gpointer data)
   g_free (sn_data);
 }
 
-typedef struct 
+typedef struct
 {
   GSList *contexts;
   guint timeout_id;
@@ -210,19 +198,19 @@ startup_timeout (void *data)
       next = tmp->next;
 
       elapsed =
-       ((((double) now.tv_sec - sn_data->time.tv_sec) * G_USEC_PER_SEC +
-         (now.tv_usec - sn_data->time.tv_usec))) / 1000.0;
+        ((((double) now.tv_sec - sn_data->time.tv_sec) * G_USEC_PER_SEC +
+          (now.tv_usec - sn_data->time.tv_usec))) / 1000.0;
 
       if (elapsed >= STARTUP_TIMEOUT_LENGTH)
-       {
-         std->contexts = g_slist_remove (std->contexts, sn_data);
-         end_startup_notification (sn_data->display, sn_data->startup_id);
-         free_startup_notification_data (sn_data);
-       }
+        {
+          std->contexts = g_slist_remove (std->contexts, sn_data);
+          end_startup_notification (sn_data->display, sn_data->startup_id);
+          free_startup_notification_data (sn_data);
+        }
       else
-       {
-         min_timeout = MIN (min_timeout, (STARTUP_TIMEOUT_LENGTH - elapsed));
-       }
+        {
+          min_timeout = MIN (min_timeout, (STARTUP_TIMEOUT_LENGTH - elapsed));
+        }
 
       tmp = next;
     }
@@ -239,7 +227,7 @@ startup_timeout (void *data)
 
 static void
 add_startup_timeout (GdkScreen  *screen,
-                    const char *startup_id)
+                     const char *startup_id)
 {
   StartupTimeoutData *data;
   StartupNotificationData *sn_data;
@@ -253,7 +241,7 @@ add_startup_timeout (GdkScreen  *screen,
       data->timeout_id = 0;
 
       g_object_set_data_full (G_OBJECT (screen), "appinfo-startup-data",
-                             data, free_startup_timeout);
+                              data, free_startup_timeout);
     }
 
   sn_data = g_new (StartupNotificationData, 1);
@@ -265,17 +253,16 @@ add_startup_timeout (GdkScreen  *screen,
 
   if (data->timeout_id == 0)
     data->timeout_id = g_timeout_add_seconds (STARTUP_TIMEOUT_LENGTH_SECONDS,
-                                             startup_timeout, data);
+                                              startup_timeout, data);
 }
 
 
-char *
-_gdk_windowing_get_startup_notify_id (GAppLaunchContext *context,
-                                     GAppInfo          *info, 
-                                     GList             *files)
+static char *
+gdk_x11_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
+                                                  GAppInfo          *info,
+                                                  GList             *files)
 {
   static int sequence = 0;
-  GdkAppLaunchContextPrivate *priv;
   GdkDisplay *display;
   GdkScreen *screen;
   int files_count;
@@ -288,73 +275,79 @@ _gdk_windowing_get_startup_notify_id (GAppLaunchContext *context,
   GIcon *icon;
   guint32 timestamp;
   char *startup_id;
+  GFileInfo *fileinfo;
+  GdkAppLaunchContext *ctx;
 
-  priv = GDK_APP_LAUNCH_CONTEXT (context)->priv;
+  ctx = GDK_APP_LAUNCH_CONTEXT (context);
 
-  if (priv->screen)
-    {
-      screen = priv->screen;
-      display = gdk_screen_get_display (priv->screen);
-    }
-  else if (priv->display)
-    {
-      display = priv->display;
-      screen = gdk_display_get_default_screen (display);
-    }
+  display = ctx->display;
+  if (ctx->screen)
+    screen = ctx->screen;
   else
-    {
-      display = gdk_display_get_default ();
-      screen = gdk_display_get_default_screen (display);
-    }
+    screen = gdk_display_get_default_screen (ctx->display);
+
+  fileinfo = NULL;
 
   files_count = g_list_length (files);
   if (files_count == 0)
-    description = g_strdup_printf (_("Starting %s"), g_app_info_get_name (info));
+    {
+      description = g_strdup_printf (_("Starting %s"), g_app_info_get_name (info));
+    }
   else if (files_count == 1)
     {
-      gchar *display_name = get_display_name (files->data);
+      gchar *display_name;
+
+      if (g_file_is_native (files->data))
+        fileinfo = g_file_query_info (files->data,
+                                      G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
+                                      G_FILE_ATTRIBUTE_STANDARD_ICON,
+                                      0, NULL, NULL);
+
+      display_name = get_display_name (files->data, fileinfo);
       description = g_strdup_printf (_("Opening %s"), display_name);
       g_free (display_name);
     }
   else
     description = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
-                                               "Opening %d Item",
-                                               "Opening %d Items",
-                                               files_count), files_count);
+                                                "Opening %d Item",
+                                                "Opening %d Items",
+                                                files_count), files_count);
 
   icon_name = NULL;
-  if (priv->icon_name)
-    icon_name = g_strdup (priv->icon_name);
+  if (ctx->icon_name)
+    icon_name = g_strdup (ctx->icon_name);
   else
     {
       icon = NULL;
 
-      if (priv->icon != NULL)
-       icon = g_object_ref (priv->icon);
+      if (ctx->icon != NULL)
+        icon = g_object_ref (ctx->icon);
       else if (files_count == 1)
-       icon = get_icon (files->data);
+        icon = get_icon (files->data, fileinfo);
 
       if (icon == NULL)
-       {
-         icon = g_app_info_get_icon (info);
-         g_object_ref (icon);
-       }
-
-      if (icon)
-       icon_name = gicon_to_string (icon);
-
-      g_object_unref (icon);
+        {
+          icon = g_app_info_get_icon (info);
+          if (icon != NULL)
+            g_object_ref (icon);
+        }
+
+      if (icon != NULL)
+        {
+          icon_name = gicon_to_string (icon);
+          g_object_unref (icon);
+        }
     }
 
   binary_name = g_app_info_get_executable (info);
 
-  timestamp = priv->timestamp;
+  timestamp = ctx->timestamp;
   if (timestamp == GDK_CURRENT_TIME)
     timestamp = gdk_x11_display_get_user_time (display);
 
   screen_str = g_strdup_printf ("%d", gdk_screen_get_number (screen));
-  if (priv->workspace > -1) 
-    workspace_str = g_strdup_printf ("%d", priv->workspace);
+  if (ctx->workspace > -1)
+    workspace_str = g_strdup_printf ("%d", ctx->workspace);
   else
     workspace_str = NULL;
 
@@ -364,30 +357,31 @@ _gdk_windowing_get_startup_notify_id (GAppLaunchContext *context,
     application_id = NULL;
 
   startup_id = g_strdup_printf ("%s-%lu-%s-%s-%d_TIME%lu",
-                               g_get_prgname (),
-                               (unsigned long)getpid (),
-                               g_get_host_name (),
-                               binary_name,
-                               sequence++,
-                               (unsigned long)timestamp);
-
-  
+                                g_get_prgname (),
+                                (unsigned long)getpid (),
+                                g_get_host_name (),
+                                binary_name,
+                                sequence++,
+                                (unsigned long)timestamp);
+
   gdk_x11_display_broadcast_startup_message (display, "new",
-                                            "ID", startup_id,
-                                            "NAME", g_app_info_get_name (info),
-                                            "SCREEN", screen_str,
-                                            "BIN", binary_name,
-                                            "ICON", icon_name,
-                                            "DESKTOP", workspace_str,
-                                            "DESCRIPTION", description,
-                                            "WMCLASS", NULL, /* FIXME */
-                                            "APPLICATION_ID", application_id,
-                                            NULL);
+                                             "ID", startup_id,
+                                             "NAME", g_app_info_get_name (info),
+                                             "SCREEN", screen_str,
+                                             "BIN", binary_name,
+                                             "ICON", icon_name,
+                                             "DESKTOP", workspace_str,
+                                             "DESCRIPTION", description,
+                                             "WMCLASS", NULL, /* FIXME */
+                                             "APPLICATION_ID", application_id,
+                                             NULL);
 
   g_free (description);
   g_free (screen_str);
   g_free (workspace_str);
   g_free (icon_name);
+  if (fileinfo)
+    g_object_unref (fileinfo);
 
   add_startup_timeout (screen, startup_id);
 
@@ -395,46 +389,83 @@ _gdk_windowing_get_startup_notify_id (GAppLaunchContext *context,
 }
 
 
-void
-_gdk_windowing_launch_failed (GAppLaunchContext *context, 
-                             const char        *startup_notify_id)
+static void
+gdk_x11_app_launch_context_launch_failed (GAppLaunchContext *context,
+                                          const gchar       *startup_notify_id)
 {
-  GdkAppLaunchContextPrivate *priv;
+  GdkAppLaunchContext *ctx;
   GdkScreen *screen;
   StartupTimeoutData *data;
   StartupNotificationData *sn_data;
   GSList *l;
 
-  priv = GDK_APP_LAUNCH_CONTEXT (context)->priv;
+  ctx = GDK_APP_LAUNCH_CONTEXT (context);
 
-  if (priv->screen)
-    screen = priv->screen;
-  else if (priv->display)
-    screen = gdk_display_get_default_screen (priv->display);
+  if (ctx->screen)
+    screen = ctx->screen;
   else
-    screen = gdk_display_get_default_screen (gdk_display_get_default ());
+    screen = gdk_display_get_default_screen (ctx->display);
 
   data = g_object_get_data (G_OBJECT (screen), "appinfo-startup-data");
 
   if (data)
     {
       for (l = data->contexts; l != NULL; l = l->next)
-       {
-         sn_data = l->data;
-         if (strcmp (startup_notify_id, sn_data->startup_id) == 0)
-           {
-             data->contexts = g_slist_remove (data->contexts, sn_data);
-             end_startup_notification (sn_data->display, sn_data->startup_id);
-             free_startup_notification_data (sn_data);
-                                             
-             break;
-           }
-       }
+        {
+          sn_data = l->data;
+          if (strcmp (startup_notify_id, sn_data->startup_id) == 0)
+            {
+              data->contexts = g_slist_remove (data->contexts, sn_data);
+              end_startup_notification (sn_data->display, sn_data->startup_id);
+              free_startup_notification_data (sn_data);
+
+              break;
+            }
+        }
 
       if (data->contexts == NULL)
-       {
-         g_source_remove (data->timeout_id);
-         data->timeout_id = 0;
-       }
+        {
+          g_source_remove (data->timeout_id);
+          data->timeout_id = 0;
+        }
     }
 }
+
+struct _GdkX11AppLaunchContext
+{
+  GdkAppLaunchContext parent_instance;
+};
+
+struct _GdkX11AppLaunchContextClass
+{
+  GdkAppLaunchContextClass parent_class;
+};
+
+
+G_DEFINE_TYPE (GdkX11AppLaunchContext, gdk_x11_app_launch_context, GDK_TYPE_APP_LAUNCH_CONTEXT)
+
+static void
+gdk_x11_app_launch_context_class_init (GdkX11AppLaunchContextClass *klass)
+{
+  GAppLaunchContextClass *ctx_class = G_APP_LAUNCH_CONTEXT_CLASS (klass);
+
+  ctx_class->get_startup_notify_id = gdk_x11_app_launch_context_get_startup_notify_id;
+  ctx_class->launch_failed = gdk_x11_app_launch_context_launch_failed;
+}
+
+static void
+gdk_x11_app_launch_context_init (GdkX11AppLaunchContext *ctx)
+{
+}
+
+GdkAppLaunchContext *
+_gdk_x11_display_get_app_launch_context (GdkDisplay *display)
+{
+  GdkAppLaunchContext *ctx;
+
+  ctx = g_object_new (GDK_TYPE_X11_APP_LAUNCH_CONTEXT,
+                      "display", display,
+                      NULL);
+
+  return ctx;
+}