+static void
+empathy_roster_view_row_activated (GtkListBox *box,
+ GtkListBoxRow *row)
+{
+ EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (box);
+ EmpathyRosterContact *contact;
+ FolksIndividual *individual;
+ GList *l;
+
+ if (!EMPATHY_IS_ROSTER_CONTACT (row))
+ return;
+
+ contact = EMPATHY_ROSTER_CONTACT (row);
+ individual = empathy_roster_contact_get_individual (contact);
+
+ /* Activate the oldest event associated with this contact, if any */
+ for (l = g_queue_peek_tail_link (self->priv->events); l != NULL;
+ l = g_list_previous (l))
+ {
+ Event *event = l->data;
+
+ if (event->individual == individual)
+ {
+ g_signal_emit (box, signals[SIG_EVENT_ACTIVATED], 0, individual,
+ event->user_data);
+ return;
+ }
+ }
+
+ g_signal_emit (box, signals[SIG_INDIVIDUAL_ACTIVATED], 0, individual);
+}
+
+static void
+fire_popup_individual_menu (EmpathyRosterView *self,
+ GtkListBoxRow *row,
+ guint button,
+ guint time)
+{
+ EmpathyRosterContact *contact;
+ FolksIndividual *individual;
+ const gchar *active_group;
+
+ if (!EMPATHY_IS_ROSTER_CONTACT (row))
+ return;
+
+ contact = EMPATHY_ROSTER_CONTACT (row);
+ individual = empathy_roster_contact_get_individual (contact);
+
+ active_group = empathy_roster_contact_get_group (contact);
+ g_signal_emit (self, signals[SIG_POPUP_INDIVIDUAL_MENU], 0,
+ active_group, individual, button, time);
+}
+
+static gboolean
+empathy_roster_view_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (widget);
+ gboolean (*chain_up) (GtkWidget *, GdkEventButton *) =
+ ((GtkWidgetClass *) empathy_roster_view_parent_class)->button_press_event;
+
+ if (event->button == 3)
+ {
+ GtkListBoxRow *row;
+
+ row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (self), event->y);
+
+ if (row != NULL)
+ {
+ gtk_list_box_select_row (GTK_LIST_BOX (self), row);
+
+ fire_popup_individual_menu (self, row, event->button, event->time);
+ }
+ }
+
+ return chain_up (widget, event);
+}
+
+static gboolean
+empathy_roster_view_key_press_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (widget);
+ gboolean (*chain_up) (GtkWidget *, GdkEventKey *) =
+ ((GtkWidgetClass *) empathy_roster_view_parent_class)->key_press_event;
+
+ if (event->keyval == GDK_KEY_Menu)
+ {
+ GtkListBoxRow *row;
+
+ row = gtk_list_box_get_selected_row (GTK_LIST_BOX (self));
+
+ if (row != NULL)
+ fire_popup_individual_menu (self, row, 0, event->time);
+ }
+
+ return chain_up (widget, event);
+}
+
+/**
+ * @out_row: (out) (allow-none)
+ */
+FolksIndividual *
+empathy_roster_view_get_individual_at_y (EmpathyRosterView *self,
+ gint y,
+ GtkListBoxRow **out_row)
+{
+ GtkListBoxRow *row;
+
+ row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (self), y);
+
+ if (out_row != NULL)
+ *out_row = row;
+
+ if (!EMPATHY_IS_ROSTER_CONTACT (row))
+ return NULL;
+
+ return empathy_roster_contact_get_individual (EMPATHY_ROSTER_CONTACT (row));
+}
+
+const gchar *
+empathy_roster_view_get_group_at_y (EmpathyRosterView *self,
+ gint y)
+{
+ GtkListBoxRow *row;
+
+ row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (self), y);
+
+ if (EMPATHY_IS_ROSTER_CONTACT (row))
+ return empathy_roster_contact_get_group (EMPATHY_ROSTER_CONTACT (row));
+ else if (EMPATHY_IS_ROSTER_GROUP (row))
+ return empathy_roster_group_get_name (EMPATHY_ROSTER_GROUP (row));
+
+ return NULL;
+}
+
+static gboolean
+empathy_roster_view_query_tooltip (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_mode,
+ GtkTooltip *tooltip)
+{
+ EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (widget);
+ FolksIndividual *individual;
+ gboolean result;
+ GtkListBoxRow *row;
+
+ individual = empathy_roster_view_get_individual_at_y (self, y, &row);
+ if (individual == NULL)
+ return FALSE;
+
+ g_signal_emit (self, signals[SIG_INDIVIDUAL_TOOLTIP], 0,
+ individual, keyboard_mode, tooltip, &result);
+
+ if (result)
+ {
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (GTK_WIDGET (row), &allocation);
+ gtk_tooltip_set_tip_area (tooltip, (GdkRectangle *) &allocation);
+ }
+
+ return result;
+}
+
+static void
+empathy_roster_view_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (container);
+ void (*chain_up) (GtkContainer *, GtkWidget *) =
+ ((GtkContainerClass *) empathy_roster_view_parent_class)->remove;
+
+ chain_up (container, widget);
+
+ if (EMPATHY_IS_ROSTER_CONTACT (widget))
+ remove_from_displayed (self, (EmpathyRosterContact *) widget);
+}
+