Restrict the types of characters that can be entered in a GtkEntry

⌚Time: 2026-03-19 19:42:00

👨‍💻Author: Jack Ge

If I want to restrict GtkEntry to only input numbers, I can set the "input-purpose" property to numeric input. However, this does not restrict the type of characters that can be entered. It only adjusts the keyboard to the corresponding input mode.

gtk_entry_set_input_purpose(GTK_ENTRY(entry_min), GTK_INPUT_PURPOSE_DIGITS);
typedef enum {
  GTK_INPUT_PURPOSE_FREE_FORM,
  GTK_INPUT_PURPOSE_ALPHA,
  GTK_INPUT_PURPOSE_DIGITS,
  GTK_INPUT_PURPOSE_NUMBER,
  GTK_INPUT_PURPOSE_PHONE,
  GTK_INPUT_PURPOSE_URL,
  GTK_INPUT_PURPOSE_EMAIL,
  GTK_INPUT_PURPOSE_NAME,
  GTK_INPUT_PURPOSE_PASSWORD,
  GTK_INPUT_PURPOSE_PIN
} GtkInputPurpose;

This property can be used by on-screen keyboards and other input methods to adjust their behaviour.

To truly restrict user input, you need to handle the "insert-text" signal in the callback function. Its function prototype is:

The "insert-text" signal

void                user_function                      (GtkEditable *editable,
                                                        gchar       *new_text,
                                                        gint         new_text_length,
                                                        gpointer     position,
                                                        gpointer     user_data);

This signal is emitted when text is inserted into the widget by the user. The default handler for this signal will normally be responsible for inserting the text, so by connecting to this signal and then stopping the signal with g_signal_stop_emission(), it is possible to modify the inserted text, or prevent it from being inserted entirely.

editable :
    the object which received the signal

new_text :
    the new text to insert

new_text_length :
    the length of the new text, in bytes, or -1 if new_text is nul-terminated

position :
    the position, in characters, at which to insert the new text. this is an in-out parameter. After the signal emission is finished, it should point after the newly inserted text. [inout][type int]

user_data :
    user data set when the signal handler was connected.

I implemented a callback function that directly calls the g_signal_stop_emission_by_name function to discard the signal when a non-numeric value is encountered.

static void  digit_filter(GtkEditable *editable, gchar *new_text, gint new_text_length, gpointer position,  gpointer user_data){
                
    for (int i = 0; i < new_text_length; i++) {
        if (!isdigit(new_text[i])) {
            g_signal_stop_emission_by_name(editable, "insert-text");
            return;
        }
    }
    
}

Connect the 'insert-text' signal of GtkEntry to a callback function

g_signal_connect(entry_min, "insert-text", G_CALLBACK(digit_filter), NULL);

This allows you to restrict users to only entering numbers. If you need to restrict other characters, you just need to make the judgment in the callback function.