]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-live-search.c
Use a flat namespace for internal includes
[empathy.git] / libempathy-gtk / empathy-live-search.c
index 21aefed902e2e29a93e4131a574185f28765bf64..3047612b03c7764fcaa767c9ee37ae289b3b2a82 100644 (file)
  *          Claudio Saavedra <csaavedra@igalia.com>
  */
 
-#include <config.h>
-#include <string.h>
+#include "config.h"
 
-#include <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
-
-#include <libempathy/empathy-utils.h>
+#include "empathy-utils.h"
 
 #include "empathy-live-search.h"
-#include "empathy-gtk-marshal.h"
 
 G_DEFINE_TYPE (EmpathyLiveSearch, empathy_live_search, GTK_TYPE_HBOX)
 
@@ -74,8 +69,6 @@ stripped_char (gunichar ch)
 {
   gunichar retval = 0;
   GUnicodeType utype;
-  gunichar *decomp;
-  gsize dlen;
 
   utype = g_unichar_type (ch);
 
@@ -115,12 +108,7 @@ stripped_char (gunichar ch)
     case G_UNICODE_SPACE_SEPARATOR:
     default:
       ch = g_unichar_tolower (ch);
-      decomp = g_unicode_canonical_decomposition (ch, &dlen);
-      if (decomp != NULL)
-        {
-          retval = decomp[0];
-          g_free (decomp);
-        }
+      g_unichar_fully_decompose (ch, FALSE, &retval, 1);
     }
 
   return retval;
@@ -139,8 +127,8 @@ append_word (GPtrArray **word_array,
     }
 }
 
-static GPtrArray *
-strip_utf8_string (const gchar *string)
+GPtrArray *
+empathy_live_search_strip_utf8_string (const gchar *string)
 {
   GPtrArray *word_array = NULL;
   GString *word = NULL;
@@ -230,8 +218,8 @@ live_search_match_prefix (const gchar *string,
   return FALSE;
 }
 
-static gboolean
-live_search_match_words (const gchar *string,
+gboolean
+empathy_live_search_match_words (const gchar *string,
     GPtrArray *words)
 {
   guint i;
@@ -271,15 +259,18 @@ live_search_entry_key_pressed_cb (GtkEntry *entry,
     }
 
   /* emit key navigation signal, so other widgets can respond to it properly */
-  if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_Down)
+  if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_Down
+      || event->keyval == GDK_KEY_Page_Up || event->keyval == GDK_KEY_Page_Down
+      || event->keyval == GDK_KEY_Menu)
      {
        return fire_key_navigation_sig (self, event);
      }
 
-  if (event->keyval == GDK_KEY_Home || event->keyval == GDK_KEY_End)
+  if (event->keyval == GDK_KEY_Home || event->keyval == GDK_KEY_End ||
+      event->keyval == GDK_KEY_space)
     {
       /* If the live search is visible, the entry should catch the Home/End
-       * events */
+       * and space events */
       if (!gtk_widget_get_visible (GTK_WIDGET (self)))
         {
           return fire_key_navigation_sig (self, event);
@@ -307,7 +298,7 @@ live_search_text_changed (GtkEntry *entry,
   if (priv->stripped_words != NULL)
     g_ptr_array_unref (priv->stripped_words);
 
-  priv->stripped_words = strip_utf8_string (text);
+  priv->stripped_words = empathy_live_search_strip_utf8_string (text);
 
   g_object_notify (G_OBJECT (self), "text");
 }
@@ -347,19 +338,31 @@ live_search_key_press_event_cb (GtkWidget *widget,
       event->keyval == GDK_KEY_Control_R)
     return FALSE;
 
-  /* dont forward the up and down arrow keys to the entry, they are needed for
-   * navigation in the treeview and are not needed in the search entry */
-   if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_Down)
+  /* dont forward the up/down and Page Up/Down arrow keys to the entry,
+   * they are needed for navigation in the treeview and are not needed in
+   * the search entry */
+   if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_Down ||
+       event->keyval == GDK_KEY_Page_Up || event->keyval == GDK_KEY_Page_Down ||
+       event->keyval == GDK_KEY_Menu)
      return FALSE;
 
-   if (event->keyval == GDK_KEY_Home || event->keyval == GDK_KEY_End)
+   if (event->keyval == GDK_KEY_Home || event->keyval == GDK_KEY_End ||
+       event->keyval == GDK_KEY_space)
      {
-       /* Home/End keys have to be forwarded to the entry only if the live
-        * search is visible (to move the cursor inside the entry). */
+       /* Home/End and space keys have to be forwarded to the entry only if
+        * the live search is visible (to move the cursor inside the entry). */
        if (!gtk_widget_get_visible (GTK_WIDGET (self)))
          return FALSE;
      }
 
+   /* Don't forward shift keys events as focusing the search entry would
+    * cancel an in-progress editing on a cell renderer (like when renaming a
+    * group). There is no point focusing it anyway as we don't display the
+    * search entry when only a shift key is pressed. */
+   if (event->keyval == GDK_KEY_Shift_L ||
+       event->keyval == GDK_KEY_Shift_R)
+       return FALSE;
+
   /* realize the widget if it is not realized yet */
   gtk_widget_realize (priv->search_entry);
   if (!gtk_widget_has_focus (priv->search_entry))
@@ -479,15 +482,22 @@ live_search_set_property (GObject *object,
 }
 
 static void
-live_search_hide (GtkWidget *widget)
+live_search_unmap (GtkWidget *widget)
 {
   EmpathyLiveSearch *self = EMPATHY_LIVE_SEARCH (widget);
   EmpathyLiveSearchPriv *priv = GET_PRIV (self);
 
-  GTK_WIDGET_CLASS (empathy_live_search_parent_class)->hide (widget);
+  GTK_WIDGET_CLASS (empathy_live_search_parent_class)->unmap (widget);
+
+  /* unmap can happen if a parent gets hidden, in that case we want to hide
+   * the live search as well, so when it gets mapped again, the live search
+   * won't be shown. */
+  gtk_widget_hide (widget);
 
   gtk_entry_set_text (GTK_ENTRY (priv->search_entry), "");
-  gtk_widget_grab_focus (priv->hook_widget);
+
+  if (priv->hook_widget != NULL)
+    gtk_widget_grab_focus (priv->hook_widget);
 }
 
 static void
@@ -527,7 +537,7 @@ empathy_live_search_class_init (EmpathyLiveSearchClass *klass)
   object_class->get_property = live_search_get_property;
   object_class->set_property = live_search_set_property;
 
-  widget_class->hide = live_search_hide;
+  widget_class->unmap = live_search_unmap;
   widget_class->show = live_search_show;
   widget_class->grab_focus = live_search_grab_focus;
 
@@ -536,7 +546,7 @@ empathy_live_search_class_init (EmpathyLiveSearchClass *klass)
       G_SIGNAL_RUN_LAST,
       0,
       NULL, NULL,
-      g_cclosure_marshal_VOID__VOID,
+      g_cclosure_marshal_generic,
       G_TYPE_NONE, 0);
 
   signals[KEYNAV] = g_signal_new ("key-navigation",
@@ -544,7 +554,7 @@ empathy_live_search_class_init (EmpathyLiveSearchClass *klass)
       G_SIGNAL_RUN_LAST,
       0,
       g_signal_accumulator_true_handled, NULL,
-      _empathy_gtk_marshal_BOOLEAN__BOXED,
+      g_cclosure_marshal_generic,
       G_TYPE_BOOLEAN, 1, GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 
   param_spec = g_param_spec_object ("hook-widget", "Live Search Hook Widget",
@@ -692,7 +702,7 @@ empathy_live_search_match (EmpathyLiveSearch *self,
 
   priv = GET_PRIV (self);
 
-  return live_search_match_words (string, priv->stripped_words);
+  return empathy_live_search_match_words (string, priv->stripped_words);
 }
 
 gboolean
@@ -702,11 +712,18 @@ empathy_live_search_match_string (const gchar *string,
   GPtrArray *words;
   gboolean match;
 
-  words = strip_utf8_string (prefix);
-  match = live_search_match_words (string, words);
+  words = empathy_live_search_strip_utf8_string (prefix);
+  match = empathy_live_search_match_words (string, words);
   if (words != NULL)
     g_ptr_array_unref (words);
 
   return match;
 }
 
+GPtrArray *
+empathy_live_search_get_words (EmpathyLiveSearch *self)
+{
+  EmpathyLiveSearchPriv *priv = GET_PRIV (self);
+
+  return priv->stripped_words;
+}