]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-ui-utils.c
individual_view_drag_end: remove the auto scroll
[empathy.git] / libempathy-gtk / empathy-ui-utils.c
index 060e0aab58dfe4c0237628e0c9c96cfa7277ca13..f3761e5cdf989db13cc4ace95b5760779c5151a5 100644 (file)
@@ -491,7 +491,10 @@ empathy_pixbuf_from_avatar_scaled (EmpathyAvatar *avatar,
                          G_CALLBACK (pixbuf_from_avatar_size_prepared_cb),
                          &data);
 
-       if (!gdk_pixbuf_loader_write (loader, avatar->data, avatar->len, &error)) {
+       if (avatar->len == 0) {
+               g_warning ("Avatar has 0 length");
+               return NULL;
+       } else if (!gdk_pixbuf_loader_write (loader, avatar->data, avatar->len, &error)) {
                g_warning ("Couldn't write avatar image:%p with "
                           "length:%" G_GSIZE_FORMAT " to pixbuf loader: %s",
                           avatar->data, avatar->len, error->message);
@@ -549,7 +552,8 @@ pixbuf_avatar_from_individual_closure_new (FolksIndividual    *individual,
        closure->result = g_object_ref (result);
        closure->width = width;
        closure->height = height;
-       closure->cancellable = g_object_ref (cancellable);
+       if (cancellable != NULL)
+               closure->cancellable = g_object_ref (cancellable);
 
        return closure;
 }
@@ -558,13 +562,28 @@ static void
 pixbuf_avatar_from_individual_closure_free (
                PixbufAvatarFromIndividualClosure *closure)
 {
-       g_object_unref (closure->cancellable);
+       g_clear_object (&closure->cancellable);
        tp_clear_object (&closure->loader);
        g_object_unref (closure->individual);
        g_object_unref (closure->result);
        g_free (closure);
 }
 
+static void
+avatar_icon_load_close_cb (GObject      *object,
+                           GAsyncResult *result,
+                           gpointer      user_data)
+{
+       GError *error = NULL;
+
+       g_input_stream_close_finish (G_INPUT_STREAM (object), result, &error);
+
+       if (error != NULL) {
+               DEBUG ("Failed to close pixbuf stream: %s", error->message);
+               g_error_free (error);
+       }
+}
+
 static void
 avatar_icon_load_read_cb (GObject      *object,
                           GAsyncResult *result,
@@ -623,6 +642,11 @@ out_close:
        gdk_pixbuf_loader_close (closure->loader, NULL);
 
 out:
+       /* Close the file for safety (even though it should be
+        * automatically closed when the stream is finalised). */
+       g_input_stream_close_async (stream, G_PRIORITY_DEFAULT, NULL,
+               (GAsyncReadyCallback) avatar_icon_load_close_cb, NULL);
+
        g_simple_async_result_complete (closure->result);
 
        g_clear_error (&error);
@@ -694,26 +718,25 @@ empathy_pixbuf_avatar_from_individual_scaled_async (
 
        avatar_icon =
                folks_avatar_details_get_avatar (FOLKS_AVATAR_DETAILS (individual));
-       if (avatar_icon == NULL)
-               goto out;
+       if (avatar_icon == NULL) {
+               g_simple_async_result_set_error (result, TP_ERRORS,
+                       TP_ERROR_INVALID_ARGUMENT, "no avatar found");
+
+               g_simple_async_result_complete (result);
+               g_object_unref (result);
+               return;
+       }
 
        closure = pixbuf_avatar_from_individual_closure_new (individual, result,
                                                             width, height,
                                                             cancellable);
-       if (closure == NULL)
-               goto out;
+
+       g_return_if_fail (closure != NULL);
 
        g_loadable_icon_load_async (avatar_icon, width, cancellable,
                        avatar_icon_load_cb, closure);
 
        g_object_unref (result);
-
-       return;
-
-out:
-       g_simple_async_result_set_op_res_gpointer (result, NULL, NULL);
-       g_simple_async_result_complete (result);
-       g_object_unref (result);
 }
 
 /* Return a ref on the GdkPixbuf */
@@ -927,6 +950,9 @@ empathy_filename_from_icon_name (const gchar *icon_name,
        }
 
        icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size, 0);
+       if (icon_info == NULL)
+               return NULL;
+
        ret = g_strdup (gtk_icon_info_get_filename (icon_info));
        gtk_icon_info_free (icon_info);
 
@@ -1739,7 +1765,8 @@ empathy_send_file (EmpathyContact *contact, GFile *file)
 
        factory = empathy_ft_factory_dup_singleton ();
 
-       empathy_ft_factory_new_transfer_outgoing (factory, contact, file);
+       empathy_ft_factory_new_transfer_outgoing (factory, contact, file,
+               empathy_get_current_action_time ());
 
        uri = g_file_get_uri (file);
        manager = gtk_recent_manager_get_default ();
@@ -1798,6 +1825,27 @@ file_manager_send_file_response_cb (GtkDialog      *widget,
        gtk_widget_destroy (GTK_WIDGET (widget));
 }
 
+static gboolean
+filter_cb (const GtkFileFilterInfo *filter_info,
+               gpointer data)
+{
+       /* filter out socket files */
+       return tp_strdiff (filter_info->mime_type, "inode/socket");
+}
+
+static GtkFileFilter *
+create_file_filter (void)
+{
+       GtkFileFilter *filter;
+
+       filter = gtk_file_filter_new ();
+
+       gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_MIME_TYPE, filter_cb,
+               NULL, NULL);
+
+       return filter;
+}
+
 void
 empathy_send_file_with_file_chooser (EmpathyContact *contact)
 {
@@ -1832,6 +1880,9 @@ empathy_send_file_with_file_chooser (EmpathyContact *contact)
        gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget),
                g_get_home_dir ());
 
+       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget),
+               create_file_filter ());
+
        g_signal_connect (widget, "response",
                          G_CALLBACK (file_manager_send_file_response_cb),
                          g_object_ref (contact));
@@ -1883,8 +1934,8 @@ file_manager_receive_file_response_cb (GtkDialog *dialog,
                                _("Insufficient free space to save file"));
                        char *file_size_str, *free_space_str;
 
-                       file_size_str = g_format_size_for_display (file_size);
-                       free_space_str = g_format_size_for_display (free_space);
+                       file_size_str = g_format_size (file_size);
+                       free_space_str = g_format_size (free_space);
 
                        gtk_message_dialog_format_secondary_text (
                                GTK_MESSAGE_DIALOG (message),
@@ -2075,108 +2126,6 @@ empathy_individual_match_string (FolksIndividual *individual,
   return retval;
 }
 
-static gboolean
-dtmf_dialpad_button_pressed_cb (GObject *button,
-    GtkEntry *entry)
-{
-  GtkEntryBuffer *buffer = gtk_entry_get_buffer (entry);
-  const gchar *label;
-
-  label = g_object_get_data (button, "label");
-  gtk_entry_buffer_insert_text (buffer, -1, label, -1);
-
-  return FALSE;
-}
-
-GtkWidget *
-empathy_create_dtmf_dialpad (GObject *self,
-    GCallback dtmf_button_pressed_cb,
-    GCallback dtmf_button_released_cb)
-{
-  GtkWidget *box, *entry, *table;
-  int i;
-  GQuark button_quark;
-  struct {
-    const gchar *label;
-    const gchar *sublabel;
-    TpDTMFEvent event;
-  } dtmfbuttons[] = { { "1", "",     TP_DTMF_EVENT_DIGIT_1 },
-                      { "2", "abc",  TP_DTMF_EVENT_DIGIT_2 },
-                      { "3", "def",  TP_DTMF_EVENT_DIGIT_3 },
-                      { "4", "ghi",  TP_DTMF_EVENT_DIGIT_4 },
-                      { "5", "jkl",  TP_DTMF_EVENT_DIGIT_5 },
-                      { "6", "mno",  TP_DTMF_EVENT_DIGIT_6 },
-                      { "7", "pqrs", TP_DTMF_EVENT_DIGIT_7 },
-                      { "8", "tuv",  TP_DTMF_EVENT_DIGIT_8 },
-                      { "9", "wxyz", TP_DTMF_EVENT_DIGIT_9 },
-                      { "#", "",     TP_DTMF_EVENT_HASH },
-                      { "0", "",     TP_DTMF_EVENT_DIGIT_0 },
-                      { "*", "",     TP_DTMF_EVENT_ASTERISK },
-                      { NULL, } };
-
-  box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
-
-  entry = gtk_entry_new ();
-  gtk_editable_set_editable (GTK_EDITABLE (entry), FALSE);
-
-  gtk_box_pack_start (GTK_BOX (box), entry, FALSE, FALSE, 3);
-
-  button_quark = g_quark_from_static_string (EMPATHY_DTMF_BUTTON_ID);
-
-  table = gtk_table_new (4, 3, TRUE);
-
-  for (i = 0; dtmfbuttons[i].label != NULL; i++)
-    {
-      GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
-      GtkWidget *button = gtk_button_new ();
-      GtkWidget *label;
-      gchar *str;
-
-      gtk_container_add (GTK_CONTAINER (button), vbox);
-
-      /* main label */
-      label = gtk_label_new ("");
-      str = g_strdup_printf ("<span size='x-large'>%s</span>",
-          dtmfbuttons[i].label);
-      gtk_label_set_markup (GTK_LABEL (label), str);
-      g_free (str);
-
-      g_object_set_data (G_OBJECT (button), "label",
-          (gpointer) dtmfbuttons[i].label);
-
-      gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 3);
-
-      /* sub label */
-      label = gtk_label_new ("");
-      str = g_strdup_printf (
-          "<span foreground='#555555'>%s</span>",
-          dtmfbuttons[i].sublabel);
-      gtk_label_set_markup (GTK_LABEL (label), str);
-      g_free (str);
-
-      gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
-
-      gtk_table_attach (GTK_TABLE (table), button, i % 3, i % 3 + 1,
-        i/3, i/3 + 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 1, 1);
-
-      g_object_set_qdata (G_OBJECT (button), button_quark,
-        GUINT_TO_POINTER (dtmfbuttons[i].event));
-
-      /* To update the GtkEntry */
-      g_signal_connect (G_OBJECT (button), "pressed",
-        G_CALLBACK (dtmf_dialpad_button_pressed_cb), entry);
-
-      g_signal_connect (G_OBJECT (button), "pressed",
-        dtmf_button_pressed_cb, self);
-      g_signal_connect (G_OBJECT (button), "released",
-        dtmf_button_released_cb, self);
-    }
-
-  gtk_box_pack_start (GTK_BOX (box), table, FALSE, FALSE, 3);
-
-  return box;
-}
-
 void
 empathy_launch_program (const gchar *dir,
     const gchar *name,
@@ -2228,3 +2177,120 @@ out:
   g_free (path);
   g_free (cmd);
 }
+
+/* Most of the workspace manipulation code has been copied from libwnck
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2005-2007 Vincent Untz
+ */
+static void
+_wnck_activate_workspace (Screen *screen,
+    int new_active_space,
+    Time timestamp)
+{
+  Display *display;
+  Window   root;
+  XEvent   xev;
+
+  display = DisplayOfScreen (screen);
+  root = RootWindowOfScreen (screen);
+
+  xev.xclient.type = ClientMessage;
+  xev.xclient.serial = 0;
+  xev.xclient.send_event = True;
+  xev.xclient.display = display;
+  xev.xclient.window = root;
+  xev.xclient.message_type = gdk_x11_get_xatom_by_name ("_NET_CURRENT_DESKTOP");
+  xev.xclient.format = 32;
+  xev.xclient.data.l[0] = new_active_space;
+  xev.xclient.data.l[1] = timestamp;
+  xev.xclient.data.l[2] = 0;
+  xev.xclient.data.l[3] = 0;
+  xev.xclient.data.l[4] = 0;
+
+  gdk_error_trap_push ();
+  XSendEvent (display, root, False,
+      SubstructureRedirectMask | SubstructureNotifyMask,
+      &xev);
+  XSync (display, False);
+  gdk_error_trap_pop_ignored ();
+}
+
+static gboolean
+_wnck_get_cardinal (Screen *screen,
+    Window xwindow,
+    Atom atom,
+    int *val)
+{
+  Display *display;
+  Atom type;
+  int format;
+  gulong nitems;
+  gulong bytes_after;
+  gulong *num;
+  int err, result;
+
+  display = DisplayOfScreen (screen);
+
+  *val = 0;
+
+  gdk_error_trap_push ();
+  type = None;
+  result = XGetWindowProperty (display, xwindow, atom,
+      0, G_MAXLONG, False, XA_CARDINAL, &type, &format, &nitems,
+      &bytes_after, (void *) &num);
+  err = gdk_error_trap_pop ();
+  if (err != Success ||
+      result != Success)
+    return FALSE;
+
+  if (type != XA_CARDINAL)
+    {
+      XFree (num);
+      return FALSE;
+    }
+
+  *val = *num;
+
+  XFree (num);
+
+  return TRUE;
+}
+
+static int
+window_get_workspace (Screen *xscreen,
+    Window win)
+{
+  int number;
+
+  if (!_wnck_get_cardinal (xscreen, win,
+        gdk_x11_get_xatom_by_name ("_NET_WM_DESKTOP"), &number))
+    return -1;
+
+  return number;
+}
+
+/* Ask X to move to the desktop on which @window currently is
+ * and the present @window. */
+void
+empathy_move_to_window_desktop (GtkWindow *window,
+    guint32 timestamp)
+{
+  GdkScreen *screen;
+  Screen *xscreen;
+  GdkWindow *gdk_window;
+  int workspace;
+
+  screen = gtk_window_get_screen (window);
+  xscreen = gdk_x11_screen_get_xscreen (screen);
+  gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
+
+  workspace = window_get_workspace (xscreen,
+      gdk_x11_window_get_xid (gdk_window));
+  if (workspace == -1)
+    goto out;
+
+  _wnck_activate_workspace (xscreen, workspace, timestamp);
+
+out:
+  gtk_window_present_with_time (window, timestamp);
+}