Make "changed" signal emission of PanelCfgInputButton check gboolean return.
authorAndriy Grytsenko <andrej@rep.kiev.ua>
Sun, 23 Nov 2014 19:01:33 +0000 (21:01 +0200)
committerAndriy Grytsenko <andrej@rep.kiev.ua>
Sun, 23 Nov 2014 19:01:33 +0000 (21:01 +0200)
This way callbacks may inform the widget if they accept change or not,
therefore button can be correctly updated.

src/input-button.c
src/plugin.h

index 24f7a81..72d5cbe 100644 (file)
 
 #include <keybinder.h>
 
+/* generated by glib-genmarshal for BOOL:STRING */
+void _marshal_BOOLEAN__STRING (GClosure     *closure,
+                               GValue       *return_value G_GNUC_UNUSED,
+                               guint         n_param_values,
+                               const GValue *param_values,
+                               gpointer      invocation_hint G_GNUC_UNUSED,
+                               gpointer      marshal_data)
+{
+    typedef gboolean (*GMarshalFunc_BOOLEAN__STRING) (gpointer     data1,
+                                                      gpointer     arg_1,
+                                                      gpointer     data2);
+    register GMarshalFunc_BOOLEAN__STRING callback;
+    register GCClosure *cc = (GCClosure*) closure;
+    register gpointer data1, data2;
+    gboolean v_return;
+
+    g_return_if_fail (return_value != NULL);
+    g_return_if_fail (n_param_values == 2);
+
+    if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+        data1 = closure->data;
+        data2 = g_value_peek_pointer (param_values + 0);
+    }
+    else
+    {
+        data1 = g_value_peek_pointer (param_values + 0);
+        data2 = closure->data;
+    }
+    callback = (GMarshalFunc_BOOLEAN__STRING) (marshal_data ? marshal_data : cc->callback);
+
+    v_return = callback (data1, (char*) g_value_get_string(param_values + 1), data2);
+
+    g_value_set_boolean (return_value, v_return);
+}
+
 #define PANEL_TYPE_CFG_INPUT_BUTTON     (config_input_button_get_type())
 
 typedef struct _PanelCfgInputButton      PanelCfgInputButton;
@@ -50,7 +86,7 @@ struct _PanelCfgInputButton
 struct _PanelCfgInputButtonClass
 {
     GtkFrameClass parent_class;
-    void (*changed)(PanelCfgInputButton *btn, char *accel);
+    gboolean (*changed)(PanelCfgInputButton *btn, char *accel);
 };
 
 enum
@@ -84,11 +120,41 @@ static void on_focus_out_event(GtkButton *test, GdkEvent *event,
         gdk_keyboard_ungrab(GDK_CURRENT_TIME);
 }
 
+static void _button_set_click_label(GtkButton *btn, guint keyval, GdkModifierType state)
+{
+    char *mod_text, *text;
+    const char *btn_text;
+    char buff[64];
+
+    mod_text = gtk_accelerator_get_label(0, state);
+    btn_text = gdk_keyval_name(keyval);
+    switch (btn_text[0])
+    {
+    case '1':
+        btn_text = _("LeftBtn");
+        break;
+    case '2':
+        btn_text = _("MiddleBtn");
+        break;
+    case '3':
+        btn_text = _("RightBtn");
+        break;
+    default:
+        snprintf(buff, sizeof(buff), _("Btn%s"), btn_text);
+        btn_text = buff;
+    }
+    text = g_strdup_printf("%s%s", mod_text, btn_text);
+    gtk_button_set_label(btn, text);
+    g_free(text);
+    g_free(mod_text);
+}
+
 static gboolean on_key_event(GtkButton *test, GdkEventKey *event,
                              PanelCfgInputButton *btn)
 {
     GdkModifierType state;
     char *text;
+    gboolean ret = FALSE;
 
     /* ignore Tab completely so user can leave focus */
     if (event->keyval == GDK_KEY_Tab)
@@ -103,7 +169,16 @@ static gboolean on_key_event(GtkButton *test, GdkEventKey *event,
     /* if mod key event then update test label and go */
     if (event->is_modifier)
     {
-        text = gtk_accelerator_get_label(0, state);
+        if (state != 0)
+            text = gtk_accelerator_get_label(0, state);
+        /* if no modifiers currently then show original state */
+        else if (btn->do_key)
+            text = gtk_accelerator_get_label(btn->key, btn->mods);
+        else
+        {
+            _button_set_click_label(test, btn->key, btn->mods);
+            return FALSE;
+        }
         gtk_button_set_label(test, text);
         g_free(text);
         return FALSE;
@@ -136,44 +211,18 @@ static gboolean on_key_event(GtkButton *test, GdkEventKey *event,
         return FALSE;
     }
     /* send a signal that it's changed */
-    btn->mods = state;
-    btn->key = event->keyval;
-    text = gtk_accelerator_name(btn->key, state);
-    g_signal_emit(btn, signals[CHANGED], 0, text);
-    g_free(text);
-    text = gtk_accelerator_get_label(event->keyval, state);
-    gtk_button_set_label(test, text);
+    text = gtk_accelerator_name(event->keyval, state);
+    g_signal_emit(btn, signals[CHANGED], 0, text, &ret);
     g_free(text);
-    return FALSE;
-}
-
-static void _button_set_click_label(GtkButton *btn, guint keyval, GdkModifierType state)
-{
-    char *mod_text, *text;
-    const char *btn_text;
-    char buff[64];
-
-    mod_text = gtk_accelerator_get_label(0, state);
-    btn_text = gdk_keyval_name(keyval);
-    switch (btn_text[0])
+    if (ret)
     {
-    case '1':
-        btn_text = _("LeftBtn");
-        break;
-    case '2':
-        btn_text = _("MiddleBtn");
-        break;
-    case '3':
-        btn_text = _("RightBtn");
-        break;
-    default:
-        snprintf(buff, sizeof(buff), _("Btn%s"), btn_text);
-        btn_text = buff;
+        btn->mods = state;
+        btn->key = event->keyval;
     }
-    text = g_strdup_printf("%s%s", mod_text, btn_text);
-    gtk_button_set_label(btn, text);
+    text = gtk_accelerator_get_label(btn->key, btn->mods);
+    gtk_button_set_label(test, text);
     g_free(text);
-    g_free(mod_text);
+    return FALSE;
 }
 
 static gboolean on_button_press_event(GtkButton *test, GdkEventButton *event,
@@ -183,6 +232,7 @@ static gboolean on_button_press_event(GtkButton *test, GdkEventButton *event,
     char *text;
     char digit[4];
     guint keyval;
+    gboolean ret = FALSE;
 
     if (!btn->do_click)
         return FALSE;
@@ -206,23 +256,27 @@ static gboolean on_button_press_event(GtkButton *test, GdkEventButton *event,
         return FALSE;
     }
     /* send a signal that it's changed */
-    btn->mods = state;
-    btn->key = keyval;
-    _button_set_click_label(test, keyval, state);
     text = gtk_accelerator_name(keyval, state);
-    g_signal_emit(btn, signals[CHANGED], 0, text);
+    g_signal_emit(btn, signals[CHANGED], 0, text, &ret);
     g_free(text);
+    if (ret)
+    {
+        btn->mods = state;
+        btn->key = keyval;
+    }
+    _button_set_click_label(test, btn->key, btn->mods);
     return FALSE;
 }
 
 static void on_reset(GtkRadioButton *rb, PanelCfgInputButton *btn)
 {
+    gboolean ret = FALSE;
     if (!gtk_toggle_button_get_active(btn->none))
         return;
     btn->mods = 0;
     btn->key = 0;
     gtk_button_set_label(btn->btn, "");
-    g_signal_emit(btn, signals[CHANGED], 0, NULL);
+    g_signal_emit(btn, signals[CHANGED], 0, NULL, &ret);
 }
 
 /* ---- Class implementation ---- */
@@ -234,11 +288,11 @@ static void config_input_button_class_init(PanelCfgInputButtonClass *klass)
     signals[CHANGED] =
         g_signal_new("changed",
                      G_TYPE_FROM_CLASS(klass),
-                     G_SIGNAL_RUN_FIRST,
+                     G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET(PanelCfgInputButtonClass, changed),
-                     NULL, NULL,
-                     g_cclosure_marshal_VOID__STRING,
-                     G_TYPE_NONE, 1, G_TYPE_STRING);
+                     g_signal_accumulator_true_handled, NULL,
+                     _marshal_BOOLEAN__STRING,
+                     G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
 }
 
 static void config_input_button_init(PanelCfgInputButton *self)
@@ -362,13 +416,13 @@ static void handler(const char *keystring, void *user_data)
 
 static char *hotkey = NULL;
 
-static void cb(PanelCfgInputButton *btn, char *text, gpointer unused)
+static gboolean cb(PanelCfgInputButton *btn, char *text, gpointer unused)
 {
     g_print("got keystring \"%s\"\n", text);
 
     if (!btn->do_key)
-        return;
-    lxpanel_apply_hotkey(&hotkey, text, &handler, NULL, TRUE);
+        return TRUE;
+    return lxpanel_apply_hotkey(&hotkey, text, &handler, NULL, TRUE);
 }
 
 int main(int argc, char **argv)
index 39ee10c..bf8428d 100644 (file)
@@ -305,10 +305,18 @@ extern GtkWidget *panel_config_int_button_new(const char *name, gint *val,
                                               gint min, gint max);
 
 /*
- * creates GtkFrame derived widget which can change hotkey or mouse binding
- * emits "changed" signal: void callback(PanelCfgInputButton *, char *, gpointer);
- * caller should test if keybinding can be used in the callback
- * widget can be used for lxpanel_generic_config_dlg as CONF_TYPE_EXTERNAL
+ * panel_config_hotkey_button_new
+ * @label: text representing the option in dialog
+ * @hotkey: (allow-none): current hotkey
+ *
+ * Creates a #GtkFrame derived widget which can select hotkey binding.
+ * The widget emits "changed" signal when some new combination selected
+ *      gboolean callback(PanelCfgInputButton *, char *, gpointer);
+ * Caller should test if keybinding can be used in the callback and then
+ * return test result as %TRUE or %FALSE.
+ * Widget can be used for lxpanel_generic_config_dlg as CONF_TYPE_EXTERNAL
+ *
+ * Returns: (transfer full): a created widget.
  *
  * Since: 0.8.0
  */