[gnome-flashback] input-sources: implement accelerator_activated_cb



commit 36c3a4dd2a24c2938718f3f6dba0f81e694d08e6
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Thu Sep 24 23:06:35 2015 +0300

    input-sources: implement accelerator_activated_cb

 gnome-flashback/Adwaita.css                        |   10 +
 gnome-flashback/HighContrast.css                   |   10 +
 gnome-flashback/libinput-sources/Makefile.am       |    2 +
 .../libinput-sources/gf-input-source-manager.c     |  111 ++++-
 .../libinput-sources/gf-input-source-popup.c       |  493 ++++++++++++++++++++
 .../libinput-sources/gf-input-source-popup.h       |   36 ++
 6 files changed, 639 insertions(+), 23 deletions(-)
---
diff --git a/gnome-flashback/Adwaita.css b/gnome-flashback/Adwaita.css
index c9c39c9..794e263 100644
--- a/gnome-flashback/Adwaita.css
+++ b/gnome-flashback/Adwaita.css
@@ -4,6 +4,16 @@ GfPopupWindow
   border: 1px solid rgba(0, 0, 0, 0.23);
 }
 
+GfInputSourcePopup #input-source
+{
+   font-size: 22px;
+}
+
+GfInputSourcePopup #input-source:selected
+{
+  border-radius: 10px;
+}
+
 FlashbackLabelWindow
 {
   font-size: 40px;
diff --git a/gnome-flashback/HighContrast.css b/gnome-flashback/HighContrast.css
index c9c39c9..794e263 100644
--- a/gnome-flashback/HighContrast.css
+++ b/gnome-flashback/HighContrast.css
@@ -4,6 +4,16 @@ GfPopupWindow
   border: 1px solid rgba(0, 0, 0, 0.23);
 }
 
+GfInputSourcePopup #input-source
+{
+   font-size: 22px;
+}
+
+GfInputSourcePopup #input-source:selected
+{
+  border-radius: 10px;
+}
+
 FlashbackLabelWindow
 {
   font-size: 40px;
diff --git a/gnome-flashback/libinput-sources/Makefile.am b/gnome-flashback/libinput-sources/Makefile.am
index 4d62710..a3e2b26 100644
--- a/gnome-flashback/libinput-sources/Makefile.am
+++ b/gnome-flashback/libinput-sources/Makefile.am
@@ -25,6 +25,8 @@ libinput_sources_la_SOURCES = \
        gf-input-sources.h \
        gf-input-source-manager.c \
        gf-input-source-manager.h \
+       gf-input-source-popup.c \
+       gf-input-source-popup.h \
        gf-input-source-settings.c \
        gf-input-source-settings.h \
        gf-keyboard-manager.c \
diff --git a/gnome-flashback/libinput-sources/gf-input-source-manager.c 
b/gnome-flashback/libinput-sources/gf-input-source-manager.c
index 29fd3fe..943413d 100644
--- a/gnome-flashback/libinput-sources/gf-input-source-manager.c
+++ b/gnome-flashback/libinput-sources/gf-input-source-manager.c
@@ -26,6 +26,7 @@
 #include "gf-ibus-manager.h"
 #include "gf-input-source.h"
 #include "gf-input-source-manager.h"
+#include "gf-input-source-popup.h"
 #include "gf-input-source-settings.h"
 #include "gf-keyboard-manager.h"
 
@@ -70,6 +71,8 @@ struct _GfInputSourceManager
 
   GList                 *mru_sources;
   GList                 *mru_sources_backup;
+
+  GtkWidget             *popup;
 };
 
 enum
@@ -210,11 +213,53 @@ switch_input_backward_changed_cb (GSettings *settings,
 }
 
 static void
+fade_finished_cb (GfInputSourcePopup *popup,
+                  gpointer            user_data)
+{
+  GfInputSourceManager *manager;
+  GtkWidget *widget;
+
+  manager = GF_INPUT_SOURCE_MANAGER (user_data);
+  widget = GTK_WIDGET (popup);
+
+  gtk_widget_destroy (widget);
+  manager->popup = NULL;
+}
+
+static void
 accelerator_activated_cb (GfKeybindings *keybindings,
                           guint          action,
                           GVariant      *parameters,
                           gpointer       user_data)
 {
+  GfInputSourceManager *manager;
+  gboolean backward;
+  guint keyval;
+  guint modifiers;
+
+  manager = GF_INPUT_SOURCE_MANAGER (user_data);
+
+  if (action != manager->switch_source_action &&
+      action != manager->switch_source_backward_action)
+    return;
+
+  if (g_list_length (manager->mru_sources) < 2)
+    return;
+
+  if (manager->popup != NULL)
+    return;
+
+  backward = action == manager->switch_source_backward_action;
+  keyval = gf_keybindings_get_keyval (manager->keybindings, action);
+  modifiers = gf_keybindings_get_modifiers (manager->keybindings, action);
+
+  manager->popup = gf_input_source_popup_new (manager->mru_sources, backward,
+                                              keyval, modifiers);
+
+  g_signal_connect (manager->popup, "fade-finished",
+                    G_CALLBACK (fade_finished_cb), manager);
+
+  gtk_widget_show (manager->popup);
 }
 
 static void
@@ -371,10 +416,47 @@ get_source_info_list (GfInputSourceManager *manager)
   return list;
 }
 
+static gboolean
+compare_sources (GfInputSource *source1,
+                 GfInputSource *source2)
+{
+  const gchar *type1;
+  const gchar *type2;
+  const gchar *id1;
+  const gchar *id2;
+
+  type1 = gf_input_source_get_source_type (source1);
+  type2 = gf_input_source_get_source_type (source2);
+
+  id1 = gf_input_source_get_id (source1);
+  id2 = gf_input_source_get_id (source2);
+
+  if (g_strcmp0 (type1, type2) == 0 && g_strcmp0 (id1, id2) == 0)
+    return TRUE;
+
+  return FALSE;
+}
+
 static void
 current_input_source_changed (GfInputSourceManager *manager,
                               GfInputSource        *new_source)
 {
+  GList *l;
+
+  for (l = manager->mru_sources; l != NULL; l = g_list_next (l))
+    {
+      GfInputSource *source;
+
+      source = GF_INPUT_SOURCE (l->data);
+
+      if (compare_sources (source, new_source))
+        {
+          manager->mru_sources = g_list_remove_link (manager->mru_sources, l);
+          manager->mru_sources = g_list_concat (l, manager->mru_sources);
+
+          break;
+        }
+    }
 }
 
 static void
@@ -532,27 +614,6 @@ sources_by_name_free (gpointer key,
   return TRUE;
 }
 
-static gboolean
-compare_sources (GfInputSource *source1,
-                 GfInputSource *source2)
-{
-  const gchar *type1;
-  const gchar *type2;
-  const gchar *id1;
-  const gchar *id2;
-
-  type1 = gf_input_source_get_source_type (source1);
-  type2 = gf_input_source_get_source_type (source2);
-
-  id1 = gf_input_source_get_id (source1);
-  id2 = gf_input_source_get_id (source2);
-
-  if (g_strcmp0 (type1, type2) == 0 && g_strcmp0 (id1, id2) == 0)
-    return TRUE;
-
-  return FALSE;
-}
-
 static void
 update_mru_sources_list (GfInputSourceManager *manager)
 {
@@ -591,8 +652,6 @@ update_mru_sources_list (GfInputSourceManager *manager)
           if (!compare_sources (source1, source2))
             continue;
 
-          g_warning ("equal...");
-
           source = g_list_remove_link (sources, l2);
           mru_sources = g_list_concat (mru_sources, source);
 
@@ -876,6 +935,12 @@ gf_input_source_manager_dispose (GObject *object)
       manager->mru_sources_backup = NULL;
     }
 
+  if (manager->popup != NULL)
+    {
+      gtk_widget_destroy (manager->popup);
+      manager->popup = NULL;
+    }
+
   G_OBJECT_CLASS (gf_input_source_manager_parent_class)->dispose (object);
 }
 
diff --git a/gnome-flashback/libinput-sources/gf-input-source-popup.c 
b/gnome-flashback/libinput-sources/gf-input-source-popup.c
new file mode 100644
index 0000000..20c5cc6
--- /dev/null
+++ b/gnome-flashback/libinput-sources/gf-input-source-popup.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2015 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gdk/gdkx.h>
+
+#include "gf-input-source.h"
+#include "gf-input-source-popup.h"
+
+struct _GfInputSourcePopup
+{
+  GfPopupWindow  parent;
+
+  GdkDevice     *pointer;
+  GdkDevice     *keyboard;
+
+  GList         *mru_sources;
+  gboolean       backward;
+  guint          keyval;
+  guint          modifiers;
+
+  GtkWidget     *sources_box;
+
+  gint           selected_index;
+  GtkWidget     *selected_name;
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_MRU_SOURCES,
+  PROP_BACKWARD,
+  PROP_KEYVAL,
+  PROP_MODIFIERS,
+
+  LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP] = { NULL };
+
+G_DEFINE_TYPE (GfInputSourcePopup, gf_input_source_popup, GF_TYPE_POPUP_WINDOW)
+
+static gboolean
+is_mouse_over_input_source (GfInputSourcePopup *popup,
+                            gdouble             x,
+                            gdouble             y,
+                            gint               *index)
+{
+  gboolean mouse_over;
+  GList *sources;
+  GList *l;
+
+  mouse_over = FALSE;
+  sources = gtk_container_get_children (GTK_CONTAINER (popup->sources_box));
+
+  for (l = sources; l != NULL; l = g_list_next (l))
+    {
+      GtkWidget *widget;
+      GtkAllocation rect;
+
+      widget = GTK_WIDGET (l->data);
+
+      gtk_widget_get_allocation (widget, &rect);
+
+      if (x >= rect.x && x <= rect.x + rect.width &&
+          y >= rect.y && y <= rect.y + rect.height)
+        {
+          gpointer pointer;
+
+          pointer = g_object_get_data (G_OBJECT (widget), "index");
+
+          *index = GPOINTER_TO_INT (pointer);
+          mouse_over = TRUE;
+
+          break;
+        }
+    }
+
+  g_list_free (sources);
+
+  return mouse_over;
+}
+
+static void
+selected_source_changed (GfInputSourcePopup *popup)
+{
+  GtkWidget *widget;
+  GfInputSource *source;
+  const gchar *display_name;
+
+  widget = GTK_WIDGET (popup);
+  source = (GfInputSource *) g_list_nth_data (popup->mru_sources,
+                                              popup->selected_index);
+
+  display_name = gf_input_source_get_display_name (source);
+  gtk_label_set_text (GTK_LABEL (popup->selected_name), display_name);
+
+  gtk_widget_queue_draw (widget);
+}
+
+static gboolean
+draw_cb (GtkWidget *widget,
+         cairo_t   *cr,
+         gpointer   user_data)
+{
+  GfInputSourcePopup *popup;
+  GtkStyleContext *context;
+  gpointer index;
+
+  popup = GF_INPUT_SOURCE_POPUP (user_data);
+  context = gtk_widget_get_style_context (widget);
+  index = g_object_get_data (G_OBJECT (widget), "index");
+
+  if (popup->selected_index == GPOINTER_TO_INT (index))
+    gtk_style_context_set_state (context, GTK_STATE_FLAG_SELECTED);
+  else
+    gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
+
+  return FALSE;
+}
+
+static void
+setup_popup_window (GfInputSourcePopup *popup)
+{
+  GfInputSource *selected_source;
+  GtkWidget *vertical_box;
+  gint index;
+  GList *l;
+  const gchar *display_name;
+
+  selected_source = (GfInputSource *) g_list_nth_data (popup->mru_sources,
+                                                       popup->selected_index);
+
+  gtk_container_set_border_width (GTK_CONTAINER (popup), 12);
+
+  vertical_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  gtk_container_add (GTK_CONTAINER (popup), vertical_box);
+
+  popup->sources_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  gtk_box_pack_start (GTK_BOX (vertical_box), popup->sources_box, TRUE, TRUE, 0);
+
+  index = 0;
+  for (l = popup->mru_sources; l != NULL; l = g_list_next (l))
+    {
+      GfInputSource *source;
+      const gchar *short_name;
+      GtkWidget *label;
+
+      source = (GfInputSource *) l->data;
+      short_name = gf_input_source_get_short_name (source);
+      label = gtk_label_new (short_name);
+
+      g_object_set_data (G_OBJECT (label), "index", GINT_TO_POINTER (index));
+      g_signal_connect (label, "draw", G_CALLBACK (draw_cb), popup);
+
+      gtk_widget_set_name (label, "input-source");
+      gtk_widget_set_size_request (label, 120, 120);
+
+      gtk_box_pack_start (GTK_BOX (popup->sources_box), label, FALSE, FALSE, 0);
+
+      index++;
+    }
+
+  display_name = gf_input_source_get_display_name (selected_source);
+  popup->selected_name = gtk_label_new (display_name);
+  gtk_widget_set_halign (popup->selected_name, GTK_ALIGN_CENTER);
+  gtk_box_pack_start (GTK_BOX (vertical_box), popup->selected_name, FALSE,
+                      FALSE, 0);
+
+  gtk_widget_show_all (vertical_box);
+}
+
+static void
+ungrab (GfInputSourcePopup *popup)
+{
+  if (popup->pointer != NULL)
+    {
+      gdk_device_ungrab (popup->pointer, GDK_CURRENT_TIME);
+      popup->pointer = NULL;
+    }
+
+  if (popup->keyboard != NULL)
+    {
+      gdk_device_ungrab (popup->keyboard, GDK_CURRENT_TIME);
+      popup->keyboard = NULL;
+    }
+}
+
+static void
+activate_selected_input_source (GfInputSourcePopup *popup)
+{
+  GfPopupWindow *popup_window;
+  GfInputSource *source;
+
+  popup_window = GF_POPUP_WINDOW (popup);
+  source = (GfInputSource *) g_list_nth_data (popup->mru_sources,
+                                              popup->selected_index);
+
+  ungrab (popup);
+
+  gf_popup_window_fade_start (popup_window);
+  gf_input_source_activate (source);
+}
+
+static void
+gf_input_source_popup_constructed (GObject *object)
+{
+  GfInputSourcePopup *popup;
+
+  popup = GF_INPUT_SOURCE_POPUP (object);
+
+  G_OBJECT_CLASS (gf_input_source_popup_parent_class)->constructed (object);
+
+  if (popup->backward)
+    popup->selected_index = g_list_length (popup->mru_sources) - 1;
+  else
+    popup->selected_index = 1;
+
+  setup_popup_window (popup);
+}
+
+static void
+gf_input_source_popup_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  GfInputSourcePopup *popup;
+
+  popup = GF_INPUT_SOURCE_POPUP (object);
+
+  switch (prop_id)
+    {
+      case PROP_MRU_SOURCES:
+        popup->mru_sources = g_value_get_pointer (value);
+        break;
+
+      case PROP_BACKWARD:
+        popup->backward = g_value_get_boolean (value);
+        break;
+
+      case PROP_KEYVAL:
+        popup->keyval = g_value_get_uint (value);
+        break;
+
+      case PROP_MODIFIERS:
+        popup->modifiers = g_value_get_uint (value);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+static gboolean
+gf_input_source_popup_button_press_event (GtkWidget         *widget,
+                                                                       GdkEventButton *event)
+{
+  GfInputSourcePopup *popup;
+  GfPopupWindow *popup_window;
+  gint index;
+
+  popup = GF_INPUT_SOURCE_POPUP (widget);
+  popup_window = GF_POPUP_WINDOW (widget);
+
+  if (!is_mouse_over_input_source (popup, event->x, event->y, &index))
+    {
+      gf_popup_window_fade_start (popup_window);
+
+      return TRUE;
+    }
+
+  popup->selected_index = index;
+  selected_source_changed (popup);
+
+  activate_selected_input_source (popup);
+
+  return TRUE;
+}
+
+static gboolean
+gf_input_source_popup_key_press_event (GtkWidget   *widget,
+                                       GdkEventKey *event)
+{
+  GfInputSourcePopup *popup;
+  gint index;
+  gint last_index;
+
+  popup = GF_INPUT_SOURCE_POPUP (widget);
+  index = popup->selected_index;
+
+  if (event->keyval == GDK_KEY_Left)
+    {
+      index--;
+    }
+  else if (event->keyval == GDK_KEY_Right)
+    {
+      index++;
+    }
+  else if (event->keyval == popup->keyval)
+    {
+      if (popup->backward)
+        index--;
+      else
+        index++;
+    }
+
+  last_index = g_list_length (popup->mru_sources) - 1;
+  if (index > last_index)
+    index = 0;
+  else if (index < 0)
+    index = last_index;
+
+  popup->selected_index = index;
+  selected_source_changed (popup);
+
+  return TRUE;
+}
+
+static gboolean
+gf_input_source_popup_key_release_event (GtkWidget   *widget,
+                                         GdkEventKey *event)
+{
+  GfInputSourcePopup *popup;
+  GdkModifierType modifiers;
+
+  if (!event->is_modifier)
+    return TRUE;
+
+  popup = GF_INPUT_SOURCE_POPUP (widget);
+  modifiers = gtk_accelerator_get_default_mod_mask ();
+
+  if ((event->state & modifiers) != popup->modifiers)
+    return TRUE;
+
+  activate_selected_input_source (popup);
+
+  return TRUE;
+}
+
+static gboolean
+gf_input_source_popup_motion_notify_event (GtkWidget       *widget,
+                                                                        GdkEventMotion *event)
+{
+  GfInputSourcePopup *popup;
+  gint index;
+
+  popup = GF_INPUT_SOURCE_POPUP (widget);
+
+  if (!is_mouse_over_input_source (popup, event->x, event->y, &index))
+    return TRUE;
+
+  popup->selected_index = index;
+  selected_source_changed (popup);
+
+  return TRUE;
+}
+
+static void
+gf_input_source_popup_show (GtkWidget *widget)
+{
+  GfInputSourcePopup *popup;
+  GdkDisplay *display;
+  GdkDeviceManager *manager;
+  GdkWindow *window;
+  GdkGrabStatus status;
+
+  popup = GF_INPUT_SOURCE_POPUP (widget);
+
+  GTK_WIDGET_CLASS (gf_input_source_popup_parent_class)->show (widget);
+
+  display = gdk_display_get_default ();
+  manager = gdk_display_get_device_manager (display);
+  window = gtk_widget_get_window (widget);
+
+  popup->pointer = gdk_device_manager_get_client_pointer (manager);
+  status = gdk_device_grab (popup->pointer, window, GDK_OWNERSHIP_NONE, FALSE,
+                            GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK,
+                            NULL, GDK_CURRENT_TIME);
+
+  if (status != GDK_GRAB_SUCCESS)
+    {
+      popup->pointer = NULL;
+
+      return;
+    }
+
+  popup->keyboard = gdk_device_get_associated_device (popup->pointer);
+  status = gdk_device_grab (popup->keyboard, window, GDK_OWNERSHIP_NONE, FALSE,
+                            GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
+                            NULL, GDK_CURRENT_TIME);
+
+  if (status != GDK_GRAB_SUCCESS)
+    {
+      gdk_device_ungrab (popup->pointer, GDK_CURRENT_TIME);
+
+      popup->pointer = NULL;
+      popup->keyboard = NULL;
+
+      return;
+    }
+}
+
+static void
+gf_input_source_popup_class_init (GfInputSourcePopupClass *popup_class)
+{
+  GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+
+  object_class = G_OBJECT_CLASS (popup_class);
+  widget_class = GTK_WIDGET_CLASS (popup_class);
+
+  object_class->constructed = gf_input_source_popup_constructed;
+  object_class->set_property = gf_input_source_popup_set_property;
+
+  widget_class->button_press_event = gf_input_source_popup_button_press_event;
+  widget_class->key_press_event = gf_input_source_popup_key_press_event;
+  widget_class->key_release_event = gf_input_source_popup_key_release_event;
+  widget_class->motion_notify_event = gf_input_source_popup_motion_notify_event;
+  widget_class->show = gf_input_source_popup_show;
+
+  properties[PROP_MRU_SOURCES] =
+    g_param_spec_pointer ("mru-sources", "mru-sources", "mru-sources",
+                         G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
+                         G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_BACKWARD] =
+    g_param_spec_boolean ("backward", "backward", "backward", FALSE,
+                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
+                          G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_KEYVAL] =
+    g_param_spec_uint ("keyval", "keyval", "keyval", 0, G_MAXUINT, 0,
+                       G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
+                       G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_MODIFIERS] =
+    g_param_spec_uint ("modifiers", "modifiers", "modifiers", 0, G_MAXUINT, 0,
+                       G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
+                       G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+static void
+gf_input_source_popup_init (GfInputSourcePopup *popup)
+{
+  GtkWindow *window;
+  GtkWidget *widget;
+  gint events;
+
+  window = GTK_WINDOW (popup);
+  widget = GTK_WIDGET (popup);
+
+  events = GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
+           GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK;
+
+  gtk_window_set_position (window, GTK_WIN_POS_CENTER_ALWAYS);
+
+  gtk_widget_add_events (widget, events);
+}
+
+GtkWidget *
+gf_input_source_popup_new (GList    *mru_sources,
+                           gboolean  backward,
+                           guint     keyval,
+                           guint     modifiers)
+{
+  return g_object_new (GF_TYPE_INPUT_SOURCE_POPUP,
+                       "type", GTK_WINDOW_POPUP,
+                       "mru-sources", mru_sources,
+                       "backward", backward,
+                       "keyval", keyval,
+                       "modifiers", modifiers,
+                       NULL);
+}
diff --git a/gnome-flashback/libinput-sources/gf-input-source-popup.h 
b/gnome-flashback/libinput-sources/gf-input-source-popup.h
new file mode 100644
index 0000000..b991605
--- /dev/null
+++ b/gnome-flashback/libinput-sources/gf-input-source-popup.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GF_INPUT_SOURCE_POPUP_H
+#define GF_INPUT_SOURCE_POPUP_H
+
+#include <libcommon/gf-popup-window.h>
+
+G_BEGIN_DECLS
+
+#define GF_TYPE_INPUT_SOURCE_POPUP gf_input_source_popup_get_type ()
+G_DECLARE_FINAL_TYPE (GfInputSourcePopup, gf_input_source_popup,
+                      GF, INPUT_SOURCE_POPUP, GfPopupWindow)
+
+GtkWidget *gf_input_source_popup_new (GList    *mru_sources,
+                                      gboolean  backward,
+                                      guint     keyval,
+                                      guint     modifiers);
+
+G_END_DECLS
+
+#endif


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