[gnome-flashback/wip/segeiger/gnome-3-18-inputmethods: 4/4] input-sources: implement candidate popup functionality



commit d8c4cf002ed8fe4ebbcabc6e4b5699fb9e9167ec
Author: Sebastian Geiger <sbastig gmx net>
Date:   Mon Jan 18 15:14:20 2016 +0100

    input-sources: implement candidate popup functionality

 .../libinput-sources/gf-candidate-popup.c          |  209 ++++++++++++++++++--
 1 files changed, 197 insertions(+), 12 deletions(-)
---
diff --git a/gnome-flashback/libinput-sources/gf-candidate-popup.c 
b/gnome-flashback/libinput-sources/gf-candidate-popup.c
index c66be7a..f804213 100644
--- a/gnome-flashback/libinput-sources/gf-candidate-popup.c
+++ b/gnome-flashback/libinput-sources/gf-candidate-popup.c
@@ -17,6 +17,8 @@
 
 #include "config.h"
 
+#include <math.h>
+
 #include "gf-candidate-area.h"
 #include "gf-candidate-popup.h"
 
@@ -29,6 +31,11 @@ struct _GfCandidatePopup
   GtkWidget        *pre_edit_text;
   GtkWidget        *aux_text;
   GtkWidget        *candidate_area;
+
+  gint              cursor_x_pos;
+  gint              cursor_y_pos;
+  gint              cursor_height;
+  gint              cursor_width;
 };
 
 G_DEFINE_TYPE (GfCandidatePopup, gf_candidate_popup, GF_TYPE_POPUP_WINDOW)
@@ -39,8 +46,53 @@ set_cursor_location_cb (IBusPanelService *service,
                         gint              y,
                         gint              w,
                         gint              h,
-                        gpointer          user_data)
+                        GfCandidatePopup *popup)
+{
+  popup->cursor_x_pos = x;
+  popup->cursor_y_pos = y;
+  popup->cursor_height = h;
+  popup->cursor_width = w;
+}
+
+static void
+update_window_location (GfCandidatePopup *popup)
 {
+  gint popup_height, popup_width;
+  GdkScreen *screen;
+  GdkWindow *window;
+  GdkRectangle monitor_geometry;
+  GtkRequisition preferred_window_size;
+  gint monitor;
+  gint x, y;
+
+  gtk_window_get_size (GTK_WINDOW (popup), &popup_width, &popup_height);
+
+  window = gtk_widget_get_window (GTK_WIDGET (popup));
+
+  if (window == NULL)
+    return;
+
+  screen = gdk_window_get_screen (window);
+  monitor = gdk_screen_get_monitor_at_window (screen, window);
+  gdk_screen_get_monitor_geometry (screen, monitor, &monitor_geometry);
+
+  x = popup->cursor_x_pos;
+  y = popup->cursor_y_pos;
+
+  if (x + popup_width > monitor_geometry.width)
+    x = x - popup_width + popup->cursor_width;
+
+  if (y + popup_height > monitor_geometry.height)
+    y = y - popup_height;
+  else
+    y = y + popup->cursor_height;
+
+  gtk_window_move (GTK_WINDOW (popup), x, y);
+
+  gtk_widget_get_preferred_size (GTK_WIDGET (popup), NULL,
+                                 &preferred_window_size);
+  gtk_window_resize (GTK_WINDOW (popup),
+                     preferred_window_size.width, preferred_window_size.height);
 }
 
 static void
@@ -48,67 +100,191 @@ update_preedit_text_cb (IBusPanelService *service,
                         IBusText         *text,
                         guint             cursor_pos,
                         gboolean          visible,
-                        gpointer          user_data)
+                        GfCandidatePopup *popup)
 {
+  IBusAttrList *attributes;
+
+  gtk_widget_set_visible (popup->pre_edit_text, visible);
+
+  gtk_label_set_text (GTK_LABEL (popup->pre_edit_text),
+                      ibus_text_get_text (text));
+
+  attributes = ibus_text_get_attributes (text);
+
+  if (attributes)
+  {
+    IBusAttribute *attribute;
+    guint i;
+
+    for (i = 0; (attribute = ibus_attr_list_get (attributes, i)) != NULL; i++)
+    {
+      guint start;
+      guint end;
+      if (ibus_attribute_get_type () != IBUS_ATTR_TYPE_BACKGROUND)
+        continue;
+
+      start = ibus_attribute_get_start_index (attribute);
+      end = ibus_attribute_get_end_index (attribute);
+      gtk_label_select_region (GTK_LABEL (popup->pre_edit_text), start, end);
+    }
+  }
 }
 
 static void
 show_preedit_text_cb (IBusPanelService *service,
-                      gpointer          user_data)
+                      GfCandidatePopup *popup)
 {
+  gtk_widget_show (popup->pre_edit_text);
 }
 
 static void
 hide_preedit_text_cb (IBusPanelService *service,
-                      gpointer          user_data)
+                      GfCandidatePopup *popup)
 {
+  gtk_widget_hide (popup->pre_edit_text);
 }
 
 static void
 update_auxiliary_text_cb (IBusPanelService *service,
                           IBusText         *text,
                           gboolean          visible,
-                          gpointer          user_data)
+                          GfCandidatePopup *popup)
 {
+  gtk_widget_set_visible (popup->aux_text, visible);
+
+  gtk_label_set_text (GTK_LABEL (popup->aux_text), ibus_text_get_text (text));
 }
 
 static void
 show_auxiliary_text_cb (IBusPanelService *service,
-                        gpointer          user_data)
+                        GfCandidatePopup *popup)
 {
+  gtk_widget_show (popup->aux_text);
 }
 
 static void
 hide_auxiliary_text_cb (IBusPanelService *service,
-                        gpointer          user_data)
+                        GfCandidatePopup *popup)
 {
+  gtk_widget_hide (popup->aux_text);
 }
 
 static void
 update_lookup_table_cb (IBusPanelService *service,
                         IBusLookupTable  *lookup_table,
                         gboolean          visible,
-                        gpointer          user_data)
+                        GfCandidatePopup *popup)
 {
+  guint n_candidates,
+        cursor_position,
+        page_size, n_pages, page,
+        start_index, end_index,
+        i;
+  GSList *indexes, *candidates;
+  IBusText *index_label;
+  gint orientation;
+
+  indexes = NULL;
+  candidates = NULL;
+
+  gtk_widget_set_visible (GTK_WIDGET (popup), visible);
+  update_window_location (popup);
+  n_candidates = ibus_lookup_table_get_number_of_candidates (lookup_table);
+  cursor_position = ibus_lookup_table_get_cursor_pos (lookup_table);
+  page_size = ibus_lookup_table_get_page_size (lookup_table);
+  n_pages = (guint) ceil (n_candidates / ((gdouble) page_size));
+  page = ((cursor_position == 0) ? 0 :
+          (guint) floor (cursor_position / ((gdouble) page_size)));
+  start_index = page * page_size;
+  end_index = MIN ((page + 1) * page_size, n_candidates);
+
+  for (i = 0; (index_label = ibus_lookup_table_get_label (lookup_table, i)) != NULL; i++)
+    {
+      const gchar *text;
+
+      text = ibus_text_get_text (index_label);
+      indexes = g_slist_append (indexes, (gpointer) text);
+    }
+
+  for (i = start_index; i < end_index; i++)
+    {
+      IBusText *ibus_text;
+      const gchar* text;
+
+      ibus_text = ibus_lookup_table_get_candidate (lookup_table, i);
+      text = ibus_text_get_text (ibus_text);
+      candidates = g_slist_append (candidates, (gpointer) text);
+    }
+
+  gf_candidate_area_set_candidates (GF_CANDIDATE_AREA (popup->candidate_area),
+                                    indexes, candidates, cursor_position,
+                                    visible);
+
+  orientation = ibus_lookup_table_get_orientation (lookup_table);
+
+  gf_candidate_area_set_orientation (GF_CANDIDATE_AREA (popup->candidate_area),
+                                     (IBusOrientation) orientation);
+
+  gf_candidate_area_update_buttons (GF_CANDIDATE_AREA (popup->candidate_area),
+                                    ibus_lookup_table_is_round (lookup_table),
+                                    page, n_pages);
+
+  g_slist_free (indexes);
+  g_slist_free (candidates);
 }
 
 static void
 show_lookup_table_cb (IBusPanelService *service,
-                      gpointer          user_data)
+                      GfCandidatePopup *popup)
 {
+  gtk_widget_show (GTK_WIDGET (popup));
+  update_window_location (popup);
 }
 
 static void
 hide_lookup_table_cb (IBusPanelService *service,
-                      gpointer          user_data)
+                      GfCandidatePopup *popup)
 {
+  gtk_widget_hide (GTK_WIDGET (popup));
+  update_window_location (popup);
 }
 
 static void
 focus_out_cb (IBusPanelService *service,
-              const gchar      *input_context_path,
-              gpointer          user_data)
+              GfCandidatePopup *popup)
+{
+}
+
+static void
+area_page_prev_cb (GfCandidateArea  *area,
+                   GfCandidatePopup *popup)
 {
+  ibus_panel_service_page_up (popup->service);
+}
+
+static void
+area_page_next_cb (GfCandidateArea  *area,
+                   GfCandidatePopup *popup)
+{
+  ibus_panel_service_page_down (popup->service);
+}
+
+static void
+area_candidate_clicked_cb (GfCandidateArea  *area,
+                           guint             index,
+                           GdkEvent         *event,
+                           GfCandidatePopup *popup)
+{
+  guint button;
+  GdkModifierType state;
+
+  gdk_event_get_button (event, &button);
+  gdk_event_get_state (event, &state);
+
+  ibus_panel_service_candidate_clicked (popup->service,
+                                        index,
+                                        button,
+                                        state);
 }
 
 static void
@@ -141,6 +317,8 @@ gf_candidate_popup_init (GfCandidatePopup *popup)
   gtk_window_set_focus_on_map (GTK_WINDOW (popup), TRUE);
   gtk_window_set_type_hint (GTK_WINDOW (popup), GDK_WINDOW_TYPE_HINT_NORMAL);
 
+  gtk_widget_set_size_request (GTK_WIDGET (popup), 1, 1);
+
   popup->candidate_area = gf_candidate_area_new();
 
   box_layout = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
@@ -155,6 +333,13 @@ gf_candidate_popup_init (GfCandidatePopup *popup)
 
   gtk_widget_show (box_layout);
   gtk_widget_show (popup->candidate_area);
+
+  g_signal_connect (popup->candidate_area, "previous-page",
+                    G_CALLBACK (area_page_prev_cb), popup);
+  g_signal_connect (popup->candidate_area, "next-page",
+                    G_CALLBACK (area_page_next_cb), popup);
+  g_signal_connect (popup->candidate_area, "candidate-clicked",
+                    G_CALLBACK (area_candidate_clicked_cb), popup);
 }
 
 GfCandidatePopup *


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